From 62ddd4873ff3a9ba3591965e8dfd0274a7cb7c2c Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Thu, 1 Aug 2024 18:44:39 +0200 Subject: [PATCH] refactor: Projektdateien migriert. Cloud-NuGet-Pakete durch lokale NuGet-Projekte ersetzt. --- .editorconfig | 4 + DAL/DAL.csproj | 14 + DAL/Models/Entities/AdWebAppToWebAppRole.cs | 26 + DAL/Models/Entities/CostCentre.cs | 20 + DAL/Models/Entities/Department.cs | 41 + ...DepartmentToWebAppToEmployeeForWindream.cs | 25 + DAL/Models/Entities/DocumentArt.cs | 28 + .../Entities/DocumentArtToDepartment.cs | 32 + DAL/Models/Entities/Employee.cs | 58 ++ DAL/Models/Entities/EmployeeAttribute.cs | 22 + DAL/Models/Entities/EmployeeStatus.cs | 19 + DAL/Models/Entities/EmployeeToAttribute.cs | 21 + DAL/Models/Entities/EmployeeToDepartment.cs | 29 + DAL/Models/Entities/EmployeeToWebApp.cs | 45 ++ DAL/Models/Entities/Project.cs | 19 + DAL/Models/Entities/Rang.cs | 21 + DAL/Models/Entities/Subsidiary.cs | 25 + DAL/Models/Entities/WebApp.cs | 23 + DAL/Models/Entities/WebAppAdditionalRole.cs | 21 + DAL/Models/Entities/WebAppRole.cs | 20 + DAL/Models/Entities/WebAppToDepartment.cs | 24 + .../Entities/WebAppToWebAppAdditionalRole.cs | 20 + DAL/Models/Entities/WebAppToWebAppRole.cs | 27 + .../Entities/WindreamColumnsToDepartment.cs | 33 + DAL/Models/Entities/WindreamIndex.cs | 25 + ...ndreamIndexToWindreamSearchToDepartment.cs | 28 + DAL/Models/Entities/WindreamInputFolder.cs | 22 + DAL/Models/Entities/WindreamSearch.cs | 24 + DAL/Models/Entities/WindreamSearchItem.cs | 30 + ...mSearchItemToWindreamSearchToDepartment.cs | 49 ++ .../Entities/WindreamSearchToDepartment.cs | 38 + DAL/Models/Filters/ClientIdFilter.cs | 9 + DAL/Models/Filters/DepartmentFilter.cs | 10 + DAL/Models/Filters/DepartmentFullFilter.cs | 9 + DAL/Models/Filters/EmployeeFilter.cs | 11 + DAL/Models/Filters/EmployeeFullFilter.cs | 18 + DAL/Models/Filters/EmployeeToWebAppFilter.cs | 9 + DAL/Models/Filters/WebAppFilter.cs | 9 + .../Filters/WindreamInputFolderFilter.cs | 10 + .../WindreamSearchToDepartmentFilter.cs | 10 + .../AdWebAppToWebAppRoleRepository.cs | 12 + DAL/Repositories/CostCentreRepository.cs | 12 + DAL/Repositories/DepartmentRepository.cs | 34 + ...ToWebAppToEmployeeForWindreamRepository.cs | 40 + DAL/Repositories/DocumentArtRepository.cs | 12 + .../DocumentArtToDepartmentRepository.cs | 29 + .../EmployeeAttributeRepository.cs | 12 + DAL/Repositories/EmployeeRepository.cs | 96 +++ DAL/Repositories/EmployeeStatusRepository.cs | 12 + .../EmployeeToAttributeRepository.cs | 29 + .../EmployeeToDepartmentRepository.cs | 29 + .../EmployeeToWebAppRepository.cs | 253 ++++++ DAL/Repositories/ProjectRepository.cs | 12 + DAL/Repositories/RangRepository.cs | 12 + DAL/Repositories/SubsidiaryRepository.cs | 12 + .../WebAppAdditionalRoleRepository.cs | 29 + DAL/Repositories/WebAppRepository.cs | 12 + DAL/Repositories/WebAppRoleRepository.cs | 12 + .../WebAppToDepartmentRepository.cs | 178 +++++ .../WebAppToWebAppAdditionalRoleRepository.cs | 176 +++++ .../WebAppToWebAppRoleRepository.cs | 29 + .../WindreamColumnsToDepartmentRepository.cs | 34 + DAL/Repositories/WindreamIndexRepository.cs | 29 + ...xToWindreamSearchToDepartmentRepository.cs | 29 + .../WindreamInputFolderRepository.cs | 34 + .../WindreamSearchItemRepository.cs | 29 + ...mToWindreamSearchToDepartmentRepository.cs | 33 + DAL/Repositories/WindreamSearchRepository.cs | 29 + .../WindreamSearchToDepartmentRepository.cs | 36 + DAL/WebApiContext.cs | 213 +++++ .../SharedModels/WebAppEmployeeInfo.cs | 37 + DAL/_Shared/SharedModels/WebAppUser.cs | 59 ++ .../WebAppEmployeeInfoRepository.cs | 114 +++ .../WebAppUserRepository.cs | 12 + DAL/_Shared/init_context.bat | 2 + HRD.AppLogger/AppLoggerConfig.cs | 255 ++++++ HRD.AppLogger/HRD.AppLogger.csproj | 15 + HRD.AppLogger/ILoggerManager.cs | 17 + HRD.AppLogger/LoggerManager.cs | 214 +++++ HRD.AppLogger/NlogSentryConfig.cs | 29 + HRD.LDAPService/HRD.LDAPService.csproj | 24 + HRD.LDAPService/JWT/HttpErrorDetails.cs | 21 + HRD.LDAPService/JWT/JWTAuthorizeAttribute.cs | 40 + HRD.LDAPService/JWT/JWTAuthorizeVendorId.cs | 125 +++ HRD.LDAPService/JWT/JWTCrypt.cs | 31 + HRD.LDAPService/JWT/JwtGlobals.cs | 19 + HRD.LDAPService/JWT/JwtManager.cs | 355 +++++++++ HRD.LDAPService/JWT/JwtMiddleware.cs | 97 +++ .../JWT/JwtMiddlewareExtensions.cs | 69 ++ HRD.LDAPService/JWT/JwtMiddlewareOptions.cs | 18 + HRD.LDAPService/JWT/JwtRole.cs | 32 + HRD.LDAPService/JWT/JwtTokenConfig.cs | 49 ++ HRD.LDAPService/Ldap/EN_LdapRoleListFilter.cs | 9 + .../Ldap/LdapAuthenticationService.cs | 213 +++++ HRD.LDAPService/Ldap/LdapExtensions.cs | 52 ++ HRD.LDAPService/Ldap/LdapGlobals.cs | 22 + HRD.LDAPService/Ldap/LdapManager.cs | 265 +++++++ HRD.LDAPService/Ldap/LdapUser.cs | 268 +++++++ .../HRD.LdapService.Test.csproj | 25 + HRD.LdapService.Test/LdapTest.cs | 134 ++++ HRD.WebApi/Configs/WebApiConfig.cs | 178 +++++ HRD.WebApi/Configs/WebApiEnums.cs | 16 + HRD.WebApi/Controllers/BaseController.cs | 196 +++++ HRD.WebApi/Controllers/BaseMiniController.cs | 52 ++ .../Controllers/HttpStatusCodeException.cs | 33 + HRD.WebApi/Controllers/InfoBaseController.cs | 55 ++ HRD.WebApi/DAL/WebApiBaseContext.cs | 17 + HRD.WebApi/Extensions/EnumExtensions.cs | 24 + HRD.WebApi/Extensions/StringExtensions.cs | 22 + HRD.WebApi/Extensions/SystemExtensions.cs | 45 ++ HRD.WebApi/HRD.WebApi.csproj | 16 + HRD.WebApi/Helpers/AttributeReader.cs | 25 + HRD.WebApi/Helpers/CorsExtension.cs | 24 + HRD.WebApi/Helpers/ExceptionExtension.cs | 39 + HRD.WebApi/Helpers/HttpErrorDetails.cs | 69 ++ HRD.WebApi/Helpers/JsonConvert.cs | 42 + HRD.WebApi/Helpers/ServerInfoHelper.cs | 40 + .../Middleware/HttpStatusCodeException.cs | 31 + HRD.WebApi/Middleware/WebApiMiddleware.cs | 52 ++ .../Middleware/WebApiMiddlewareExtensions.cs | 36 + .../Middleware/WebApiMiddlewareOptions.cs | 22 + HRD.WebApi/Models/BaseEntity.cs | 6 + HRD.WebApi/Models/BaseEntityCore.cs | 17 + HRD.WebApi/Models/BaseFilter.cs | 6 + HRD.WebApi/Models/IBaseEntityCore.cs | 6 + HRD.WebApi/Models/IBaseFilter.cs | 6 + HRD.WebApi/Models/ServerInfo.cs | 37 + HRD.WebApi/Repositories/BaseRepository.cs | 11 + HRD.WebApi/Repositories/BaseRepositoryCore.cs | 619 +++++++++++++++ HRD.WebApi/Repositories/IBaseRepository.cs | 6 + .../Repositories/IBaseRepositoryCore.cs | 66 ++ README.md | 24 +- Scripts/Core/EntityController_test.tmpl | 25 + .../EntityFilteredListController_test.tmpl | 27 + Scripts/Core/add_CommonTestController.bat | 54 ++ Scripts/Core/add_ServiceExtensions.bat | 61 ++ Scripts/Core/add_WebApiContext.bat | 69 ++ Scripts/Core/add_controller.bat | 15 + Scripts/Core/add_controller_filter.bat | 36 + Scripts/Core/add_entity.bat | 23 + Scripts/Core/add_filter.bat | 11 + Scripts/Core/add_repository.bat | 12 + Scripts/Core/add_repository_filter.bat | 51 ++ Scripts/Core/add_test_project.bat | 20 + Scripts/Core/add_tests_generic.bat | 65 ++ Scripts/Core/replaceinfile.bat | 33 + Scripts/Core/sample_entity.bat | 10 + Scripts/Core/start_add_entity_to_project.bat | 45 ++ Scripts/Run/EntitiesFilterList.lst | 17 + Scripts/Run/EntitiesList.lst | 10 + Scripts/Run/add_list_entities.bat | 27 + Scripts/Run/add_one_entity.bat | 6 + Scripts/Run/prepare_project.bat | 73 ++ StaffDBServer.sln | 62 ++ StaffDBServer/.config/dotnet-tools.json | 5 + .../AdWebAppToWebAppRoleController.cs | 15 + .../Controllers/CostCentreController.cs | 15 + .../Controllers/DepartmentController.cs | 54 ++ ...ToWebAppToEmployeeForWindreamController.cs | 36 + .../Controllers/DocumentArtController.cs | 15 + .../DocumentArtToDepartmentController.cs | 36 + .../EmployeeAttributeController.cs | 15 + .../Controllers/EmployeeController.cs | 36 + .../Controllers/EmployeeStatusController.cs | 15 + .../EmployeeToAttributeController.cs | 36 + .../EmployeeToDepartmentController.cs | 36 + .../Controllers/EmployeeToWebAppController.cs | 36 + .../Controllers/ProjectController.cs | 15 + StaffDBServer/Controllers/RangController.cs | 15 + .../Controllers/SubsidiaryController.cs | 15 + .../WebAppAdditionalRoleController.cs | 36 + StaffDBServer/Controllers/WebAppController.cs | 15 + .../Controllers/WebAppRoleController.cs | 15 + .../WebAppToDepartmentController.cs | 36 + .../WebAppToWebAppAdditionalRoleController.cs | 36 + .../WebAppToWebAppRoleController.cs | 36 + .../WindreamColumnsToDepartmentController.cs | 36 + .../Controllers/WindreamIndexController.cs | 36 + ...xToWindreamSearchToDepartmentController.cs | 36 + .../WindreamInputFolderController.cs | 36 + .../Controllers/WindreamSearchController.cs | 36 + .../WindreamSearchItemController.cs | 36 + ...mToWindreamSearchToDepartmentController.cs | 36 + .../WindreamSearchToDepartmentController.cs | 54 ++ .../Extends/JwtMiddlewareOptionsHelper.cs | 37 + .../ServiceExtensions4BaseRepository.cs | 47 ++ StaffDBServer/Nuget.config | 11 + StaffDBServer/Program.cs | 67 ++ StaffDBServer/Properties/launchSettings.json | 13 + StaffDBServer/StaffDBServer.csproj | 25 + StaffDBServer/Startup.cs | 69 ++ .../SharedControllers/InfoController.cs | 16 + .../SharedControllers/WebAppUserController.cs | 99 +++ .../SharedControllers/WebAppUserHelper.cs | 204 +++++ .../SharedExtensions/ServiceExtensions.cs | 49 ++ .../ServiceSwaggerExtensions.cs | 59 ++ .../WebApiMiddlewareOptionsHelper.cs | 26 + StaffDBServer/appsettings.json | 30 + XUnitDAL.Test/Test_Controller_Entity.cs | 730 ++++++++++++++++++ XUnitDAL.Test/Test_Controller_Filter.cs | 534 +++++++++++++ XUnitDAL.Test/XUnitWebApi.Test.csproj | 27 + .../_Shared/Shared_Test_Controller_Generic.cs | 89 +++ XUnitDAL.Test/_Shared/Shared_Test_DAL.cs | 88 +++ XUnitDAL.Test/_Shared/Shared_Test_LDAP.cs | 98 +++ XUnitDAL.Test/_Shared/Shared_Utils.cs | 46 ++ XUnitDAL.Test/_Shared/Shared_test_config.cs | 41 + 206 files changed, 10927 insertions(+), 1 deletion(-) create mode 100644 .editorconfig create mode 100644 DAL/DAL.csproj create mode 100644 DAL/Models/Entities/AdWebAppToWebAppRole.cs create mode 100644 DAL/Models/Entities/CostCentre.cs create mode 100644 DAL/Models/Entities/Department.cs create mode 100644 DAL/Models/Entities/DepartmentToWebAppToEmployeeForWindream.cs create mode 100644 DAL/Models/Entities/DocumentArt.cs create mode 100644 DAL/Models/Entities/DocumentArtToDepartment.cs create mode 100644 DAL/Models/Entities/Employee.cs create mode 100644 DAL/Models/Entities/EmployeeAttribute.cs create mode 100644 DAL/Models/Entities/EmployeeStatus.cs create mode 100644 DAL/Models/Entities/EmployeeToAttribute.cs create mode 100644 DAL/Models/Entities/EmployeeToDepartment.cs create mode 100644 DAL/Models/Entities/EmployeeToWebApp.cs create mode 100644 DAL/Models/Entities/Project.cs create mode 100644 DAL/Models/Entities/Rang.cs create mode 100644 DAL/Models/Entities/Subsidiary.cs create mode 100644 DAL/Models/Entities/WebApp.cs create mode 100644 DAL/Models/Entities/WebAppAdditionalRole.cs create mode 100644 DAL/Models/Entities/WebAppRole.cs create mode 100644 DAL/Models/Entities/WebAppToDepartment.cs create mode 100644 DAL/Models/Entities/WebAppToWebAppAdditionalRole.cs create mode 100644 DAL/Models/Entities/WebAppToWebAppRole.cs create mode 100644 DAL/Models/Entities/WindreamColumnsToDepartment.cs create mode 100644 DAL/Models/Entities/WindreamIndex.cs create mode 100644 DAL/Models/Entities/WindreamIndexToWindreamSearchToDepartment.cs create mode 100644 DAL/Models/Entities/WindreamInputFolder.cs create mode 100644 DAL/Models/Entities/WindreamSearch.cs create mode 100644 DAL/Models/Entities/WindreamSearchItem.cs create mode 100644 DAL/Models/Entities/WindreamSearchItemToWindreamSearchToDepartment.cs create mode 100644 DAL/Models/Entities/WindreamSearchToDepartment.cs create mode 100644 DAL/Models/Filters/ClientIdFilter.cs create mode 100644 DAL/Models/Filters/DepartmentFilter.cs create mode 100644 DAL/Models/Filters/DepartmentFullFilter.cs create mode 100644 DAL/Models/Filters/EmployeeFilter.cs create mode 100644 DAL/Models/Filters/EmployeeFullFilter.cs create mode 100644 DAL/Models/Filters/EmployeeToWebAppFilter.cs create mode 100644 DAL/Models/Filters/WebAppFilter.cs create mode 100644 DAL/Models/Filters/WindreamInputFolderFilter.cs create mode 100644 DAL/Models/Filters/WindreamSearchToDepartmentFilter.cs create mode 100644 DAL/Repositories/AdWebAppToWebAppRoleRepository.cs create mode 100644 DAL/Repositories/CostCentreRepository.cs create mode 100644 DAL/Repositories/DepartmentRepository.cs create mode 100644 DAL/Repositories/DepartmentToWebAppToEmployeeForWindreamRepository.cs create mode 100644 DAL/Repositories/DocumentArtRepository.cs create mode 100644 DAL/Repositories/DocumentArtToDepartmentRepository.cs create mode 100644 DAL/Repositories/EmployeeAttributeRepository.cs create mode 100644 DAL/Repositories/EmployeeRepository.cs create mode 100644 DAL/Repositories/EmployeeStatusRepository.cs create mode 100644 DAL/Repositories/EmployeeToAttributeRepository.cs create mode 100644 DAL/Repositories/EmployeeToDepartmentRepository.cs create mode 100644 DAL/Repositories/EmployeeToWebAppRepository.cs create mode 100644 DAL/Repositories/ProjectRepository.cs create mode 100644 DAL/Repositories/RangRepository.cs create mode 100644 DAL/Repositories/SubsidiaryRepository.cs create mode 100644 DAL/Repositories/WebAppAdditionalRoleRepository.cs create mode 100644 DAL/Repositories/WebAppRepository.cs create mode 100644 DAL/Repositories/WebAppRoleRepository.cs create mode 100644 DAL/Repositories/WebAppToDepartmentRepository.cs create mode 100644 DAL/Repositories/WebAppToWebAppAdditionalRoleRepository.cs create mode 100644 DAL/Repositories/WebAppToWebAppRoleRepository.cs create mode 100644 DAL/Repositories/WindreamColumnsToDepartmentRepository.cs create mode 100644 DAL/Repositories/WindreamIndexRepository.cs create mode 100644 DAL/Repositories/WindreamIndexToWindreamSearchToDepartmentRepository.cs create mode 100644 DAL/Repositories/WindreamInputFolderRepository.cs create mode 100644 DAL/Repositories/WindreamSearchItemRepository.cs create mode 100644 DAL/Repositories/WindreamSearchItemToWindreamSearchToDepartmentRepository.cs create mode 100644 DAL/Repositories/WindreamSearchRepository.cs create mode 100644 DAL/Repositories/WindreamSearchToDepartmentRepository.cs create mode 100644 DAL/WebApiContext.cs create mode 100644 DAL/_Shared/SharedModels/WebAppEmployeeInfo.cs create mode 100644 DAL/_Shared/SharedModels/WebAppUser.cs create mode 100644 DAL/_Shared/SharedRepositories/WebAppEmployeeInfoRepository.cs create mode 100644 DAL/_Shared/SharedRepositories/WebAppUserRepository.cs create mode 100644 DAL/_Shared/init_context.bat create mode 100644 HRD.AppLogger/AppLoggerConfig.cs create mode 100644 HRD.AppLogger/HRD.AppLogger.csproj create mode 100644 HRD.AppLogger/ILoggerManager.cs create mode 100644 HRD.AppLogger/LoggerManager.cs create mode 100644 HRD.AppLogger/NlogSentryConfig.cs create mode 100644 HRD.LDAPService/HRD.LDAPService.csproj create mode 100644 HRD.LDAPService/JWT/HttpErrorDetails.cs create mode 100644 HRD.LDAPService/JWT/JWTAuthorizeAttribute.cs create mode 100644 HRD.LDAPService/JWT/JWTAuthorizeVendorId.cs create mode 100644 HRD.LDAPService/JWT/JWTCrypt.cs create mode 100644 HRD.LDAPService/JWT/JwtGlobals.cs create mode 100644 HRD.LDAPService/JWT/JwtManager.cs create mode 100644 HRD.LDAPService/JWT/JwtMiddleware.cs create mode 100644 HRD.LDAPService/JWT/JwtMiddlewareExtensions.cs create mode 100644 HRD.LDAPService/JWT/JwtMiddlewareOptions.cs create mode 100644 HRD.LDAPService/JWT/JwtRole.cs create mode 100644 HRD.LDAPService/JWT/JwtTokenConfig.cs create mode 100644 HRD.LDAPService/Ldap/EN_LdapRoleListFilter.cs create mode 100644 HRD.LDAPService/Ldap/LdapAuthenticationService.cs create mode 100644 HRD.LDAPService/Ldap/LdapExtensions.cs create mode 100644 HRD.LDAPService/Ldap/LdapGlobals.cs create mode 100644 HRD.LDAPService/Ldap/LdapManager.cs create mode 100644 HRD.LDAPService/Ldap/LdapUser.cs create mode 100644 HRD.LdapService.Test/HRD.LdapService.Test.csproj create mode 100644 HRD.LdapService.Test/LdapTest.cs create mode 100644 HRD.WebApi/Configs/WebApiConfig.cs create mode 100644 HRD.WebApi/Configs/WebApiEnums.cs create mode 100644 HRD.WebApi/Controllers/BaseController.cs create mode 100644 HRD.WebApi/Controllers/BaseMiniController.cs create mode 100644 HRD.WebApi/Controllers/HttpStatusCodeException.cs create mode 100644 HRD.WebApi/Controllers/InfoBaseController.cs create mode 100644 HRD.WebApi/DAL/WebApiBaseContext.cs create mode 100644 HRD.WebApi/Extensions/EnumExtensions.cs create mode 100644 HRD.WebApi/Extensions/StringExtensions.cs create mode 100644 HRD.WebApi/Extensions/SystemExtensions.cs create mode 100644 HRD.WebApi/HRD.WebApi.csproj create mode 100644 HRD.WebApi/Helpers/AttributeReader.cs create mode 100644 HRD.WebApi/Helpers/CorsExtension.cs create mode 100644 HRD.WebApi/Helpers/ExceptionExtension.cs create mode 100644 HRD.WebApi/Helpers/HttpErrorDetails.cs create mode 100644 HRD.WebApi/Helpers/JsonConvert.cs create mode 100644 HRD.WebApi/Helpers/ServerInfoHelper.cs create mode 100644 HRD.WebApi/Middleware/HttpStatusCodeException.cs create mode 100644 HRD.WebApi/Middleware/WebApiMiddleware.cs create mode 100644 HRD.WebApi/Middleware/WebApiMiddlewareExtensions.cs create mode 100644 HRD.WebApi/Middleware/WebApiMiddlewareOptions.cs create mode 100644 HRD.WebApi/Models/BaseEntity.cs create mode 100644 HRD.WebApi/Models/BaseEntityCore.cs create mode 100644 HRD.WebApi/Models/BaseFilter.cs create mode 100644 HRD.WebApi/Models/IBaseEntityCore.cs create mode 100644 HRD.WebApi/Models/IBaseFilter.cs create mode 100644 HRD.WebApi/Models/ServerInfo.cs create mode 100644 HRD.WebApi/Repositories/BaseRepository.cs create mode 100644 HRD.WebApi/Repositories/BaseRepositoryCore.cs create mode 100644 HRD.WebApi/Repositories/IBaseRepository.cs create mode 100644 HRD.WebApi/Repositories/IBaseRepositoryCore.cs create mode 100644 Scripts/Core/EntityController_test.tmpl create mode 100644 Scripts/Core/EntityFilteredListController_test.tmpl create mode 100644 Scripts/Core/add_CommonTestController.bat create mode 100644 Scripts/Core/add_ServiceExtensions.bat create mode 100644 Scripts/Core/add_WebApiContext.bat create mode 100644 Scripts/Core/add_controller.bat create mode 100644 Scripts/Core/add_controller_filter.bat create mode 100644 Scripts/Core/add_entity.bat create mode 100644 Scripts/Core/add_filter.bat create mode 100644 Scripts/Core/add_repository.bat create mode 100644 Scripts/Core/add_repository_filter.bat create mode 100644 Scripts/Core/add_test_project.bat create mode 100644 Scripts/Core/add_tests_generic.bat create mode 100644 Scripts/Core/replaceinfile.bat create mode 100644 Scripts/Core/sample_entity.bat create mode 100644 Scripts/Core/start_add_entity_to_project.bat create mode 100644 Scripts/Run/EntitiesFilterList.lst create mode 100644 Scripts/Run/EntitiesList.lst create mode 100644 Scripts/Run/add_list_entities.bat create mode 100644 Scripts/Run/add_one_entity.bat create mode 100644 Scripts/Run/prepare_project.bat create mode 100644 StaffDBServer.sln create mode 100644 StaffDBServer/.config/dotnet-tools.json create mode 100644 StaffDBServer/Controllers/AdWebAppToWebAppRoleController.cs create mode 100644 StaffDBServer/Controllers/CostCentreController.cs create mode 100644 StaffDBServer/Controllers/DepartmentController.cs create mode 100644 StaffDBServer/Controllers/DepartmentToWebAppToEmployeeForWindreamController.cs create mode 100644 StaffDBServer/Controllers/DocumentArtController.cs create mode 100644 StaffDBServer/Controllers/DocumentArtToDepartmentController.cs create mode 100644 StaffDBServer/Controllers/EmployeeAttributeController.cs create mode 100644 StaffDBServer/Controllers/EmployeeController.cs create mode 100644 StaffDBServer/Controllers/EmployeeStatusController.cs create mode 100644 StaffDBServer/Controllers/EmployeeToAttributeController.cs create mode 100644 StaffDBServer/Controllers/EmployeeToDepartmentController.cs create mode 100644 StaffDBServer/Controllers/EmployeeToWebAppController.cs create mode 100644 StaffDBServer/Controllers/ProjectController.cs create mode 100644 StaffDBServer/Controllers/RangController.cs create mode 100644 StaffDBServer/Controllers/SubsidiaryController.cs create mode 100644 StaffDBServer/Controllers/WebAppAdditionalRoleController.cs create mode 100644 StaffDBServer/Controllers/WebAppController.cs create mode 100644 StaffDBServer/Controllers/WebAppRoleController.cs create mode 100644 StaffDBServer/Controllers/WebAppToDepartmentController.cs create mode 100644 StaffDBServer/Controllers/WebAppToWebAppAdditionalRoleController.cs create mode 100644 StaffDBServer/Controllers/WebAppToWebAppRoleController.cs create mode 100644 StaffDBServer/Controllers/WindreamColumnsToDepartmentController.cs create mode 100644 StaffDBServer/Controllers/WindreamIndexController.cs create mode 100644 StaffDBServer/Controllers/WindreamIndexToWindreamSearchToDepartmentController.cs create mode 100644 StaffDBServer/Controllers/WindreamInputFolderController.cs create mode 100644 StaffDBServer/Controllers/WindreamSearchController.cs create mode 100644 StaffDBServer/Controllers/WindreamSearchItemController.cs create mode 100644 StaffDBServer/Controllers/WindreamSearchItemToWindreamSearchToDepartmentController.cs create mode 100644 StaffDBServer/Controllers/WindreamSearchToDepartmentController.cs create mode 100644 StaffDBServer/Extends/JwtMiddlewareOptionsHelper.cs create mode 100644 StaffDBServer/Extends/ServiceExtensions4BaseRepository.cs create mode 100644 StaffDBServer/Nuget.config create mode 100644 StaffDBServer/Program.cs create mode 100644 StaffDBServer/Properties/launchSettings.json create mode 100644 StaffDBServer/StaffDBServer.csproj create mode 100644 StaffDBServer/Startup.cs create mode 100644 StaffDBServer/_Shared/SharedControllers/InfoController.cs create mode 100644 StaffDBServer/_Shared/SharedControllers/WebAppUserController.cs create mode 100644 StaffDBServer/_Shared/SharedControllers/WebAppUserHelper.cs create mode 100644 StaffDBServer/_Shared/SharedExtensions/ServiceExtensions.cs create mode 100644 StaffDBServer/_Shared/SharedExtensions/ServiceSwaggerExtensions.cs create mode 100644 StaffDBServer/_Shared/SharedExtensions/WebApiMiddlewareOptionsHelper.cs create mode 100644 StaffDBServer/appsettings.json create mode 100644 XUnitDAL.Test/Test_Controller_Entity.cs create mode 100644 XUnitDAL.Test/Test_Controller_Filter.cs create mode 100644 XUnitDAL.Test/XUnitWebApi.Test.csproj create mode 100644 XUnitDAL.Test/_Shared/Shared_Test_Controller_Generic.cs create mode 100644 XUnitDAL.Test/_Shared/Shared_Test_DAL.cs create mode 100644 XUnitDAL.Test/_Shared/Shared_Test_LDAP.cs create mode 100644 XUnitDAL.Test/_Shared/Shared_Utils.cs create mode 100644 XUnitDAL.Test/_Shared/Shared_test_config.cs diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..1110d08 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +[*.cs] + +# CA1707: Identifiers should not contain underscores +dotnet_diagnostic.CA1707.severity = silent diff --git a/DAL/DAL.csproj b/DAL/DAL.csproj new file mode 100644 index 0000000..014b2d7 --- /dev/null +++ b/DAL/DAL.csproj @@ -0,0 +1,14 @@ + + + + net7.0 + 2.3.7 + 2.3.7.0 + 2.3.7.0 + + + + + + + \ No newline at end of file diff --git a/DAL/Models/Entities/AdWebAppToWebAppRole.cs b/DAL/Models/Entities/AdWebAppToWebAppRole.cs new file mode 100644 index 0000000..dbc9a5a --- /dev/null +++ b/DAL/Models/Entities/AdWebAppToWebAppRole.cs @@ -0,0 +1,26 @@ +using HRD.WebApi.DAL; + +namespace DAL.Models.Entities +{ + public partial class AdWebAppToWebAppRole : BaseEntity + { + public int AdWebAppToWebAppRoleId { get; set; } + public int WebAppId { get; set; } + public string AdWebAppName { get; set; } + public string AdWebAppRoleName { get; set; } + + public string GetAdGrupSuffix() + { + return $"{AdWebAppName}_{AdWebAppRoleName}"; + } + + //generic Id + public override int GetEntityId() => AdWebAppToWebAppRoleId; + + //generic ToString() + public override string ToString() => $"AdWebAppToWebAppRoleId: {GetEntityId()}; AdWebAppRoleName: {AdWebAppRoleName}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/CostCentre.cs b/DAL/Models/Entities/CostCentre.cs new file mode 100644 index 0000000..1519da9 --- /dev/null +++ b/DAL/Models/Entities/CostCentre.cs @@ -0,0 +1,20 @@ +using HRD.WebApi.DAL; + +namespace DAL.Models.Entities +{ + public partial class CostCentre : BaseEntity + { + public int CostCentreId { get; set; } + public string CostCentreName { get; set; } + public int SortOrder { get; set; } + + //generic Id + public override int GetEntityId() => CostCentreId; + + //generic ToString() + public override string ToString() => $"CostCentreId: {GetEntityId()}; Name: {CostCentreName}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/Department.cs b/DAL/Models/Entities/Department.cs new file mode 100644 index 0000000..8ea4f30 --- /dev/null +++ b/DAL/Models/Entities/Department.cs @@ -0,0 +1,41 @@ +using HRD.WebApi.DAL; +using System.ComponentModel.DataAnnotations.Schema; + +namespace DAL.Models.Entities +{ + public partial class Department : BaseEntity + { + public int DepartmentId { get; set; } + public string DepartmentName { get; set; } + public int CostCentreId { get; set; } + public int DepartmentTypeId { get; set; } + public int? HeadofDepartmentId { get; set; } + public int? ExecutiveDirectorId { get; set; } + public int? ManagingDirectorId { get; set; } + public string DepartmentNameFolder { get; set; } + public string AdGroupDepartmentName { get; set; } + public int? ClientId { get; set; } + public bool IsVirtual { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string CostCentre { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string HeadofDepartment { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string ExecutiveDirector { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string ManagingDirector { get; set; } + + //generic Id + public override int GetEntityId() => DepartmentId; + + //generic ToString() + public override string ToString() => $"DepartmentId: {GetEntityId()}; Name: {DepartmentName}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/DepartmentToWebAppToEmployeeForWindream.cs b/DAL/Models/Entities/DepartmentToWebAppToEmployeeForWindream.cs new file mode 100644 index 0000000..a38c113 --- /dev/null +++ b/DAL/Models/Entities/DepartmentToWebAppToEmployeeForWindream.cs @@ -0,0 +1,25 @@ +using HRD.WebApi.DAL; + +namespace DAL.Models.Entities +{ + public partial class DepartmentToWebAppToEmployeeForWindream : BaseEntity + { + public int DepartmentToWebAppToEmployeeForWindreamId { get; set; } + public int EmployeeId { get; set; } + public int DepartmentId { get; set; } + public string DepartmentName { get; set; } + public string ShortName { get; set; } + public string LoginName { get; set; } + public int IsMain { get; set; } + public int? ClientId { get; set; } + + //generic Id + public override int GetEntityId() => DepartmentToWebAppToEmployeeForWindreamId; + + //generic ToString() + public override string ToString() => $"DepartmentToWebAppToEmployeeForWindreamId: {GetEntityId()}; EmployeeId: {EmployeeId}; DepartmentId: {DepartmentId}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/DocumentArt.cs b/DAL/Models/Entities/DocumentArt.cs new file mode 100644 index 0000000..5e6ad00 --- /dev/null +++ b/DAL/Models/Entities/DocumentArt.cs @@ -0,0 +1,28 @@ +using HRD.WebApi.DAL; +using System.ComponentModel.DataAnnotations.Schema; + +namespace DAL.Models.Entities +{ + public partial class DocumentArt : BaseEntity + { + public int DocumentArtId { get; set; } + public string Name { get; set; } + public string Shortname { get; set; } + public string RootPath { get; set; } + public string Folder { get; set; } + public string Comment { get; set; } + public int ClientId { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string DepartmentNamesList { get; set; } + + //generic Id + public override int GetEntityId() => DocumentArtId; + + //generic ToString() + public override string ToString() => $"DocumentArtId: {GetEntityId()}; Name: {Name}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/DocumentArtToDepartment.cs b/DAL/Models/Entities/DocumentArtToDepartment.cs new file mode 100644 index 0000000..7ecd341 --- /dev/null +++ b/DAL/Models/Entities/DocumentArtToDepartment.cs @@ -0,0 +1,32 @@ +using HRD.WebApi.DAL; +using System.ComponentModel.DataAnnotations.Schema; + +namespace DAL.Models.Entities +{ + public partial class DocumentArtToDepartment : BaseEntity + { + public int DocumentArtToDepartmentId { get; set; } + public int DepartmentId { get; set; } + public int DocumentArtId { get; set; } + public bool IsActive { get; set; } + public bool? UseGlobix { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string DocumentArtName { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string DocumentArtShortname { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string DocumentArtFolder { get; set; } + + //generic Id + public override int GetEntityId() => DocumentArtToDepartmentId; + + //generic ToString() + public override string ToString() => $"DocumentArtToDepartmentId: {GetEntityId()}; DepartmentId : {DepartmentId}; DocumentArtId : {DocumentArtId}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/Employee.cs b/DAL/Models/Entities/Employee.cs new file mode 100644 index 0000000..459ec74 --- /dev/null +++ b/DAL/Models/Entities/Employee.cs @@ -0,0 +1,58 @@ +using HRD.WebApi.DAL; +using System.ComponentModel.DataAnnotations.Schema; + +namespace DAL.Models.Entities +{ + public partial class Employee : BaseEntity + { + public int EmployeeId { get; set; } + public string EmployeeNo { get; set; } + public string Salutation { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + public string ShortName { get; set; } + public string Title { get; set; } + public string Position { get; set; } + public string LoginName { get; set; } + public string Email { get; set; } + public int? RangId { get; set; } + public int ClientId { get; set; } + public bool? IsActive { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string MandantCode { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public int? MainDepartmentId { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string DepartmentNamesList { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string DepartmentIdList { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string WebappNamesList { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string WebappIdList { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string AttributeNamesList { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string AttributeIdList { get; set; } + + public string MobilePhoneNo { get; set; } + public string PhoneNo { get; set; } + + //generic Id + public override int GetEntityId() => EmployeeId; + + //generic ToString() + public override string ToString() => $"EmployeeId: {GetEntityId()}; LoginName: {LoginName}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/EmployeeAttribute.cs b/DAL/Models/Entities/EmployeeAttribute.cs new file mode 100644 index 0000000..7ed42d0 --- /dev/null +++ b/DAL/Models/Entities/EmployeeAttribute.cs @@ -0,0 +1,22 @@ +using HRD.WebApi.DAL; + +namespace DAL.Models.Entities +{ + public partial class EmployeeAttribute : BaseEntity + { + public int EmployeeAttributeId { get; set; } + public string Name { get; set; } + public string Shortname { get; set; } + public string RoleList { get; set; } + public int? SeqNo { get; set; } + + //generic Id + public override int GetEntityId() => EmployeeAttributeId; + + //generic ToString() + public override string ToString() => $"EmployeeAttributeId: {GetEntityId()}; Name: {Name}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/EmployeeStatus.cs b/DAL/Models/Entities/EmployeeStatus.cs new file mode 100644 index 0000000..f246cbc --- /dev/null +++ b/DAL/Models/Entities/EmployeeStatus.cs @@ -0,0 +1,19 @@ +using HRD.WebApi.DAL; + +namespace DAL.Models.Entities +{ + public partial class EmployeeStatus : BaseEntity + { + public int EmployeeStatusId { get; set; } + public string EmployeeStatusName { get; set; } + + //generic Id + public override int GetEntityId() => EmployeeStatusId; + + //generic ToString() + public override string ToString() => $"EmployeeStatusId: {GetEntityId()}; Name: {EmployeeStatusName}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/EmployeeToAttribute.cs b/DAL/Models/Entities/EmployeeToAttribute.cs new file mode 100644 index 0000000..77593d2 --- /dev/null +++ b/DAL/Models/Entities/EmployeeToAttribute.cs @@ -0,0 +1,21 @@ +using HRD.WebApi.DAL; + +namespace DAL.Models.Entities +{ + public partial class EmployeeToAttribute : BaseEntity + { + public int EmployeeToAttributeId { get; set; } + public int EmployeeId { get; set; } + + public int EmployeeAttributeId { get; set; } + + //generic Id + public override int GetEntityId() => EmployeeToAttributeId; + + //generic ToString() + public override string ToString() => $"EmployeeToAttributeId: {GetEntityId()}; EmployeeId: {EmployeeId}; EmployeeAttributeId: {EmployeeAttributeId}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/EmployeeToDepartment.cs b/DAL/Models/Entities/EmployeeToDepartment.cs new file mode 100644 index 0000000..8ddc572 --- /dev/null +++ b/DAL/Models/Entities/EmployeeToDepartment.cs @@ -0,0 +1,29 @@ +using HRD.WebApi.DAL; +using System.ComponentModel.DataAnnotations.Schema; + +namespace DAL.Models.Entities +{ + public partial class EmployeeToDepartment : BaseEntity + { + public int EmployeeToDepartmentId { get; set; } + public int EmployeeId { get; set; } + + public int DepartmentId { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string DepartmentName { get; set; } + + public decimal EmployeeBudget { get; set; } + public int? EmployeeStatusId { get; set; } + public int? RangId { get; set; } + + //generic Id + public override int GetEntityId() => EmployeeToDepartmentId; + + //generic ToString() + public override string ToString() => $"EmployeeToDepartmentId: {GetEntityId()}; EmployeeId: {EmployeeId}; DepartmentId: {DepartmentId}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/EmployeeToWebApp.cs b/DAL/Models/Entities/EmployeeToWebApp.cs new file mode 100644 index 0000000..4048fd4 --- /dev/null +++ b/DAL/Models/Entities/EmployeeToWebApp.cs @@ -0,0 +1,45 @@ +using HRD.WebApi.DAL; +using System.ComponentModel.DataAnnotations.Schema; + +namespace DAL.Models.Entities +{ + public partial class EmployeeToWebApp : BaseEntity + { + public int EmployeeToWebAppId { get; set; } + public int EmployeeId { get; set; } + public int WebAppId { get; set; } + + public int WebAppRoleId { get; set; } + public int? DepartmentId { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string WebAppRoleName { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string WebAppName { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string DepartmentName { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string ExtendedDepartmentNameList { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string ExtendedDepartmentIdList { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string AdditionalRoleNameList { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string AdditionalRoleIdList { get; set; } + + //generic Id + public override int GetEntityId() => EmployeeToWebAppId; + + //generic ToString() + public override string ToString() => $"EmployeeToWebAppId: {GetEntityId()}; EmployeeId: {EmployeeId}; WebAppId: {WebAppId}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/Project.cs b/DAL/Models/Entities/Project.cs new file mode 100644 index 0000000..2239068 --- /dev/null +++ b/DAL/Models/Entities/Project.cs @@ -0,0 +1,19 @@ +using HRD.WebApi.DAL; + +namespace DAL.Models.Entities +{ + public partial class Project : BaseEntity + { + public int ProjectId { get; set; } + public string ProjectName { get; set; } + + //generic Id + public override int GetEntityId() => ProjectId; + + //generic ToString() + public override string ToString() => $"ProjectId: {GetEntityId()}; Name: {ProjectName}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/Rang.cs b/DAL/Models/Entities/Rang.cs new file mode 100644 index 0000000..220d1e3 --- /dev/null +++ b/DAL/Models/Entities/Rang.cs @@ -0,0 +1,21 @@ +using HRD.WebApi.DAL; + +namespace DAL.Models.Entities +{ + public partial class Rang : BaseEntity + { + public int RangId { get; set; } + public string RangName { get; set; } + public string RangShortname { get; set; } + public int RangOrder { get; set; } + + //generic Id + public override int GetEntityId() => RangId; + + //generic ToString() + public override string ToString() => $"RangId: {GetEntityId()}; Name: {RangName}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/Subsidiary.cs b/DAL/Models/Entities/Subsidiary.cs new file mode 100644 index 0000000..6233633 --- /dev/null +++ b/DAL/Models/Entities/Subsidiary.cs @@ -0,0 +1,25 @@ +using HRD.WebApi.DAL; + +namespace DAL.Models.Entities +{ + public partial class Subsidiary : BaseEntity + { + public int SubsidiaryId { get; set; } + public int? ClientId { get; set; } + public string Name { get; set; } + public string SubsidiaryCode { get; set; } + public string Comment { get; set; } + + // [NotMapped] + // [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + + //generic Id + public override int GetEntityId() => SubsidiaryId; + + //generic ToString() + public override string ToString() => $"SubsidiaryId: {GetEntityId()}; Name: {Name}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/WebApp.cs b/DAL/Models/Entities/WebApp.cs new file mode 100644 index 0000000..213bd18 --- /dev/null +++ b/DAL/Models/Entities/WebApp.cs @@ -0,0 +1,23 @@ +using HRD.WebApi.DAL; + +namespace DAL.Models.Entities +{ + public partial class WebApp : BaseEntity + { + public int WebAppId { get; set; } + public string WebAppName { get; set; } + public string WebAppLinkLive { get; set; } + public string WebAppLinkDev { get; set; } + public bool IsActive { get; set; } + public string AdWebAppName { get; set; } + + //generic Id + public override int GetEntityId() => WebAppId; + + //generic ToString() + public override string ToString() => $"WebAppId: {GetEntityId()}; Name: {WebAppName}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/WebAppAdditionalRole.cs b/DAL/Models/Entities/WebAppAdditionalRole.cs new file mode 100644 index 0000000..744e1af --- /dev/null +++ b/DAL/Models/Entities/WebAppAdditionalRole.cs @@ -0,0 +1,21 @@ +using HRD.WebApi.DAL; + +namespace DAL.Models.Entities +{ + public partial class WebAppAdditionalRole : BaseEntity + { + public int WebAppAdditionalRoleId { get; set; } + public int WebAppId { get; set; } + public string WebAppAdditionalRoleName { get; set; } + public string AdWebAppAdditionalRoleName { get; set; } + + //generic Id + public override int GetEntityId() => WebAppAdditionalRoleId; + + //generic ToString() + public override string ToString() => $"WebAppAdditionalRoleId: {GetEntityId()}; WebAppId: {WebAppId}; WebAppAdditionalRoleName: {WebAppAdditionalRoleName}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/WebAppRole.cs b/DAL/Models/Entities/WebAppRole.cs new file mode 100644 index 0000000..ddb6466 --- /dev/null +++ b/DAL/Models/Entities/WebAppRole.cs @@ -0,0 +1,20 @@ +using HRD.WebApi.DAL; + +namespace DAL.Models.Entities +{ + public partial class WebAppRole : BaseEntity + { + public int WebAppRoleId { get; set; } + public string WebAppRoleName { get; set; } + public int WebAppRoleHierarchy { get; set; } + + //generic Id + public override int GetEntityId() => WebAppRoleId; + + //generic ToString() + public override string ToString() => $"WebAppRoleId: {GetEntityId()}; WebAppRoleName: {WebAppRoleName}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/WebAppToDepartment.cs b/DAL/Models/Entities/WebAppToDepartment.cs new file mode 100644 index 0000000..6a93fec --- /dev/null +++ b/DAL/Models/Entities/WebAppToDepartment.cs @@ -0,0 +1,24 @@ +using HRD.WebApi.DAL; +using System.ComponentModel.DataAnnotations.Schema; + +namespace DAL.Models.Entities +{ + public partial class WebAppToDepartment : BaseEntity + { + public int WebAppToDepartmentId { get; set; } + public int EmployeeToWebAppId { get; set; } + public int DepartmentId { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string DepartmentName { get; set; } + + //generic Id + public override int GetEntityId() => WebAppToDepartmentId; + + //generic ToString() + public override string ToString() => $"WebAppToDepartmentId: {GetEntityId()}; EmployeeToWebAppId: {EmployeeToWebAppId}; DepartmentId: {DepartmentId}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/WebAppToWebAppAdditionalRole.cs b/DAL/Models/Entities/WebAppToWebAppAdditionalRole.cs new file mode 100644 index 0000000..aadd7fe --- /dev/null +++ b/DAL/Models/Entities/WebAppToWebAppAdditionalRole.cs @@ -0,0 +1,20 @@ +using HRD.WebApi.DAL; + +namespace DAL.Models.Entities +{ + public partial class WebAppToWebAppAdditionalRole : BaseEntity + { + public int WebAppToWebAppAdditionalRoleId { get; set; } + public int WebAppAdditionalRoleId { get; set; } + public int EmployeeToWebAppId { get; set; } + + //generic Id + public override int GetEntityId() => WebAppToWebAppAdditionalRoleId; + + //generic ToString() + public override string ToString() => $"WebAppToWebAppAdditionalRoleId: {GetEntityId()}; WebAppAdditionalRoleId: {WebAppAdditionalRoleId}; EmployeeToWebAppId: {EmployeeToWebAppId}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/WebAppToWebAppRole.cs b/DAL/Models/Entities/WebAppToWebAppRole.cs new file mode 100644 index 0000000..672fddb --- /dev/null +++ b/DAL/Models/Entities/WebAppToWebAppRole.cs @@ -0,0 +1,27 @@ +using HRD.WebApi.DAL; +using System.ComponentModel.DataAnnotations.Schema; + +namespace DAL.Models.Entities +{ + public partial class WebAppToWebAppRole : BaseEntity + { + public int WebAppToWebAppRoleId { get; set; } + public int WebAppId { get; set; } + public int WebAppRoleId { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string WebAppRoleName { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public int WebAppRoleHierarchy { get; set; } + + //generic Id + public override int GetEntityId() => WebAppToWebAppRoleId; + + //generic ToString() + public override string ToString() => $"WebAppToWebAppRoleId: {GetEntityId()}; WebAppId: {WebAppId}; WebAppRoleId: {WebAppRoleId}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/WindreamColumnsToDepartment.cs b/DAL/Models/Entities/WindreamColumnsToDepartment.cs new file mode 100644 index 0000000..a32c377 --- /dev/null +++ b/DAL/Models/Entities/WindreamColumnsToDepartment.cs @@ -0,0 +1,33 @@ +using HRD.WebApi.DAL; +using System.ComponentModel.DataAnnotations.Schema; + +namespace DAL.Models.Entities +{ + public partial class WindreamColumnsToDepartment : BaseEntity + { + public int WindreamColumnsToDepartmentId { get; set; } + public int AttributeDwAttrId { get; set; } + public string AttributeSzColumnName { get; set; } + public string Comment { get; set; } + public int AttributeDwAttrType { get; set; } + public int ComumnLength { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string ObjectTypeAttributeSzName { get; set; } + + public int ClientId { get; set; } + public string ObjectTypeszDocTypeName { get; set; } + public int DepartmentId { get; set; } + public int Seq { get; set; } + public int WindreamSearchId { get; set; } + + //generic Id + public override int GetEntityId() => WindreamColumnsToDepartmentId; + + //generic ToString() + public override string ToString() => $"WindreamColumnsToDepartmentId: {GetEntityId()}; AttributeSzColumnName: {AttributeSzColumnName}; DepartmentId: {DepartmentId}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/WindreamIndex.cs b/DAL/Models/Entities/WindreamIndex.cs new file mode 100644 index 0000000..f2ffd7a --- /dev/null +++ b/DAL/Models/Entities/WindreamIndex.cs @@ -0,0 +1,25 @@ +using HRD.WebApi.DAL; + +namespace DAL.Models.Entities +{ + public partial class WindreamIndex : BaseEntity + { + public int WindreamIndexId { get; set; } + public int AttributeDwAttrId { get; set; } + public string AttributeSzColumnName { get; set; } + public string Comment { get; set; } + public int? ComumnLength { get; set; } + public int? AttributeDwAttrType { get; set; } + public int ClientId { get; set; } + public string ObjectTypeAttributeSzName { get; set; } + + //generic Id + public override int GetEntityId() => WindreamIndexId; + + //generic ToString() + public override string ToString() => $"WindreamIndexId: {GetEntityId()}; AttributeSzColumnName: {AttributeSzColumnName}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/WindreamIndexToWindreamSearchToDepartment.cs b/DAL/Models/Entities/WindreamIndexToWindreamSearchToDepartment.cs new file mode 100644 index 0000000..c2f2ca7 --- /dev/null +++ b/DAL/Models/Entities/WindreamIndexToWindreamSearchToDepartment.cs @@ -0,0 +1,28 @@ +using HRD.WebApi.DAL; +using System.ComponentModel.DataAnnotations.Schema; + +namespace DAL.Models.Entities +{ + public partial class WindreamIndexToWindreamSearchToDepartment : BaseEntity + { + public int WindreamIndexToWindreamSearchToDepartmentId { get; set; } + public int WindreamSearchToDepartmentId { get; set; } + public int WindreamIndexId { get; set; } + public int Seq { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string AttributeSzColumnName { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string ObjectTypeAttributeSzName { get; set; } + + //generic Id + public override int GetEntityId() => WindreamIndexToWindreamSearchToDepartmentId; + + //generic ToString() + public override string ToString() => $"WindreamIndexToWindreamSearchToDepartmentId: {GetEntityId()}; WindreamSearchToDepartmentId: {WindreamSearchToDepartmentId}; AttributeSzColumnName: {AttributeSzColumnName}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/WindreamInputFolder.cs b/DAL/Models/Entities/WindreamInputFolder.cs new file mode 100644 index 0000000..9762bd2 --- /dev/null +++ b/DAL/Models/Entities/WindreamInputFolder.cs @@ -0,0 +1,22 @@ +using HRD.WebApi.DAL; + +namespace DAL.Models.Entities +{ + public partial class WindreamInputFolder : BaseEntity + { + public int WindreamInputFolderId { get; set; } + public string Name { get; set; } + public string XMLPath { get; set; } + public string Comment { get; set; } + public int? ClientId { get; set; } + + //generic Id + public override int GetEntityId() => WindreamInputFolderId; + + //generic ToString() + public override string ToString() => $"WindreamInputFolderId: {GetEntityId()}; Name: {Name}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/WindreamSearch.cs b/DAL/Models/Entities/WindreamSearch.cs new file mode 100644 index 0000000..4ccd30f --- /dev/null +++ b/DAL/Models/Entities/WindreamSearch.cs @@ -0,0 +1,24 @@ +using HRD.WebApi.DAL; + +namespace DAL.Models.Entities +{ + public partial class WindreamSearch : BaseEntity + { + public int WindreamSearchId { get; set; } + public string Name { get; set; } + public string XMLPath { get; set; } + public string Comment { get; set; } + public int ClientId { get; set; } + public int? Color { get; set; } + public int? SearchIndex { get; set; } + + //generic Id + public override int GetEntityId() => WindreamSearchId; + + //generic ToString() + public override string ToString() => $"WindreamSearchId: {GetEntityId()}; Name: {Name}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/WindreamSearchItem.cs b/DAL/Models/Entities/WindreamSearchItem.cs new file mode 100644 index 0000000..d5ccb2d --- /dev/null +++ b/DAL/Models/Entities/WindreamSearchItem.cs @@ -0,0 +1,30 @@ +using HRD.WebApi.DAL; +using System.ComponentModel.DataAnnotations.Schema; + +namespace DAL.Models.Entities +{ + public partial class WindreamSearchItem : BaseEntity + { + public int WindreamSearchItemId { get; set; } + public string Name { get; set; } + public string Comment { get; set; } + public int ClientId { get; set; } + public string Caption { get; set; } + public string PlaceHolder { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string SearchTemplate { get; set; } + + public string ConnectedList { get; set; } + public string AlternativeWindreamSearchItemIdList { get; set; } + + //generic Id + public override int GetEntityId() => WindreamSearchItemId; + + //generic ToString() + public override string ToString() => $"WindreamSearchItemId: {GetEntityId()}; Name: {Name}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/WindreamSearchItemToWindreamSearchToDepartment.cs b/DAL/Models/Entities/WindreamSearchItemToWindreamSearchToDepartment.cs new file mode 100644 index 0000000..537d229 --- /dev/null +++ b/DAL/Models/Entities/WindreamSearchItemToWindreamSearchToDepartment.cs @@ -0,0 +1,49 @@ +using HRD.WebApi.DAL; +using System.ComponentModel.DataAnnotations.Schema; + +namespace DAL.Models.Entities +{ + public partial class WindreamSearchItemToWindreamSearchToDepartment : BaseEntity + { + public int WindreamSearchItemToWindreamSearchToDepartmentId { get; set; } + public int WindreamSearchToDepartmentId { get; set; } + public int Seq { get; set; } + public int WindreamSearchItemId { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public int DepartmentId { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string WindreamSearchItemName { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string WindreamSearchItemCaption { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string WindreamSearchItemPlaceHolder { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string WindreamSearchItemSearchTemplate { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string WindreamSearchItemTemplate { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string WindreamSearchItemConnectedList { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string WindreamSearchItemComment { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public int? WindreamSearchIndexType { get; set; } + + //generic Id + public override int GetEntityId() => WindreamSearchItemToWindreamSearchToDepartmentId; + + //generic ToString() + public override string ToString() => $"WindreamSearchItemToWindreamSearchToDepartmentId: {GetEntityId()}; WindreamSearchToDepartmentId: {WindreamSearchToDepartmentId}; WindreamSearchItemName: {WindreamSearchItemName}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Entities/WindreamSearchToDepartment.cs b/DAL/Models/Entities/WindreamSearchToDepartment.cs new file mode 100644 index 0000000..cdf8687 --- /dev/null +++ b/DAL/Models/Entities/WindreamSearchToDepartment.cs @@ -0,0 +1,38 @@ +using HRD.WebApi.DAL; +using System.ComponentModel.DataAnnotations.Schema; + +namespace DAL.Models.Entities +{ + public partial class WindreamSearchToDepartment : BaseEntity + { + public int WindreamSearchToDepartmentId { get; set; } + public int DepartmentId { get; set; } + public int WindreamSearchId { get; set; } + public int Seq { get; set; } + public bool IsActive { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string DepartmentName { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string WindreamSearchName { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string WindreamSearchXMLPath { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public string WindreamSearchComment { get; set; } + + [DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public int? WindreamSearchColor { get; set; } + + //generic Id + public override int GetEntityId() => WindreamSearchToDepartmentId; + + //generic ToString() + public override string ToString() => $"WindreamSearchToDepartmentId: {GetEntityId()}; DepartmentName: {DepartmentName}; WindreamSearchName: {WindreamSearchName}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/Models/Filters/ClientIdFilter.cs b/DAL/Models/Filters/ClientIdFilter.cs new file mode 100644 index 0000000..ff6b981 --- /dev/null +++ b/DAL/Models/Filters/ClientIdFilter.cs @@ -0,0 +1,9 @@ +using HRD.WebApi.DAL; + +namespace DAL.Models.Filters +{ + public partial class ClientIdFilter : BaseFilter + { + public int? ClientId { get; set; } + } +} \ No newline at end of file diff --git a/DAL/Models/Filters/DepartmentFilter.cs b/DAL/Models/Filters/DepartmentFilter.cs new file mode 100644 index 0000000..4fe2aac --- /dev/null +++ b/DAL/Models/Filters/DepartmentFilter.cs @@ -0,0 +1,10 @@ +using HRD.WebApi.DAL; + +namespace DAL.Models.Filters +{ + public partial class DepartmentFilter : BaseFilter + { + public int? DepartmentId { get; set; } + public int? WindreamSearchId { get; set; } + } +} \ No newline at end of file diff --git a/DAL/Models/Filters/DepartmentFullFilter.cs b/DAL/Models/Filters/DepartmentFullFilter.cs new file mode 100644 index 0000000..8899eba --- /dev/null +++ b/DAL/Models/Filters/DepartmentFullFilter.cs @@ -0,0 +1,9 @@ +using HRD.WebApi.DAL; + +namespace DAL.Models.Filters +{ + public partial class DepartmentFullFilter : BaseFilter + { + public string DepartmentName { get; set; } + } +} \ No newline at end of file diff --git a/DAL/Models/Filters/EmployeeFilter.cs b/DAL/Models/Filters/EmployeeFilter.cs new file mode 100644 index 0000000..00c57d5 --- /dev/null +++ b/DAL/Models/Filters/EmployeeFilter.cs @@ -0,0 +1,11 @@ +using HRD.WebApi.DAL; + +namespace DAL.Models.Filters +{ + public partial class EmployeeFilter : BaseFilter + { + public int? EmployeeId { get; set; } + public string LoginName { get; set; } + public string ShortName { get; set; } + } +} \ No newline at end of file diff --git a/DAL/Models/Filters/EmployeeFullFilter.cs b/DAL/Models/Filters/EmployeeFullFilter.cs new file mode 100644 index 0000000..d4bb6dc --- /dev/null +++ b/DAL/Models/Filters/EmployeeFullFilter.cs @@ -0,0 +1,18 @@ +using HRD.WebApi.DAL; + +namespace DAL.Models.Filters +{ + public partial class EmployeeFullFilter : BaseFilter + { + public int? EmployeeId { get; set; } + public string Name { get; set; } + public string ShortName { get; set; } + public string LoginName { get; set; } + public string Email { get; set; } + public int[] WebappIds { get; set; } + public int[] DepartmentIds { get; set; } + public int[] AttributeIds { get; set; } + public int? ClientId { get; set; } + public bool? IsActive { get; set; } + } +} \ No newline at end of file diff --git a/DAL/Models/Filters/EmployeeToWebAppFilter.cs b/DAL/Models/Filters/EmployeeToWebAppFilter.cs new file mode 100644 index 0000000..bd4b591 --- /dev/null +++ b/DAL/Models/Filters/EmployeeToWebAppFilter.cs @@ -0,0 +1,9 @@ +using HRD.WebApi.DAL; + +namespace DAL.Models.Filters +{ + public partial class EmployeeToWebAppFilter : BaseFilter + { + public int? EmployeeToWebAppId { get; set; } + } +} \ No newline at end of file diff --git a/DAL/Models/Filters/WebAppFilter.cs b/DAL/Models/Filters/WebAppFilter.cs new file mode 100644 index 0000000..4d991a8 --- /dev/null +++ b/DAL/Models/Filters/WebAppFilter.cs @@ -0,0 +1,9 @@ +using HRD.WebApi.DAL; + +namespace DAL.Models.Filters +{ + public partial class WebAppFilter : BaseFilter + { + public int? WebAppId { get; set; } + } +} \ No newline at end of file diff --git a/DAL/Models/Filters/WindreamInputFolderFilter.cs b/DAL/Models/Filters/WindreamInputFolderFilter.cs new file mode 100644 index 0000000..e4f838e --- /dev/null +++ b/DAL/Models/Filters/WindreamInputFolderFilter.cs @@ -0,0 +1,10 @@ +using HRD.WebApi.DAL; + +namespace DAL.Models.Filters +{ + public partial class WindreamInputFolderFilter : BaseFilter + { + public int? WindreamInputFolderId { get; set; } + public int? ClientId { get; set; } + } +} \ No newline at end of file diff --git a/DAL/Models/Filters/WindreamSearchToDepartmentFilter.cs b/DAL/Models/Filters/WindreamSearchToDepartmentFilter.cs new file mode 100644 index 0000000..1054241 --- /dev/null +++ b/DAL/Models/Filters/WindreamSearchToDepartmentFilter.cs @@ -0,0 +1,10 @@ +using HRD.WebApi.DAL; + +namespace DAL.Models.Filters +{ + public partial class WindreamSearchToDepartmentFilter : BaseFilter + { + public int? WindreamSearchToDepartmentId { get; set; } + public int? DepartmentId { get; set; } + } +} \ No newline at end of file diff --git a/DAL/Repositories/AdWebAppToWebAppRoleRepository.cs b/DAL/Repositories/AdWebAppToWebAppRoleRepository.cs new file mode 100644 index 0000000..3797d02 --- /dev/null +++ b/DAL/Repositories/AdWebAppToWebAppRoleRepository.cs @@ -0,0 +1,12 @@ +using DAL.Models.Entities; +using HRD.WebApi.Repositories; + +namespace DAL.Repositories +{ + public class AdWebAppToWebAppRoleRepository : BaseRepository + { + public AdWebAppToWebAppRoleRepository() : base(new WebApiContext()) + { + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/CostCentreRepository.cs b/DAL/Repositories/CostCentreRepository.cs new file mode 100644 index 0000000..329856f --- /dev/null +++ b/DAL/Repositories/CostCentreRepository.cs @@ -0,0 +1,12 @@ +using DAL.Models.Entities; +using HRD.WebApi.Repositories; + +namespace DAL.Repositories +{ + public class CostCentreRepository : BaseRepository + { + public CostCentreRepository() : base(new WebApiContext()) + { + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/DepartmentRepository.cs b/DAL/Repositories/DepartmentRepository.cs new file mode 100644 index 0000000..2db3a34 --- /dev/null +++ b/DAL/Repositories/DepartmentRepository.cs @@ -0,0 +1,34 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using HRD.WebApi.Repositories; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace DAL.Repositories +{ + public class DepartmentRepository : BaseRepository + { + public DepartmentRepository() : base(new WebApiContext()) + { + } + + public async Task> GetDepartmentListAsync(DepartmentFullFilter filter, bool asNoTracking = true) + { + var items = this.RepositoryContext.Set().AsQueryable(); + + if (!string.IsNullOrEmpty(filter.DepartmentName)) + { + items = items.Where(x => EF.Functions.Like(x.DepartmentName, $"%{filter.DepartmentName}%")); + } + + return asNoTracking ? await items.AsNoTracking().ToListAsync() : await items.ToListAsync(); + } + + public async Task ReplaceWindreamTiles(int srcDepartmentId, string trgDepartmentIds) + { + return await ExecStoredProcedureAsync("webapi.sp_TransferWindreamSettings", $"{srcDepartmentId}, null, \"{trgDepartmentIds}\""); + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/DepartmentToWebAppToEmployeeForWindreamRepository.cs b/DAL/Repositories/DepartmentToWebAppToEmployeeForWindreamRepository.cs new file mode 100644 index 0000000..dca4313 --- /dev/null +++ b/DAL/Repositories/DepartmentToWebAppToEmployeeForWindreamRepository.cs @@ -0,0 +1,40 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using HRD.WebApi.Repositories; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace DAL.Repositories +{ + public class DepartmentToWebAppToEmployeeForWindreamRepository : BaseRepository + { + public DepartmentToWebAppToEmployeeForWindreamRepository() : base(new WebApiContext()) + { + } + + public async Task> GetListByFilterAsync(EmployeeFilter filter, bool asNoTracking = true) + { + var items = this.RepositoryContext.Set().AsQueryable(); + + if (filter.EmployeeId != null && filter.EmployeeId != 0) + { + items = items.Where(x => x.EmployeeId == filter.EmployeeId); + return asNoTracking ? await items.ToListAsync() : await items.ToListAsync(); + } + + if (!string.IsNullOrEmpty(filter.ShortName)) + { + items = items.Where(x => x.ShortName == filter.ShortName); + } + + if (!string.IsNullOrEmpty(filter.LoginName)) + { + items = items.Where(x => x.LoginName.ToLower() == filter.LoginName.ToLower()); + } + + return asNoTracking ? await items.OrderBy(x => x.DepartmentName).AsNoTracking().ToListAsync() : await items.OrderBy(x => x.DepartmentName).ToListAsync(); + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/DocumentArtRepository.cs b/DAL/Repositories/DocumentArtRepository.cs new file mode 100644 index 0000000..7f4d27f --- /dev/null +++ b/DAL/Repositories/DocumentArtRepository.cs @@ -0,0 +1,12 @@ +using DAL.Models.Entities; +using HRD.WebApi.Repositories; + +namespace DAL.Repositories +{ + public class DocumentArtRepository : BaseRepository + { + public DocumentArtRepository() : base(new WebApiContext()) + { + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/DocumentArtToDepartmentRepository.cs b/DAL/Repositories/DocumentArtToDepartmentRepository.cs new file mode 100644 index 0000000..0e4edcd --- /dev/null +++ b/DAL/Repositories/DocumentArtToDepartmentRepository.cs @@ -0,0 +1,29 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using HRD.WebApi.Repositories; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace DAL.Repositories +{ + public class DocumentArtToDepartmentRepository : BaseRepository + { + public DocumentArtToDepartmentRepository() : base(new WebApiContext()) + { + } + + public async Task> GetListByFilterAsync(DepartmentFilter filter, bool asNoTracking = true) + { + var items = this.RepositoryContext.Set().AsQueryable(); + + if (filter.DepartmentId != null && filter.DepartmentId != 0) + { + items = items.Where(x => x.DepartmentId == filter.DepartmentId); + } + + return asNoTracking ? await items.AsNoTracking().ToListAsync() : await items.ToListAsync(); + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/EmployeeAttributeRepository.cs b/DAL/Repositories/EmployeeAttributeRepository.cs new file mode 100644 index 0000000..9df3f78 --- /dev/null +++ b/DAL/Repositories/EmployeeAttributeRepository.cs @@ -0,0 +1,12 @@ +using DAL.Models.Entities; +using HRD.WebApi.Repositories; + +namespace DAL.Repositories +{ + public class EmployeeAttributeRepository : BaseRepository + { + public EmployeeAttributeRepository() : base(new WebApiContext()) + { + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/EmployeeRepository.cs b/DAL/Repositories/EmployeeRepository.cs new file mode 100644 index 0000000..0065e26 --- /dev/null +++ b/DAL/Repositories/EmployeeRepository.cs @@ -0,0 +1,96 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using HRD.WebApi.Repositories; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace DAL.Repositories +{ + public class EmployeeRepository : BaseRepository + { + public EmployeeRepository() : base(new WebApiContext()) + { + } + + public async Task> GetListByFilterAsync(EmployeeFullFilter filter, bool asNoTracking = true) + { + var items = this.RepositoryContext.Set().AsQueryable(); + + if (filter.EmployeeId != null && filter.EmployeeId != 0) + { + items = items.Where(x => x.EmployeeId == filter.EmployeeId); + return asNoTracking ? await items.AsNoTracking().ToListAsync() : await items.ToListAsync(); + } + + if (!string.IsNullOrEmpty(filter.Name)) + { + items = items.Where(x => EF.Functions.Like(x.FirstName.ToLower() + ' ' + x.LastName.ToLower(), $"%{filter.Name.ToLower()}%")); + } + + if (!string.IsNullOrEmpty(filter.Email)) + { + items = items.Where(x => EF.Functions.Like(x.Email.ToLower(), $"%{filter.Email.ToLower()}%")); + } + + if (!string.IsNullOrEmpty(filter.ShortName)) + { + items = items.Where(x => EF.Functions.Like(x.ShortName.ToLower(), $"%{filter.ShortName.ToLower()}%")); + } + + if (!string.IsNullOrEmpty(filter.LoginName)) + { + items = items.Where(x => EF.Functions.Like(x.LoginName.ToLower(), $"%{filter.LoginName.ToLower()}%")); + } + + if (filter.DepartmentIds != null && filter.DepartmentIds.Length > 0) + { + IQueryable itemsTmp = null; + for (int i = 0; i < filter.DepartmentIds.Length; i++) + { + var inx = filter.DepartmentIds[i]; + var items_ = items.Where(x => EF.Functions.Like("," + x.DepartmentIdList.Replace(" ", "") + ",", $"%,{inx},%")); + itemsTmp = itemsTmp != null ? itemsTmp.Union(items_) : items_; + } + items = itemsTmp; + } + + if (filter.WebappIds != null && filter.WebappIds.Length > 0) + { + IQueryable itemsTmp = null; + for (int i = 0; i < filter.WebappIds.Length; i++) + { + var inx = filter.WebappIds[i]; + var items_ = items.Where(x => EF.Functions.Like("," + x.WebappIdList.Replace(" ", "") + ",", $"%,{inx},%")); + itemsTmp = (itemsTmp != null) ? itemsTmp.Union(items_) : items_; + } + items = itemsTmp; + } + + if (filter.AttributeIds != null && filter.AttributeIds.Length > 0) + { + IQueryable itemsTmp = null; + for (int i = 0; i < filter.AttributeIds.Length; i++) + { + var inx = filter.AttributeIds[i]; + var items_ = items.Where(x => EF.Functions.Like("," + x.AttributeIdList.Replace(" ", "") + ",", $"%,{inx},%")); + itemsTmp = (itemsTmp != null) ? itemsTmp.Concat(items_) : items_; + } + items = itemsTmp; + } + + if (filter.ClientId != null && filter.ClientId != 0) + { + items = items.Where(x => x.ClientId == filter.ClientId); + } + + if (filter.IsActive != null) + { + items = items.Where(x => x.IsActive == filter.IsActive); + } + + return asNoTracking ? await items.AsNoTracking().ToListAsync() : await items.ToListAsync(); + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/EmployeeStatusRepository.cs b/DAL/Repositories/EmployeeStatusRepository.cs new file mode 100644 index 0000000..8711a80 --- /dev/null +++ b/DAL/Repositories/EmployeeStatusRepository.cs @@ -0,0 +1,12 @@ +using DAL.Models.Entities; +using HRD.WebApi.Repositories; + +namespace DAL.Repositories +{ + public class EmployeeStatusRepository : BaseRepository + { + public EmployeeStatusRepository() : base(new WebApiContext()) + { + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/EmployeeToAttributeRepository.cs b/DAL/Repositories/EmployeeToAttributeRepository.cs new file mode 100644 index 0000000..7edf87c --- /dev/null +++ b/DAL/Repositories/EmployeeToAttributeRepository.cs @@ -0,0 +1,29 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using HRD.WebApi.Repositories; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace DAL.Repositories +{ + public class EmployeeToAttributeRepository : BaseRepository + { + public EmployeeToAttributeRepository() : base(new WebApiContext()) + { + } + + public async Task> GetListByFilterAsync(EmployeeFilter filter, bool asNoTracking = true) + { + var items = this.RepositoryContext.Set().AsQueryable(); + + if (filter.EmployeeId != null && filter.EmployeeId != 0) + { + items = items.Where(x => x.EmployeeId == filter.EmployeeId); + } + + return asNoTracking ? await items.AsNoTracking().ToListAsync() : await items.ToListAsync(); + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/EmployeeToDepartmentRepository.cs b/DAL/Repositories/EmployeeToDepartmentRepository.cs new file mode 100644 index 0000000..dab874a --- /dev/null +++ b/DAL/Repositories/EmployeeToDepartmentRepository.cs @@ -0,0 +1,29 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using HRD.WebApi.Repositories; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace DAL.Repositories +{ + public class EmployeeToDepartmentRepository : BaseRepository + { + public EmployeeToDepartmentRepository() : base(new WebApiContext()) + { + } + + public async Task> GetListByFilterAsync(EmployeeFilter filter, bool asNoTracking = true) + { + var items = this.RepositoryContext.Set().AsQueryable(); + + if (filter.EmployeeId != null && filter.EmployeeId != 0) + { + items = items.Where(x => x.EmployeeId == filter.EmployeeId); + } + + return asNoTracking ? await items.AsNoTracking().ToListAsync() : await items.ToListAsync(); + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/EmployeeToWebAppRepository.cs b/DAL/Repositories/EmployeeToWebAppRepository.cs new file mode 100644 index 0000000..9ad32f3 --- /dev/null +++ b/DAL/Repositories/EmployeeToWebAppRepository.cs @@ -0,0 +1,253 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using HRD.LDAPService; +using HRD.WebApi.Repositories; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace DAL.Repositories +{ + public class EmployeeToWebAppRepository : BaseRepository + { + public EmployeeToWebAppRepository() : base(new WebApiContext()) + { + } + + public async Task DeleteEmloyeeToWebAppAsync(int webAppId) + { + var list = await GetListByAsync(x => x.WebAppId == webAppId); + foreach (var item in list) + { + if (!await DeleteByIdAsync(item.EmployeeId)) + { + throw new Exception($"Couldn't delete the Employee-Id: {item.EmployeeId}"); + } + } + return true; + } + + public async Task> GetListByFilterAsync(EmployeeFilter filter, bool asNoTracking = true) + { + var items = this.RepositoryContext.Set().AsQueryable(); + + if (filter.EmployeeId != null && filter.EmployeeId != 0) + { + items = items.Where(x => x.EmployeeId == filter.EmployeeId); + } + + return asNoTracking ? await items.AsNoTracking().ToListAsync() : await items.ToListAsync(); + } + + private async Task AddUserToAdGroup(EmployeeToWebApp entity, int webRoleId, int? departementId) + { + return await ProcessGroup(entity, "adding", webRoleId, departementId); + } + + private async Task RemoveUserFromAdGroup(EmployeeToWebApp entity, int webRoleId, int? departementId) + { + return await ProcessGroup(entity, "deleting", webRoleId, departementId); + } + + private async Task ProcessGroup(EmployeeToWebApp entity, string action, int webRoleId, int? departementId) + { + string groupSuffix = null; + if (entity == default) throw new ArgumentNullException(nameof(entity)); + if (entity == default) throw new ArgumentNullException(nameof(entity)); + + var department = await GetDepartmentById(departementId); + + var employee = await GetEmployeeById(entity.EmployeeId); + if (employee == default) throw new ArgumentNullException(nameof(employee)); + + var webapp = await GetWebAppById(entity.WebAppId); + if (webapp == default) throw new ArgumentNullException(nameof(webapp)); + + bool result = true; + var isAdding = action == "adding"; + + var webappRole = await GetWebAppRoleById(webRoleId); + + try + { + if (department != default && !string.IsNullOrEmpty(department.AdGroupDepartmentName)) + { + groupSuffix = $"{webapp.AdWebAppName}_{department.AdGroupDepartmentName}"; + if (LdapManager.IsWindreamSuffixGroup(groupSuffix)) + { + if (isAdding) result = LdapManager.AD_AddUserloginToGroup(employee.LoginName, groupSuffix); + else result = LdapManager.AD_RemoveUserFromGroup(employee.LoginName, groupSuffix); + } + } + + if (webappRole != default) + { + groupSuffix = $"{webapp.AdWebAppName}_{webappRole.WebAppRoleName}"; + if (isAdding) result = LdapManager.AD_AddUserloginToGroup(employee.LoginName, groupSuffix); + else result = LdapManager.AD_RemoveUserFromGroup(employee.LoginName, groupSuffix); + + if (LdapManager.IsWindreamAdminGroup(groupSuffix)) + { + groupSuffix = $"{webapp.AdWebAppName}_User"; + if (isAdding) result = LdapManager.AD_AddUserloginToGroup(employee.LoginName, groupSuffix); + else result = LdapManager.AD_RemoveUserFromGroup(employee.LoginName, groupSuffix); + } + } + } + catch (Exception ex) + { + WriteLogException(ex, $"An error occurred while '{action}' the '{employee.LoginName}' into '{groupSuffix}'."); + return false; + } + + if (!result) + { + WriteLogError($"An error occurred while '{action}' the '{employee.LoginName}' into '{groupSuffix}'."); + return false; + }; + return true; + } + + public override async Task UpdateAsync(EmployeeToWebApp entity, bool saveEntity = true) + { + if (entity == default) + { + throw new ArgumentNullException(nameof(entity)); + } + + var orgEntity = await base.GetByIdAsync(entity.EmployeeToWebAppId, true); + var oldWebAppRoleId = 0; + var newWebAppRoleId = 0; + if (orgEntity.WebAppRoleId != entity.WebAppRoleId) + { + oldWebAppRoleId = orgEntity.WebAppRoleId; + newWebAppRoleId = entity.WebAppRoleId; + } + int? oldDepartmentId = 0; + int? newDepartmentId = 0; + if (orgEntity.DepartmentId != entity.DepartmentId) + { + oldDepartmentId = orgEntity.DepartmentId; + newDepartmentId = entity.DepartmentId; + } + orgEntity = null; + + if ((oldDepartmentId == 0 && oldWebAppRoleId == 0) || + await RemoveUserFromAdGroup(entity, oldWebAppRoleId, oldDepartmentId) + && await AddUserToAdGroup(entity, newWebAppRoleId, newDepartmentId)) + { + var result = await base.UpdateAsync(entity, saveEntity); + return result; + } + return false; + } + + public override async Task UpdateListAsync(List entities, bool saveEntity = true) + { + var result = true; + for (int i = 0; i < entities.Count; i++) + { + if (!await UpdateAsync(entities[i], saveEntity)) result = false; + } + return result; + } + + public override async Task AddAsync(EmployeeToWebApp entity, bool saveEntity = true) + { + if (await AddUserToAdGroup(entity, entity.WebAppRoleId, entity.DepartmentId)) + { + var result = await base.AddAsync(entity, saveEntity); + return result; + } + return false; + } + + public override async Task AddListAsync(List entities, bool saveEntity = true) + { + var result = true; + for (int i = 0; i < entities.Count; i++) + { + if (!await AddAsync(entities[i], saveEntity)) result = false; + } + return result; + } + + public override async Task DeleteByIdAsync(int id, bool saveEntity = true) + { + try + { + var entity = await base.GetByIdAsync(id); + if (entity == default) + { + throw new ArgumentNullException(nameof(entity)); + } + + if (await RemoveUserFromAdGroup(entity, entity.WebAppRoleId, entity.DepartmentId)) + { + var result = await base.DeleteByIdAsync(id, saveEntity); + return result; + } + return false; + } + catch (Exception ex) + { + WriteLogException(ex, $"An error occurred while deleting the Id {id}"); + return false; + } + } + + public async Task GetWebAppById(int entityId) + { + try + { + return await this.RepositoryContext.Set().FindAsync(entityId); + } + catch (Exception ex) + { + base.WriteLogException(ex, $"{typeof(WebApp).Name} id:{entityId}"); + } + return default; + } + + public async Task GetDepartmentById(int? entityId) + { + try + { + return await this.RepositoryContext.Set().FindAsync(entityId); + } + catch (Exception ex) + { + WriteLogException(ex, $"{typeof(Department).Name} id:{entityId}"); + } + return default; + } + + public async Task GetEmployeeById(int entityId) + { + try + { + return await this.RepositoryContext.Set().FindAsync(entityId); + } + catch (Exception ex) + { + WriteLogException(ex, $"{typeof(Employee).Name} id:{entityId}"); + } + return default; + } + + public async Task GetWebAppRoleById(int entityId) + { + try + { + return await this.RepositoryContext.Set().FindAsync(entityId); + } + catch (Exception ex) + { + WriteLogException(ex, $"{typeof(WebAppRole).Name} id:{entityId}"); + } + return default; + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/ProjectRepository.cs b/DAL/Repositories/ProjectRepository.cs new file mode 100644 index 0000000..9db6c2a --- /dev/null +++ b/DAL/Repositories/ProjectRepository.cs @@ -0,0 +1,12 @@ +using DAL.Models.Entities; +using HRD.WebApi.Repositories; + +namespace DAL.Repositories +{ + public class ProjectRepository : BaseRepository + { + public ProjectRepository() : base(new WebApiContext()) + { + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/RangRepository.cs b/DAL/Repositories/RangRepository.cs new file mode 100644 index 0000000..17fba1b --- /dev/null +++ b/DAL/Repositories/RangRepository.cs @@ -0,0 +1,12 @@ +using DAL.Models.Entities; +using HRD.WebApi.Repositories; + +namespace DAL.Repositories +{ + public class RangRepository : BaseRepository + { + public RangRepository() : base(new WebApiContext()) + { + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/SubsidiaryRepository.cs b/DAL/Repositories/SubsidiaryRepository.cs new file mode 100644 index 0000000..d9ede89 --- /dev/null +++ b/DAL/Repositories/SubsidiaryRepository.cs @@ -0,0 +1,12 @@ +using DAL.Models.Entities; +using HRD.WebApi.Repositories; + +namespace DAL.Repositories +{ + public class SubsidiaryRepository : BaseRepository + { + public SubsidiaryRepository() : base(new WebApiContext()) + { + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/WebAppAdditionalRoleRepository.cs b/DAL/Repositories/WebAppAdditionalRoleRepository.cs new file mode 100644 index 0000000..67d31c0 --- /dev/null +++ b/DAL/Repositories/WebAppAdditionalRoleRepository.cs @@ -0,0 +1,29 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using HRD.WebApi.Repositories; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace DAL.Repositories +{ + public class WebAppAdditionalRoleRepository : BaseRepository + { + public WebAppAdditionalRoleRepository() : base(new WebApiContext()) + { + } + + public async Task> GetListByFilterAsync(WebAppFilter filter, bool asNoTracking = true) + { + var items = this.RepositoryContext.Set().AsQueryable(); + + if (filter.WebAppId != null && filter.WebAppId != 0) + { + items = items.Where(x => x.WebAppId == filter.WebAppId); + } + + return asNoTracking ? await items.AsNoTracking().ToListAsync() : await items.ToListAsync(); + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/WebAppRepository.cs b/DAL/Repositories/WebAppRepository.cs new file mode 100644 index 0000000..4b6483f --- /dev/null +++ b/DAL/Repositories/WebAppRepository.cs @@ -0,0 +1,12 @@ +using DAL.Models.Entities; +using HRD.WebApi.Repositories; + +namespace DAL.Repositories +{ + public class WebAppRepository : BaseRepository + { + public WebAppRepository() : base(new WebApiContext()) + { + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/WebAppRoleRepository.cs b/DAL/Repositories/WebAppRoleRepository.cs new file mode 100644 index 0000000..6c82c4a --- /dev/null +++ b/DAL/Repositories/WebAppRoleRepository.cs @@ -0,0 +1,12 @@ +using DAL.Models.Entities; +using HRD.WebApi.Repositories; + +namespace DAL.Repositories +{ + public class WebAppRoleRepository : BaseRepository + { + public WebAppRoleRepository() : base(new WebApiContext()) + { + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/WebAppToDepartmentRepository.cs b/DAL/Repositories/WebAppToDepartmentRepository.cs new file mode 100644 index 0000000..e43c27e --- /dev/null +++ b/DAL/Repositories/WebAppToDepartmentRepository.cs @@ -0,0 +1,178 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using HRD.LDAPService; +using HRD.WebApi.Repositories; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace DAL.Repositories +{ + public class WebAppToDepartmentRepository : BaseRepository + { + public WebAppToDepartmentRepository() : base(new WebApiContext()) + { + } + + public async Task> GetListByFilterAsync(EmployeeToWebAppFilter filter, bool asNoTracking = true) + { + var items = this.RepositoryContext.Set().AsQueryable(); + + if (filter.EmployeeToWebAppId != null && filter.EmployeeToWebAppId != 0) + { + items = items.Where(x => x.EmployeeToWebAppId == filter.EmployeeToWebAppId); + } + + return asNoTracking ? await items.AsNoTracking().ToListAsync() : await items.ToListAsync(); + } + + private async Task AddUserToAdGroup(WebAppToDepartment entity) + { + return await ProcessGroup(entity, "adding"); + } + + private async Task RemoveUserFromAdGroup(WebAppToDepartment entity) + { + return await ProcessGroup(entity, "deleting"); + } + + private async Task ProcessGroup(WebAppToDepartment entity, string action) + { + if (entity == default) throw new ArgumentNullException(nameof(entity)); + + var employee2Web = await GetEmployeeToWebAppById(entity.EmployeeToWebAppId); + if (employee2Web == default) throw new ArgumentNullException(nameof(employee2Web)); + + var department = await GetDepartmentById(entity.DepartmentId); + if (department == default) throw new ArgumentNullException(nameof(department)); + if (string.IsNullOrEmpty(department.AdGroupDepartmentName)) return true; + + var employee = await GetEmployeeById(employee2Web.EmployeeId); + if (employee == default) throw new ArgumentNullException(nameof(employee)); + + var webapp = await GetWebAppById(employee2Web.WebAppId); + if (webapp == default) throw new ArgumentNullException(nameof(webapp)); + + bool result; + var isAdding = action == "adding"; + + var groupSuffix = $"{webapp.AdWebAppName}_{department.AdGroupDepartmentName}"; + if (!LdapManager.IsWindreamSuffixGroup(groupSuffix)) return true; + try + { + if (isAdding) result = LdapManager.AD_AddUserloginToGroup(employee.LoginName, groupSuffix); + else result = LdapManager.AD_RemoveUserFromGroup(employee.LoginName, groupSuffix); + } + catch (Exception ex) + { + WriteLogException(ex, $"An error occurred while '{action}' the '{employee.LoginName}' into '{groupSuffix}'."); + return false; + } + + if (!result) + { + WriteLogError($"An error occurred while '{action}' the '{employee.LoginName}' into '{groupSuffix}'."); + return false; + }; + return true; + } + + public override async Task AddAsync(WebAppToDepartment entity, bool saveEntity = true) + { + if (await AddUserToAdGroup(entity)) + { + var result = await base.AddAsync(entity, saveEntity); + return result; + } + return false; + } + + public override async Task AddListAsync(List entities, bool saveEntity = true) + { + var result = true; + for (int i = 0; i < entities.Count; i++) + { + if (!await AddAsync(entities[i], saveEntity)) result = false; + } + return result; + } + + public override async Task DeleteByIdAsync(int id, bool saveEntity = true) + { + try + { + var entity = await base.GetByIdAsync(id); + if (entity == default) + { + throw new ArgumentNullException(nameof(entity)); + } + + if (await RemoveUserFromAdGroup(entity)) + { + var result = await base.DeleteByIdAsync(id, saveEntity); + return result; + } + return false; + } + catch (Exception ex) + { + WriteLogException(ex, $"An error occurred while deleting the Id {id}"); + return false; + } + } + + public async Task GetEmployeeToWebAppById(int entityId) + { + try + { + return await this.RepositoryContext.Set().FindAsync(entityId); + } + catch (Exception ex) + { + WriteLogException(ex, $"{typeof(EmployeeToWebApp).Name} id:{entityId}"); + } + return default; + } + + public async Task GetWebAppById(int entityId) + { + try + { + return await this.RepositoryContext.Set().FindAsync(entityId); + } + catch (Exception ex) + { + WriteLogException(ex, $"{typeof(WebApp).Name} id:{entityId}"); + } + return default; + } + + public async Task GetDepartmentById(int entityId) + { + try + { + return await this.RepositoryContext.Set().FindAsync(entityId); + } + catch (Exception ex) + { + WriteLogException(ex, $"{typeof(Department).Name} id:{entityId}"); + } + return default; + } + + public async Task GetEmployeeById(int entityId) + { + try + { + return await this.RepositoryContext.Set().FindAsync(entityId); + } + catch (Exception ex) + { + WriteLogException(ex, $"{typeof(Employee).Name} id:{entityId}"); + } + return default; + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/WebAppToWebAppAdditionalRoleRepository.cs b/DAL/Repositories/WebAppToWebAppAdditionalRoleRepository.cs new file mode 100644 index 0000000..17d7444 --- /dev/null +++ b/DAL/Repositories/WebAppToWebAppAdditionalRoleRepository.cs @@ -0,0 +1,176 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using HRD.LDAPService; +using HRD.WebApi.Repositories; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace DAL.Repositories +{ + public class WebAppToWebAppAdditionalRoleRepository : BaseRepository + { + public WebAppToWebAppAdditionalRoleRepository() : base(new WebApiContext()) + { + } + + public async Task> GetListByFilterAsync(EmployeeToWebAppFilter filter, bool asNoTracking = true) + { + var items = this.RepositoryContext.Set().AsQueryable(); + + if (filter.EmployeeToWebAppId != null && filter.EmployeeToWebAppId != 0) + { + items = items.Where(x => x.EmployeeToWebAppId == filter.EmployeeToWebAppId); + } + + return asNoTracking ? await items.AsNoTracking().ToListAsync() : await items.ToListAsync(); + } + + private async Task AddUserToAdGroup(WebAppToWebAppAdditionalRole entity) + { + return await ProcessGroup(entity, "adding"); + } + + private async Task RemoveUserFromAdGroup(WebAppToWebAppAdditionalRole entity) + { + return await ProcessGroup(entity, "deleting"); + } + + private async Task ProcessGroup(WebAppToWebAppAdditionalRole entity, string action) + { + if (entity == default) throw new ArgumentNullException(nameof(entity)); + + var employee2Web = await GetEmployeeToWebAppById(entity.EmployeeToWebAppId); + if (employee2Web == default) throw new ArgumentNullException(nameof(employee2Web)); + + var webappRole = await GetWebAppAddRoleById(entity.WebAppAdditionalRoleId); + if (webappRole == default) throw new ArgumentNullException(nameof(webappRole)); + if (string.IsNullOrEmpty(webappRole.AdWebAppAdditionalRoleName)) return true; + + var employee = await GetEmployeeById(employee2Web.EmployeeId); + if (employee == default) throw new ArgumentNullException(nameof(employee)); + + var webapp = await GetWebAppById(employee2Web.WebAppId); + if (webapp == default) throw new ArgumentNullException(nameof(webapp)); + + bool result; + var isAdding = action == "adding"; + var groupSuffix = $"{webapp.AdWebAppName}_{webappRole.AdWebAppAdditionalRoleName}"; + try + { + if (isAdding) result = LdapManager.AD_AddUserloginToGroup(employee.LoginName, groupSuffix); + else result = LdapManager.AD_RemoveUserFromGroup(employee.LoginName, groupSuffix); + } + catch (Exception ex) + { + WriteLogException(ex, $"An error occurred while '{action}' the '{employee.LoginName}' into '{groupSuffix}'."); + return false; + } + + if (!result) + { + WriteLogError($"An error occurred while '{action}' the '{employee.LoginName}' into '{groupSuffix}'."); + return false; + }; + return true; + } + + public override async Task AddAsync(WebAppToWebAppAdditionalRole entity, bool saveEntity = true) + { + if (await AddUserToAdGroup(entity)) + { + var result = await base.AddAsync(entity, saveEntity); + return result; + } + return false; + } + + public override async Task AddListAsync(List entities, bool saveEntity = true) + { + var result = true; + for (int i = 0; i < entities.Count; i++) + { + if (!await AddAsync(entities[i], saveEntity)) result = false; + } + return result; + } + + public override async Task DeleteByIdAsync(int id, bool saveEntity = true) + { + try + { + var entity = await base.GetByIdAsync(id); + if (entity == default) + { + throw new ArgumentNullException(nameof(entity)); + } + + if (await RemoveUserFromAdGroup(entity)) + { + var result = await base.DeleteByIdAsync(id, saveEntity); + return result; + } + return false; + } + catch (Exception ex) + { + WriteLogException(ex, $"An error occurred while deleting the Id {id}"); + return false; + } + } + + public async Task GetEmployeeToWebAppById(int entityId) + { + try + { + return await this.RepositoryContext.Set().FindAsync(entityId); + } + catch (Exception ex) + { + WriteLogException(ex, $"{typeof(EmployeeToWebApp).Name} id:{entityId}"); + } + return default; + } + + public async Task GetWebAppById(int entityId) + { + try + { + return await this.RepositoryContext.Set().FindAsync(entityId); + } + catch (Exception ex) + { + WriteLogException(ex, $"{typeof(WebApp).Name} id:{entityId}"); + } + return default; + } + + public async Task GetWebAppAddRoleById(int entityId) + { + try + { + return await this.RepositoryContext.Set().FindAsync(entityId); + } + catch (Exception ex) + { + WriteLogException(ex, $"{typeof(WebAppAdditionalRole).Name} id:{entityId}"); + } + return default; + } + + public async Task GetEmployeeById(int entityId) + { + try + { + return await this.RepositoryContext.Set().FindAsync(entityId); + } + catch (Exception ex) + { + WriteLogException(ex, $"{typeof(Employee).Name} id:{entityId}"); + } + return default; + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/WebAppToWebAppRoleRepository.cs b/DAL/Repositories/WebAppToWebAppRoleRepository.cs new file mode 100644 index 0000000..ca1fd3c --- /dev/null +++ b/DAL/Repositories/WebAppToWebAppRoleRepository.cs @@ -0,0 +1,29 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using HRD.WebApi.Repositories; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace DAL.Repositories +{ + public class WebAppToWebAppRoleRepository : BaseRepository + { + public WebAppToWebAppRoleRepository() : base(new WebApiContext()) + { + } + + public async Task> GetListByFilterAsync(WebAppFilter filter, bool asNoTracking = true) + { + var items = this.RepositoryContext.Set().AsQueryable(); + + if (filter.WebAppId != null && filter.WebAppId != 0) + { + items = items.Where(x => x.WebAppId == filter.WebAppId); + } + + return asNoTracking ? await items.AsNoTracking().ToListAsync() : await items.ToListAsync(); + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/WindreamColumnsToDepartmentRepository.cs b/DAL/Repositories/WindreamColumnsToDepartmentRepository.cs new file mode 100644 index 0000000..d3acd5a --- /dev/null +++ b/DAL/Repositories/WindreamColumnsToDepartmentRepository.cs @@ -0,0 +1,34 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using HRD.WebApi.Repositories; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace DAL.Repositories +{ + public class WindreamColumnsToDepartmentRepository : BaseRepository + { + public WindreamColumnsToDepartmentRepository() : base(new WebApiContext()) + { + } + + public async Task> GetListByFilterAsync(DepartmentFilter filter, bool asNoTracking = true) + { + var items = this.RepositoryContext.Set().AsQueryable(); + + if (filter.DepartmentId != null && filter.DepartmentId != 0) + { + items = items.Where(x => x.DepartmentId == filter.DepartmentId); + } + + if (filter.WindreamSearchId != null && filter.WindreamSearchId != 0) + { + items = items.Where(x => x.WindreamSearchId == filter.WindreamSearchId); + } + + return asNoTracking ? await items.OrderBy(x => x.Seq).AsNoTracking().ToListAsync() : await items.OrderBy(x => x.Seq).ToListAsync(); + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/WindreamIndexRepository.cs b/DAL/Repositories/WindreamIndexRepository.cs new file mode 100644 index 0000000..48d8d95 --- /dev/null +++ b/DAL/Repositories/WindreamIndexRepository.cs @@ -0,0 +1,29 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using HRD.WebApi.Repositories; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace DAL.Repositories +{ + public class WindreamIndexRepository : BaseRepository + { + public WindreamIndexRepository() : base(new WebApiContext()) + { + } + + public async Task> GetListByFilterAsync(ClientIdFilter filter, bool asNoTracking = true) + { + var items = this.RepositoryContext.Set().AsQueryable(); + + if (filter.ClientId != null) + { + items = items.Where(x => x.ClientId == filter.ClientId); + } + + return asNoTracking ? await items.AsNoTracking().ToListAsync() : await items.ToListAsync(); + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/WindreamIndexToWindreamSearchToDepartmentRepository.cs b/DAL/Repositories/WindreamIndexToWindreamSearchToDepartmentRepository.cs new file mode 100644 index 0000000..810151c --- /dev/null +++ b/DAL/Repositories/WindreamIndexToWindreamSearchToDepartmentRepository.cs @@ -0,0 +1,29 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using HRD.WebApi.Repositories; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace DAL.Repositories +{ + public class WindreamIndexToWindreamSearchToDepartmentRepository : BaseRepository + { + public WindreamIndexToWindreamSearchToDepartmentRepository() : base(new WebApiContext()) + { + } + + public async Task> GetListByFilterAsync(WindreamSearchToDepartmentFilter filter, bool asNoTracking = true) + { + var items = this.RepositoryContext.Set().AsQueryable(); + + if (filter.WindreamSearchToDepartmentId != null && filter.WindreamSearchToDepartmentId != 0) + { + items = items.Where(x => x.WindreamSearchToDepartmentId == filter.WindreamSearchToDepartmentId); + } + + return asNoTracking ? await items.OrderBy(x => x.Seq).AsNoTracking().ToListAsync() : await items.OrderBy(x => x.Seq).ToListAsync(); + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/WindreamInputFolderRepository.cs b/DAL/Repositories/WindreamInputFolderRepository.cs new file mode 100644 index 0000000..732049a --- /dev/null +++ b/DAL/Repositories/WindreamInputFolderRepository.cs @@ -0,0 +1,34 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using HRD.WebApi.Repositories; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace DAL.Repositories +{ + public class WindreamInputFolderRepository : BaseRepository + { + public WindreamInputFolderRepository() : base(new WebApiContext()) + { + } + + public async Task> GetListByFilterAsync(WindreamInputFolderFilter filter, bool asNoTracking = true) + { + var items = this.RepositoryContext.Set().AsQueryable(); + + if (filter.WindreamInputFolderId != null && filter.WindreamInputFolderId != 0) + { + items = items.Where(x => x.WindreamInputFolderId == filter.WindreamInputFolderId); + return asNoTracking ? await items.ToListAsync() : await items.ToListAsync(); + } + + if (filter.ClientId != null) + { + items = items.Where(x => x.ClientId == filter.ClientId); + } + return asNoTracking ? await items.AsNoTracking().ToListAsync() : await items.ToListAsync(); + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/WindreamSearchItemRepository.cs b/DAL/Repositories/WindreamSearchItemRepository.cs new file mode 100644 index 0000000..83391fa --- /dev/null +++ b/DAL/Repositories/WindreamSearchItemRepository.cs @@ -0,0 +1,29 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using HRD.WebApi.Repositories; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace DAL.Repositories +{ + public class WindreamSearchItemRepository : BaseRepository + { + public WindreamSearchItemRepository() : base(new WebApiContext()) + { + } + + public async Task> GetListByFilterAsync(ClientIdFilter filter, bool asNoTracking = true) + { + var items = this.RepositoryContext.Set().AsQueryable(); + + if (filter.ClientId != null) + { + items = items.Where(x => x.ClientId == filter.ClientId); + } + + return asNoTracking ? await items.AsNoTracking().ToListAsync() : await items.ToListAsync(); + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/WindreamSearchItemToWindreamSearchToDepartmentRepository.cs b/DAL/Repositories/WindreamSearchItemToWindreamSearchToDepartmentRepository.cs new file mode 100644 index 0000000..ba925dc --- /dev/null +++ b/DAL/Repositories/WindreamSearchItemToWindreamSearchToDepartmentRepository.cs @@ -0,0 +1,33 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using HRD.WebApi.Repositories; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace DAL.Repositories +{ + public class WindreamSearchItemToWindreamSearchToDepartmentRepository : BaseRepository + { + public WindreamSearchItemToWindreamSearchToDepartmentRepository() : base(new WebApiContext()) + { + } + + public async Task> GetListByFilterAsync(WindreamSearchToDepartmentFilter filter, bool asNoTracking = true) + { + var items = this.RepositoryContext.Set().AsQueryable(); + + if (filter.WindreamSearchToDepartmentId != null && filter.WindreamSearchToDepartmentId != 0) + { + items = items.Where(x => x.WindreamSearchToDepartmentId == filter.WindreamSearchToDepartmentId); + } + + if (filter.DepartmentId != null && filter.DepartmentId != 0) + { + items = items.Where(x => x.DepartmentId == filter.DepartmentId); + } + return asNoTracking ? await items.OrderBy(x => x.Seq).AsNoTracking().ToListAsync() : await items.OrderBy(x => x.Seq).ToListAsync(); + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/WindreamSearchRepository.cs b/DAL/Repositories/WindreamSearchRepository.cs new file mode 100644 index 0000000..ebc17ea --- /dev/null +++ b/DAL/Repositories/WindreamSearchRepository.cs @@ -0,0 +1,29 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using HRD.WebApi.Repositories; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace DAL.Repositories +{ + public class WindreamSearchRepository : BaseRepository + { + public WindreamSearchRepository() : base(new WebApiContext()) + { + } + + public async Task> GetListByFilterAsync(ClientIdFilter filter, bool asNoTracking = true) + { + var items = this.RepositoryContext.Set().AsQueryable(); + + if (filter.ClientId != null) + { + items = items.Where(x => x.ClientId == filter.ClientId); + } + + return asNoTracking ? await items.AsNoTracking().ToListAsync() : await items.ToListAsync(); + } + } +} \ No newline at end of file diff --git a/DAL/Repositories/WindreamSearchToDepartmentRepository.cs b/DAL/Repositories/WindreamSearchToDepartmentRepository.cs new file mode 100644 index 0000000..591e610 --- /dev/null +++ b/DAL/Repositories/WindreamSearchToDepartmentRepository.cs @@ -0,0 +1,36 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using HRD.WebApi.Repositories; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace DAL.Repositories +{ + public class WindreamSearchToDepartmentRepository : BaseRepository + { + public WindreamSearchToDepartmentRepository() : base(new WebApiContext()) + { + } + + public async Task> GetListByFilterAsync(DepartmentFilter filter, bool asNoTracking = true) + { + var items = this.RepositoryContext.Set().AsQueryable(); + + if (filter.DepartmentId != null && filter.DepartmentId != 0) + { + items = items.Where(x => x.DepartmentId == filter.DepartmentId); + } + + items = items.Where(x => x.IsActive); + + return asNoTracking ? await items.OrderBy(x => x.Seq).AsNoTracking().ToListAsync() : await items.OrderBy(x => x.Seq).ToListAsync(); + } + + public async Task AddWindreamTile(int srcWindreamSearch2DepartmentId, string trgDepartmentIds) + { + return await ExecStoredProcedureAsync("webapi.sp_TransferWindreamSettings", $"null, {srcWindreamSearch2DepartmentId}, \"{trgDepartmentIds}\""); + } + } +} \ No newline at end of file diff --git a/DAL/WebApiContext.cs b/DAL/WebApiContext.cs new file mode 100644 index 0000000..8621862 --- /dev/null +++ b/DAL/WebApiContext.cs @@ -0,0 +1,213 @@ +using DAL._Shared.SharedModels; +using DAL.Models.Entities; +using HRD.WebApi.DAL; + +using Microsoft.EntityFrameworkCore; + +namespace DAL +{ + public partial class WebApiContext : WebApiBaseContext + { + public WebApiContext() : base() + { + } + + public WebApiContext(DbContextOptions options) : base(options) + { + } + + public virtual DbSet WebAppUserSet { get; set; } + public virtual DbSet WebAppEmployeeInfo { get; set; } + + public virtual DbSet AdWebAppToWebAppRoleSet { get; set; } + public virtual DbSet CostCentreSet { get; set; } + public virtual DbSet DepartmentSet { get; set; } + public virtual DbSet DocumentArtSet { get; set; } + public virtual DbSet EmployeeAttributeSet { get; set; } + public virtual DbSet EmployeeStatusSet { get; set; } + public virtual DbSet ProjectSet { get; set; } + public virtual DbSet RangSet { get; set; } + public virtual DbSet WebAppSet { get; set; } + public virtual DbSet WebAppRoleSet { get; set; } + public virtual DbSet DepartmentToWebAppToEmployeeForWindreamSet { get; set; } + public virtual DbSet DocumentArtToDepartmentSet { get; set; } + public virtual DbSet EmployeeSet { get; set; } + public virtual DbSet EmployeeToAttributeSet { get; set; } + public virtual DbSet EmployeeToDepartmentSet { get; set; } + public virtual DbSet EmployeeToWebAppSet { get; set; } + public virtual DbSet WebAppAdditionalRoleSet { get; set; } + public virtual DbSet WebAppToDepartmentSet { get; set; } + public virtual DbSet WebAppToWebAppAdditionalRoleSet { get; set; } + public virtual DbSet WebAppToWebAppRoleSet { get; set; } + public virtual DbSet WindreamColumnsToDepartmentSet { get; set; } + public virtual DbSet WindreamIndexSet { get; set; } + public virtual DbSet WindreamIndexToWindreamSearchToDepartmentSet { get; set; } + public virtual DbSet WindreamSearchSet { get; set; } + public virtual DbSet WindreamSearchItemSet { get; set; } + public virtual DbSet WindreamSearchItemToWindreamSearchToDepartmentSet { get; set; } + public virtual DbSet WindreamSearchToDepartmentSet { get; set; } + public virtual DbSet WindreamInputFolderSet { get; set; } + public virtual DbSet SubsidiarySet { get; set; } + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity(entity => + { + entity.ToTable("Subsidiary", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("WindreamInputFolder", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("WindreamSearchToDepartment", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("WindreamSearchItemToWindreamSearchToDepartment", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("WindreamSearchItem", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("WindreamSearch", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("WindreamIndexToWindreamSearchToDepartment", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("WindreamIndex", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("WindreamColumnsToDepartment", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("WebAppToWebAppRole", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("WebAppToWebAppAdditionalRole", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("WebAppToDepartment", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("WebAppAdditionalRole", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("EmployeeToWebApp", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("EmployeeToDepartment", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("EmployeeToAttribute", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("Employee", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("DocumentArtToDepartment", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("DepartmentToWebAppToEmployeeForWindream", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("WebAppRole", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("WebApp", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("Rang", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("Project", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("EmployeeStatus", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("EmployeeAttribute", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("DocumentArt", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("Department", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("CostCentre", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("AdWebAppToWebAppRole", "webapi"); + }); + + + modelBuilder.Entity(entity => + { + entity.ToTable("WebAppUser", "webapi"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("WebAppEmployeeInfo", "webapi"); + }); + + base.OnModelCreating(modelBuilder); + } + + } +} diff --git a/DAL/_Shared/SharedModels/WebAppEmployeeInfo.cs b/DAL/_Shared/SharedModels/WebAppEmployeeInfo.cs new file mode 100644 index 0000000..3740618 --- /dev/null +++ b/DAL/_Shared/SharedModels/WebAppEmployeeInfo.cs @@ -0,0 +1,37 @@ +using HRD.WebApi.DAL; + +namespace DAL._Shared.SharedModels +{ + public partial class WebAppEmployeeInfo : BaseEntity + { + public int WebAppEmployeeInfoId { get; set; } + public string EmployeeNo { get; set; } + public string Salutation { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + public string ShortName { get; set; } + public string Title { get; set; } + public string Position { get; set; } + public string LoginName { get; set; } + public string Email { get; set; } + public int DepartmentId { get; set; } + public string ExtendedDepartmentIdList { get; set; } + public string DepartmentName { get; set; } + public int EmployeeId { get; set; } + public int CostCentreId { get; set; } + public string RangShortname { get; set; } + public string RangName { get; set; } + public int RangOrder { get; set; } + public int ClientId { get; set; } + public int WebAppId { get; set; } + + //generic Id + public override int GetEntityId() => WebAppEmployeeInfoId; + + //generic ToString() + public override string ToString() => $"WebAppEmployeeInfoId: {GetEntityId()}; Name: {LoginName}"; + + //generic EntityInfo() + public override string EntityInfo() => base.EntityInfo(); + } +} \ No newline at end of file diff --git a/DAL/_Shared/SharedModels/WebAppUser.cs b/DAL/_Shared/SharedModels/WebAppUser.cs new file mode 100644 index 0000000..924dd78 --- /dev/null +++ b/DAL/_Shared/SharedModels/WebAppUser.cs @@ -0,0 +1,59 @@ +using HRD.WebApi.DAL; +using System; +using System.ComponentModel.DataAnnotations.Schema; + +namespace DAL._Shared.SharedModels +{ + public partial class WebAppUser : BaseEntity + { + public WebAppUser() + { + } + + public WebAppUser(string loginName, string shortName, string roleList, string name) + { + LoginName = loginName; + ShortName = shortName; + RoleList = roleList; + Name = name; + } + + public int WebAppUserId { get; set; } + public string Name { get; set; } + public string ShortName { get; set; } + + public string LoginName { get; set; } + + public string Password { get; set; } = string.Empty; + public string RoleList { get; set; } + public string WebAppRoleList { get; set; } = string.Empty; + + public DateTime? JwtExpiredOn { get; set; } + public DateTime? LastLogin { get; set; } + + [NotMapped] + public string Token { get; set; } + + public string ClientVersion { get; set; } + + [NotMapped] + public int TimeZoneOffsetInMin { get; set; } + + public string Language { get; set; } + public string Culture { get; set; } + + public bool IsGermanCulture() => Culture?.Substring(0, 2).ToLower() == "de"; + + //generic Id + public override int GetEntityId() => WebAppUserId; + + //generic ToString() + public override string ToString() => $"WebAppUserId: {GetEntityId()}; Name: {Name}"; + + //generic EntityInfo() + public override string EntityInfo() + { + return $"WebAppUserId: {GetEntityId()}; Loginname:{LoginName}; JwtExpiredOn:{JwtExpiredOn}"; + } + } +} \ No newline at end of file diff --git a/DAL/_Shared/SharedRepositories/WebAppEmployeeInfoRepository.cs b/DAL/_Shared/SharedRepositories/WebAppEmployeeInfoRepository.cs new file mode 100644 index 0000000..fac6207 --- /dev/null +++ b/DAL/_Shared/SharedRepositories/WebAppEmployeeInfoRepository.cs @@ -0,0 +1,114 @@ +using DAL._Shared.SharedModels; +using HRD.LDAPService; +using HRD.WebApi.Repositories; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace DAL._Shared.SharedRepositories +{ + public class WebAppEmployeeInfoRepository : BaseRepository + + { + public WebAppEmployeeInfoRepository() : base(new WebApiContext()) + { + } + + private IQueryable PrepareList(List departmentIds) + { + IQueryable items = RepositoryContext.Set().AsNoTracking(); + return items.Where(x => departmentIds.Contains(x.DepartmentId)); + } + + public async Task> GetEmailListForDepartmentsAsync(List departmentIds) + { + return await PrepareList(departmentIds).Select(x => x.Email).ToListAsync(); + } + + public async Task> GetLoginnameListForDepartmentsAsync(List departmentIds) + { + return await PrepareList(departmentIds).Select(x => x.LoginName).ToListAsync(); + } + + public async Task> GetShortnameListForDepartmentsAsync(List departmentIds) + { + return await PrepareList(departmentIds).Select(x => x.ShortName).ToListAsync(); + } + + public async Task GetShortnameForLoginAsync(string loginname) + { + return (await RepositoryContext.Set().FirstAsync(x => x.LoginName == loginname)).ShortName; + } + + //---------------- + public List GetEmailListForDepartments(List departmentIds) + { + return PrepareList(departmentIds).Select(x => x.Email).ToList(); + } + + public List GetLoginnameListForDepartments(List departmentIds) + { + return PrepareList(departmentIds).Select(x => x.LoginName).ToList(); + } + + public List GetShortnameListForDepartments(List departmentIds) + { + return PrepareList(departmentIds).Select(x => x.ShortName).ToList(); + } + + public string GetShortnameForLogin(string loginname) + { + return RepositoryContext.Set().First(x => x.LoginName == loginname).ShortName; + } + + //---------------- + public bool PrepareForUserLoginnameOrLoginnameListFilter(LdapUser ldapUser, ref string loginName, ref List loginNameList) + { + if (ldapUser.IsAdmin() || ldapUser.IsMaster()) + { + } + else if (ldapUser.IsDepartmentMaster() || ldapUser.IsDepartmentUser()) + { + loginNameList = GetLoginnameListForDepartments(ldapUser.DepartmentIdListAll()); + loginName = default; + } + else if (ldapUser.IsUser()) + { + loginNameList = default; + loginName = ldapUser.LoginName; + } + else + { + return false; //shouldn't happen + } + return true; + } + + public bool PrepareForUserEmailOrEmailListFilter(LdapUser ldapUser, ref string EmailBV, ref List EmailBVList) + { + if (string.IsNullOrEmpty(EmailBV)) //check for user & master + { + if (ldapUser.IsAdmin() || ldapUser.IsMaster()) + { + // No correction + } + else if (ldapUser.IsDepartmentMaster() || ldapUser.IsDepartmentUser()) + { + EmailBVList = GetEmailListForDepartments(ldapUser.DepartmentIdListAll()); + EmailBV = default; + } + else if (ldapUser.IsUser()) + { + EmailBVList = default; + EmailBV = ldapUser.Email; + } + else + { + return false; //shouldn't happen + } + } + return true; + } + } +} \ No newline at end of file diff --git a/DAL/_Shared/SharedRepositories/WebAppUserRepository.cs b/DAL/_Shared/SharedRepositories/WebAppUserRepository.cs new file mode 100644 index 0000000..191ff67 --- /dev/null +++ b/DAL/_Shared/SharedRepositories/WebAppUserRepository.cs @@ -0,0 +1,12 @@ +using DAL._Shared.SharedModels; +using HRD.WebApi.Repositories; + +namespace DAL._Shared.SharedRepositories +{ + public class WebAppUserRepository : BaseRepository + { + public WebAppUserRepository() : base(new WebApiContext()) + { + } + } +} \ No newline at end of file diff --git a/DAL/_Shared/init_context.bat b/DAL/_Shared/init_context.bat new file mode 100644 index 0000000..191a34b --- /dev/null +++ b/DAL/_Shared/init_context.bat @@ -0,0 +1,2 @@ +dotnet ef dbcontext scaffold "Server=192.168.110.105\\DEV1;Database=ctx;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -o ModelCTX +pause \ No newline at end of file diff --git a/HRD.AppLogger/AppLoggerConfig.cs b/HRD.AppLogger/AppLoggerConfig.cs new file mode 100644 index 0000000..e414180 --- /dev/null +++ b/HRD.AppLogger/AppLoggerConfig.cs @@ -0,0 +1,255 @@ +using HRD.AppLogger; +using NLog; +using NLog.Config; +using NLog.Targets; +using System; +using System.Collections.Generic; +using System.IO; + +namespace HRD.AppLogger +{ + public enum EN_LoggingLevel + { + Trace = 1, + Debug = 2, + Info = 3, + Warn = 4, + Error = 5, + Fatal = 6, + Off = 7 + } +} + +public static class AppLoggerConfig +{ + private static readonly string DBLOG_CommandText = + @" + INSERT INTO dbo.DBLog + ( MachineName, + Application, + Logged, + Level, + Message, + Logger, + CallSite, + Webrequest, + Stacktrace, + InnerException, + Exception, + Version, + Entity + ) + VALUES + ( @machineName, + @application, + @logged, + @level, + @message, + @logger, + @callsite, + iif(@webrequestaction='',@webrequest, concat(@webrequest,' | action:',@webrequestaction)), + @stacktrace, + @innerException, + @exception, + @Version, + @Entity + );"; + + private static readonly Dictionary DBLOG_Parameters = new Dictionary() { + //Globals + {"@version", "${gdc:item=Version}"}, + {"@application", "${gdc:item=Application}"}, + + //Local + //{"@webrequest", "${mdlc:item=Webrequest}"}, + {"@entity", "${mdlc:item=Entity}"}, + + //WebApi + {"@webrequest", "${aspnet-request-url}"}, + {"@webrequestaction", "${aspnet-mvc-action}"}, + + //Nlog + {"@machineName", "${machinename}" }, + {"@logged", "${date}"}, + {"@level", "${level:upperCase=true}"}, + {"@message", "${message}"}, + {"@logger", "${logger}"}, + {"@callSite", "${callsite:fileName=true:includeSourcePath=false:skipFrames=1}"}, //{"@callSite", "${callsite:filename=false:className=true:methodName=true}"}, + {"@stacktrace", "${stacktrace:topFrames=10}"}, + {"@InnerException", "${exception:format=Message,StackTrace,Data:maxInnerExceptionLevel=10}"}, + {"@Exception", "${exception:format=ToString}"}, + }; + + public static string AssemblyName { get; set; } + public static string AssemblyVersion { get; set; } + public static EN_LoggingLevel DBLogLevel { get; set; } = EN_LoggingLevel.Warn; + public static EN_LoggingLevel FileLogLevel { get; set; } = EN_LoggingLevel.Error; + public static string LogDirectory { get; set; } = String.Empty; + public static string NlogConnectionstring { get; set; } + public static LogLevel NlogDBLogLevel { get; set; } + public static LogLevel NlogFileLogLevel { get; set; } + public static NlogSentryConfig NlogSentryConfig { get; set; } = new NlogSentryConfig(); + + public static LoggingConfiguration CreateConfig() + { + NlogDBLogLevel = MapLogLevel(DBLogLevel); + NlogFileLogLevel = MapLogLevel(FileLogLevel); + + var config = new LoggingConfiguration(); + + DatabaseTarget dbTarget = CreateDatabaseTarget(config); + var dbRule = new LoggingRule("*", NlogDBLogLevel, dbTarget); + config.LoggingRules.Add(dbRule); + + //Rules + FileTarget targetFile = CreateFileTarget(config); + var rule = new LoggingRule("*", NlogFileLogLevel, targetFile); + config.LoggingRules.Add(rule); + if (NlogSentryConfig.NlogSentryIsEnable) + { + AddSentry(config); + } + + return config; + } + + public static void Init( + string assemblyName, + string assemblyVersion, + EN_LoggingLevel dbLogLevel = EN_LoggingLevel.Warn + , EN_LoggingLevel fileLoogLevel = EN_LoggingLevel.Off + , string logDirectory = "") + { + AssemblyVersion = assemblyVersion; + AssemblyName = assemblyName; + DBLogLevel = dbLogLevel; + FileLogLevel = fileLoogLevel; + LogDirectory = logDirectory; + } + + private static void AddSentry(LoggingConfiguration config) + { + config.AddSentry(o => + { + o.Dsn = NlogSentryConfig.Dsn; + + o.Layout = "${message}"; + + o.BreadcrumbLayout = "${logger}: ${message} #url: ${aspnet-request-url} | #action: ${aspnet-mvc-action}"; + // Optionally specify a separate format for breadcrumbs + + o.MinimumBreadcrumbLevel = NlogSentryConfig.MinimumBreadcrumbLevel; // Debug and higher are stored as breadcrumbs (default is Info) + o.MinimumEventLevel = NlogSentryConfig.MinimumEventLevel; // Error and higher is sent as event (default is Error) + + // If DSN is not set, the SDK will look for an environment variable called SENTRY_DSN. If + // nothing is found, SDK is disabled. + + o.AttachStacktrace = NlogSentryConfig.AttachStacktrace; + o.SendDefaultPii = NlogSentryConfig.SendDefaultPii; // Send Personal Identifiable information like the username of the user logged in to the device + + o.IncludeEventDataOnBreadcrumbs = NlogSentryConfig.IncludeEventDataOnBreadcrumbs; // Optionally include event properties with breadcrumbs + o.ShutdownTimeoutSeconds = 5; + o.TracesSampleRate = 0.3; + + //Optionally specify user properties via NLog (here using MappedDiagnosticsLogicalContext as an example) + // o.User = new SentryNLogUser + // { + // Id = "${mdlc:item=id}", + // Username = "${mdlc:item=username}", + // Email = "${mdlc:item=email}", + // IpAddress = "${mdlc:item=ipAddress}", + // Other = + //{ + // new TargetPropertyWithContext("mood", "joyous") + //}, + //}; + + o.AddTag("Backend", "${gdc:item=Application}"); // Send the logger name as a tag + o.AddTag("BackendVersion", "${gdc:item=Version}"); // Send the logger name as a tag + o.AddTag("logger", "${logger}"); // Send the logger name as a tag + + // Other configuration + }); + } + + private static DatabaseTarget CreateDatabaseTarget(LoggingConfiguration config) + { + var dbTarget = new DatabaseTarget + { + ConnectionString = NlogConnectionstring, + + CommandText = DBLOG_CommandText + }; + + foreach (var item in DBLOG_Parameters) + { + dbTarget.Parameters.Add(new DatabaseParameterInfo(item.Key, item.Value)); + } + + config.AddTarget("database", dbTarget); + return dbTarget; + } + + private static FileTarget CreateFileTarget(LoggingConfiguration config) + { + var targetFile = + new FileTarget + { + FileName = Path.Combine( + !string.IsNullOrEmpty(LogDirectory) ? LogDirectory : "${basedir}/_logs/", + "${gdc:item=Application}" + "_V." + "${gdc:item=Version}" + $"_{DateTime.Now:yyyyMMdd}.log"), + Layout = "${date}|${uppercase:${level}}|${stacktrace}|${message}" + + "|${exception:format=Message,StackTrace,Data:maxInnerExceptionLevel=10}" + + "${event-properties:item=EventId.Id}" + }; + + config.AddTarget("logfile", targetFile); + return targetFile; + } + + private static LogLevel MapLogLevel(EN_LoggingLevel loggingLevel) + { + LogLevel logLevel = LogLevel.Error; + switch (loggingLevel) + { + case EN_LoggingLevel.Trace: + logLevel = LogLevel.Trace; + break; + + case EN_LoggingLevel.Debug: + logLevel = LogLevel.Debug; + break; + + case EN_LoggingLevel.Info: + logLevel = LogLevel.Info; + break; + + case EN_LoggingLevel.Warn: + logLevel = LogLevel.Warn; + break; + + case EN_LoggingLevel.Error: + logLevel = LogLevel.Error; + break; + + case EN_LoggingLevel.Fatal: + logLevel = LogLevel.Fatal; + break; + + case EN_LoggingLevel.Off: + logLevel = LogLevel.Off; + break; + + default: + break; + } + return logLevel; + } + + public static void SetSentryUser(int id, string login, string email, IDictionary others = null) + { + NlogSentryConfig.SentryUser = new Sentry.User { Id = id.ToString(), Username = login, Email = email }; + if (others != null) NlogSentryConfig.SentryUser.Other = others; + Sentry.SentrySdk.ConfigureScope(scope => { scope.User = NlogSentryConfig.SentryUser; }); + } +} \ No newline at end of file diff --git a/HRD.AppLogger/HRD.AppLogger.csproj b/HRD.AppLogger/HRD.AppLogger.csproj new file mode 100644 index 0000000..5e132c4 --- /dev/null +++ b/HRD.AppLogger/HRD.AppLogger.csproj @@ -0,0 +1,15 @@ + + + + netcoreapp7.0 + Hensel Recycling GmbH + IT Entwicklung + 1.5.0 + + + + + + + + \ No newline at end of file diff --git a/HRD.AppLogger/ILoggerManager.cs b/HRD.AppLogger/ILoggerManager.cs new file mode 100644 index 0000000..de1df6c --- /dev/null +++ b/HRD.AppLogger/ILoggerManager.cs @@ -0,0 +1,17 @@ +using System; + +namespace HRD.AppLogger +{ + public interface ILoggerManager + { + void LogDebug(string message, string entityMessage = null, string webrequest = null, string userLogin = null); + + void LogError(string message, string entityMessage = null, string webrequest = null, string userLogin = null); + + void LogInfo(string message, string entityMessage = null, string webrequest = null, string userLogin = null); + + void LogWarn(string message, string entityMessage = null, string webrequest = null, string userLogin = null); + + void LogException(Exception exception, string entityMessage = null, string webrequest = null, string userLogin = null); + } +} \ No newline at end of file diff --git a/HRD.AppLogger/LoggerManager.cs b/HRD.AppLogger/LoggerManager.cs new file mode 100644 index 0000000..c39f96f --- /dev/null +++ b/HRD.AppLogger/LoggerManager.cs @@ -0,0 +1,214 @@ +using NLog; +using Sentry; +using System; + +namespace HRD.AppLogger +{ + public class LoggerManager : ILoggerManager + { + private static readonly ILogger logger = LogManager.GetCurrentClassLogger(); + + public LoggerManager(bool throwExceptions = true) : this() + { + LogManager.ThrowExceptions = throwExceptions; + } + + public LoggerManager() + { + GlobalDiagnosticsContext.Set("Version", AppLoggerConfig.AssemblyVersion); + GlobalDiagnosticsContext.Set("Application", AppLoggerConfig.AssemblyName); + + LogManager.ThrowConfigExceptions = true; + LogManager.ThrowExceptions = false; + LogManager.Configuration = AppLoggerConfig.CreateConfig(); + } + + public void WriteLog(Action log, Object message, string entityMessage = null, string webrequest = null, string userLogin = null) + { + MappedDiagnosticsLogicalContext.Set("Entity", !String.IsNullOrEmpty(entityMessage) ? entityMessage : ""); + MappedDiagnosticsLogicalContext.Set("Webrequest", !String.IsNullOrEmpty(webrequest) ? webrequest : ""); + + if (AppLoggerConfig.NlogSentryConfig.NlogSentryIsEnable) + { + SentrySdk.WithScope(scope => + { + if (!String.IsNullOrEmpty(entityMessage)) + { + scope.SetTag("Entity", entityMessage); + } + + if (!String.IsNullOrEmpty(webrequest)) + { + scope.SetTag("Webrequest", webrequest); + } + + if (!String.IsNullOrEmpty(userLogin)) + { + scope.SetTag("UserLogin", userLogin); + } + + log(message); + }); + } + else log(message); + } + + public void LogDebug(string message, string entityMessage = null, string webrequest = null, string userLogin = null) + { + WriteLog(logger.Debug, message, entityMessage, webrequest, userLogin); + + /* MappedDiagnosticsLogicalContext.Set("Entity", !String.IsNullOrEmpty(entityMessage) ? entityMessage : ""); + MappedDiagnosticsLogicalContext.Set("Webrequest", !String.IsNullOrEmpty(webrequest) ? webrequest : ""); + + if (AppLoggerConfig.NlogSentryConfig.NlogSentryIsEnable) + { + SentrySdk.WithScope(scope => + { + if (!String.IsNullOrEmpty(entityMessage)) + { + scope.SetTag("Entity", entityMessage); + } + + if (!String.IsNullOrEmpty(webrequest)) + { + scope.SetTag("Webrequest", webrequest); + } + + if (!String.IsNullOrEmpty(userLogin)) + { + scope.SetTag("UserLogin", userLogin); + } + + logger.Debug(message); + }); + } + else logger.Debug(message);*/ + } + + public void LogError(string message, string entityMessage = null, string webrequest = null, string userLogin = null) + { + //WriteLog(logger.Error, message, entityMessage, webrequest, userLogin); + MappedDiagnosticsLogicalContext.Set("Entity", !String.IsNullOrEmpty(entityMessage) ? entityMessage : ""); + MappedDiagnosticsLogicalContext.Set("Webrequest", !String.IsNullOrEmpty(webrequest) ? webrequest : ""); + + if (AppLoggerConfig.NlogSentryConfig.NlogSentryIsEnable) + { + SentrySdk.WithScope(scope => + { + if (!String.IsNullOrEmpty(entityMessage)) + { + scope.SetTag("Entity", entityMessage); + } + + if (!String.IsNullOrEmpty(webrequest)) + { + scope.SetTag("Webrequest", webrequest); + } + + if (!String.IsNullOrEmpty(userLogin)) + { + scope.SetTag("UserLogin", userLogin); + } + + logger.Error(message); + }); + } + else logger.Error(message); + } + + public void LogException(Exception exception, string entityMessage = null, string webrequest = null, string userLogin = null) + { + //WriteLog(logger.Error, exception, entityMessage, webrequest, userLogin); + + MappedDiagnosticsLogicalContext.Set("Entity", !String.IsNullOrEmpty(entityMessage) ? entityMessage : ""); + MappedDiagnosticsLogicalContext.Set("Webrequest", !String.IsNullOrEmpty(webrequest) ? webrequest : ""); + + if (AppLoggerConfig.NlogSentryConfig.NlogSentryIsEnable) + { + SentrySdk.WithScope(scope => + { + if (!String.IsNullOrEmpty(entityMessage)) + { + scope.SetTag("Entity", entityMessage); + } + + if (!String.IsNullOrEmpty(webrequest)) + { + scope.SetTag("Webrequest", webrequest); + } + + if (!String.IsNullOrEmpty(userLogin)) + { + scope.SetTag("UserLogin", userLogin); + } + + logger.Error(exception); + }); + } + else logger.Error(exception); + } + + public void LogWarn(string message, string entityMessage = null, string webrequest = null, string userLogin = null) + { + //WriteLog(logger.Warn, message, entityMessage, webrequest, userLogin); + + MappedDiagnosticsLogicalContext.Set("Entity", !String.IsNullOrEmpty(entityMessage) ? entityMessage : ""); + MappedDiagnosticsLogicalContext.Set("Webrequest", !String.IsNullOrEmpty(webrequest) ? webrequest : ""); + + if (AppLoggerConfig.NlogSentryConfig.NlogSentryIsEnable) + { + SentrySdk.WithScope(scope => + { + if (!String.IsNullOrEmpty(entityMessage)) + { + scope.SetTag("Entity", entityMessage); + } + + if (!String.IsNullOrEmpty(webrequest)) + { + scope.SetTag("Webrequest", webrequest); + } + + if (!String.IsNullOrEmpty(userLogin)) + { + scope.SetTag("UserLogin", userLogin); + } + + logger.Warn(message); + }); + } + else logger.Warn(message); + } + + public void LogInfo(string message, string entityMessage = null, string webrequest = null, string userLogin = null) + { + //WriteLog(logger.Info, message, entityMessage, webrequest, userLogin); + MappedDiagnosticsLogicalContext.Set("Entity", !String.IsNullOrEmpty(entityMessage) ? entityMessage : ""); + MappedDiagnosticsLogicalContext.Set("Webrequest", !String.IsNullOrEmpty(webrequest) ? webrequest : ""); + + if (AppLoggerConfig.NlogSentryConfig.NlogSentryIsEnable) + { + SentrySdk.WithScope(scope => + { + if (!String.IsNullOrEmpty(entityMessage)) + { + scope.SetTag("Entity", entityMessage); + } + + if (!String.IsNullOrEmpty(webrequest)) + { + scope.SetTag("Webrequest", webrequest); + } + + if (!String.IsNullOrEmpty(userLogin)) + { + scope.SetTag("UserLogin", userLogin); + } + + logger.Info(message); + }); + } + else logger.Info(message); + } + } +} \ No newline at end of file diff --git a/HRD.AppLogger/NlogSentryConfig.cs b/HRD.AppLogger/NlogSentryConfig.cs new file mode 100644 index 0000000..39939b1 --- /dev/null +++ b/HRD.AppLogger/NlogSentryConfig.cs @@ -0,0 +1,29 @@ +using NLog; +using Sentry; + +namespace HRD.AppLogger +{ + public class NlogSentryConfig + { + public bool AttachStacktrace { get; set; } = false; + public string Dsn { get; set; } + + // + // Summary: + // Determines whether or not to include event-level data as data in breadcrumbs + // for future errors. Defaults to false. + public bool IncludeEventDataOnBreadcrumbs { get; set; } = false; + + // Minimum log level to be included in the breadcrumb. Defaults to LogLevel.Info. + public LogLevel MinimumBreadcrumbLevel { get; set; } = LogLevel.Warn; + + // + // Summary: + // Minimum log level for events to trigger a send to Sentry. Defaults to LogLevel.Error. + public LogLevel MinimumEventLevel { get; set; } = LogLevel.Warn; + + public bool NlogSentryIsEnable { get; set; } + public bool SendDefaultPii { get; set; } = false; + public User? SentryUser { get; set; } + } +} \ No newline at end of file diff --git a/HRD.LDAPService/HRD.LDAPService.csproj b/HRD.LDAPService/HRD.LDAPService.csproj new file mode 100644 index 0000000..561ff4a --- /dev/null +++ b/HRD.LDAPService/HRD.LDAPService.csproj @@ -0,0 +1,24 @@ + + + + net7.0 + HRD.LDAPService + Valeri Bojarski + Hensel Recycling GmbH + 1.4.6 + Json Web Token (JWT) & LDAP user authentication + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/HRD.LDAPService/JWT/HttpErrorDetails.cs b/HRD.LDAPService/JWT/HttpErrorDetails.cs new file mode 100644 index 0000000..6980369 --- /dev/null +++ b/HRD.LDAPService/JWT/HttpErrorDetails.cs @@ -0,0 +1,21 @@ +using Newtonsoft.Json; + +namespace HRD.LDAPService.JWT +{ + public class HttpErrorDetails + { + public HttpErrorDetails(int statusCode, string message) + { + StatusCode = statusCode; + Message = message; + } + + public string Message { get; set; } + public int StatusCode { get; set; } + + public override string ToString() + { + return JsonConvert.SerializeObject(this); + } + } +} \ No newline at end of file diff --git a/HRD.LDAPService/JWT/JWTAuthorizeAttribute.cs b/HRD.LDAPService/JWT/JWTAuthorizeAttribute.cs new file mode 100644 index 0000000..3936e66 --- /dev/null +++ b/HRD.LDAPService/JWT/JWTAuthorizeAttribute.cs @@ -0,0 +1,40 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using System; + +namespace HRD.LDAPService.JWT +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] + public class JWTAuthorizeAttribute : Attribute, IAuthorizationFilter + { + public void OnAuthorization(AuthorizationFilterContext context) + { + if (JwtTokenConfig.AktivateAuthorizationFilter) + { + bool isInWhiteList = false; + + //allow access with logn & pwd and without Authorization token + var path = context?.HttpContext.Request.Path.Value; + if (!string.IsNullOrEmpty(path)) + { + if (JwtTokenConfig.IsInBlackList(path)) + { + context.Result = new JsonResult(new { message = $"Unauthorized access. Path is in a blacklist: '${path}'" }) { StatusCode = StatusCodes.Status403Forbidden }; + } + + isInWhiteList = JwtTokenConfig.IsInWhiteList(path); + + if (!isInWhiteList) + { //need jwt check + var check = (string)context.HttpContext.Items[JwtGlobals.HttpContextItem_IsValidHenselToken]; + if (check == null) + { + context.Result = new JsonResult(new { message = $"Unauthorized access. Path: '${path}'" }) { StatusCode = StatusCodes.Status401Unauthorized }; + } + } + } + } + } + } +} \ No newline at end of file diff --git a/HRD.LDAPService/JWT/JWTAuthorizeVendorId.cs b/HRD.LDAPService/JWT/JWTAuthorizeVendorId.cs new file mode 100644 index 0000000..653c9dd --- /dev/null +++ b/HRD.LDAPService/JWT/JWTAuthorizeVendorId.cs @@ -0,0 +1,125 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace HRD.LDAPService.JWT +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] + public class JWTAuthorizeVendorId : Attribute, IAuthorizationFilter + { + public void OnAuthorization(AuthorizationFilterContext context) + { + if (JwtTokenConfig.AktivateAuthorizationFilter) + { + //allow access with logn & pwd and without Authorization token + var path = context?.HttpContext.Request.Path.Value; + if (!string.IsNullOrEmpty(path)) + { + if (JwtTokenConfig.IsInBlackList(path)) + { + context.Result = new JsonResult(new { message = $"Unauthorized access. Path is in a blacklist: '${path}'" }) { StatusCode = StatusCodes.Status403Forbidden }; + return; + } + + if (JwtTokenConfig.IsInWhiteList(path)) + { + return; + } + else //need jwt check + { + var check = (string)context.HttpContext.Items[JwtGlobals.HttpContextItem_IsValidHenselToken]; + if (check == null) + { + context.Result = new JsonResult(new { message = $"Unauthorized access. Path: '${path}'" }) { StatusCode = StatusCodes.Status401Unauthorized }; + return; + } + } + + var headerAuthorization = context.HttpContext.Request.Headers["Authorization"]; + + var authorizationType = headerAuthorization.FirstOrDefault()?.Split(" ").First(); + if (authorizationType == null) + { + context.Result = new JsonResult(new { message = $"Eror. Path: '${path}'" }) { StatusCode = StatusCodes.Status401Unauthorized }; + return; + } + var jwt = headerAuthorization.FirstOrDefault(); + + if (!JwtManager.IsValidatJwtTokenSubject(jwt)) + { + throw new UnauthorizedAccessException($"Not valid JWT"); + } + + LdapUser ldapUser = JwtManager.DecryptTokenAsLdapUser(jwt); + string ldapUserVendorId = ldapUser.GetExtendedAttributeValue("VendorId"); + if (string.IsNullOrEmpty(ldapUserVendorId)) + { + context.Result = new JsonResult(new { message = $"Vendor Id is empty. Path: '${path}'" }) { StatusCode = StatusCodes.Status401Unauthorized }; + return; + } + var syncIOFeature = context.HttpContext.Features.Get(); + if (syncIOFeature != null) + { + syncIOFeature.AllowSynchronousIO = true; + + var req = context.HttpContext.Request; + + req.EnableBuffering(); + + // read the body here as a workarond for the JSON parser disposing the stream + if (req.Body.CanSeek) + { + req.Body.Seek(0, SeekOrigin.Begin); + + // if body (stream) can seek, we can read the body to a string for logging purposes + using (var reader = new StreamReader( + req.Body, + encoding: Encoding.UTF8, + detectEncodingFromByteOrderMarks: false, + bufferSize: 8192, + leaveOpen: true)) + { + var jsonString = reader.ReadToEnd(); + var content = JsonConvert.DeserializeObject(jsonString); + if (content == null) + { + context.Result = new JsonResult(new { message = $"Unauthorized access. Can not deserialize the the Request: '${path}'" }) { StatusCode = StatusCodes.Status403Forbidden }; + } + + if (content?.Root != null && string.Equals(content?.Root?.Type.ToString(), "Array", StringComparison.InvariantCulture)) + { + List contentList = JsonConvert.DeserializeObject>(jsonString); + string jwtVendorId = contentList?.FirstOrDefault()?.vendorId; + if (string.IsNullOrEmpty(jwtVendorId) || ldapUserVendorId != jwtVendorId) + { + context.Result = new JsonResult(new { message = $"Vendor {ldapUserVendorId} is not equal to Vendor from Token {jwtVendorId} List. Path: '${path}'" }) { StatusCode = StatusCodes.Status401Unauthorized }; + return; + } + } + else + { + string jwtVendorId = content.vendorId; + if (string.IsNullOrEmpty(jwtVendorId) || ldapUserVendorId != jwtVendorId) + { + context.Result = new JsonResult(new { message = $"Vendor {ldapUserVendorId} is not equal to Vendor from Token {jwtVendorId}. Path: '${path}'" }) { StatusCode = StatusCodes.Status401Unauthorized }; + return; + } + } + } + + // Important! go back to beginning so json reader get's the whole thing + req.Body.Seek(0, SeekOrigin.Begin); + } + } + } + } + } + } +} \ No newline at end of file diff --git a/HRD.LDAPService/JWT/JWTCrypt.cs b/HRD.LDAPService/JWT/JWTCrypt.cs new file mode 100644 index 0000000..7d794f8 --- /dev/null +++ b/HRD.LDAPService/JWT/JWTCrypt.cs @@ -0,0 +1,31 @@ +namespace HRD.LDAPService.JWT +{ + public static class JWTCrypt + { + public static string GenerateHashPassword(string inputKey) + { + return BCrypt.Net.BCrypt.EnhancedHashPassword(inputKey, 11, BCrypt.Net.HashType.SHA512); + } + + public static bool VerifyHashPassword(string hashedPassword, string providedPassword) + { + return BCrypt.Net.BCrypt.Verify(providedPassword, hashedPassword, true, BCrypt.Net.HashType.SHA512); + } + + public static string SHA512(string input) + { + var bytes = System.Text.Encoding.UTF8.GetBytes(input); + using (var hash = System.Security.Cryptography.SHA512.Create()) + { + var hashedInputBytes = hash.ComputeHash(bytes); + + // Convert to text + // StringBuilder Capacity is 128, because 512 bits / 8 bits in byte * 2 symbols for byte + var hashedInputStringBuilder = new System.Text.StringBuilder(128); + foreach (var b in hashedInputBytes) + hashedInputStringBuilder.Append(b.ToString("X2")); + return hashedInputStringBuilder.ToString(); + } + } + } +} \ No newline at end of file diff --git a/HRD.LDAPService/JWT/JwtGlobals.cs b/HRD.LDAPService/JWT/JwtGlobals.cs new file mode 100644 index 0000000..5495cb0 --- /dev/null +++ b/HRD.LDAPService/JWT/JwtGlobals.cs @@ -0,0 +1,19 @@ +namespace HRD.LDAPService.JWT +{ + public static class JwtGlobals + { + public const string HttpContextItem_LdapUser = "ldapuser"; + public const string HttpContextItem_IsValidHenselToken = "IsValidHenselToken"; + + public const string CLAIM_DEPARTNENTID = "departmentid"; + public const string CLAIM_EXTENDETDEPARTNENTIDLIST = "extendetdepartmentidlist"; + + public const string CLAIM_ROLE = "role"; + + public const string ROLE_USER = "User"; + public const string ROLE_DEPARTMENTUSER = "DepartmentUser"; + public const string ROLE_DEPARTMENTMASTER = "DepartmentMaster"; + public const string ROLE_MASTER = "Master"; + public const string ROLE_ADMIN = "Admin"; + } +} \ No newline at end of file diff --git a/HRD.LDAPService/JWT/JwtManager.cs b/HRD.LDAPService/JWT/JwtManager.cs new file mode 100644 index 0000000..473b0c5 --- /dev/null +++ b/HRD.LDAPService/JWT/JwtManager.cs @@ -0,0 +1,355 @@ +using Microsoft.IdentityModel.Tokens; +using System; +using System.Collections.Generic; +using System.IdentityModel.Tokens.Jwt; +using System.Linq; +using System.Security.Claims; +using System.Text; + +namespace HRD.LDAPService.JWT +{ + public static class JwtManager + + { + private const string GlbExtendedAttributes = "ExtendedAttributes_"; + + public static LdapUser DecryptTokenAsLdapUser(string token) + { + if (string.IsNullOrEmpty(token)) { return default; } + //Check token with "Bearer" prefix + if (token.StartsWith("Bearer", StringComparison.InvariantCultureIgnoreCase)) + { + token = token.Split(" ").Last(); + } + if (string.IsNullOrEmpty(token)) { return default; } + + JwtSecurityToken jwtSecurityToken = DecryptToken(token); + if (jwtSecurityToken == null) { return default; } + + LdapUser ldapUser = ClaimsIdentityToLdapUser(jwtSecurityToken.Claims.ToList()); + if (ldapUser == null) + { + return default; + } + + ldapUser.Token = token; + + return ldapUser; + } + + public static JwtSecurityToken DecryptToken(string token) + { + var tokenHandler = new JwtSecurityTokenHandler(); + var key = Encoding.ASCII.GetBytes(JwtTokenConfig.Secret); + try + { + tokenHandler.ValidateToken(token, new TokenValidationParameters + { + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey(key), + ValidateIssuer = false, + ValidateAudience = false, + ClockSkew = TimeSpan.FromSeconds(60) // set clockskew to zero so tokens expire exactly at token expiration time + }, out SecurityToken validatedToken); + + var jwtToken = (JwtSecurityToken)validatedToken; + return jwtToken; + } + //IDX10223: Lifetime validation failed. The token is expired. ValidTo: 'System.DateTime', Current time: 'System.DateTime'. + catch (SecurityTokenExpiredException ex) + { + throw ex; + } + catch (Exception ex) + { + // return null if validation fails + throw ex; + } + } + + public static LdapUser RenewLdapUserWithJwtToken(string token) + { + LdapUser renewLdapUser = null; + try + { + if (string.IsNullOrEmpty(token)) + { + throw new ArgumentNullException($"Token is missing!"); + } + + renewLdapUser = LdapAuthenticationService.RenewIdentity(token); + if (renewLdapUser is null) + { + throw new Exception($"Can't renew from token!"); + } + + if (!renewLdapUser.IsValidatCredentials) + { + throw new Exception($"Invalid credentials!"); + } + + if (!renewLdapUser.Enabled) + { + throw new Exception($"Ldap-User is disabled!"); + } + + (string newtoken, DateTime newExpiredOn) = CreateToken(renewLdapUser); + renewLdapUser.Token = newtoken; + renewLdapUser.JwtExpiredOn = newExpiredOn; + + if (!renewLdapUser.IsValid()) + { + throw new Exception($"Ldapuser is not valid!"); + } + + return renewLdapUser; + } + catch (Exception ex) + { + throw ex; + } + } + + public static LdapUser RenewLdapUserWithJwtToken(LdapUser ldapUser) + { + LdapUser renewLdapUser = null; + try + { + if (string.IsNullOrEmpty(ldapUser?.Token)) + { + throw new Exception($"Token is missing (Login:{ldapUser.LoginName})"); + } + + renewLdapUser = LdapAuthenticationService.RenewIdentity(ldapUser); + if (renewLdapUser is null) + { + return default; + } + + //if (!ldapUser.IsValidatCredentials) + //{ + // ldapUser.Token = string.Empty; + // return false; + //} + + if (!renewLdapUser.Enabled) + { + renewLdapUser.Token = string.Empty; + return renewLdapUser; + } + + var tokenHandler = new JwtSecurityTokenHandler(); + var key = Encoding.ASCII.GetBytes(JwtTokenConfig.Secret); + var claims = CreateClaimsIdentity(renewLdapUser); + + var tokenDescriptor = new SecurityTokenDescriptor + { + Subject = claims, + Expires = DateTime.UtcNow.AddMinutes(JwtTokenConfig.ExpirationInMin), + SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) + }; + var token = tokenHandler.CreateToken(tokenDescriptor); + ldapUser.Token = tokenHandler.WriteToken(token); + ldapUser.JwtExpiredOn = token.ValidTo; + if (renewLdapUser.IsValid()) + { + return renewLdapUser; + } + + return default; + } + catch (Exception ex) + { + throw ex; + } + } + + public static bool GenerateLdapUserWithJwtToken(LdapUser ldapUser) + { + try + { + if (!LdapAuthenticationService.CheckAndUpdateIdentityWithPassword(ldapUser)) + { + return false; + } + + if (!ldapUser.IsValidatCredentials) + { + ldapUser.Token = string.Empty; + return false; + } + + if (!ldapUser.Enabled) + { + ldapUser.Token = string.Empty; + return false; + } + + (string token, DateTime jwtExpiredOn) = CreateToken(ldapUser); + ldapUser.Token = token; + ldapUser.JwtExpiredOn = jwtExpiredOn; + return ldapUser.IsValid(); + } + catch (Exception ex) + { + throw ex; + } + } + + public static string GenerateHash(string password) + { + return JWTCrypt.SHA512(password); + } + + private static (string, DateTime) CreateToken(LdapUser ldapUser) + { + var tokenHandler = new JwtSecurityTokenHandler(); + var key = Encoding.ASCII.GetBytes(JwtTokenConfig.Secret); + var claims = CreateClaimsIdentity(ldapUser); + + var tokenDescriptor = new SecurityTokenDescriptor + { + Subject = claims, + Expires = DateTime.UtcNow.AddMinutes(JwtTokenConfig.ExpirationInMin), + SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) + }; + var token = tokenHandler.CreateToken(tokenDescriptor); + return (tokenHandler.WriteToken(token), token.ValidTo); + } + + public static bool IsValidatJwtTokenSubject(string token) + { + if (string.IsNullOrEmpty(token)) + { + return false; + } + + token = token.Trim(); + + if (token.IndexOf(" ", StringComparison.InvariantCultureIgnoreCase) > 0) + { + if (token.StartsWith("Bearer", StringComparison.InvariantCultureIgnoreCase)) //token with "Bearer" prefix + { + token = token.Split(" ").Last(); + } + else + { + token = token.Split(" ").First(); + } + } + + try + { + var jwtToken = DecryptToken(token); + return !String.IsNullOrEmpty(jwtToken?.Subject); //Loginname + } + catch (Exception ex) + { + throw ex; + } + } + + private static LdapUser ClaimsIdentityToLdapUser(List claims) + { + LdapUser user = new LdapUser(""); + foreach (var claim in claims) + { + switch (claim.Type) + { + case JwtRegisteredClaimNames.Sub: + user.LoginName = claim.Value; + break; + + case JwtRegisteredClaimNames.Email: + user.Email = claim.Value; + break; + + case JwtRegisteredClaimNames.NameId: + { + if (int.TryParse(claim.Value, out int id)) + { + user.UserId = id; + } + } + break; + + case JwtRegisteredClaimNames.Jti: + { + if (Guid.TryParse(claim.Value, out Guid g)) + { + user.LdapGuid = g; + } + } + break; + + case JwtGlobals.CLAIM_DEPARTNENTID: + user.DepartmentId = int.Parse(claim.Value); + break; + + case JwtGlobals.CLAIM_EXTENDETDEPARTNENTIDLIST: + user.ExtendedDepartmentIdList = claim.Value; + break; + + case JwtGlobals.CLAIM_ROLE: + user.AddRole(claim.Value); + break; + + case JwtRegisteredClaimNames.Exp: + { + //#pragma warning disable CA1305 // Specify IFormatProvider + var expValue = Convert.ToInt32(claim.Value); + //#pragma warning restore CA1305 // Specify IFormatProvider + DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(expValue); + user.JwtExpiredOn = dateTimeOffset.UtcDateTime; + } + break; + + case var s when claim.Type.StartsWith(GlbExtendedAttributes): + var strKey = claim.Type.Substring(GlbExtendedAttributes.Length, claim.Type.Length - GlbExtendedAttributes.Length); + user.ExtendedAttributesList.Add(new KeyValuePair(strKey, claim.Value)); + break; + + default: + break; + } + } + + return user; + } + + private static ClaimsIdentity CreateClaimsIdentity(LdapUser user) + { + ClaimsIdentity claimsIdentity = new ClaimsIdentity(); + + List claims = new List + { + CreateClaim(JwtRegisteredClaimNames.Sub, user.LoginName), + CreateClaim(JwtRegisteredClaimNames.NameId, user.UserId), + CreateClaim(JwtRegisteredClaimNames.Email, user.Email), + CreateClaim(JwtGlobals.CLAIM_DEPARTNENTID, user.DepartmentId), + CreateClaim(JwtGlobals.CLAIM_EXTENDETDEPARTNENTIDLIST, user.ExtendedDepartmentIdList) + }; + + user.RoleList.ForEach(role => claims.Add( + CreateClaim(ClaimTypes.Role, role.Role) + )); + + user.ExtendedAttributesList.ForEach(item => claims.Add( + CreateClaim($"{GlbExtendedAttributes}{item.Key}", item.Value) + )); + + claimsIdentity.AddClaims(claims); + return claimsIdentity; + } + + private static Claim CreateClaim(string claimName, int claimValue) + { + return new Claim(claimName, string.IsNullOrEmpty($"{claimValue}") ? string.Empty : $"{claimValue}"); + } + + private static Claim CreateClaim(string claimName, string claimValue) + { + return new Claim(claimName, string.IsNullOrEmpty(claimValue) ? string.Empty : claimValue); + } + } +} \ No newline at end of file diff --git a/HRD.LDAPService/JWT/JwtMiddleware.cs b/HRD.LDAPService/JWT/JwtMiddleware.cs new file mode 100644 index 0000000..8035e83 --- /dev/null +++ b/HRD.LDAPService/JWT/JwtMiddleware.cs @@ -0,0 +1,97 @@ +using Microsoft.AspNetCore.Http; +using Newtonsoft.Json; +using System; +using System.Linq; +using System.Net.Mime; +using System.Threading.Tasks; + +namespace HRD.LDAPService.JWT +{ + public class JwtMiddleware + { + private readonly RequestDelegate _next; + + public JwtMiddleware(RequestDelegate next) + { + _next = next; + } + +#pragma warning disable AMNF0001 // Asynchronous method name is not ending with 'Async' + + public async Task Invoke(HttpContext httpContext) +#pragma warning restore AMNF0001 // Asynchronous method name is not ending with 'Async' + { + if (httpContext == null) + { + throw new ArgumentNullException($"Jwt {httpContext} is null"); + } + + if (JwtTokenConfig.AktivateAuthorizationFilter) + { + var path = httpContext.Request.Path.Value; + if (!string.IsNullOrEmpty(path)) + { + if (JwtTokenConfig.IsInBlackList(path)) + { + httpContext.Response.ContentType = MediaTypeNames.Application.Json; + httpContext.Response.StatusCode = StatusCodes.Status403Forbidden; + var responseJson = JsonConvert.SerializeObject($"Path is in a blacklist: '${path}'"); + await httpContext.Response.WriteAsync(responseJson).ConfigureAwait(false); + return; + } + + if (JwtTokenConfig.IsInWhiteList(path)) + { + await _next(httpContext).ConfigureAwait(false); // calling next middleware + return; + } + } + } + var headerAuthorization = httpContext.Request.Headers["Authorization"]; + + var authorizationType = headerAuthorization.FirstOrDefault()?.Split(" ").First(); + if (authorizationType == null) + { + await _next(httpContext).ConfigureAwait(false); // calling next middleware + return; + } + var jwt = headerAuthorization.FirstOrDefault(); + + //Check token + if (JwtManager.IsValidatJwtTokenSubject(jwt)) + { + var user = JwtManager.DecryptTokenAsLdapUser(jwt); + if (user == default) + { + httpContext.Response.ContentType = MediaTypeNames.Application.Json; + httpContext.Response.StatusCode = StatusCodes.Status401Unauthorized; + var responseJson = JsonConvert.SerializeObject($"Failed to decode JWT. The User was not valid"); + await httpContext.Response.WriteAsync(responseJson).ConfigureAwait(false); + return; + } + + httpContext.Items[JwtGlobals.HttpContextItem_IsValidHenselToken] = "true"; + httpContext.Items[JwtGlobals.HttpContextItem_LdapUser] = user; + await _next(httpContext).ConfigureAwait(false); // calling next middleware + return; + } + else + { + httpContext.Response.ContentType = MediaTypeNames.Application.Json; + httpContext.Response.StatusCode = StatusCodes.Status401Unauthorized; + var responseJson = JsonConvert.SerializeObject($"The JWT was not valid."); + await httpContext.Response.WriteAsync(responseJson).ConfigureAwait(false); + return; + } + } + + private string GetAction(HttpContext httpContext) + { + if (httpContext.Request.Headers.ContainsKey("action")) + { + return httpContext.Request.Headers["action"].ToString(); + } + return string.Empty; + } + } +} \ No newline at end of file diff --git a/HRD.LDAPService/JWT/JwtMiddlewareExtensions.cs b/HRD.LDAPService/JWT/JwtMiddlewareExtensions.cs new file mode 100644 index 0000000..5d2d172 --- /dev/null +++ b/HRD.LDAPService/JWT/JwtMiddlewareExtensions.cs @@ -0,0 +1,69 @@ +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.IdentityModel.Tokens; +using System; +using System.Security.Claims; +using System.Text; + +namespace HRD.LDAPService.JWT +{ + public static class JwtMiddlewareExtensions + { + public static IApplicationBuilder UseJwtMiddleware(this IApplicationBuilder builder) + { + return builder.UseMiddleware(); + } + + public static void ConfigureJWT(this IServiceCollection services, JwtMiddlewareOptions options) + { + if (options == null) + { + throw new ArgumentNullException(nameof(options)); + } + + JwtTokenConfig.DeaktivateLDAP = options.DeaktivateLDAP; //if true => use login + pwd only + + JwtTokenConfig.Secret = options.Secret; + JwtTokenConfig.Issuer = options.Issuer; + JwtTokenConfig.Audience = options.Audience; + JwtTokenConfig.JwtRoleList = options.JwtRoleList; + JwtTokenConfig.ExpirationInMin = options.ExpirationInMin; + JwtTokenConfig.AktivateAuthorizationFilter = options.AktivateAuthorizationFilter; + JwtTokenConfig.AuthorizationFilterWhitelistPath = options.AuthorizationFilterWhitelistPath; + JwtTokenConfig.AuthorizationFilterBlacklistPath = options.AuthorizationFilterBlacklistPath; + + //Authentication + services.AddAuthentication(options => + { + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultSignInScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + }) + //JwtBearer + .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => + { + options.RequireHttpsMetadata = true; + options.SaveToken = true; + options.TokenValidationParameters = new TokenValidationParameters + { + ValidateIssuer = true, + ValidIssuer = JwtTokenConfig.Issuer, //JWT-Site + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(JwtTokenConfig.Secret)), + ValidAudience = JwtTokenConfig.Audience, + ValidateAudience = true, //App-Site + ValidateLifetime = true, + ClockSkew = TimeSpan.FromMinutes(1), + NameClaimType = ClaimTypes.NameIdentifier + }; + }); + + //Authorization + services.AddAuthorization(authopt => + { + authopt.AddPolicy("UserMustHaveRole", polBuilder => polBuilder.RequireClaim(ClaimTypes.Role)); + }); + } + } +} \ No newline at end of file diff --git a/HRD.LDAPService/JWT/JwtMiddlewareOptions.cs b/HRD.LDAPService/JWT/JwtMiddlewareOptions.cs new file mode 100644 index 0000000..3df9693 --- /dev/null +++ b/HRD.LDAPService/JWT/JwtMiddlewareOptions.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; + +namespace HRD.LDAPService.JWT +{ + public class JwtMiddlewareOptions + { + public string Secret { get; set; } + + public int ExpirationInMin { get; set; } = 60 * 24 * 28; //28 Tage + public List JwtRoleList { get; set; } + public List AuthorizationFilterWhitelistPath { get; set; } + public List AuthorizationFilterBlacklistPath { get; set; } + public bool AktivateAuthorizationFilter { get; set; } = true; + public string Issuer { get; set; } + public string Audience { get; set; } + public bool DeaktivateLDAP { get; set; } + } +} \ No newline at end of file diff --git a/HRD.LDAPService/JWT/JwtRole.cs b/HRD.LDAPService/JWT/JwtRole.cs new file mode 100644 index 0000000..229a6e0 --- /dev/null +++ b/HRD.LDAPService/JWT/JwtRole.cs @@ -0,0 +1,32 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace HRD.LDAPService +{ + public class JwtRole + { + private string role; + private string _group; + + public JwtRole(string role) : this(role, string.Empty) + { } + + public JwtRole(string role, string group) + { + Role = role; + Group = group; + } + + [Required] + public string Role { get => role; set => role = value; } + + [Required] + public string Group + { + get => _group; + + //"dhr/" prefix should be removed + set => _group = string.IsNullOrEmpty(value) ? string.Empty : value.Replace(@"DHR\", "", StringComparison.InvariantCultureIgnoreCase); + } + } +} \ No newline at end of file diff --git a/HRD.LDAPService/JWT/JwtTokenConfig.cs b/HRD.LDAPService/JWT/JwtTokenConfig.cs new file mode 100644 index 0000000..1905476 --- /dev/null +++ b/HRD.LDAPService/JWT/JwtTokenConfig.cs @@ -0,0 +1,49 @@ +using System.Collections.Generic; + +namespace HRD.LDAPService.JWT +{ + public static class JwtTokenConfig + { + private static string secret; + + public static int ExpirationInMin { get; set; } + public static string Secret { get; set; } + public static string Issuer { get; internal set; } + public static string Audience { get; internal set; } + +#warning use internal setter + public static List JwtRoleList { get; set; } = new List(); + public static List AuthorizationFilterWhitelistPath { get; set; } + public static List AuthorizationFilterBlacklistPath { get; set; } + public static bool AktivateAuthorizationFilter { get; set; } + public static bool DeaktivateLDAP { get; set; } + + public static bool IsInWhiteList(string path) + { + if (string.IsNullOrEmpty(path)) { return false; } + foreach (var item in JwtTokenConfig.AuthorizationFilterWhitelistPath) + { + if (path.Contains(item, System.StringComparison.InvariantCultureIgnoreCase)) + { + return true; + } + } + + return false; + } + + public static bool IsInBlackList(string path) + { + if (string.IsNullOrEmpty(path)) { return false; } + foreach (var item in JwtTokenConfig.AuthorizationFilterBlacklistPath) + { + if (path.Contains(item, System.StringComparison.InvariantCultureIgnoreCase)) + { + return true; + } + } + + return false; + } + } +} \ No newline at end of file diff --git a/HRD.LDAPService/Ldap/EN_LdapRoleListFilter.cs b/HRD.LDAPService/Ldap/EN_LdapRoleListFilter.cs new file mode 100644 index 0000000..a6692e2 --- /dev/null +++ b/HRD.LDAPService/Ldap/EN_LdapRoleListFilter.cs @@ -0,0 +1,9 @@ +namespace HRD.LDAPService +{ + public enum EN_LdapRoleListFilter + { + All = 1, + OnlyRoleList = 2, + OnlyWebAppRoleList = 3 + } +} \ No newline at end of file diff --git a/HRD.LDAPService/Ldap/LdapAuthenticationService.cs b/HRD.LDAPService/Ldap/LdapAuthenticationService.cs new file mode 100644 index 0000000..e160c34 --- /dev/null +++ b/HRD.LDAPService/Ldap/LdapAuthenticationService.cs @@ -0,0 +1,213 @@ +using HRD.LDAPService.JWT; +using System; +using System.DirectoryServices.AccountManagement; +using System.Linq; + +namespace HRD.LDAPService +{ + public static class LdapAuthenticationService + { + private const string LDAP_DOMAIN = "dhr.local"; + + private static UserPrincipal GetUserPrincipal(string loginName, PrincipalContext principalContext) + { + try + { + UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(principalContext, IdentityType.SamAccountName, loginName); + if (userPrincipal == null) + { + userPrincipal = UserPrincipal.FindByIdentity(principalContext, loginName); + if (userPrincipal == null) + { + throw new Exception($"Can't find an user by name: '{loginName}'"); + } + } + + return userPrincipal; + } + catch (Exception ex) + { + throw new Exception($"Login failed wrong user credentials '{loginName}'", ex); + } + } + + /// + /// Returns a User without LDAP user authentication + /// + /// + /// + public static LdapUser RenewIdentity(string token) + { + if (string.IsNullOrEmpty(token)) { throw new ArgumentNullException("Token is empty!"); } + + try + { + LdapUser ldapUserFromToken = JwtManager.DecryptTokenAsLdapUser(token); + if (ldapUserFromToken == default) + { + throw new Exception($"Wrong token"); + } + + using PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, LDAP_DOMAIN); + ldapUserFromToken.IsValidatCredentials = true; + UpdateLdapUserFromPrincipalContext(ref ldapUserFromToken, principalContext); + return ldapUserFromToken; + } + catch (Exception ex) + { + throw new Exception($"Renew failed", ex); + } + } + + /// + /// Returns a User without LDAP user authentication + /// + /// + /// + public static LdapUser RenewIdentity(LdapUser ldapUser) + { + if (ldapUser == default) { return default; } + try + { + if (String.IsNullOrEmpty(ldapUser.LoginName)) + { + throw new Exception($"Renew Login failed empty user Loginname"); + } + + LdapUser ldapUserFromToken = JwtManager.DecryptTokenAsLdapUser(ldapUser.Token); + if (ldapUserFromToken == default) + { + throw new Exception($"Wrong token"); + } + + if (!string.Equals(ldapUserFromToken.LoginName, ldapUser.LoginName, StringComparison.OrdinalIgnoreCase)) + { + throw new Exception($"Loginname and Token-Loginname are not the same"); + } + + if (ldapUser.IsRealLDAPUser) + { + ldapUserFromToken.IsRealLDAPUser = ldapUser.IsRealLDAPUser; + using PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, LDAP_DOMAIN); + ldapUser.IsValidatCredentials = true; + UpdateLdapUserFromPrincipalContext(ref ldapUserFromToken, principalContext); + } + else + { + ldapUserFromToken.IsRealLDAPUser = false; + ldapUserFromToken.AddPasswordHash(ldapUser.PasswordHash); + + if (!string.Equals(ldapUserFromToken.PasswordHashShort, ldapUser.PasswordHashShort, StringComparison.OrdinalIgnoreCase)) + { + throw new Exception($"PasswordHashShort and Token-PasswordHashShortare not the same"); + } + + ldapUserFromToken.IsValidatCredentials = !string.IsNullOrEmpty(ldapUserFromToken.PasswordHash); + ldapUserFromToken.Enabled = ldapUserFromToken.IsValidatCredentials; + + ldapUserFromToken.BadLogonCount = ldapUserFromToken.IsValidatCredentials ? 0 : ldapUserFromToken.BadLogonCount + 1; + + //ldapUserFromToken.IsAccountLockedOut = ; + //ldapUserFromToken.LdapName = ; + //ldapUserFromToken.LdapSurname = ; + //ldapUserFromToken.LdapGuid = ; + //ldapUserFromToken.Email = ; + //ldapUserFromToken.AccountLockoutTime = ; + } + return ldapUserFromToken; + } + catch (Exception ex) + { + throw new Exception($"Login failed wrong user credentials '{ldapUser.LoginName}'", ex); + } + } + + /// + /// Returns a User after LDAP user authentication + /// + /// + /// + public static bool CheckAndUpdateIdentityWithPassword(LdapUser ldapUser) + { + if (ldapUser == default) { return false; } + try + { + if (String.IsNullOrEmpty(ldapUser.LoginName)) + { + throw new Exception($"Login failed wrong user Loginname"); + } + + if (!JwtTokenConfig.DeaktivateLDAP) + { + ldapUser.IsRealLDAPUser = true; + using var principalContext = new PrincipalContext(ContextType.Domain, LDAP_DOMAIN); + //Check PWD + ldapUser.IsValidatCredentials = principalContext.ValidateCredentials(ldapUser.LoginName, ldapUser.Password); + + UpdateLdapUserFromPrincipalContext(ref ldapUser, principalContext); + } + else + { + ldapUser.IsRealLDAPUser = false; + + //ldapUser.AddPasswordHash(JWTCrypt.GenerateHashPassword(ldapUser.Password)); + var hash = JWTCrypt.SHA512(ldapUser.Password); + ldapUser.AddPasswordHash(hash); + ldapUser.IsValidatCredentials = !string.IsNullOrEmpty(ldapUser.PasswordHash); + if (ldapUser.IsValidatCredentials) + { + ldapUser.Enabled = true; + ldapUser.BadLogonCount = 0; + ldapUser.LastBadPasswordAttempt = null; + } + else + { + ldapUser.Enabled = false; + ldapUser.BadLogonCount = +1; + ldapUser.LastBadPasswordAttempt = DateTime.UtcNow; + } + + //ldapUser.IsAccountLockedOut = ; + //ldapUser.LdapName = ; + //ldapUser.LdapSurname = ; + //ldapUser.LdapGuid = ; + //ldapUser.Email = ; + //ldapUser.AccountLockoutTime = ; + } + + return true; + } + catch (Exception ex) + { + ldapUser.IsValidatCredentials = false; + throw new Exception($"Login failed wrong user credentials '{ldapUser.LoginName}'", ex); + } + } + + private static void UpdateLdapUserFromPrincipalContext(ref LdapUser ldapUser, PrincipalContext principalContext) + { + UserPrincipal userPrincipal = GetUserPrincipal(ldapUser.LoginName, principalContext); + if (userPrincipal == default) + { + throw new Exception($"Renew Login failed wrong user credentials '{ldapUser.LoginName}'"); + } + + ldapUser.IsAccountLockedOut = userPrincipal.IsAccountLockedOut(); + ldapUser.BadLogonCount = userPrincipal.BadLogonCount; + ldapUser.Enabled = userPrincipal.Enabled ?? false; + ldapUser.LastBadPasswordAttempt = userPrincipal.LastBadPasswordAttempt; + ldapUser.LdapName = userPrincipal.Name; + ldapUser.LdapSurname = userPrincipal.Surname; + ldapUser.LdapGuid = userPrincipal.Guid; + ldapUser.Email = userPrincipal.EmailAddress; + ldapUser.AccountLockoutTime = userPrincipal.AccountLockoutTime; + + ldapUser.RoleList = ldapUser.RoleList.Union(JWT.JwtTokenConfig.JwtRoleList).ToList(); + + if (ldapUser.RoleList?.Count > 0) + { + ldapUser = userPrincipal.Context.CheckAndAddGroupMembers(userPrincipal, ldapUser); + } + } + } +} \ No newline at end of file diff --git a/HRD.LDAPService/Ldap/LdapExtensions.cs b/HRD.LDAPService/Ldap/LdapExtensions.cs new file mode 100644 index 0000000..d0bbaf9 --- /dev/null +++ b/HRD.LDAPService/Ldap/LdapExtensions.cs @@ -0,0 +1,52 @@ +using HRD.LDAPService.JWT; +using System; +using System.Collections.Generic; +using System.DirectoryServices.AccountManagement; +using System.Linq; + +namespace HRD.LDAPService +{ + public static class LdapExtensions + { + public static LdapUser CheckAndAddGroupMembers(this PrincipalContext context, UserPrincipal userPrincipal, LdapUser ldapUser) + { + if (context == null || userPrincipal == null || ldapUser == null) + { + throw new Exception($"UserPrincipal failed"); + } + + if (ldapUser.RoleList?.Count == 0) + { + ldapUser.RoleList = new List(); + return ldapUser; + } + + try + { + List userGroupList = userPrincipal.GetGroups().ToList(); // all groups of which the user is a direct member + List jwtRoleList = ldapUser.RoleList; //keep all possible Roles of the user + List fullRoleList = new List(); + fullRoleList = fullRoleList.Union(jwtRoleList).ToList(); //add Roles from backend + fullRoleList = fullRoleList.Union(JwtTokenConfig.JwtRoleList).ToList(); //add Roles from JwtTokenConfig.JwtRoleList + + ldapUser.RoleList = new List(); + + if (fullRoleList.Count > 0) + { + foreach (JwtRole jwtRole in jwtRoleList) + { + if (userGroupList.Exists(userGroup => userGroup.Name == jwtRole.Group)) + { + ldapUser.AddRole(jwtRole.Role); + } + } + } + } + catch (Exception ex) + { + throw ex; + } + return ldapUser; + } + } +} \ No newline at end of file diff --git a/HRD.LDAPService/Ldap/LdapGlobals.cs b/HRD.LDAPService/Ldap/LdapGlobals.cs new file mode 100644 index 0000000..16a1941 --- /dev/null +++ b/HRD.LDAPService/Ldap/LdapGlobals.cs @@ -0,0 +1,22 @@ +namespace HRD.LDAPService +{ + public static class LdapGlobals + { + private static bool _isLive; + public static bool LDAP_WebAppGroup_Is_Live { get => _isLive; set => _isLive = value; } + + public const string LDAP_WINDREAM = "Windream_"; + + public const string LDAP_DOMAIN = "dhr.local"; + + public const string LDAP_PATH_EDM = "OU=DMS,OU=Gruppen,OU=DHDEAB,DC=dhr,DC=local"; + public const string LDAP_PATH_WEBAPPS = "OU=Web-Apps,OU=Gruppen,OU=DHDEAB,DC=dhr,DC=local"; + + public const string LDAP_EDMUser_Prefix = "GG_EDMUser_Group"; + public const string LDAP_EDMAdmin_Prefix = "GG_EDMAdmin_Group"; + + public const string LDAP_EDM_Prefix = "GG_EDM"; + public const string LDAP_WebAppp_Prefix = "GG_WebApp"; + public const string LDAP_Prefix_Test = "__Test"; + } +} \ No newline at end of file diff --git a/HRD.LDAPService/Ldap/LdapManager.cs b/HRD.LDAPService/Ldap/LdapManager.cs new file mode 100644 index 0000000..549f446 --- /dev/null +++ b/HRD.LDAPService/Ldap/LdapManager.cs @@ -0,0 +1,265 @@ +using System; +using System.Collections.Generic; +using System.DirectoryServices.AccountManagement; +using System.Linq; + +namespace HRD.LDAPService +{ + public static class LdapManager + { + public static bool AD_AddUserloginToGroup(string userLogin, string group4User) + { + string groupName = GetFullGroupName(group4User); + + try + { + using (PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, LdapGlobals.LDAP_DOMAIN)) + { + UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(principalContext, IdentityType.SamAccountName, userLogin); + if (userPrincipal == default) + { + throw new Exception($". Can't find the UserPrincipal by userId:{userLogin}"); + } + List userGroupList = userPrincipal.GetGroups().ToList(); // all groups of which the user is a direct member + if (userGroupList == default) + { + throw new Exception($". Can't find the userGroupList; userId:{userLogin}"); + } + + GroupPrincipal userGroup = userGroupList.Find(x => string.Equals(x.Name, groupName, StringComparison.OrdinalIgnoreCase)) as GroupPrincipal; + if (userGroup != default) + { + return true; //is already here + } + else + { + GroupPrincipal group = GroupPrincipal.FindByIdentity(principalContext, IdentityType.Name, groupName); + if (group == default) //try to create a group + { + if (CreateAdGroup(groupName)) + { + group = GroupPrincipal.FindByIdentity(principalContext, IdentityType.Name, groupName); + } + } + + if (group == default) + { + throw new Exception($". Can't create the AD-group: \"{groupName}\""); + } + group.Members.Add(principalContext, IdentityType.SamAccountName, userLogin); + group.Save(); + } + } + + return true; + } + catch (Exception ex) + { + throw; + } + } + + public static bool CheckAndCreateAdGroup(string adGroupName) + { + try + { + // set up domain context and binding to the OU=Web-Apps + var adPath = AD_GroupPath(adGroupName); + using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, LdapGlobals.LDAP_DOMAIN, adPath)) + { + var group = GroupPrincipal.FindByIdentity(ctx, IdentityType.Name, adGroupName); + if (group != null) + { + return true; + } + + // create a new group principal, give it a name + GroupPrincipal newGroup = new GroupPrincipal(ctx, adGroupName); + + // save the group + newGroup.Save(); + return true; + } + } + catch (Exception ex) + { + return false; + //throw; + } + } + + public static List GetAdUserLoginList4AdGroups(List adGroupNames) + { + if (adGroupNames == null) { return default; } + List result = new List(); + + foreach (var adGroupName in adGroupNames) + { + var list = GetAdUserLoginList4AdGroup(adGroupName); + result.AddRange(list); + } + + return result; + } + + public static List GetAdUserLoginList4AdGroup(string adGroupName) + { + try + { + List result = new List(); + // set up domain context and binding to the OU=Web-Apps + var adPath = AD_GroupPath(adGroupName); + using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, LdapGlobals.LDAP_DOMAIN, adPath)) + { + var group = GroupPrincipal.FindByIdentity(ctx, IdentityType.Name, adGroupName); + if (group == null) + { + throw new Exception($". Can't find the AD-group: \"{adGroupName}\""); + } + + result = group.Members.Select(x => x.SamAccountName).ToList(); + return result; + } + } + catch (Exception ex) + { + //_logger.LogException(ex, $"An error occurred while getting user for the AD-group {adGroupName}"); + return default; + //throw; + } + } + + public static bool CheckAndCreateAdGroups(List adGroupNames) + { + if (adGroupNames == null) { return false; } + + foreach (var adGroupName in adGroupNames) + { + if (!CheckAndCreateAdGroup(adGroupName)) + { + return false; + } + } + + return true; + } + + public static bool CreateAdGroup(string adGroupName) + { + try + { + // set up domain context and binding to the OU=TechWriters organizational unit in your company + var adPath = AD_GroupPath(adGroupName); + using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, LdapGlobals.LDAP_DOMAIN, adPath)) + { + // create a new group principal, give it a name + using (GroupPrincipal group = new GroupPrincipal(ctx, adGroupName)) + { + // optionally set additional properties on the newly created group here.... + + // save the group + group.Save(); + } + return true; + } + } + catch (Exception) + { + return false; + //throw; + } + } + + public static bool IsWindreamADGroup(string adGroupName) + { + return adGroupName.StartsWith(LdapGlobals.LDAP_EDM_Prefix, StringComparison.InvariantCultureIgnoreCase); + } + + public static bool IsWindreamSuffixGroup(string suffixGroupName) + { + return suffixGroupName.StartsWith(LdapGlobals.LDAP_WINDREAM, StringComparison.InvariantCultureIgnoreCase); + } + + public static bool IsWindreamAdminGroup(string suffixGroupName) + { + return suffixGroupName.StartsWith(LdapGlobals.LDAP_WINDREAM + "Admin", StringComparison.InvariantCultureIgnoreCase); + } + + public static bool IsWindreamUserGroup(string suffixGroupName) + { + return suffixGroupName.StartsWith(LdapGlobals.LDAP_WINDREAM + "User", StringComparison.InvariantCultureIgnoreCase); + } + + public static string AD_GroupPath(string adGroupName) + { + if (IsWindreamADGroup(adGroupName)) + { + return LdapGlobals.LDAP_PATH_EDM; + } + else + { + return LdapGlobals.LDAP_PATH_WEBAPPS; + } + } + + public static string GetFullGroupName(string groupNameSuffix) + { + //Mapping Windream_User => GG_EDMUser_Group_Live or GG_EDM__Test_User_Group + //Mapping Windream_Admin => GG_EDMAdmin_Group or GG_EDM__Test_Admin_Group + //Mapping Windream_Technik => GG_EDM_Technik or GG_EDM__Test_Technik + + var testPrefix = !LdapGlobals.LDAP_WebAppGroup_Is_Live ? LdapGlobals.LDAP_Prefix_Test : ""; + if (IsWindreamAdminGroup(groupNameSuffix)) + { + return LdapGlobals.LDAP_EDMAdmin_Prefix + testPrefix; + } + else if (IsWindreamUserGroup(groupNameSuffix)) + { + return LdapGlobals.LDAP_EDMUser_Prefix + testPrefix; + } + else + { + return (IsWindreamSuffixGroup(groupNameSuffix) ? LdapGlobals.LDAP_EDM_Prefix : LdapGlobals.LDAP_WebAppp_Prefix) + testPrefix + "_" + groupNameSuffix.Replace(LdapGlobals.LDAP_WINDREAM, ""); + } + } + + public static bool AD_RemoveUserFromGroup(string userId, string group4User) + { + string groupName = GetFullGroupName(group4User); + // secure that no windream user or admin can be deleted + if (groupName.Equals(LdapGlobals.LDAP_EDMUser_Prefix, StringComparison.CurrentCultureIgnoreCase) + || groupName.Equals(LdapGlobals.LDAP_EDMAdmin_Prefix, StringComparison.CurrentCultureIgnoreCase)) + { + return true; + } + try + { + using var principalContext = new PrincipalContext(ContextType.Domain, LdapGlobals.LDAP_DOMAIN); + UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(principalContext, IdentityType.SamAccountName, userId); + if (userPrincipal == default) + { + throw new Exception($". Can't find the UserPrincipal by userId: {userId}"); + } + List userGroupList = userPrincipal.GetGroups().ToList(); // all groups of which the user is a direct member + if (userGroupList == default) + { + throw new Exception($". Can't find the userGroupList; userId: {userId}"); + } + + GroupPrincipal group = userGroupList.Find(x => x.Name == groupName) as GroupPrincipal; + if (group == default) + { + return true; //the user is not in the group - nothing to do more + //throw new Exception($". Can't find the AD-group: \"{groupName}\""); + } + group.Members.Remove(principalContext, IdentityType.SamAccountName, userId); + group.Save(); + return true; + } + catch (Exception ex) + { + throw; + } + } + } +} \ No newline at end of file diff --git a/HRD.LDAPService/Ldap/LdapUser.cs b/HRD.LDAPService/Ldap/LdapUser.cs new file mode 100644 index 0000000..21ea5b2 --- /dev/null +++ b/HRD.LDAPService/Ldap/LdapUser.cs @@ -0,0 +1,268 @@ +using HRD.LDAPService.JWT; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text.Json.Serialization; + +namespace HRD.LDAPService +{ + public class LdapUser + { + private const string PASSWORD_HASH_SHORT = "PasswordHashShort"; + + public bool IsRealLDAPUser { get; set; } + + public LdapUser() + { + } + + public LdapUser(string loginName) + { + LoginName = loginName; + } + + public LdapUser(string loginname, int userId, string password, int departmentId, string extendedDepartmentIdList, List> extendedAttributesList = null) : base() + { + LoginName = loginname; + UserId = userId; + Password = password; + DepartmentId = departmentId; + ExtendedDepartmentIdList = extendedDepartmentIdList; + ExtendedAttributesList = extendedAttributesList == null ? new List>() : extendedAttributesList; + } + + public LdapUser(string loginname, int userId, string password) + { + LoginName = loginname; + UserId = userId; + Password = password; + } + + #region Ldap Fields + + public Guid? LdapGuid { get; internal set; } + public string LdapName { get; set; } + public string LdapSurname { get; set; } + + #endregion Ldap Fields + + public int DepartmentId { get; set; } + public bool IsValidatCredentials { get; set; } + + public string Email + { + get; set; // { return $"{LoginName}@hensel-recycling.com"; } + } + + public string ExtendedDepartmentIdList { get; set; } + public DateTime JwtExpiredOn { get; set; } + + [Required] + public string LoginName { get; set; } + + [JsonIgnore] + public string Password { get; set; } + + [JsonIgnore] + public string PasswordHash { get; set; } + + public List> ExtendedAttributesList { get; set; } = new List>(); + public List RoleList { get; set; } = new List(); + public string Token { get; set; } + public int UserId { get; set; } + public int BadLogonCount { get; set; } + public DateTime? LastBadPasswordAttempt { get; internal set; } + + public string PasswordHashShort + { + get + { + if (PasswordHash?.Length <= 10) { return string.Empty; }; + + return PasswordHash.Substring(PasswordHash.Length - 10); + } + } + + public string GetLastBadPasswordAttemptAsLocalTime() + { + if (LastBadPasswordAttempt == null) + { + return string.Empty; + } + + return ((DateTime)LastBadPasswordAttempt).ToLocalTime().ToLongTimeString(); + } + + public void AddPasswordHash(string passwordHash) + { + PasswordHash = passwordHash; + + if (!ExistsExtendedAttributeValue(PASSWORD_HASH_SHORT)) + { + AddExtendedAttribute(PASSWORD_HASH_SHORT, PasswordHashShort); + } + } + + public string GetExtendedAttributePasswordHash() + { + return GetExtendedAttributeValue(PASSWORD_HASH_SHORT); + } + + public bool ExistsExtendedAttributeValue(string key) + { + foreach (var item in ExtendedAttributesList) + { + if (item.Key == key) { return true; } + } + + return false; + } + + public string GetExtendedAttributeValue(string key) + { + foreach (var item in ExtendedAttributesList) + { + if (item.Key == key) { return item.Value; } + } + + return string.Empty; + } + + public string GetAccountLockoutTimeAsLocalTime() + { + if (AccountLockoutTime == null) + { + return string.Empty; + } + + return ((DateTime)AccountLockoutTime).ToLocalTime().ToLongTimeString(); + } + + public bool IsAccountLockedOut { get; internal set; } + public DateTime? AccountLockoutTime { get; internal set; } + public bool Enabled { get; set; } + + public static bool IsJwtGlobalsRole(string roleName) + { + return string.Equals(roleName, JwtGlobals.ROLE_USER, StringComparison.OrdinalIgnoreCase) + || string.Equals(roleName, JwtGlobals.ROLE_DEPARTMENTUSER, StringComparison.OrdinalIgnoreCase) + || string.Equals(roleName, JwtGlobals.ROLE_DEPARTMENTMASTER, StringComparison.OrdinalIgnoreCase) + || string.Equals(roleName, JwtGlobals.ROLE_MASTER, StringComparison.OrdinalIgnoreCase) + || string.Equals(roleName, JwtGlobals.ROLE_ADMIN, StringComparison.OrdinalIgnoreCase); + } + + public void AddExtendedAttribute(string key, string value) + { + ExtendedAttributesList.Add(new KeyValuePair(key, value)); + } + + public void AddRole(JwtRole jwtRole) + { + if (!RoleList.Exists(x => x.Role == jwtRole.Role && x.Group == jwtRole.Group)) + { + RoleList.Add(jwtRole); + } + } + + public void AddRole(string role) + { + if (!string.IsNullOrEmpty(role) && !RoleList.Exists(x => x.Role == role)) + { + RoleList.Add(new JwtRole(role)); + } + } + + public List DepartmentIdListAll() + { + List list = new List() { DepartmentId }; + + if (!string.IsNullOrEmpty(ExtendedDepartmentIdList)) + { + List extendetList = ExtendedDepartmentIdList.Split(',').Select(x => int.Parse(x.Trim())).ToList(); + + list = list.Union(extendetList).ToList(); + } + return list; + } + + public bool IsAdmin() + { + return IsExistsRole(JwtGlobals.ROLE_ADMIN); + } + + public bool IsDepartmentMaster() + { + return IsExistsRole(JwtGlobals.ROLE_DEPARTMENTMASTER); + } + + public bool IsDepartmentUser() + { + return IsExistsRole(JwtGlobals.ROLE_DEPARTMENTUSER); + } + + public bool IsExistsRole(string role) + { + return RoleList.Exists(x => String.Equals(x.Role, role, StringComparison.OrdinalIgnoreCase)); + } + + public bool IsMaster() + { + return IsExistsRole(JwtGlobals.ROLE_MASTER); + } + + public bool IsUser() + { + return IsExistsRole(JwtGlobals.ROLE_USER); + } + + public bool IsValid() + { + if (IsRealLDAPUser) + { + return !string.IsNullOrEmpty(LoginName) + //&& RoleList.Count > 0 + && (LdapGuid != null) + && Enabled + && IsValidatCredentials; + } + else + { + return !string.IsNullOrEmpty(LoginName) + && Enabled + && IsValidatCredentials; + } + } + + public string RoleListAsString(EN_LdapRoleListFilter filter = EN_LdapRoleListFilter.All) + { + List resultList = new List(); + foreach (var item in RoleList) + { + switch (filter) + { + case EN_LdapRoleListFilter.All: + resultList.Add(item.Role); + break; + + case EN_LdapRoleListFilter.OnlyRoleList: + if (IsJwtGlobalsRole(item.Role)) { resultList.Add(item.Role); } + break; + + case EN_LdapRoleListFilter.OnlyWebAppRoleList: + if (!IsJwtGlobalsRole(item.Role)) { resultList.Add(item.Role); } + break; + + default: + break; + } + } + return string.Join(",", resultList); + } + + public override string ToString() + { + return $"{this.LoginName}; Roles: {RoleList.Count}; ExtendedDepartmentIdList: {ExtendedDepartmentIdList}, ExtendedAttributesList: {ExtendedAttributesList} "; + } + } +} \ No newline at end of file diff --git a/HRD.LdapService.Test/HRD.LdapService.Test.csproj b/HRD.LdapService.Test/HRD.LdapService.Test.csproj new file mode 100644 index 0000000..b82c929 --- /dev/null +++ b/HRD.LdapService.Test/HRD.LdapService.Test.csproj @@ -0,0 +1,25 @@ + + + + netcoreapp7.0 + false + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/HRD.LdapService.Test/LdapTest.cs b/HRD.LdapService.Test/LdapTest.cs new file mode 100644 index 0000000..46c9fb3 --- /dev/null +++ b/HRD.LdapService.Test/LdapTest.cs @@ -0,0 +1,134 @@ +using HRD.LDAPService; +using HRD.LDAPService.JWT; +using System; +using System.Collections.Generic; +using System.ComponentModel.Design; +using Xunit; + +namespace HRD.LdapService.Text +{ + public class LdapTest + { + + private static void InitJWTConfig(bool deaktivateLDAP = false) + { + var list = new List(); + var ADGroupPrefix = ""; + //Admin Role + list.Add(new JwtRole(JwtGlobals.ROLE_ADMIN, "GG_WebApp" + ADGroupPrefix + "_Visitors_Admin")); + //Core RoleList + list.Add(new JwtRole(JwtGlobals.ROLE_USER, "GG_WebApp" + ADGroupPrefix + "_Visitors_User")); //(RO) nur eigene + list.Add(new JwtRole(JwtGlobals.ROLE_MASTER, "GG_WebApp" + ADGroupPrefix + "_Visitors_Master")); //RW ALLE Abteilungen + list.Add(new JwtRole(JwtGlobals.ROLE_DEPARTMENTUSER, "GG_WebApp" + ADGroupPrefix + "_Visitors_DepartmentUser")); //(RW) auch andere aus eigener Abteilung + list.Add(new JwtRole(JwtGlobals.ROLE_DEPARTMENTMASTER, "GG_WebApp" + ADGroupPrefix + "_Visitors_DepartmentMaster")); //(RW) auch andere aus eigener Abteilung + + //WebApp RoleList + list.Add(new JwtRole("Ipad", "GG_WebApp" + ADGroupPrefix + "_Visitors_Ipad")); //RW ALLE Abteilungen + list.Add(new JwtRole("Security", "GG_WebApp" + ADGroupPrefix + "_Visitors_Security")); //RW ALLE Abteilungen + + + JwtTokenConfig.JwtRoleList = list; + + JwtTokenConfig.Secret = "12345678901234567809_WEBAPISERVER"; + JwtTokenConfig.ExpirationInMin = 60 * 1 * 100; //100 min + JwtTokenConfig.DeaktivateLDAP = deaktivateLDAP; + + } + + + [Fact] + public void Renew_LDAP() + { + InitJWTConfig(false); + var token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ2LmJvamFyc2tpIiwibmFtZWlkIjoiMCIsImVtYWlsIjoiVi5Cb2phcnNraUBoZW5zZWwtcmVjeWNsaW5nLmNvbSIsImRlcGFydG1lbnRpZCI6IjAiLCJleHRlbmRldGRlcGFydG1lbnRpZGxpc3QiOiIiLCJFeHRlbmRlZEF0dHJpYnV0ZXNfUmVnaW9uIjoiMTAsMjAiLCJFeHRlbmRlZEF0dHJpYnV0ZXNfQXR0cmlidXQjMSI6IkFCQ0BBQkMuREUsREVGQEFCQy5ERSxHRUhAQUJDLkRFIiwibmJmIjoxNjU4NzU4NDE0LCJleHAiOjE2NTkxMTg0MTQsImlhdCI6MTY1ODc1ODQxNH0.KUODwRBRn-xc3-0RaVKJ0uzwsXZ7RgORRAZUzTfxfNk"; + var loginName = "v.bojarski"; + + LdapUser renewLdapUser = JwtManager.RenewLdapUserWithJwtToken(token); + + Assert.Same(renewLdapUser.LoginName, loginName); + Assert.True(renewLdapUser.IsValid()); + } + + + + [Fact] + public void Login_LDAP() + { + InitJWTConfig(); + //JwtTokenConfig.ExpirationInMin = 60 * 24 * 30 * 12; //12 Month + + var LoginName = "visitoripad2"; + var Password = "HenselVisitor2020!"; + + LdapUser ldapUser = new LdapUser(LoginName); + ldapUser.Password = Password; + + List> extendedAttributesList = new List>(); + //List>> extendedAttributesList = new(); + //List list = new() { "10,20" }; + + extendedAttributesList.Add(new KeyValuePair("VendorId", "100210")); + extendedAttributesList.Add(new KeyValuePair("Region", "10,20")); + extendedAttributesList.Add(new KeyValuePair("Attribut#1", "ABC@ABC.DE,DEF@ABC.DE,GEH@ABC.DE")); + + + ldapUser.ExtendedAttributesList = extendedAttributesList; + var isOk = JwtManager.GenerateLdapUserWithJwtToken(ldapUser); + LdapUser ldapUserWithJWT = new LdapUser(ldapUser.LoginName); + ldapUserWithJWT.Token = ldapUser.Token; + + extendedAttributesList = new List>(); + extendedAttributesList.Add(new KeyValuePair("Attribut#1", "ABC@ABC.DE,DEF@ABC.DE,GEH@ABC.DE")); + ldapUser.ExtendedAttributesList = extendedAttributesList; + var renewLdapUserWithJWT = LdapAuthenticationService.RenewIdentity( ldapUserWithJWT); + + Assert.True(renewLdapUserWithJWT.IsValid()); + } + + + [Fact] + public void JWT_GeneratePasswordHash() + { + InitJWTConfig(true); + + var LoginName = "visitoripad2"; + var Password = "HenselVisitor2020!"; + + LdapUser ldapUser = new LdapUser(LoginName); + ldapUser.Password = Password; + + //var passwordHash = JWTCrypt.GenerateHashPassword(ldapUser.Password); + + ldapUser.AddExtendedAttribute("Attribut#1", "ABC@ABC.DE,DEF@ABC.DE,GEH@ABC.DE"); + ldapUser.AddExtendedAttribute("VendorId", "100210"); + var isOk = JwtManager.GenerateLdapUserWithJwtToken(ldapUser); + LdapUser ldapUserWithJWT = new LdapUser(ldapUser.LoginName); + ldapUserWithJWT.Token = ldapUser.Token; + ldapUserWithJWT.PasswordHash = ldapUser.PasswordHash; + + var renewLdapUserWithJWT = LdapAuthenticationService.RenewIdentity(ldapUserWithJWT); + + LdapUser ldapUser2 = new LdapUser(LoginName); + ldapUser2.PasswordHash = ldapUser.PasswordHash; + + var returLdapUser = JwtManager.RenewLdapUserWithJwtToken(ldapUserWithJWT); + + Assert.Equal(ldapUser.PasswordHashShort, ldapUserWithJWT.PasswordHashShort); + Assert.True(renewLdapUserWithJWT.IsValid()); + + } + + + [Fact] + public void Add_User_To_Group() + { + var loginName = "v.bojarski"; + var groupName = "GG_WebApp__Test_Apps_User"; + + Assert.True(LdapManager.AD_AddUserloginToGroup(loginName, groupName)); + + + + } + } +} \ No newline at end of file diff --git a/HRD.WebApi/Configs/WebApiConfig.cs b/HRD.WebApi/Configs/WebApiConfig.cs new file mode 100644 index 0000000..f194418 --- /dev/null +++ b/HRD.WebApi/Configs/WebApiConfig.cs @@ -0,0 +1,178 @@ +using HRD.AppLogger; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace HRD.WebApi +{ + public class MonitoringWebRequest + { + public string WebRequestMethod { get; set; } + public string WebRequestPath { get; set; } + public EN_LoggingLevel LoggingLevel { get; set; } = EN_LoggingLevel.Info; + } + + public static class WebApiConfig + { + private static string _dalConnectionstring; + + internal static EN_LoggingLevel GetMonitoringWebRequestLevel(string method, string path) + { + var entity = NlogMonitoringWebRequest.FirstOrDefault( + x => x.WebRequestMethod.Equals(method, StringComparison.OrdinalIgnoreCase) && + (x.WebRequestPath == "*" || path.StartsWith(x.WebRequestPath, StringComparison.OrdinalIgnoreCase)) + ); + if (entity == default) { return EN_LoggingLevel.Off; } + return entity.LoggingLevel; + } + + private static Dictionary _customConfig = new Dictionary(); + + public static int ConnectionstringTimeoutInMin { get; set; } = 5; + public static bool RaiseRepositoryExceptions { get; set; } = false; //if true, all Repository-Exception are thrown + + public static void Init(dynamic appSettings, System.Reflection.AssemblyName assemblyName = null) + { + AssemblyName = assemblyName?.Name ?? string.Empty; + AssemblyVersion = assemblyName?.Version.ToString() ?? string.Empty; + + Connectionstring = appSettings["ConnectionStrings:sqlConnection"]; + ClientVersion = appSettings["AppConfig:ClientVersion"]; + OfficeFileServerUrl = appSettings["AppConfig:OfficeFileServerUrl"]; + IsLive = bool.Parse(appSettings["AppConfig:LDAP_WebAppGroup_Is_Live"]); + + //LDAP + //LDAPService.LdapGlobals.LDAP_WebAppGroup_Is_Live = IsLive; + + //Nlog + NlogConnectionstring = appSettings["Nlog:NlogConnectionstring"]; + if (NlogConnectionstring.Equals("%sqlConnection%", StringComparison.OrdinalIgnoreCase)) + { + NlogConnectionstring = appSettings["ConnectionStrings:sqlConnection"]; + } + + NlogDBLogLevel = ToEnumLoggingLevel(appSettings["Nlog:NlogDBLogLevel"]); + NlogFileLogLevel = ToEnumLoggingLevel(appSettings["Nlog:NlogFileLogLevel"]); + NlogLogDirectory = appSettings["Nlog:NlogLogDirectory"]; + NlogSentryDSN = appSettings["Nlog:NlogSentryDSN"]; + NlogSentryIsEnable = bool.Parse(appSettings["Nlog:NlogSentryIsEnable"]); + + for (int i = 1; i < 100; i++) + { + string configString = appSettings[$"Nlog:MonitoringWebRequest{i}"]; + if (!string.IsNullOrEmpty(configString)) + { + string[] configArr = configString.Split("|").Select(x => x.Trim()).ToArray(); + NlogMonitoringWebRequest.Add(new MonitoringWebRequest { WebRequestMethod = configArr[0], WebRequestPath = configArr[1], LoggingLevel = ToEnumLoggingLevel(configArr[2]) }); + } + } + + AppLoggerConfig.Init( + WebApiConfig.AssemblyName, WebApiConfig.AssemblyVersion, + WebApiConfig.NlogDBLogLevel, + WebApiConfig.NlogFileLogLevel, + WebApiConfig.NlogLogDirectory); + AppLoggerConfig.NlogConnectionstring = NlogConnectionstring; + AppLoggerConfig.NlogSentryConfig.Dsn = WebApiConfig.NlogSentryDSN; + AppLoggerConfig.NlogSentryConfig.NlogSentryIsEnable = WebApiConfig.NlogSentryIsEnable; + + //custom + var list = appSettings.GetSection("CustomConfig").GetChildren(); + foreach (var item in list) + { + _customConfig.Add(item.Key, item.Value); + } + } + + public static EN_LoggingLevel ToEnumLoggingLevel(string enumString) + { + if (string.IsNullOrEmpty(enumString)) + { + return EN_LoggingLevel.Off; + } + + return (EN_LoggingLevel)Enum.Parse(typeof(EN_LoggingLevel), enumString); + } + + internal static void InitCustomSetting(Dictionary customConfig) + { + _customConfig = customConfig; + } + + public static string Connectionstring + { + get { return _dalConnectionstring; } + set + { + _dalConnectionstring = value; + } + } + + public static string GetCustomconfig(string key) + { + _customConfig.TryGetValue(key, out string result); + return result; + } + + public static string AssemblyName { get; set; } + public static string AssemblyVersion { get; set; } + + //OfficeFileServer + public static string OfficeFileServerUrl { get; set; } + + //DAL + + public static string ClientVersion { get; set; } + public static bool IsLive { get; set; } + + //Logger + public static List NlogMonitoringWebRequest { get; set; } = new List(); + + public static string NlogLogDirectory { get; set; } = string.Empty; + + public static string NlogSentryDSN { get; set; } = string.Empty; + public static bool NlogSentryIsEnable { get; set; } = true; + + public static string NlogConnectionstring { get; set; } + public static EN_LoggingLevel NlogFileLogLevel { get; set; } = EN_LoggingLevel.Error; + public static EN_LoggingLevel NlogDBLogLevel { get; set; } = EN_LoggingLevel.Error; + + public static DbContextOptions SQLOptions() + { + if (string.IsNullOrEmpty(Connectionstring)) + { + throw new NullReferenceException("Connectnion string is empty!"); + } + var optionsBuilder = new DbContextOptionsBuilder(); + optionsBuilder + .EnableDetailedErrors() + .UseSqlServer(Connectionstring, + opts => + { + opts.CommandTimeout((int)TimeSpan.FromMinutes(ConnectionstringTimeoutInMin).TotalSeconds); + opts.EnableRetryOnFailure( + maxRetryCount: 5, + maxRetryDelay: TimeSpan.FromSeconds(30), + errorNumbersToAdd: null + ); + } + ); + + return optionsBuilder.Options; + } + + public static string ConnectionString(EN_ConnectionType connectionType = EN_ConnectionType.SQLServer) + { + switch (connectionType) + { + case EN_ConnectionType.SQLServer: + return Connectionstring; + + default: + + return String.Empty; + } + } + } +} \ No newline at end of file diff --git a/HRD.WebApi/Configs/WebApiEnums.cs b/HRD.WebApi/Configs/WebApiEnums.cs new file mode 100644 index 0000000..08f71bb --- /dev/null +++ b/HRD.WebApi/Configs/WebApiEnums.cs @@ -0,0 +1,16 @@ +using System.ComponentModel; + +namespace HRD.WebApi +{ + public enum EN_ConnectionType + { + [Description("SQL-Server")] + SQLServer = 1, + + //[Description("Hangfire-Server")] + //Hangfire = 2, + + [Description("Unknown")] + Unknown = 666 + } +} \ No newline at end of file diff --git a/HRD.WebApi/Controllers/BaseController.cs b/HRD.WebApi/Controllers/BaseController.cs new file mode 100644 index 0000000..50f1755 --- /dev/null +++ b/HRD.WebApi/Controllers/BaseController.cs @@ -0,0 +1,196 @@ +using HRD.AppLogger; +using HRD.WebApi.DAL; +using HRD.WebApi.Repositories; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace HRD.WebApi.Controllers +{ + [Route("api/[controller]")] + [Produces("application/json")] + [ApiController] //Automatically responding with a 400 when validation errors occur + public abstract class BaseController : Microsoft.AspNetCore.Mvc.Controller where TEntity : BaseEntity, new() + { + private readonly IBaseRepository _entityRepository; + private readonly ILoggerManager _logger; + + public BaseController(IBaseRepository baseRepository) : base() + { + _entityRepository = baseRepository; + _logger = new LoggerManager(); + } + + protected IBaseRepository EntityRepository => _entityRepository; + + [HttpPost()] + public virtual async Task> CreateAsync([FromBody] TEntity entity) + { + try + { + if (!await EntityRepository.AddAsync(entity)) + { + WriteLogError($"Cann't add a {typeof(TEntity).Name}"); + return StatusCode(StatusCodes.Status400BadRequest, $"Can't create a {typeof(TEntity).Name}"); + } + return new OkObjectResult(entity); + } + catch (Exception ex) + { + WriteLogException(ex, typeof(TEntity).Name); + WriteLogError($"Cann't create : {ex.Message}"); + return StatusCode(StatusCodes.Status400BadRequest, $"Can't create a {typeof(TEntity).Name}"); + } + } + + [HttpPost("List")] + public virtual async Task CreateListAsync([FromBody] List entities) + { + try + { + if (!await EntityRepository.AddListAsync(entities)) + { + WriteLogError($"Can't create a list of {typeof(TEntity).Name}"); + return StatusCode(StatusCodes.Status400BadRequest, $"Can't create a list of {typeof(TEntity).Name}"); + } + return new OkObjectResult(entities); + } + catch (Exception ex) + { + WriteLogException(ex, typeof(TEntity).Name); + return StatusCode(StatusCodes.Status400BadRequest, $"Can't create a list of {typeof(TEntity).Name}"); + } + } + + [HttpDelete("{id}")] + public virtual async Task> DeleteAsync(int id) + { + try + { + if (!await EntityRepository.DeleteByIdAsync(id)) + { + WriteLogError($"Cann't delete the entity {typeof(TEntity).Name} Id: {id}"); + return StatusCode(StatusCodes.Status404NotFound, $"Cann't delete {typeof(TEntity).Name} by Id: {id}"); + } + return StatusCode(StatusCodes.Status200OK, true); + } + catch (Exception ex) + { + WriteLogException(ex, typeof(TEntity).Name); + return StatusCode(StatusCodes.Status404NotFound, $"Cann't delete entity by Id: {id} {ex.Message}"); + } + } + + [HttpGet("all")] + public virtual async Task GetAllAsync() + { + try + { + List list = await EntityRepository.GetAllAsync(); + if (list == default) + { + WriteLogError($"The List of {typeof(TEntity).Name} is null"); + return StatusCode(StatusCodes.Status400BadRequest, $"The list {typeof(TEntity).Name} cannot be loaded"); + } + return new OkObjectResult(list); + } + catch (Exception ex) + { + WriteLogException(ex, typeof(TEntity).Name); + return StatusCode(StatusCodes.Status400BadRequest, $"The list {typeof(TEntity).Name} cannot be loaded"); + } + } + + [HttpGet("{id}")] + public virtual async Task> GetEntityAsync(int id) + { + try + { + var result = await EntityRepository.GetByIdAsync(id); + + if (result == null) + { + WriteLogError($"Cann't get the entity: {typeof(TEntity).Name} Id: {id}"); + return StatusCode(StatusCodes.Status404NotFound, $"Cann't get the entity: {typeof(TEntity).Name} Id: {id}"); + } + + return new OkObjectResult(result); + } + catch (Exception ex) + { + WriteLogException(ex, typeof(TEntity).Name); + return StatusCode(StatusCodes.Status404NotFound, $"Cann't get the entity: {typeof(TEntity).Name} Id: {id}"); + } + } + + [HttpPut("list")] + public virtual async Task> UpdateAsync(List entities) + { + try + { + if (!await EntityRepository.UpdateListAsync(entities)) + { + WriteLogError($"Cann't update the list of {typeof(TEntity).Name}"); + return StatusCode(StatusCodes.Status400BadRequest, $"Cann't update the list of {typeof(TEntity).Name}"); + } + return new ObjectResult(true); + } + catch (Exception ex) + { + WriteLogException(ex, typeof(TEntity).Name); + return StatusCode(StatusCodes.Status400BadRequest, $"Cann't update the list of {typeof(TEntity).Name}"); + } + } + + [HttpPut("{id}")] + public virtual async Task> UpdateAsync(TEntity entity) + { + try + { + if (!await EntityRepository.UpdateAsync(entity)) + { + WriteLogError($"Cann't update the a {typeof(TEntity).Name}"); + return StatusCode(StatusCodes.Status400BadRequest, $"{nameof(entity).GetType().Name} could not be updated"); + } + return new OkObjectResult(entity); + } + catch (Exception ex) + { + WriteLogException(ex, typeof(TEntity).Name); + return StatusCode(StatusCodes.Status400BadRequest, $"{nameof(entity).GetType().Name} could not be updated"); + } + } + + [NonAction] + public void WriteLogDebug(string message, String entityMessage = null) + { + WriteLogDebug(message, entityMessage); + } + + [NonAction] + public void WriteLogError(string message, String entityMessage = null) + { + _logger.LogError(message, entityMessage); + } + + [NonAction] + public void WriteLogException(Exception exception, String entityMessage = null) + { + _logger.LogException(exception, entityMessage); + } + + [NonAction] + public void WriteLogInfo(string message) + { + _logger.LogInfo(message); + } + + [NonAction] + public void WriteLogWarn(string message, String entityMessage = null) + { + _logger.LogWarn(message, entityMessage); + } + } +} \ No newline at end of file diff --git a/HRD.WebApi/Controllers/BaseMiniController.cs b/HRD.WebApi/Controllers/BaseMiniController.cs new file mode 100644 index 0000000..f08baae --- /dev/null +++ b/HRD.WebApi/Controllers/BaseMiniController.cs @@ -0,0 +1,52 @@ +using HRD.AppLogger; +using HRD.WebApi.DAL; +using Microsoft.AspNetCore.Mvc; +using System; + +namespace HRD.WebApi.Controllers +{ + [Route("api/[controller]")] + [Produces("application/json")] + [ApiController] + public abstract class BaseMiniController : Microsoft.AspNetCore.Mvc.Controller + { + private readonly ILoggerManager _logger; + public readonly WebApiBaseContext Context; + + public BaseMiniController(WebApiBaseContext webApiBaseContext) + { + Context = webApiBaseContext; + _logger = new LoggerManager(); + } + + [NonAction] + public void WriteLogDebug(string message, String entityMessage = null) + { + WriteLogDebug(message, entityMessage); + } + + [NonAction] + public void WriteLogError(string message, String entityMessage = null) + { + _logger.LogError(message, entityMessage); + } + + [NonAction] + public void WriteLogException(Exception exception, String entityMessage = null) + { + _logger.LogException(exception, entityMessage); + } + + [NonAction] + public void WriteLogInfo(string message) + { + _logger.LogInfo(message); + } + + [NonAction] + public void WriteLogWarn(string message, String entityMessage = null) + { + _logger.LogWarn(message, entityMessage); + } + } +} \ No newline at end of file diff --git a/HRD.WebApi/Controllers/HttpStatusCodeException.cs b/HRD.WebApi/Controllers/HttpStatusCodeException.cs new file mode 100644 index 0000000..ac5ff9a --- /dev/null +++ b/HRD.WebApi/Controllers/HttpStatusCodeException.cs @@ -0,0 +1,33 @@ +//namespace KabionlineServer +//{ +// using Newtonsoft.Json.Linq; +// using System; + +// namespace HRD.WebApi.Controllers +// { +// public class HttpStatusCodeException : Exception +// { +// public int StatusCode { get; set; } +// public string ContentType { get; set; } = @"text/plain"; + +// public HttpStatusCodeException(int statusCode) +// { +// this.StatusCode = statusCode; +// } + +// public HttpStatusCodeException(int statusCode, string message) : base(message) +// { +// this.StatusCode = statusCode; +// } + +// public HttpStatusCodeException(int statusCode, Exception inner) : this(statusCode, inner.ToString()) +// { +// } + +// public HttpStatusCodeException(int statusCode, JObject errorObject) : this(statusCode, errorObject.ToString()) +// { +// this.ContentType = @"application/json"; +// } +// } +// } +//} \ No newline at end of file diff --git a/HRD.WebApi/Controllers/InfoBaseController.cs b/HRD.WebApi/Controllers/InfoBaseController.cs new file mode 100644 index 0000000..dd9ecec --- /dev/null +++ b/HRD.WebApi/Controllers/InfoBaseController.cs @@ -0,0 +1,55 @@ +using HRD.WebApi.DAL; +using HRD.WebApi.Helpers; +using Microsoft.AspNetCore.Mvc; +using System; + +namespace HRD.WebApi.Controllers +{ + [Route("api/[controller]")] + [Produces("application/json")] + [ApiController] + public abstract class InfoBaseController : BaseMiniController + { + public InfoBaseController(WebApiBaseContext webApiBaseContext) : base(webApiBaseContext) + { + } + + [HttpGet] + public ActionResult GetInfos() + { + try + { + var serverInfo = GetServerInfo(); + return StatusCode(serverInfo.Status, serverInfo); + } + catch (Exception ex) + { + WriteLogException(ex); + return NotFound(); + } + } + + [HttpPost] + public ActionResult GetInfos([FromBody] ServerInfo serverInfoFromClient) + { + try + { + var serverInfo = GetServerInfo(); + serverInfo.LastOfflineTime = serverInfoFromClient.LastOfflineTime; + + return new OkObjectResult(serverInfo); + } + catch (Exception ex) + { + WriteLogException(ex); + return NotFound(); + } + } + + [NonAction] + public virtual ServerInfo GetServerInfo() + { + return ServerInfoHelper.GetServerInfo(base.Context); + } + } +} \ No newline at end of file diff --git a/HRD.WebApi/DAL/WebApiBaseContext.cs b/HRD.WebApi/DAL/WebApiBaseContext.cs new file mode 100644 index 0000000..cfb3492 --- /dev/null +++ b/HRD.WebApi/DAL/WebApiBaseContext.cs @@ -0,0 +1,17 @@ +using Microsoft.EntityFrameworkCore; + +namespace HRD.WebApi.DAL +{ + public abstract class WebApiBaseContext : DbContext + { + public WebApiBaseContext() : base(WebApiConfig.SQLOptions()) + { + } + + public WebApiBaseContext(DbContextOptions options) + : base(options) + { + } + + } +} \ No newline at end of file diff --git a/HRD.WebApi/Extensions/EnumExtensions.cs b/HRD.WebApi/Extensions/EnumExtensions.cs new file mode 100644 index 0000000..f5d7bfd --- /dev/null +++ b/HRD.WebApi/Extensions/EnumExtensions.cs @@ -0,0 +1,24 @@ +using System; +using System.ComponentModel; +using System.Linq; +using System.Reflection; + +namespace HRD.WebApi.Extensions +{ + public static class EnumExtensions + { + /// + /// Get the Description from the DescriptionAttribute. + /// + /// + /// + public static string GetDescription(this Enum enumValue) + { + return enumValue.GetType() + .GetMember(enumValue.ToString()) + .First() + .GetCustomAttribute()? + .Description ?? string.Empty; + } + } +} \ No newline at end of file diff --git a/HRD.WebApi/Extensions/StringExtensions.cs b/HRD.WebApi/Extensions/StringExtensions.cs new file mode 100644 index 0000000..4d2142f --- /dev/null +++ b/HRD.WebApi/Extensions/StringExtensions.cs @@ -0,0 +1,22 @@ +using System; + +namespace HRD.WebApi.Extensions +{ + public static class StringExtensions + { + public static bool IsNullOrEmpty(this string s) + { + return string.IsNullOrEmpty(s); + } + + public static bool IsNullOrWhiteSpace(this string s) + { + return String.IsNullOrWhiteSpace(s); + } + + public static bool Contains(this string src, string toCheck, StringComparison comp) + { + return src.IndexOf(toCheck, comp) >= 0; + } + } +} \ No newline at end of file diff --git a/HRD.WebApi/Extensions/SystemExtensions.cs b/HRD.WebApi/Extensions/SystemExtensions.cs new file mode 100644 index 0000000..4b7fe27 --- /dev/null +++ b/HRD.WebApi/Extensions/SystemExtensions.cs @@ -0,0 +1,45 @@ +//using System; +//using System.IO; +//using System.Runtime.Serialization; +//using System.Runtime.Serialization.Formatters.Binary; + +//namespace HRD.WebApi.Extensions +//{ +// /// +// /// Reference Article http://www.codeproject.com/KB/tips/SerializedObjectCloner.aspx +// /// Provides a method for performing a deep copy of an object. +// /// Binary Serialization is used to perform the copy. +// /// +// public static class SystemExtensions +// { +// /// +// /// Perform a deep Copy of the object. +// /// +// /// The type of object being copied. +// /// The object instance to copy. +// /// The copied object. +// public static T Clone(this T source) +// { +// if (!typeof(T).IsSerializable) +// { +// throw new ArgumentException("The type must be serializable.", nameof(source)); +// } + +// // Don't serialize a null object, simply return the default for that object +// if (Object.ReferenceEquals(source, null)) +// { +// return default; +// } + +// IFormatter formatter = new BinaryFormatter(); +// Stream stream = new MemoryStream(); +// using (stream) +// { +// formatter.Serialize(stream, source); +// stream.Seek(0, SeekOrigin.Begin); +// return (T)formatter.Deserialize(stream); +// } +// } + +// } +//} \ No newline at end of file diff --git a/HRD.WebApi/HRD.WebApi.csproj b/HRD.WebApi/HRD.WebApi.csproj new file mode 100644 index 0000000..ea3d2a6 --- /dev/null +++ b/HRD.WebApi/HRD.WebApi.csproj @@ -0,0 +1,16 @@ + + + + netcoreapp7.0 + 1.12 + 1.12.0.0 + + + + + + + + + + \ No newline at end of file diff --git a/HRD.WebApi/Helpers/AttributeReader.cs b/HRD.WebApi/Helpers/AttributeReader.cs new file mode 100644 index 0000000..a34cfb2 --- /dev/null +++ b/HRD.WebApi/Helpers/AttributeReader.cs @@ -0,0 +1,25 @@ +using Microsoft.EntityFrameworkCore; +using System.Linq; + +namespace HRD.WebApi.Helpers +{ + public static class AttributeReader + { + //Get DB Table Name + public static string GetTableName(DbContext context) where T : class + { + // We need dbcontext to access the models + var models = context.Model; + + // Get all the entity types information + var entityTypes = models.GetEntityTypes(); + + // T is Name of class + var entityTypeOfT = entityTypes.First(t => t.ClrType == typeof(T)); + + var tableNameAnnotation = entityTypeOfT.GetAnnotation("Relational:TableName"); + var TableName = tableNameAnnotation.Value.ToString(); + return TableName; + } + } +} \ No newline at end of file diff --git a/HRD.WebApi/Helpers/CorsExtension.cs b/HRD.WebApi/Helpers/CorsExtension.cs new file mode 100644 index 0000000..f0768a6 --- /dev/null +++ b/HRD.WebApi/Helpers/CorsExtension.cs @@ -0,0 +1,24 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace HRD.WebApi.Helpers +{ + public static class CorsExtension + { + public static void AddCustomCors(this IServiceCollection services, string policyName) + { + services.AddCors(options => + { + options.AddPolicy(policyName, + builder => + { + builder + .AllowCredentials() + //.AllowAnyOrigin() + .SetIsOriginAllowed(origin => true) + .AllowAnyHeader() + .AllowAnyMethod(); + }); + }); + } + } +} \ No newline at end of file diff --git a/HRD.WebApi/Helpers/ExceptionExtension.cs b/HRD.WebApi/Helpers/ExceptionExtension.cs new file mode 100644 index 0000000..39427f7 --- /dev/null +++ b/HRD.WebApi/Helpers/ExceptionExtension.cs @@ -0,0 +1,39 @@ +using HRD.AppLogger; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Diagnostics; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Hosting; + +namespace HRD.WebApi.Helpers +{ + public static class ExceptionExtension + { + public static void AddCustomExceptionHandling(this IApplicationBuilder app) + { + app.UseExceptionHandler(errorApp => + { + errorApp.Run(async context => + { + context.Response.StatusCode = StatusCodes.Status500InternalServerError; + context.Response.ContentType = "application/json"; + var errorFeature = context.Features.Get(); + if (errorFeature != null) + { + HttpErrorDetails customError = new HttpErrorDetails + { + URI = context.Request.Path.ToUriComponent(), + Status = context.Response.StatusCode, + Detail = errorFeature.Error.Message + }; + + ILoggerManager logger = new LoggerManager(); + logger.LogException(errorFeature.Error, null, customError.URI); + + await context.Response.WriteAsync(customError.ToJsonString()).ConfigureAwait(false); + } + }); + }); + } + } +} \ No newline at end of file diff --git a/HRD.WebApi/Helpers/HttpErrorDetails.cs b/HRD.WebApi/Helpers/HttpErrorDetails.cs new file mode 100644 index 0000000..e87b877 --- /dev/null +++ b/HRD.WebApi/Helpers/HttpErrorDetails.cs @@ -0,0 +1,69 @@ +using HRD.AppLogger; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.ModelBinding; + +namespace HRD.WebApi.Helpers +{ + public class HttpErrorDetails : ValidationProblemDetails + { + public HttpErrorDetails() + { + } + + public HttpErrorDetails(ActionContext context) + { + Title = "Invalid arguments to the API"; + Detail = "The inputs supplied to the API are invalid"; + Status = StatusCodes.Status400BadRequest; + Type = context.HttpContext.TraceIdentifier; + URI = context.HttpContext.Request.Path.ToUriComponent(); + + ConstructErrorMessages(context); + } + + public string URI { get; set; } + + public string ToJsonString() + { + return JsonConvert.Serialize(this); + } + + private void ConstructErrorMessages(ActionContext context) + { + foreach (var keyModelStatePair in context.ModelState) + { + var key = keyModelStatePair.Key; + var errors = keyModelStatePair.Value.Errors; + if (errors != null && errors.Count > 0) + { + ILoggerManager logger = new LoggerManager(); + if (errors.Count == 1) + { + var errorMessage = GetErrorMessage(errors[0]); + base.Errors.Add(key, new[] { errorMessage }); + logger.LogError(errorMessage, null, URI); + Detail = errorMessage; + } + else + { + var errorMessages = new string[errors.Count]; + for (var i = 0; i < errors.Count; i++) + { + errorMessages[i] = GetErrorMessage(errors[i]); + logger.LogError(errorMessages[i], null, URI); + if (i == 0) { Detail = errorMessages[i]; } + } + base.Errors.Add(key, errorMessages); + } + } + } + } + + private string GetErrorMessage(ModelError error) + { + return string.IsNullOrEmpty(error.ErrorMessage) ? + "The input was not valid." : error.ErrorMessage; + } + } +} \ No newline at end of file diff --git a/HRD.WebApi/Helpers/JsonConvert.cs b/HRD.WebApi/Helpers/JsonConvert.cs new file mode 100644 index 0000000..db05d7f --- /dev/null +++ b/HRD.WebApi/Helpers/JsonConvert.cs @@ -0,0 +1,42 @@ +using System.IO; +using System.Runtime.Serialization.Json; +using System.Text; + +namespace HRD.WebApi.Helpers +{ + public static class JsonConvert + { + public static string Serialize(T obj) + { + using (var stream = new MemoryStream()) + { + GetSerializer().WriteObject(stream, obj); + return Encoding.UTF8.GetString(stream.ToArray()); + } + } + + public static T Deserialize(string json) + { + using (var stream = new MemoryStream()) + { + using (var writer = new StreamWriter(stream)) + { + writer.Write(json); + writer.Flush(); + stream.Position = 0; + return (T)GetSerializer().ReadObject(stream); + } + } + } + + private static DataContractJsonSerializer GetSerializer() + { + var settings = new DataContractJsonSerializerSettings + { + UseSimpleDictionaryFormat = true + }; + + return new DataContractJsonSerializer(typeof(T), settings); + } + } +} \ No newline at end of file diff --git a/HRD.WebApi/Helpers/ServerInfoHelper.cs b/HRD.WebApi/Helpers/ServerInfoHelper.cs new file mode 100644 index 0000000..35eafa7 --- /dev/null +++ b/HRD.WebApi/Helpers/ServerInfoHelper.cs @@ -0,0 +1,40 @@ +using HRD.WebApi.DAL; +using Microsoft.AspNetCore.Http; +using Microsoft.EntityFrameworkCore; +using System; +using System.Data.Common; + +namespace HRD.WebApi.Helpers +{ + public static class ServerInfoHelper + { + public static ServerInfo GetServerInfo(WebApiBaseContext context) + { + ServerInfo serverInfo = new ServerInfo(); + { + serverInfo.DatabaseName = context?.Database?.GetDbConnection()?.Database; ; + serverInfo.DatabaseServer = context?.Database?.GetDbConnection()?.DataSource; + serverInfo.Message = "Online"; + using DbConnection connection = context.Database.GetDbConnection(); + try + { + connection.Open(); + serverInfo.DatabaseStatus = "Online"; + serverInfo.Status = StatusCodes.Status200OK; + } + catch (Exception ex) + { + serverInfo.DatabaseStatus = "Offline"; + serverInfo.Status = StatusCodes.Status500InternalServerError; + serverInfo.Message = ex.Message; + } + } + serverInfo.Server = Environment.MachineName; + serverInfo.Version = WebApiConfig.AssemblyVersion; + serverInfo.IsLive = WebApiConfig.IsLive; + + serverInfo.ClientVersion = WebApiConfig.ClientVersion; + return serverInfo; + } + } +} \ No newline at end of file diff --git a/HRD.WebApi/Middleware/HttpStatusCodeException.cs b/HRD.WebApi/Middleware/HttpStatusCodeException.cs new file mode 100644 index 0000000..81ba3e8 --- /dev/null +++ b/HRD.WebApi/Middleware/HttpStatusCodeException.cs @@ -0,0 +1,31 @@ +using System; +using System.Net; + +namespace HRD.WebApi.Middleware +{ + public class HttpStatusCodeException : Exception + { + public HttpStatusCode StatusCode { get; set; } + public string ContentType { get; set; } = @"text/plain"; + + public HttpStatusCodeException(HttpStatusCode statusCode) + { + this.StatusCode = statusCode; + } + + public HttpStatusCodeException(HttpStatusCode statusCode, string message) + : base(message) + { + this.StatusCode = statusCode; + } + + public HttpStatusCodeException(HttpStatusCode statusCode, Exception inner) + : this(statusCode, inner.ToString()) { } + + //public HttpStatusCodeException(HttpStatusCode statusCode, JObject errorObject) + // : this(statusCode, errorObject.ToString()) + //{ + // this.ContentType = @"application/json"; + //} + } +} \ No newline at end of file diff --git a/HRD.WebApi/Middleware/WebApiMiddleware.cs b/HRD.WebApi/Middleware/WebApiMiddleware.cs new file mode 100644 index 0000000..99f46d4 --- /dev/null +++ b/HRD.WebApi/Middleware/WebApiMiddleware.cs @@ -0,0 +1,52 @@ +using Microsoft.AspNetCore.Http; +using System.IO; +using System.Threading.Tasks; + +namespace HRD.WebApi.DAL.Middleware +{ + /// + /// Gets the current API resource name from HTTP context + /// + /// The HTTP context + /// The current resource name if available, otherwise an empty string + + public class WebApiMiddleware + { + private readonly RequestDelegate _next; + + public WebApiMiddleware(RequestDelegate next) + { + _next = next; + } + + public async Task InvokeAsync(HttpContext httpContext) + { + try + { + var loglevel = WebApiConfig.GetMonitoringWebRequestLevel(httpContext.Request.Method, httpContext.Request.Path.Value); + if (loglevel == AppLogger.EN_LoggingLevel.Info + || loglevel == AppLogger.EN_LoggingLevel.Warn + || loglevel == AppLogger.EN_LoggingLevel.Error + ) + { + var requestReader = new StreamReader(httpContext.Request.Body); + var requestContent = await requestReader.ReadToEndAsync(); + if (string.IsNullOrEmpty(requestContent)) + { + requestContent = $"{httpContext.Request.Method} {httpContext.Request.Path.Value}"; + } + AppLogger.ILoggerManager logger = new AppLogger.LoggerManager(); + if (loglevel == AppLogger.EN_LoggingLevel.Info) { logger.LogInfo(requestContent); } + if (loglevel == AppLogger.EN_LoggingLevel.Warn) { logger.LogWarn(requestContent); } + if (loglevel == AppLogger.EN_LoggingLevel.Error) { logger.LogError(requestContent); } + } + } + catch (System.Exception) + { + //throw; + } + + await _next(httpContext).ConfigureAwait(false); + } + } +} \ No newline at end of file diff --git a/HRD.WebApi/Middleware/WebApiMiddlewareExtensions.cs b/HRD.WebApi/Middleware/WebApiMiddlewareExtensions.cs new file mode 100644 index 0000000..e8b747d --- /dev/null +++ b/HRD.WebApi/Middleware/WebApiMiddlewareExtensions.cs @@ -0,0 +1,36 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using System; + +namespace HRD.WebApi.DAL.Middleware +{ + public static class WebApiMiddlewareExtensions + { + public static IApplicationBuilder UseDALMiddleware(this IApplicationBuilder builder) + { + return builder.UseMiddleware(); + } + + public static void ConfigureDAL(this IServiceCollection services, WebApiMiddlewareOptions options) + { + if (options == null) + { + throw new ArgumentNullException(nameof(options)); + } + + SetOptions(options); + } + + private static void SetOptions(WebApiMiddlewareOptions options) + { + WebApiConfig.AssemblyVersion = options.AssemblyVersion; + WebApiConfig.AssemblyName = options.AssemblyName; + WebApiConfig.ClientVersion = options.ClientVersion; + WebApiConfig.Connectionstring = options.Connectionstring; + WebApiConfig.NlogConnectionstring = options.NlogConnectionstring; + WebApiConfig.NlogDBLogLevel = options.NlogDBLogLevel; + WebApiConfig.NlogFileLogLevel = options.NlogFileLogLevel; + WebApiConfig.NlogLogDirectory = options.NlogLogDirectory; + } + } +} \ No newline at end of file diff --git a/HRD.WebApi/Middleware/WebApiMiddlewareOptions.cs b/HRD.WebApi/Middleware/WebApiMiddlewareOptions.cs new file mode 100644 index 0000000..b523ede --- /dev/null +++ b/HRD.WebApi/Middleware/WebApiMiddlewareOptions.cs @@ -0,0 +1,22 @@ +using HRD.AppLogger; +using System; + +namespace HRD.WebApi.DAL.Middleware +{ + public class WebApiMiddlewareOptions + { + public string AssemblyVersion { get; set; } = String.Empty; + public string AssemblyName { get; set; } = String.Empty; + public string ClientVersion { get; set; } + + public string Connectionstring { get; set; } = String.Empty; + + //Logger + public string NlogLogDirectory { get; set; } = String.Empty; + + public string NlogConnectionstring { get; set; } = String.Empty; + + public EN_LoggingLevel NlogFileLogLevel { get; set; } = EN_LoggingLevel.Error; + public EN_LoggingLevel NlogDBLogLevel { get; set; } = EN_LoggingLevel.Error; + } +} \ No newline at end of file diff --git a/HRD.WebApi/Models/BaseEntity.cs b/HRD.WebApi/Models/BaseEntity.cs new file mode 100644 index 0000000..c3b7388 --- /dev/null +++ b/HRD.WebApi/Models/BaseEntity.cs @@ -0,0 +1,6 @@ +namespace HRD.WebApi.DAL +{ + public class BaseEntity : BaseEntityCore + { + } +} \ No newline at end of file diff --git a/HRD.WebApi/Models/BaseEntityCore.cs b/HRD.WebApi/Models/BaseEntityCore.cs new file mode 100644 index 0000000..e37af09 --- /dev/null +++ b/HRD.WebApi/Models/BaseEntityCore.cs @@ -0,0 +1,17 @@ +namespace HRD.WebApi.DAL +{ + public abstract class BaseEntityCore : IBaseEntityCore + { + public virtual int GetEntityId() => 0; + + public override string ToString() + { + return $"Id: {GetEntityId()}; {this.GetType().Name}"; + } + + public virtual string EntityInfo() + { + return ToString(); + } + } +} \ No newline at end of file diff --git a/HRD.WebApi/Models/BaseFilter.cs b/HRD.WebApi/Models/BaseFilter.cs new file mode 100644 index 0000000..df174c6 --- /dev/null +++ b/HRD.WebApi/Models/BaseFilter.cs @@ -0,0 +1,6 @@ +namespace HRD.WebApi.DAL +{ + public class BaseFilter : BaseEntity, IBaseFilter + { + } +} \ No newline at end of file diff --git a/HRD.WebApi/Models/IBaseEntityCore.cs b/HRD.WebApi/Models/IBaseEntityCore.cs new file mode 100644 index 0000000..535662a --- /dev/null +++ b/HRD.WebApi/Models/IBaseEntityCore.cs @@ -0,0 +1,6 @@ +namespace HRD.WebApi.DAL +{ + public interface IBaseEntityCore + { + } +} \ No newline at end of file diff --git a/HRD.WebApi/Models/IBaseFilter.cs b/HRD.WebApi/Models/IBaseFilter.cs new file mode 100644 index 0000000..f823939 --- /dev/null +++ b/HRD.WebApi/Models/IBaseFilter.cs @@ -0,0 +1,6 @@ +namespace HRD.WebApi.DAL +{ + public interface IBaseFilter + { + } +} \ No newline at end of file diff --git a/HRD.WebApi/Models/ServerInfo.cs b/HRD.WebApi/Models/ServerInfo.cs new file mode 100644 index 0000000..b4e3c9b --- /dev/null +++ b/HRD.WebApi/Models/ServerInfo.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; + +namespace HRD.WebApi.DAL +{ + public class ServerInfo : BaseEntity + { +#pragma warning disable CS1030 // #warning: 'evtl. im InfoController per DI holen' +#warning evtl. im InfoController per DI holen + public string Version { get; set; } +#pragma warning restore CS1030 // #warning: 'evtl. im InfoController per DI holen' + public bool IsLive { get; set; } + public string Server { get; set; } + public int Status { get; set; } + public string Message { get; set; } + + public string DatabaseServer { get; set; } + public string DatabaseName { get; set; } + public string DatabaseStatus { get; set; } + public string ClientVersion { get; set; } + public DateTime? FirstOnlineTime { get; set; } + public DateTime? LastOfflineTime { get; set; } + public Dictionary Attributes { get; set; } + + public string GetInfo(string clientRepresentation) + { + if (this.LastOfflineTime != default) + { + return $"InfoController ({clientRepresentation}): First online time: {FirstOnlineTime} Last offline time: {this.LastOfflineTime}"; + } + else + { + return $"InfoController ({clientRepresentation}): First online time: {FirstOnlineTime}"; + } + } + } +} \ No newline at end of file diff --git a/HRD.WebApi/Repositories/BaseRepository.cs b/HRD.WebApi/Repositories/BaseRepository.cs new file mode 100644 index 0000000..51f7062 --- /dev/null +++ b/HRD.WebApi/Repositories/BaseRepository.cs @@ -0,0 +1,11 @@ +using HRD.WebApi.DAL; + +namespace HRD.WebApi.Repositories +{ + public abstract class BaseRepository : BaseRepositoryCore where T : BaseEntity + { + public BaseRepository(WebApiBaseContext repositoryContext) : base(repositoryContext) + { + } + } +} \ No newline at end of file diff --git a/HRD.WebApi/Repositories/BaseRepositoryCore.cs b/HRD.WebApi/Repositories/BaseRepositoryCore.cs new file mode 100644 index 0000000..779cc33 --- /dev/null +++ b/HRD.WebApi/Repositories/BaseRepositoryCore.cs @@ -0,0 +1,619 @@ +using HRD.AppLogger; +using HRD.WebApi.DAL; +using HRD.WebApi.Helpers; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading.Tasks; + +namespace HRD.WebApi.Repositories +{ + public abstract class BaseRepositoryCore : IBaseRepository where T : BaseEntityCore + { + private readonly ILoggerManager _logger; + protected DbContext RepositoryContext { get; private set; } + + protected BaseRepositoryCore(WebApiBaseContext repositoryContext) + { + RepositoryContext = repositoryContext; + AppLoggerConfig.Init( + WebApiConfig.AssemblyName, + WebApiConfig.AssemblyVersion, + WebApiConfig.NlogDBLogLevel, + WebApiConfig.NlogFileLogLevel, + WebApiConfig.NlogLogDirectory); + _logger = new LoggerManager(); + } + + public virtual bool Add(T entity, bool saveEntity = true) + { + try + { + this.RepositoryContext.Set().Add(entity); + + if (saveEntity) + { + return this.SaveChanges(); + } + + return true; + } + catch (Exception ex) + { + WriteLogException(ex, typeof(T).Name + " " + entity?.EntityInfo()); + return false; + } + } + + public virtual async Task AddAsync(T entity, bool saveEntity = true) + { + try + { + await this.RepositoryContext.Set().AddAsync(entity); + + if (saveEntity) + return await this.SaveChangesAsync(); + return true; + } + catch (Exception ex) + { + WriteLogException(ex, typeof(T).Name + " " + entity?.EntityInfo()); + return false; + } + } + + public virtual async Task AddListAsync(List list, bool saveEntity = true) + { + try + { + await this.RepositoryContext.Set().AddRangeAsync(list).ConfigureAwait(false); + + if (saveEntity) + return await this.SaveChangesAsync(); + return true; + } + catch (Exception ex) + { + WriteLogException(ex, typeof(T).Name); + return false; + } + } + + public virtual bool Delete(T entity) + { + try + { + this.RepositoryContext.Set().Remove(entity); + return this.SaveChanges(); + } + catch (Exception ex) + { + WriteLogException(ex, typeof(T).Name); + return false; + } + } + + public virtual async Task DeleteAsync(T entity, bool saveEntity = true) + { + try + { + this.RepositoryContext.Set().Remove(entity); + + if (saveEntity) + return await this.SaveChangesAsync(); + return true; + } + catch (Exception ex) + { + WriteLogException(ex, typeof(T).Name); + return false; + } + } + + public virtual async Task DeleteByIdAsync(int id, bool saveEntity = true) + { + try + { + var entity = await GetByIdAsync(id).ConfigureAwait(false); + this.RepositoryContext.Set().Remove(entity); + + if (saveEntity) + return await this.SaveChangesAsync(); + return true; + } + catch (Exception ex) + { + WriteLogException(ex, typeof(T).Name); + return false; + } + } + + public virtual async Task DeleteFromTableAsync(string tablename, string whereClause = "") + { + string sql = $"DELETE FROM {tablename}"; + if (!string.IsNullOrEmpty(whereClause)) sql += $" WHERE {whereClause}"; + try + { + int count = await RepositoryContext.Database.ExecuteSqlRawAsync(sql).ConfigureAwait(false); + return true; + } + catch (Exception ex) + { + WriteLogException(ex, $"sql: {sql}"); + } + return false; + } + + public virtual bool Detach(T entity, bool saveChanges = true) + { + try + { + this.RepositoryContext.Entry(entity).State = EntityState.Detached; + if (saveChanges) + { + return this.SaveChanges(); + } + return true; + } + catch (Exception ex) + { + WriteLogException(ex, typeof(T).Name); + return false; + } + } + + public virtual async Task DetachAsync(T entity, bool saveChanges = true) + { + try + { + this.RepositoryContext.Entry(entity).State = EntityState.Detached; + if (saveChanges) + { + return await this.SaveChangesAsync(); + } + return true; + } + catch (Exception ex) + { + WriteLogException(ex, typeof(T).Name); + return false; + } + } + + public virtual async Task ExecSQLQueryAsync(string sql) + { + try + { + var result = await RepositoryContext.Database.ExecuteSqlRawAsync($"{sql}").ConfigureAwait(false); + return true; + } + catch (Exception ex) + { + WriteLogException(ex, $"{nameof(ExecSQLQueryAsync)} for '{sql}' Exception was thrown"); + } + return false; + } + + public virtual async Task ExecStoredProcedureAsync(string storedProcedureName, string param = "") + { + try + { + var x = RepositoryContext.Database.IsSqlServer(); + //var RepositoryContext = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)context).ObjectContext; + if (string.IsNullOrEmpty(param)) + { + await RepositoryContext.Database.ExecuteSqlRawAsync($"exec {storedProcedureName} ").ConfigureAwait(false); + } + else + { + await RepositoryContext.Database.ExecuteSqlRawAsync($"exec {storedProcedureName} {param}").ConfigureAwait(false); + } + return true; + } + catch (Exception ex) + { + WriteLogException(ex, $"storedProcedureName: {storedProcedureName}; param: {param}"); + } + return false; + } + + public virtual List GetAll(bool asNoTracking = true) + { + try + { + if (asNoTracking) + { + return this.RepositoryContext.Set().AsNoTracking().ToList(); + } + else + { + return this.RepositoryContext.Set().ToList(); + } + } + catch (Exception ex) + { + WriteLogException(ex, typeof(T).Name); + return default; + } + } + + public virtual List TakeList(int count, bool asNoTracking = true) + { + try + { + if (asNoTracking) + { + return this.RepositoryContext.Set().AsNoTracking().Take(count).ToList(); + } + else + { + return this.RepositoryContext.Set().Take(count).ToList(); + } + } + catch (Exception ex) + { + WriteLogException(ex, typeof(T).Name); + return default; + } + } + + public async Task> TakePagesListAsync(int pageNumber, int pageSize, bool asNoTracking = true) + { + try + { + if (asNoTracking) + { + return await RepositoryContext + .Set() + .Skip((pageNumber - 1) * pageSize) + .Take(pageSize) + .AsNoTracking() + .ToListAsync(); + } + else + { + return await RepositoryContext + .Set() + .Skip((pageNumber - 1) * pageSize) + .Take(pageSize) + .ToListAsync(); + } + } + catch (Exception ex) + { + WriteLogException(ex, typeof(T).Name); + return default; + } + } + + public virtual async Task> TakeListAsync(int count, bool asNoTracking = true) + { + try + { + if (asNoTracking) + { + return await this.RepositoryContext.Set().AsNoTracking().Take(count).ToListAsync(); + } + else + { + return await this.RepositoryContext.Set().Take(count).ToListAsync(); + } + } + catch (Exception ex) + { + WriteLogException(ex, typeof(T).Name); + return default; + } + } + + public virtual async Task> GetAllAsync(bool asNoTracking = true) + { + try + { + if (asNoTracking) + { + return await this.RepositoryContext.Set().AsNoTracking().ToListAsync(); + } + else + { + return await this.RepositoryContext.Set().ToListAsync(); + } + } + catch (Exception ex) + { + WriteLogException(ex, typeof(T).Name); + return default; + } + } + + public virtual List GetBy(Expression> expression, bool asNoTracking = true) + { + try + { + if (asNoTracking) + { + return this.RepositoryContext.Set().Where(expression).AsNoTracking().ToList(); ; + } + else + { + return this.RepositoryContext.Set().Where(expression).ToList(); ; + } + } + catch (Exception ex) + { + WriteLogException(ex, typeof(T).Name); + return default; + } + } + + public virtual async Task GetByAsync(Expression> expression, bool asNoTracking = true) + { + try + { + if (asNoTracking) + { + return await this.RepositoryContext.Set().Where(expression).AsNoTracking().FirstOrDefaultAsync(); + } + else + { + return await this.RepositoryContext.Set().Where(expression).FirstOrDefaultAsync(); + } + } + catch (Exception ex) + { + WriteLogException(ex, typeof(T).Name); + return default; + } + } + + public virtual async Task GetByIdAsync(int entityId, bool asNoTracking = false) + { + try + { + /* if (entityId == default) { + var items = await this.RepositoryContext.Set().Take(1).ToListAsync(); + entityId = items[0].GetEntityId(); + } + */ + var entity = await this.RepositoryContext.Set().FindAsync(entityId); + if (asNoTracking) + { + this.RepositoryContext.Entry(entity).State = EntityState.Detached; + } + return entity; + } + catch (Exception ex) + { + WriteLogException(ex, $"{typeof(T).Name} id:{entityId}"); + return default(T); + } + } + + public virtual async Task GetBySqlAsync(string sql, bool asNoTracking = true) + { + // return await this.RepositoryContext.Set().FromSqlInterpolated($"{apiFilter.ToString()}").AsNoTracking().ToListAsync(); + + try + { + return await this.RepositoryContext.Set().FromSqlInterpolated($"{sql}").AsNoTracking().FirstOrDefaultAsync(); + } + catch (Exception ex) + { + WriteLogException(ex, $"sql: {sql}"); + return default; + } + } + + public virtual async Task GetByWithIncludeAsync(Expression> expression, string navigationPropertyPath, bool asNoTracking = true) + { + try + { + if (asNoTracking) + { + return await this.RepositoryContext.Set() + .Where(expression) + .Include(navigationPropertyPath) + .AsNoTracking() + .FirstOrDefaultAsync(); + } + else + { + return await this.RepositoryContext.Set() + .Where(expression) + .Include(navigationPropertyPath) + .FirstOrDefaultAsync(); + } + } + catch (Exception ex) + { + WriteLogException(ex, typeof(T).Name); + return default; + } + } + + public virtual async Task> GetListByAsync(Expression> expression, bool asNoTracking = true) + { + try + { + if (asNoTracking) + { + return await this.RepositoryContext.Set().AsNoTracking().Where(expression).ToListAsync(); + } + else + { + return await this.RepositoryContext.Set().Where(expression).ToListAsync(); + } + } + catch (Exception ex) + { + WriteLogException(ex, typeof(T).Name); + } + + return default; + } + + public virtual async Task> TakeListByAsync(int count, Expression> expression, bool asNoTracking = true) + { + if (count == 0) return await GetListByAsync(expression, asNoTracking); + + var list = new List(); + try + { + if (asNoTracking) + { + return await this.RepositoryContext.Set().AsNoTracking().Where(expression).Take(count).ToListAsync(); + } + else + { + return await this.RepositoryContext.Set().Where(expression).Take(count).ToListAsync(); + } + } + catch (Exception ex) + { + WriteLogException(ex, typeof(T).Name); + } + return list; + } + + public virtual async Task> GetListByConditionFromSqlAsync(string sql) + { + // https://software-security.sans.org/developer-how-to/fix-sql-injection-microsoft-.net-with-parameterized-queries + + try + { + return await this.RepositoryContext.Set().FromSqlInterpolated($"{sql}").AsNoTracking().ToListAsync(); + } + catch (Exception ex) + { + WriteLogException(ex, $"sql:{sql}"); + return default; + } + } + + public virtual async Task> GetListByConditionFromSqlRawAsync(string sql) + { + try + { + return await this.RepositoryContext.Set().FromSqlRaw(sql).AsNoTracking().ToListAsync(); + } + catch (Exception ex) + { + WriteLogException(ex, $"sql:{sql}"); + return default; + } + } + + public string GetTableName() + { + return AttributeReader.GetTableName(RepositoryContext); + } + + public virtual bool SaveChanges() + { + try + { + this.RepositoryContext.SaveChanges(); + return true; + } + catch (Exception ex) + { + WriteLogException(ex, $"Error on {nameof(SaveChanges)} trying {nameof(SaveChanges)}"); + return false; + } + } + + public virtual async Task SaveChangesAsync() + { + try + { + var result = await this.RepositoryContext.SaveChangesAsync().ConfigureAwait(false); + return (result >= 0); + } + catch (Exception ex) + { + WriteLogException(ex, $"error on {nameof(SaveChangesAsync)} trying {nameof(SaveChangesAsync)}"); + return false; + } + } + + public virtual bool Update(T entity) + { + try + { + this.RepositoryContext.Set().Update(entity); + return true; + } + catch (Exception ex) + { + WriteLogException(ex, entity?.EntityInfo()); + return false; + } + } + + public virtual async Task UpdateAsync(T entity, bool saveEntity = true) + { + try + { + this.RepositoryContext.Set().Update(entity); + + if (saveEntity) + return await this.SaveChangesAsync(); + return true; + } + catch (Exception ex) + { + WriteLogException(ex, entity?.EntityInfo()); + return false; + } + } + + public virtual async Task UpdateListAsync(List entities, bool saveEntity = true) + { + try + { + this.RepositoryContext.Set().UpdateRange(entities); + + if (saveEntity) + return await this.SaveChangesAsync(); + return true; + } + catch (Exception ex) + { + WriteLogException(ex, typeof(T).Name); + + return false; + } + } + + public void WriteLogDebug(string message, String entityMessage = null) + { + _logger.LogDebug(message, entityMessage); + } + + public void WriteLogError(string message, String entityMessage = null) + { + _logger.LogError(message, entityMessage); + } + + public void WriteLogException(Exception exception, String entityMessage = null) + { + _logger.LogException(exception, entityMessage); + if (WebApiConfig.RaiseRepositoryExceptions) + { + throw exception; + } + } + + public void WriteLogInfo(string message) + { + _logger.LogInfo(message); + } + + public void WriteLogWarn(string message, String entityMessage = null) + { + _logger.LogWarn(message, entityMessage); + } + } +} \ No newline at end of file diff --git a/HRD.WebApi/Repositories/IBaseRepository.cs b/HRD.WebApi/Repositories/IBaseRepository.cs new file mode 100644 index 0000000..e8f65de --- /dev/null +++ b/HRD.WebApi/Repositories/IBaseRepository.cs @@ -0,0 +1,6 @@ +namespace HRD.WebApi.Repositories +{ + public interface IBaseRepository : IBaseRepositoryCore + { + } +} \ No newline at end of file diff --git a/HRD.WebApi/Repositories/IBaseRepositoryCore.cs b/HRD.WebApi/Repositories/IBaseRepositoryCore.cs new file mode 100644 index 0000000..65fb1be --- /dev/null +++ b/HRD.WebApi/Repositories/IBaseRepositoryCore.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Threading.Tasks; + +namespace HRD.WebApi.Repositories +{ + public interface IBaseRepositoryCore + { + bool Add(T entity, bool saveEntity = true); + + Task AddAsync(T entity, bool saveEntity = true); + + Task AddListAsync(List list, bool saveEntity = true); + + bool Delete(T entity); + + Task DeleteAsync(T entity, bool saveEntity = true); + + Task DeleteByIdAsync(int Id, bool saveEntity = true); + + Task DeleteFromTableAsync(string tablename, string whereClause = ""); + + bool Detach(T entity, bool saveChanges = true); + + Task DetachAsync(T entity, bool saveChanges = true); + + Task ExecStoredProcedureAsync(string storedProcedureName, string param = ""); + + List GetAll(bool asNoTracking = true); + + List TakeList(int count, bool asNoTracking = true); + + Task> TakeListAsync(int count, bool asNoTracking = true); + + Task> GetAllAsync(bool asNoTracking = true); + + List GetBy(Expression> expression, bool asNoTracking = true); + + Task GetByAsync(Expression> expression, bool asNoTracking = true); + + Task GetByIdAsync(int entityId, bool asNoTracking = false); + + Task GetBySqlAsync(string str, bool asNoTracking = true); + + Task GetByWithIncludeAsync(Expression> expression, string navigationPropertyPath, bool asNoTracking = true); + + Task> GetListByAsync(Expression> expression, bool asNoTracking = true); + + Task> GetListByConditionFromSqlAsync(string str); + + string GetTableName(); + + bool SaveChanges(); + + Task SaveChangesAsync(); + + bool Update(T entity); + + Task UpdateAsync(T entity, bool saveEntity = true); + + Task UpdateListAsync(List entity, bool saveEntity = true); + + Task> TakePagesListAsync(int pageNumber, int pageSize, bool asNoTracking = true); + } +} \ No newline at end of file diff --git a/README.md b/README.md index c429622..3cdb4da 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,24 @@ -# DigitalData.StaffDBServer +# Introduction +Sample Empty Server Project to create a new one from + +# Getting Started +1. prepare the file .\Scripts\Run\Entitieslist.lst with the list of entity names, one per line, not dedicated to use with filter +2. prepare the file .\Scripts\Run\EntitiesFilterList.lst with the list of entity names, one per line, dedicated to use with filter. + If the filter class name differs from entity class name add the filter name (w/o suffix "Filter") as the second word to the line. + Otherwise the filter name will be "Filter". + Examle: "KabiAppLagerbestand Lagerbestand" +3. Start .\Scripts\Run\prepare_project.bat : + Example: ".\Scripts\Run\prepare_project.bat Kabismart" +4. Compare and adjust Entity classes in .\DAL\Models\Entities\*.cs +5. Compare and adjust Filter classes in .\DAL\Models\Filters\*.cs +6. Compare and adjust Repository classes with filters in .\DAL\Repositories\*.cs +7. Compare and adjust Controller classes in .\Server\Controllers\*.cs +8. Compare and adjust Controller classes in .\Server\appsettings.json, + .\Server\AppSettingsFiles\Develop\appsettings.json, + .\Server\AppSettingsFiles\Production\appsettings.json +9. Compare and adjust "applicationUrl" and "sslPort".\Server\Properties\launchsettings.json +10. Apply plausible filter fields and their values for filters in .\XUnitDAL.Test\Test_Controller_Filter.cs +11. Apply plausible Id values for Ids in .\XUnitDAL.Test\Test_Controller_Entity.cs +12. Done. + diff --git a/Scripts/Core/EntityController_test.tmpl b/Scripts/Core/EntityController_test.tmpl new file mode 100644 index 0000000..47693b8 --- /dev/null +++ b/Scripts/Core/EntityController_test.tmpl @@ -0,0 +1,25 @@ + + [Fact] + public async Task Check_Get_entity_Controller() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 1; + _entity_Repository repository = new _entity_Repository(); + _entity_Controller controller = new _entity_Controller(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity._entity_Id); + } + catch (Exception ex) + { + throw ex; + } + } + diff --git a/Scripts/Core/EntityFilteredListController_test.tmpl b/Scripts/Core/EntityFilteredListController_test.tmpl new file mode 100644 index 0000000..72a207c --- /dev/null +++ b/Scripts/Core/EntityFilteredListController_test.tmpl @@ -0,0 +1,27 @@ + + [Fact] + public async Task Check_Get_entity_FilteredListController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + _filter_Filter filter = new _filter_Filter(); + filter.Name = ""; + _entity_Repository repository = new _entity_Repository(); + _entity_Controller controller = new _entity_Controller(repository); + dynamic result = await controller.Get_entity_ListAsync(filter); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.StatusCode); + + var entity = result.Value; + Assert.NotNull(entity); + + Assert.NotEqual(entity.Count, 0); + } + catch (Exception ex) + { + throw ex; + } + } + diff --git a/Scripts/Core/add_CommonTestController.bat b/Scripts/Core/add_CommonTestController.bat new file mode 100644 index 0000000..21d7cf8 --- /dev/null +++ b/Scripts/Core/add_CommonTestController.bat @@ -0,0 +1,54 @@ +setlocal disableDelayedExpansion + +:Variables +set InputFile=%2 +set OutputFile=%InputFile%# +set entity=%1 +set "_strFind=Check_Dynamic_EntityControllers" +set _strInsert1=[InlineData("%entity%")] +set "_strInsert1= %_strInsert1%" + +rem if already inserted, do nothing +:Check +for /F "delims=" %%L in ('findstr /n "^" "%InputFile%"') do ( + set "line=%%L" + setlocal EnableDelayedExpansion + + set "line=!line:*:=!" + if "!line!" neq "" ( + set "_line=!line:%_strInsert1%=!" + ) else ( + set _line=!line! + ) + if "!_line!" neq "!line!" goto finish + endlocal +) +@echo off + +:Replace +>"%OutputFile%" ( + for /F "delims=" %%L in ('findstr /n "^" "%InputFile%"') do ( + set "line=%%L" + setlocal EnableDelayedExpansion + + set "line=!line:*:=!" + if "!line!" neq "" ( + set "_line=!line:%_strFind%=!" + ) else ( + set _line=!line! + ) + + + if "!_line!" neq "!line!" ( + echo !_strInsert1! + ) + echo.!line! + endlocal + ) +) + +del %InputFile%>nul +copy %OutputFile% %InputFile%>nul +del %OutputFile%>nul + +:finish \ No newline at end of file diff --git a/Scripts/Core/add_ServiceExtensions.bat b/Scripts/Core/add_ServiceExtensions.bat new file mode 100644 index 0000000..4a8897b --- /dev/null +++ b/Scripts/Core/add_ServiceExtensions.bat @@ -0,0 +1,61 @@ +@echo off +setlocal disableDelayedExpansion + +:Variables +set InputFile=%2 +set OutputFile=%InputFile%# +set entity=%1 +set "_strFind=ConfigureRepositoryWrapper(this IServiceCollection services)" +set "_strInsert1= services.AddScoped(typeof(IBaseRepository<%entity%>), typeof(%entity%Repository));" +set doreplace=0 + +rem if already inserted, do nothing +:Check +for /F "delims=" %%L in ('findstr /n "^" "%InputFile%"') do ( + set "line=%%L" + setlocal EnableDelayedExpansion + + set "line=!line:*:=!" + if "!line!" neq "" ( + set "_line=!line:%_strInsert1%=!" + ) else ( + set _line=!line! + ) + if "!_line!" neq "!line!" goto finish + endlocal +) + +:Replace +>"%OutputFile%" ( + for /F "delims=" %%L in ('findstr /n "^" "%InputFile%"') do ( + set "line=%%L" + setlocal EnableDelayedExpansion + + set "line=!line:*:=!" + if "!line!" neq "" ( + set "_line=!line:%_strFind%=!" + ) else ( + set _line=!line! + ) + + + if "!_line!" neq "!line!" ( + echo.!line! + endlocal + set doreplace=1 + ) else ( + echo.!line! + if !doreplace!==1 ( + echo !_strInsert1! + ) + endlocal + set doreplace=0 + ) + ) +) + +del %InputFile% +copy %OutputFile% %InputFile%>nul +del %OutputFile% + +:finish \ No newline at end of file diff --git a/Scripts/Core/add_WebApiContext.bat b/Scripts/Core/add_WebApiContext.bat new file mode 100644 index 0000000..818e450 --- /dev/null +++ b/Scripts/Core/add_WebApiContext.bat @@ -0,0 +1,69 @@ +@echo off +setlocal disableDelayedExpansion + +:Variables +set InputFile=%2 +set OutputFile=%InputFile%# +set entity=%1 +set "_strFind=OnModelCreating(ModelBuilder modelBuilder)" +set "_strInsert1= public virtual DbSet<%entity%> %entity%Set { get; set; }" +set "_strInsert2= modelBuilder.Entity<%entity%>(entity =>" +set "_strInsert3= {" +set "_strInsert4= entity.ToView("%entity%", "webapi");" +set "_strInsert5= });" +set doreplace=0 + +rem if already inserted, do nothing +:Check +for /F "delims=" %%L in ('findstr /n "^" "%InputFile%"') do ( + set "line=%%L" + setlocal EnableDelayedExpansion + + set "line=!line:*:=!" + if "!line!" neq "" ( + set "_line=!line:%_strInsert1%=!" + ) else ( + set _line=!line! + ) + if "!_line!" neq "!line!" goto finish + endlocal +) + +:Replace +>"%OutputFile%" ( + for /F "delims=" %%L in ('findstr /n "^" "%InputFile%"') do ( + set "line=%%L" + setlocal EnableDelayedExpansion + + set "line=!line:*:=!" + if "!line!" neq "" ( + set "_line=!line:%_strFind%=!" + ) else ( + set _line=!line! + ) + + + if "!_line!" neq "!line!" ( + echo !_strInsert1! + echo.!line! + endlocal + set doreplace=1 + ) else ( + echo.!line! + if !doreplace!==1 ( + echo !_strInsert2! + echo !_strInsert3! + echo !_strInsert4! + echo !_strInsert5! + echo. + ) + endlocal + set doreplace=0 + ) + ) +) + +del %InputFile% +copy %OutputFile% %InputFile%>nul +del %OutputFile% +:finish \ No newline at end of file diff --git a/Scripts/Core/add_controller.bat b/Scripts/Core/add_controller.bat new file mode 100644 index 0000000..f6d9b79 --- /dev/null +++ b/Scripts/Core/add_controller.bat @@ -0,0 +1,15 @@ +@echo using HRD.LDAPService.JWT; +@echo using HRD.WebApi.Controllers; +@echo using HRD.WebApi.Repositories; +@echo using DAL.Models.Entities; +@echo. +@echo namespace %2Server.Controllers +@echo { +@echo [JWTAuthorize] +@echo public class %1Controller : BaseController^<%1^> +@echo { +@echo public %1Controller(IBaseRepository^<%1^> repositoryBase) : base(repositoryBase) +@echo { +@echo } +@echo } +@echo } diff --git a/Scripts/Core/add_controller_filter.bat b/Scripts/Core/add_controller_filter.bat new file mode 100644 index 0000000..64312f6 --- /dev/null +++ b/Scripts/Core/add_controller_filter.bat @@ -0,0 +1,36 @@ +@echo using System; +@echo using System.Threading.Tasks; +@echo using Microsoft.AspNetCore.Mvc; +@echo using Microsoft.AspNetCore.Http; +@echo using HRD.LDAPService.JWT; +@echo using HRD.WebApi.Controllers; +@echo using HRD.WebApi.Repositories; +@echo using DAL.Repositories; +@echo using DAL.Models.Entities; +@echo using DAL.Models.Filters; +@echo. +@echo namespace %2Server.Controllers +@echo { +@echo [JWTAuthorize] +@echo public class %1Controller : BaseController^<%1^> +@echo { +@echo public %1Controller(IBaseRepository^<%1^> repositoryBase) : base(repositoryBase) +@echo { +@echo } +@echo. +@echo [HttpPost("%3Filter")] +@echo public async Task^ Get%1ListAsync([FromBody] %3Filter filter) +@echo { +@echo try +@echo { +@echo var list = await ((%1Repository)EntityRepository).GetListByFilterAsync(filter); +@echo return new OkObjectResult(list); +@echo } +@echo catch (Exception ex) +@echo { +@echo this.WriteLogException(ex); +@echo return StatusCode(StatusCodes.Status400BadRequest, $"Cann't get the filtered list of {typeof(%1).Name}"); +@echo } +@echo } +@echo } +@echo } diff --git a/Scripts/Core/add_entity.bat b/Scripts/Core/add_entity.bat new file mode 100644 index 0000000..13d41a7 --- /dev/null +++ b/Scripts/Core/add_entity.bat @@ -0,0 +1,23 @@ +@echo using HRD.WebApi.DAL; +@echo using System; +@echo using System.ComponentModel.DataAnnotations.Schema; +@echo. +@echo namespace DAL.Models.Entities +@echo { +@echo public partial class %1 : BaseEntity +@echo { +@echo public int %1Id { get; set; } +@echo public string Name { get; set; } +@echo public string %1Shortname { get; set; } +@echo. +@echo // [NotMapped] +@echo // [DatabaseGenerated(DatabaseGeneratedOption.Computed)] +@echo. +@echo //generic Id +@echo public override int GetEntityId() =^> %1Id; +@echo //generic ToString() +@echo public override string ToString() =^> $"%1Id: {GetEntityId()}; Name: {Name}"; +@echo //generic EntityInfo() +@echo public override string EntityInfo() =^> base.EntityInfo(); +@echo } +@echo } diff --git a/Scripts/Core/add_filter.bat b/Scripts/Core/add_filter.bat new file mode 100644 index 0000000..b34e45a --- /dev/null +++ b/Scripts/Core/add_filter.bat @@ -0,0 +1,11 @@ +@echo using HRD.WebApi.DAL; +@echo. +@echo namespace DAL.Models.Filters +@echo { +@echo public partial class %1Filter : BaseFilter +@echo { +@echo public int? %1Id { get; set; } +@echo public string Name { get; set; } +@echo public int[] ListIds { get; set; } +@echo } +@echo } diff --git a/Scripts/Core/add_repository.bat b/Scripts/Core/add_repository.bat new file mode 100644 index 0000000..88c0853 --- /dev/null +++ b/Scripts/Core/add_repository.bat @@ -0,0 +1,12 @@ +@echo using HRD.WebApi.Repositories; +@echo using DAL.Models.Entities; +@echo. +@echo namespace DAL.Repositories +@echo { +@echo public class %1Repository : BaseRepository^<%1^> +@echo { +@echo public %1Repository() : base(new WebApiContext()) +@echo { +@echo } +@echo } +@echo } diff --git a/Scripts/Core/add_repository_filter.bat b/Scripts/Core/add_repository_filter.bat new file mode 100644 index 0000000..15e8cd7 --- /dev/null +++ b/Scripts/Core/add_repository_filter.bat @@ -0,0 +1,51 @@ +@echo using System.Collections.Generic; +@echo using System.Linq; +@echo using System.Threading.Tasks; +@echo using Microsoft.EntityFrameworkCore; +@echo using HRD.WebApi.Repositories; +@echo using DAL.Models.Entities; +@echo using DAL.Models.Filters; +@echo. +@echo namespace DAL.Repositories +@echo { +@echo public class %1Repository: BaseRepository^<%1^> +@echo { +@echo public %1Repository() : base(new WebApiContext()) +@echo { +@echo } +@echo. +@echo public async Task^^> GetListByFilterAsync(%2Filter filter, bool asNoTracking = true) +@echo { +@echo var items = this.RepositoryContext.Set^<%1^>().AsQueryable(); +@echo. +@echo if (filter.%2Id != null ^&^& filter.%2Id != 0) +@echo { +@echo items = items.Where(x =^> x.%1Id == filter.%2Id); +@echo return asNoTracking ? await items.ToListAsync() : await items.ToListAsync(); +@echo } +@echo. +@echo /* +@echo // gets entity x if x.FirstName or x.LastName contains filter.Name, case independent +@echo if (!string.IsNullOrEmpty(filter.Name)) +@echo { +@echo items = items.Where(x =^> EF.Functions.Like(x.FirstName.ToLower()+' '+ x.LastName.ToLower(), $"%%{filter.Name.ToLower()}%%")); +@echo } +@echo. +@echo // N:N - filter: gets entity x where one of Id in x.IdList (comma separated list of ids) is infilter.ListIds (array of Ids from Hensel-Selection multiselect Component) +@echo if (filter.ListIds != null ^&^& filter.ListIds.Length ^> 0) +@echo { +@echo IQueryable^<%1^> itemsTmp = null; +@echo for (int i = 0; i^< filter.ListIds.Length; i++) +@echo { +@echo var inx = filter.ListIds[i]; +@echo var items_ = items.Where(x =^> EF.Functions.Like("," + x.IdList.Replace(" ", "") + ",", $"%%,{inx},%%")); +@echo itemsTmp = (itemsTmp != null) ? itemsTmp.Concat(items_) : items_; +@echo } +@echo items = itemsTmp; +@echo } +@echo */ +@echo. +@echo return asNoTracking ? await items.AsNoTracking().ToListAsync() : await items.ToListAsync(); +@echo } +@echo } +@echo } diff --git a/Scripts/Core/add_test_project.bat b/Scripts/Core/add_test_project.bat new file mode 100644 index 0000000..370a723 --- /dev/null +++ b/Scripts/Core/add_test_project.bat @@ -0,0 +1,20 @@ +@echo off +echo ^ +echo. +echo ^ +echo ^netcoreapp3.1^ +echo. +echo ^false^ +echo ^ +echo. +echo ^ +echo ^ +echo ^ +echo ^ +echo ^ +echo ^ +echo. +echo ^ +echo ^ +echo ^ +echo ^ \ No newline at end of file diff --git a/Scripts/Core/add_tests_generic.bat b/Scripts/Core/add_tests_generic.bat new file mode 100644 index 0000000..8aea4a4 --- /dev/null +++ b/Scripts/Core/add_tests_generic.bat @@ -0,0 +1,65 @@ +@echo off +setlocal disableDelayedExpansion + +:Variables +set InputFile=%2 +set OutputFile=%InputFile%# +set entity=%1 +set filtername=%4 +set "_strFind=//----Check_GetEntity%3" +set "_strInsert1= public async Task Check_Get%entity%%3()" +set "scripts_path=%~dp0..\Core" +set templatefile_path=%scripts_path%\Entity%3_test.tmpl + + +rem if already inserted, do nothing +:Check +for /F "delims=" %%L in ('findstr /n "^" "%InputFile%"') do ( + set "line=%%L" + setlocal EnableDelayedExpansion + + set "line=!line:*:=!" + if "!line!" neq "" ( + set "_line=!line:%_strInsert1%=!" + ) else ( + set _line=!line! + ) + if "!_line!" neq "!line!" goto finish + endlocal +) + +call %scripts_path%\replaceinfile.bat %templatefile_path% _entity_ %entity% dontdelete>nul +if "%filtername%" neq "" ( + call %scripts_path%\replaceinfile.bat %templatefile_path%# _filter_ %filtername% dontdelete>nul + del %templatefile_path%# >nul + copy %templatefile_path%## %templatefile_path%# >nul + del %templatefile_path%## >nul +) + +:Replace +>"%OutputFile%" ( + for /F "delims=" %%L in ('findstr /n "^" "%InputFile%"') do ( + set "line=%%L" + setlocal EnableDelayedExpansion + + set "line=!line:*:=!" + if "!line!" neq "" ( + set "_line=!line:%_strFind%=!" + ) else ( + set _line=!line! + ) + + + echo.!line! + if "!_line!" neq "!line!" ( + type %templatefile_path%# + ) + endlocal + ) +) + +del %templatefile_path%# >nul +del %InputFile% >nul +copy %OutputFile% %InputFile% >nul +del %OutputFile% >nul +:finish \ No newline at end of file diff --git a/Scripts/Core/replaceinfile.bat b/Scripts/Core/replaceinfile.bat new file mode 100644 index 0000000..12f5b07 --- /dev/null +++ b/Scripts/Core/replaceinfile.bat @@ -0,0 +1,33 @@ +@echo off +setlocal disableDelayedExpansion + +:Variables +set InputFile=%1 +set OutputFile=%InputFile%# +set "_strFind=%2" +set "_strInsert=%3" +set "_withoutdelete=%4" + +:Replace +>"%OutputFile%" ( + for /F "delims=" %%L in ('findstr /n "^" "%InputFile%"') do ( + set "line=%%L" + setlocal EnableDelayedExpansion + + set "line=!line:*:=!" + if "!line!" neq "" ( + set "_line=!line:%_strFind%=%_strInsert%!" + ) else ( + set _line=!line! + ) + + echo.!_line! + endlocal + ) +) + +if "%_withoutdelete%"=="" ( + del %InputFile% + copy %OutputFile% %InputFile%>nul + del %OutputFile% +) diff --git a/Scripts/Core/sample_entity.bat b/Scripts/Core/sample_entity.bat new file mode 100644 index 0000000..2ad51bf --- /dev/null +++ b/Scripts/Core/sample_entity.bat @@ -0,0 +1,10 @@ +@echo set Project=%1 +@echo set NewEntity=1 +@echo set Entityname= +@echo set Filter4Entity= +@echo @@if "%%NewEntity%%"=="" exit +@echo call ..\Core\start_add_entity_to_project.bat %%Project%% %%EntityName%% %%Filter4Entity%% + + + + diff --git a/Scripts/Core/start_add_entity_to_project.bat b/Scripts/Core/start_add_entity_to_project.bat new file mode 100644 index 0000000..1f03707 --- /dev/null +++ b/Scripts/Core/start_add_entity_to_project.bat @@ -0,0 +1,45 @@ +@echo off +set project_name=%1 +set entity=%2 +set filter_name=%3 +set "project_path=%~dp0..\.." +set "scripts_path=%~dp0..\Core" +set entity_path=%project_path%\DAL\Models\Entities +set filter_path=%project_path%\DAL\Models\Filters +set repository_path=%project_path%\DAL\Repositories +set controller_path=%project_path%\%project_name%Server\Controllers +set webapicontext_path=%project_path%\DAL\WebApiContext.cs +set serviceExtensions_path=%project_path%\%project_name%Server\Extends\ServiceExtensions4BaseRepository.cs +set controllertestgeneric_path=%project_path%\XUnitDAL.Test\_Shared\Shared_Test_Controller_Generic.cs +set controllertestentity_path=%project_path%\XUnitDAL.Test\Test_Controller_Entity.cs +set controllertestfilter_path=%project_path%\XUnitDAL.Test\Test_Controller_Filter.cs + +if not exist "%entity_path%" mkdir "%entity_path%" +if not exist "%filter_path%" mkdir "%filter_path%" +if not exist "%repository_path%" mkdir "%repository_path%" +if not exist "%controller_path%" mkdir "%controller_path%" + +IF "%filter_name%"=="" ( + call %scripts_path%\add_repository.bat %entity% >"%repository_path%"\%entity%Repository.cs + call %scripts_path%\add_controller.bat %entity% %project_name% >"%controller_path%"\%entity%Controller.cs +) ELSE ( +if not exist "%filter_path%"\%filter_name%Filter.cs call %scripts_path%\add_filter.bat %filter_name% >"%filter_path%"\%filter_name%Filter.cs + call %scripts_path%\add_repository_filter.bat %entity% %filter_name% >"%repository_path%"\%entity%Repository.cs + call %scripts_path%\add_controller_filter.bat %entity% %project_name% %filter_name% >"%controller_path%"\%entity%Controller.cs +) + +call %scripts_path%\add_entity.bat %entity% >"%entity_path%"\%entity%.cs +call %scripts_path%\add_WebApiContext.bat %entity% "%webapicontext_path%" +call %scripts_path%\add_serviceExtensions.bat %entity% "%ServiceExtensions_path%" + +if exist "%controllertestgeneric_path%" call %scripts_path%\add_CommonTestController.bat %entity% %controllertestgeneric_path% +if exist "%controllertestentity_path%" call %scripts_path%\add_tests_generic.bat %entity% %controllertestentity_path% Controller +if exist "%controllertestfilter_path%" ( + IF "%filter_name%" neq "" call %scripts_path%\add_tests_generic.bat %entity% %controllertestfilter_path% FilteredListController %filter_name% +) + +echo --finished: %2 + + + + diff --git a/Scripts/Run/EntitiesFilterList.lst b/Scripts/Run/EntitiesFilterList.lst new file mode 100644 index 0000000..7802434 --- /dev/null +++ b/Scripts/Run/EntitiesFilterList.lst @@ -0,0 +1,17 @@ +DepartmentToWebAppToEmployeeForWindream Employee +DocumentArtToDepartment Department +Employee EmployeeFull +EmployeeToAttribute Employee +EmployeeToDepartment Employee +EmployeeToWebApp Employee +WebAppAdditionalRole WebApp +WebAppToDepartment EmployeeToWebApp +WebAppToWebAppAdditionalRole EmployeeToWebApp +WebAppToWebAppRole WebApp +WindreamColumnsToDepartment Department +WindreamIndex ClientId +WindreamIndexToWindreamSearchToDepartment WindreamSearchToDepartment +WindreamSearch ClientId +WindreamSearchItem ClientId +WindreamSearchItemToWindreamSearchToDepartment WindreamSearchToDepartment +WindreamSearchToDepartment Department \ No newline at end of file diff --git a/Scripts/Run/EntitiesList.lst b/Scripts/Run/EntitiesList.lst new file mode 100644 index 0000000..353bc18 --- /dev/null +++ b/Scripts/Run/EntitiesList.lst @@ -0,0 +1,10 @@ +AdWebAppToWebAppRole +CostCentre +Department +DocumentArt +EmployeeAttribute +EmployeeStatus +Project +Rang +WebApp +WebAppRole diff --git a/Scripts/Run/add_list_entities.bat b/Scripts/Run/add_list_entities.bat new file mode 100644 index 0000000..e0c37cf --- /dev/null +++ b/Scripts/Run/add_list_entities.bat @@ -0,0 +1,27 @@ +call ..\Core\start_add_entity_to_project.bat StaffDB AdWebAppToWebAppRole +call ..\Core\start_add_entity_to_project.bat StaffDB CostCentre +call ..\Core\start_add_entity_to_project.bat StaffDB Department +call ..\Core\start_add_entity_to_project.bat StaffDB DocumentArt +call ..\Core\start_add_entity_to_project.bat StaffDB EmployeeAttribute +call ..\Core\start_add_entity_to_project.bat StaffDB EmployeeStatus +call ..\Core\start_add_entity_to_project.bat StaffDB Project +call ..\Core\start_add_entity_to_project.bat StaffDB Rang +call ..\Core\start_add_entity_to_project.bat StaffDB WebApp +call ..\Core\start_add_entity_to_project.bat StaffDB WebAppRole +call ..\Core\start_add_entity_to_project.bat StaffDB DepartmentToWebAppToEmployeeForWindream Employee +call ..\Core\start_add_entity_to_project.bat StaffDB DocumentArtToDepartment Department +call ..\Core\start_add_entity_to_project.bat StaffDB Employee EmployeeFull +call ..\Core\start_add_entity_to_project.bat StaffDB EmployeeToAttribute Employee +call ..\Core\start_add_entity_to_project.bat StaffDB EmployeeToDepartment Employee +call ..\Core\start_add_entity_to_project.bat StaffDB EmployeeToWebApp Employee +call ..\Core\start_add_entity_to_project.bat StaffDB WebAppAdditionalRole WebApp +call ..\Core\start_add_entity_to_project.bat StaffDB WebAppToDepartment EmployeeToWebApp +call ..\Core\start_add_entity_to_project.bat StaffDB WebAppToWebAppAdditionalRole EmployeeToWebApp +call ..\Core\start_add_entity_to_project.bat StaffDB WebAppToWebAppRole WebApp +call ..\Core\start_add_entity_to_project.bat StaffDB WindreamColumnsToDepartment Department +call ..\Core\start_add_entity_to_project.bat StaffDB WindreamIndex ClientId +call ..\Core\start_add_entity_to_project.bat StaffDB WindreamIndexToWindreamSearchToDepartment WindreamSearchToDepartment +call ..\Core\start_add_entity_to_project.bat StaffDB WindreamSearch ClientId +call ..\Core\start_add_entity_to_project.bat StaffDB WindreamSearchItem ClientId +call ..\Core\start_add_entity_to_project.bat StaffDB WindreamSearchItemToWindreamSearchToDepartment WindreamSearchToDepartment +call ..\Core\start_add_entity_to_project.bat StaffDB WindreamSearchToDepartment Department diff --git a/Scripts/Run/add_one_entity.bat b/Scripts/Run/add_one_entity.bat new file mode 100644 index 0000000..3ca4c61 --- /dev/null +++ b/Scripts/Run/add_one_entity.bat @@ -0,0 +1,6 @@ +set Project=StaffDB +set NewEntity=1 +set Entityname=Subsidiary +set Filter4Entity= +@@if "%NewEntity%"=="" exit +call ..\Core\start_add_entity_to_project.bat %Project% %EntityName% %Filter4Entity% diff --git a/Scripts/Run/prepare_project.bat b/Scripts/Run/prepare_project.bat new file mode 100644 index 0000000..8d15adf --- /dev/null +++ b/Scripts/Run/prepare_project.bat @@ -0,0 +1,73 @@ +@echo off +setlocal disableDelayedExpansion + +:Variables +set "work_project=%1" +set template_project=Empty +set entities_list=EntitiesList.lst +set entities_filter_list=EntitiesFilterList.lst +set "project_path=%~dp0..\.." + +if "%work_project%"=="" exit +ren %project_path%\%template_project%Server\%template_project%Server.csproj %work_project%Server.csproj +ren %project_path%\%template_project%Server.sln %work_project%Server.sln +ren %project_path%\%template_project%Server %work_project%Server +call %~dp0..\Core\add_test_project.bat %work_project% >..\..\XUnitDAL.Test\XUnitWebApi.Test.csproj + + +call %~dp0..\Core\replaceinfile.bat %project_path%\%work_project%Server.sln %template_project%Server %work_project%Server +call %~dp0..\Core\replaceinfile.bat %project_path%\%work_project%Server\Program.cs %template_project%Server %work_project%Server +call %~dp0..\Core\replaceinfile.bat %project_path%\%work_project%Server\Startup.cs %template_project%Server %work_project%Server +call %~dp0..\Core\replaceinfile.bat %project_path%\%work_project%Server\_Shared\SharedControllers\InfoController.cs %template_project%Server %work_project%Server +call %~dp0..\Core\replaceinfile.bat %project_path%\%work_project%Server\_Shared\SharedControllers\WebAppUserController.cs %template_project%Server %work_project%Server +call %~dp0..\Core\replaceinfile.bat %project_path%\%work_project%Server\_Shared\SharedControllers\WebAppUserHelper.cs %template_project%Server %work_project%Server + +call %~dp0..\Core\replaceinfile.bat %project_path%\%work_project%Server\_Shared\SharedExtensions\ServiceExtensions.cs %template_project%Server %work_project%Server +call %~dp0..\Core\replaceinfile.bat %project_path%\%work_project%Server\_Shared\SharedExtensions\ServiceSwaggerExtensions.cs %template_project%Server %work_project%Server +call %~dp0..\Core\replaceinfile.bat %project_path%\%work_project%Server\_Shared\SharedExtensions\WebApiMiddlewareOptionsHelper.cs %template_project%Server %work_project%Server + +call %~dp0..\Core\replaceinfile.bat %project_path%\%work_project%Server\Extends\ServiceExtensions4BaseRepository.cs %template_project%Server %work_project%Server +call %~dp0..\Core\replaceinfile.bat %project_path%\%work_project%Server\Extends\JwtMiddlewareOptionsHelper.cs %template_project%Server %work_project%Server +call %~dp0..\Core\replaceinfile.bat %project_path%\%work_project%Server\Extends\JwtMiddlewareOptionsHelper.cs %template_project% %work_project% + +call %~dp0..\Core\replaceinfile.bat %project_path%\%work_project%Server\Properties\launchSettings.json %template_project%Server %work_project%Server + +call %~dp0..\Core\replaceinfile.bat %project_path%\XUnitDAL.Test\XUnitWebApi.Test.csproj %template_project%Server %work_project%Server +call %~dp0..\Core\replaceinfile.bat %project_path%\XUnitDAL.Test\_Shared\Shared_Test_Controller_Generic.cs %template_project%Server %work_project%Server +call %~dp0..\Core\replaceinfile.bat %project_path%\XUnitDAL.Test\_Shared\Shared_Test_LDAP.cs %template_project%Server %work_project%Server +call %~dp0..\Core\replaceinfile.bat %project_path%\XUnitDAL.Test\_Shared\shared_test_config.cs %template_project% %work_project% +call %~dp0..\Core\replaceinfile.bat %project_path%\XUnitDAL.Test\Test_Controller_Entity.cs %template_project%Server %work_project%Server +call %~dp0..\Core\replaceinfile.bat %project_path%\XUnitDAL.Test\Test_Controller_Filter.cs %template_project%Server %work_project%Server + +call %~dp0..\Core\replaceinfile.bat %project_path%\%work_project%Server\appsettings.json %template_project% %work_project% +call %~dp0..\Core\replaceinfile.bat %project_path%\%work_project%Server\AppsettingsFiles\Production\appsettings.json %template_project% %work_project% +call %~dp0..\Core\replaceinfile.bat %project_path%\%work_project%Server\AppsettingsFiles\Develop\appsettings.json %template_project% %work_project% +:Prepare_batch_files +call %~dp0..\Core\sample_entity.bat %work_project% >add_one_entity.bat +if exist add_list_entities.bat del add_list_entities.bat + +:Prepare_batch_for_entities +for /F "delims=" %%L in ('findstr /n "^" "%entities_list%"') do ( + set "line=%%L" + + setlocal EnableDelayedExpansion + set "line=!line:*:=!" + if "!line!" neq "" echo call ..\Core\start_add_entity_to_project.bat %work_project% !line! >> add_list_entities.bat + endlocal +) + +:Prepare_batch_for_entities_with_filter +for /F "delims=" %%L in ('findstr /n "^" "%entities_filter_list%"') do ( + set "line=%%L" + + setlocal EnableDelayedExpansion + set "line=!line:*:=!" + set "entity_filter=" + set "entity=" + for /f "tokens=1,2 delims= " %%a in ("!line!") do set entity=%%a& set entity_filter=%%b + if "!entity_filter!"=="" set entity_filter=!line! + if "!entity!" neq "" echo call ..\Core\start_add_entity_to_project.bat %work_project% !entity! !entity_filter! >> add_list_entities.bat + endlocal +) + +if exist add_list_entities.bat call add_list_entities.bat diff --git a/StaffDBServer.sln b/StaffDBServer.sln new file mode 100644 index 0000000..39a5f60 --- /dev/null +++ b/StaffDBServer.sln @@ -0,0 +1,62 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33627.172 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StaffDBServer", "StaffDBServer\StaffDBServer.csproj", "{CCC1191A-F9FB-4BF4-BD26-6857B24CA0C5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DAL", "DAL\DAL.csproj", "{A83436AD-7571-4358-8A71-538584F72798}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "XUnitWebApi.Test", "XUnitDAL.Test\XUnitWebApi.Test.csproj", "{19C84E30-4A21-4A95-BAAB-0AF312F3ED43}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HRD.AppLogger", "HRD.AppLogger\HRD.AppLogger.csproj", "{1F35F354-083A-4467-82E9-6FDB691CBDCA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HRD.LDAPService", "HRD.LDAPService\HRD.LDAPService.csproj", "{B90CF1F9-9AB5-4415-8211-2644D75AA276}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HRD.LdapService.Test", "HRD.LdapService.Test\HRD.LdapService.Test.csproj", "{9E719C7C-B48C-4071-9412-886B41D7D442}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HRD.WebApi", "HRD.WebApi\HRD.WebApi.csproj", "{B886F61C-1555-477B-9804-319686FAF2C9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CCC1191A-F9FB-4BF4-BD26-6857B24CA0C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CCC1191A-F9FB-4BF4-BD26-6857B24CA0C5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CCC1191A-F9FB-4BF4-BD26-6857B24CA0C5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CCC1191A-F9FB-4BF4-BD26-6857B24CA0C5}.Release|Any CPU.Build.0 = Release|Any CPU + {A83436AD-7571-4358-8A71-538584F72798}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A83436AD-7571-4358-8A71-538584F72798}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A83436AD-7571-4358-8A71-538584F72798}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A83436AD-7571-4358-8A71-538584F72798}.Release|Any CPU.Build.0 = Release|Any CPU + {19C84E30-4A21-4A95-BAAB-0AF312F3ED43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {19C84E30-4A21-4A95-BAAB-0AF312F3ED43}.Debug|Any CPU.Build.0 = Debug|Any CPU + {19C84E30-4A21-4A95-BAAB-0AF312F3ED43}.Release|Any CPU.ActiveCfg = Release|Any CPU + {19C84E30-4A21-4A95-BAAB-0AF312F3ED43}.Release|Any CPU.Build.0 = Release|Any CPU + {1F35F354-083A-4467-82E9-6FDB691CBDCA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1F35F354-083A-4467-82E9-6FDB691CBDCA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1F35F354-083A-4467-82E9-6FDB691CBDCA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1F35F354-083A-4467-82E9-6FDB691CBDCA}.Release|Any CPU.Build.0 = Release|Any CPU + {B90CF1F9-9AB5-4415-8211-2644D75AA276}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B90CF1F9-9AB5-4415-8211-2644D75AA276}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B90CF1F9-9AB5-4415-8211-2644D75AA276}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B90CF1F9-9AB5-4415-8211-2644D75AA276}.Release|Any CPU.Build.0 = Release|Any CPU + {9E719C7C-B48C-4071-9412-886B41D7D442}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9E719C7C-B48C-4071-9412-886B41D7D442}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9E719C7C-B48C-4071-9412-886B41D7D442}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9E719C7C-B48C-4071-9412-886B41D7D442}.Release|Any CPU.Build.0 = Release|Any CPU + {B886F61C-1555-477B-9804-319686FAF2C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B886F61C-1555-477B-9804-319686FAF2C9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B886F61C-1555-477B-9804-319686FAF2C9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B886F61C-1555-477B-9804-319686FAF2C9}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {F02FC958-650A-495C-B4BA-13C2AFE9AB72} + SolutionGuid = {C7A45DA6-C1A5-4BE3-8A00-F3C3ABF566BA} + SolutionGuid = {3336A9F1-24F5-40E2-B3FB-42340B3E74A7} + EndGlobalSection +EndGlobal diff --git a/StaffDBServer/.config/dotnet-tools.json b/StaffDBServer/.config/dotnet-tools.json new file mode 100644 index 0000000..b0e38ab --- /dev/null +++ b/StaffDBServer/.config/dotnet-tools.json @@ -0,0 +1,5 @@ +{ + "version": 1, + "isRoot": true, + "tools": {} +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/AdWebAppToWebAppRoleController.cs b/StaffDBServer/Controllers/AdWebAppToWebAppRoleController.cs new file mode 100644 index 0000000..6ab4745 --- /dev/null +++ b/StaffDBServer/Controllers/AdWebAppToWebAppRoleController.cs @@ -0,0 +1,15 @@ +using DAL.Models.Entities; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class AdWebAppToWebAppRoleController : BaseController + { + public AdWebAppToWebAppRoleController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/CostCentreController.cs b/StaffDBServer/Controllers/CostCentreController.cs new file mode 100644 index 0000000..34b3252 --- /dev/null +++ b/StaffDBServer/Controllers/CostCentreController.cs @@ -0,0 +1,15 @@ +using DAL.Models.Entities; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class CostCentreController : BaseController + { + public CostCentreController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/DepartmentController.cs b/StaffDBServer/Controllers/DepartmentController.cs new file mode 100644 index 0000000..f35e091 --- /dev/null +++ b/StaffDBServer/Controllers/DepartmentController.cs @@ -0,0 +1,54 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using DAL.Repositories; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class DepartmentController : BaseController + { + public DepartmentController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + + [HttpPost("DepartmentFullFilter")] + public async Task GetDepartmentListAsync([FromBody] DepartmentFullFilter filter) + { + try + { + var list = await ((DepartmentRepository)EntityRepository).GetDepartmentListAsync(filter); + return new OkObjectResult(list); + } + catch (Exception ex) + { + this.WriteLogException(ex); + return StatusCode(StatusCodes.Status400BadRequest, $"Cann't get the filtered list of {typeof(Employee).Name}"); + } + } + + [HttpPut("CopyWindreamTiles/{DepartmentId}")] + public async Task GetVisitorListAsync(int DepartmentId, [FromBody] List trgDepartmentIds) + { + var strTrgDepartmentIds = string.Join(",", trgDepartmentIds); + try + { + await ((DepartmentRepository)EntityRepository).ReplaceWindreamTiles(DepartmentId, strTrgDepartmentIds); + this.WriteLogWarn($"Windream Search Tiles from Department Id={DepartmentId} are replaced Tiles in the Departments with Ids={strTrgDepartmentIds}"); + return new OkObjectResult(true); + } + catch (Exception ex) + { + this.WriteLogException(ex); + return StatusCode(StatusCodes.Status400BadRequest, $"Windream Search Tiles from Department Id={DepartmentId} cann't replace Tiles in the Departments with Ids={strTrgDepartmentIds}"); + } + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/DepartmentToWebAppToEmployeeForWindreamController.cs b/StaffDBServer/Controllers/DepartmentToWebAppToEmployeeForWindreamController.cs new file mode 100644 index 0000000..fa5f5aa --- /dev/null +++ b/StaffDBServer/Controllers/DepartmentToWebAppToEmployeeForWindreamController.cs @@ -0,0 +1,36 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using DAL.Repositories; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class DepartmentToWebAppToEmployeeForWindreamController : BaseController + { + public DepartmentToWebAppToEmployeeForWindreamController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + + [HttpPost("EmployeeFilter")] + public async Task GetDepartmentToWebAppToEmployeeForWindreamListAsync([FromBody] EmployeeFilter filter) + { + try + { + var list = await ((DepartmentToWebAppToEmployeeForWindreamRepository)EntityRepository).GetListByFilterAsync(filter); + return new OkObjectResult(list); + } + catch (Exception ex) + { + this.WriteLogException(ex); + return StatusCode(StatusCodes.Status400BadRequest, $"Cann't get the filtered list of {typeof(DepartmentToWebAppToEmployeeForWindream).Name}"); + } + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/DocumentArtController.cs b/StaffDBServer/Controllers/DocumentArtController.cs new file mode 100644 index 0000000..3b41883 --- /dev/null +++ b/StaffDBServer/Controllers/DocumentArtController.cs @@ -0,0 +1,15 @@ +using DAL.Models.Entities; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class DocumentArtController : BaseController + { + public DocumentArtController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/DocumentArtToDepartmentController.cs b/StaffDBServer/Controllers/DocumentArtToDepartmentController.cs new file mode 100644 index 0000000..6ce3149 --- /dev/null +++ b/StaffDBServer/Controllers/DocumentArtToDepartmentController.cs @@ -0,0 +1,36 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using DAL.Repositories; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class DocumentArtToDepartmentController : BaseController + { + public DocumentArtToDepartmentController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + + [HttpPost("DepartmentFilter")] + public async Task GetDocumentArtToDepartmentListAsync([FromBody] DepartmentFilter filter) + { + try + { + var list = await ((DocumentArtToDepartmentRepository)EntityRepository).GetListByFilterAsync(filter); + return new OkObjectResult(list); + } + catch (Exception ex) + { + this.WriteLogException(ex); + return StatusCode(StatusCodes.Status400BadRequest, $"Cann't get the filtered list of {typeof(DocumentArtToDepartment).Name}"); + } + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/EmployeeAttributeController.cs b/StaffDBServer/Controllers/EmployeeAttributeController.cs new file mode 100644 index 0000000..864be45 --- /dev/null +++ b/StaffDBServer/Controllers/EmployeeAttributeController.cs @@ -0,0 +1,15 @@ +using DAL.Models.Entities; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class EmployeeAttributeController : BaseController + { + public EmployeeAttributeController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/EmployeeController.cs b/StaffDBServer/Controllers/EmployeeController.cs new file mode 100644 index 0000000..54f70f7 --- /dev/null +++ b/StaffDBServer/Controllers/EmployeeController.cs @@ -0,0 +1,36 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using DAL.Repositories; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class EmployeeController : BaseController + { + public EmployeeController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + + [HttpPost("EmployeeFullFilter")] + public async Task GetEmployeeListAsync([FromBody] EmployeeFullFilter filter) + { + try + { + var list = await ((EmployeeRepository)EntityRepository).GetListByFilterAsync(filter); + return new OkObjectResult(list); + } + catch (Exception ex) + { + this.WriteLogException(ex); + return StatusCode(StatusCodes.Status400BadRequest, $"Cann't get the filtered list of {typeof(Employee).Name}"); + } + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/EmployeeStatusController.cs b/StaffDBServer/Controllers/EmployeeStatusController.cs new file mode 100644 index 0000000..7aa1e46 --- /dev/null +++ b/StaffDBServer/Controllers/EmployeeStatusController.cs @@ -0,0 +1,15 @@ +using DAL.Models.Entities; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class EmployeeStatusController : BaseController + { + public EmployeeStatusController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/EmployeeToAttributeController.cs b/StaffDBServer/Controllers/EmployeeToAttributeController.cs new file mode 100644 index 0000000..fcc4cd2 --- /dev/null +++ b/StaffDBServer/Controllers/EmployeeToAttributeController.cs @@ -0,0 +1,36 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using DAL.Repositories; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class EmployeeToAttributeController : BaseController + { + public EmployeeToAttributeController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + + [HttpPost("EmployeeFilter")] + public async Task GetEmployeeToAttributeListAsync([FromBody] EmployeeFilter filter) + { + try + { + var list = await ((EmployeeToAttributeRepository)EntityRepository).GetListByFilterAsync(filter); + return new OkObjectResult(list); + } + catch (Exception ex) + { + this.WriteLogException(ex); + return StatusCode(StatusCodes.Status400BadRequest, $"Cann't get the filtered list of {typeof(EmployeeToAttribute).Name}"); + } + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/EmployeeToDepartmentController.cs b/StaffDBServer/Controllers/EmployeeToDepartmentController.cs new file mode 100644 index 0000000..f5bf92f --- /dev/null +++ b/StaffDBServer/Controllers/EmployeeToDepartmentController.cs @@ -0,0 +1,36 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using DAL.Repositories; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class EmployeeToDepartmentController : BaseController + { + public EmployeeToDepartmentController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + + [HttpPost("EmployeeFilter")] + public async Task GetEmployeeToDepartmentListAsync([FromBody] EmployeeFilter filter) + { + try + { + var list = await ((EmployeeToDepartmentRepository)EntityRepository).GetListByFilterAsync(filter); + return new OkObjectResult(list); + } + catch (Exception ex) + { + this.WriteLogException(ex); + return StatusCode(StatusCodes.Status400BadRequest, $"Cann't get the filtered list of {typeof(EmployeeToDepartment).Name}"); + } + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/EmployeeToWebAppController.cs b/StaffDBServer/Controllers/EmployeeToWebAppController.cs new file mode 100644 index 0000000..b578b77 --- /dev/null +++ b/StaffDBServer/Controllers/EmployeeToWebAppController.cs @@ -0,0 +1,36 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using DAL.Repositories; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class EmployeeToWebAppController : BaseController + { + public EmployeeToWebAppController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + + [HttpPost("EmployeeFilter")] + public async Task GetEmployeeToWebAppListAsync([FromBody] EmployeeFilter filter) + { + try + { + var list = await ((EmployeeToWebAppRepository)EntityRepository).GetListByFilterAsync(filter); + return new OkObjectResult(list); + } + catch (Exception ex) + { + this.WriteLogException(ex); + return StatusCode(StatusCodes.Status400BadRequest, $"Cann't get the filtered list of {typeof(EmployeeToWebApp).Name}"); + } + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/ProjectController.cs b/StaffDBServer/Controllers/ProjectController.cs new file mode 100644 index 0000000..4f02814 --- /dev/null +++ b/StaffDBServer/Controllers/ProjectController.cs @@ -0,0 +1,15 @@ +using DAL.Models.Entities; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class ProjectController : BaseController + { + public ProjectController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/RangController.cs b/StaffDBServer/Controllers/RangController.cs new file mode 100644 index 0000000..27e0ccc --- /dev/null +++ b/StaffDBServer/Controllers/RangController.cs @@ -0,0 +1,15 @@ +using DAL.Models.Entities; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class RangController : BaseController + { + public RangController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/SubsidiaryController.cs b/StaffDBServer/Controllers/SubsidiaryController.cs new file mode 100644 index 0000000..7b8e806 --- /dev/null +++ b/StaffDBServer/Controllers/SubsidiaryController.cs @@ -0,0 +1,15 @@ +using DAL.Models.Entities; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class SubsidiaryController : BaseController + { + public SubsidiaryController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/WebAppAdditionalRoleController.cs b/StaffDBServer/Controllers/WebAppAdditionalRoleController.cs new file mode 100644 index 0000000..85e2f6c --- /dev/null +++ b/StaffDBServer/Controllers/WebAppAdditionalRoleController.cs @@ -0,0 +1,36 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using DAL.Repositories; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class WebAppAdditionalRoleController : BaseController + { + public WebAppAdditionalRoleController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + + [HttpPost("WebAppFilter")] + public async Task GetWebAppAdditionalRoleListAsync([FromBody] WebAppFilter filter) + { + try + { + var list = await ((WebAppAdditionalRoleRepository)EntityRepository).GetListByFilterAsync(filter); + return new OkObjectResult(list); + } + catch (Exception ex) + { + this.WriteLogException(ex); + return StatusCode(StatusCodes.Status400BadRequest, $"Cann't get the filtered list of {typeof(WebAppAdditionalRole).Name}"); + } + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/WebAppController.cs b/StaffDBServer/Controllers/WebAppController.cs new file mode 100644 index 0000000..0b7b6c5 --- /dev/null +++ b/StaffDBServer/Controllers/WebAppController.cs @@ -0,0 +1,15 @@ +using DAL.Models.Entities; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class WebAppController : BaseController + { + public WebAppController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/WebAppRoleController.cs b/StaffDBServer/Controllers/WebAppRoleController.cs new file mode 100644 index 0000000..4675d49 --- /dev/null +++ b/StaffDBServer/Controllers/WebAppRoleController.cs @@ -0,0 +1,15 @@ +using DAL.Models.Entities; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class WebAppRoleController : BaseController + { + public WebAppRoleController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/WebAppToDepartmentController.cs b/StaffDBServer/Controllers/WebAppToDepartmentController.cs new file mode 100644 index 0000000..20f5129 --- /dev/null +++ b/StaffDBServer/Controllers/WebAppToDepartmentController.cs @@ -0,0 +1,36 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using DAL.Repositories; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class WebAppToDepartmentController : BaseController + { + public WebAppToDepartmentController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + + [HttpPost("EmployeeToWebAppFilter")] + public async Task GetWebAppToDepartmentListAsync([FromBody] EmployeeToWebAppFilter filter) + { + try + { + var list = await ((WebAppToDepartmentRepository)EntityRepository).GetListByFilterAsync(filter); + return new OkObjectResult(list); + } + catch (Exception ex) + { + this.WriteLogException(ex); + return StatusCode(StatusCodes.Status400BadRequest, $"Cann't get the filtered list of {typeof(WebAppToDepartment).Name}"); + } + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/WebAppToWebAppAdditionalRoleController.cs b/StaffDBServer/Controllers/WebAppToWebAppAdditionalRoleController.cs new file mode 100644 index 0000000..3ac623d --- /dev/null +++ b/StaffDBServer/Controllers/WebAppToWebAppAdditionalRoleController.cs @@ -0,0 +1,36 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using DAL.Repositories; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class WebAppToWebAppAdditionalRoleController : BaseController + { + public WebAppToWebAppAdditionalRoleController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + + [HttpPost("EmployeeToWebAppFilter")] + public async Task GetWebAppToWebAppAdditionalRoleListAsync([FromBody] EmployeeToWebAppFilter filter) + { + try + { + var list = await ((WebAppToWebAppAdditionalRoleRepository)EntityRepository).GetListByFilterAsync(filter); + return new OkObjectResult(list); + } + catch (Exception ex) + { + this.WriteLogException(ex); + return StatusCode(StatusCodes.Status400BadRequest, $"Cann't get the filtered list of {typeof(WebAppToWebAppAdditionalRole).Name}"); + } + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/WebAppToWebAppRoleController.cs b/StaffDBServer/Controllers/WebAppToWebAppRoleController.cs new file mode 100644 index 0000000..8208ef3 --- /dev/null +++ b/StaffDBServer/Controllers/WebAppToWebAppRoleController.cs @@ -0,0 +1,36 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using DAL.Repositories; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class WebAppToWebAppRoleController : BaseController + { + public WebAppToWebAppRoleController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + + [HttpPost("WebAppFilter")] + public async Task GetWebAppToWebAppRoleListAsync([FromBody] WebAppFilter filter) + { + try + { + var list = await ((WebAppToWebAppRoleRepository)EntityRepository).GetListByFilterAsync(filter); + return new OkObjectResult(list); + } + catch (Exception ex) + { + this.WriteLogException(ex); + return StatusCode(StatusCodes.Status400BadRequest, $"Cann't get the filtered list of {typeof(WebAppToWebAppRole).Name}"); + } + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/WindreamColumnsToDepartmentController.cs b/StaffDBServer/Controllers/WindreamColumnsToDepartmentController.cs new file mode 100644 index 0000000..8a0be37 --- /dev/null +++ b/StaffDBServer/Controllers/WindreamColumnsToDepartmentController.cs @@ -0,0 +1,36 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using DAL.Repositories; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class WindreamColumnsToDepartmentController : BaseController + { + public WindreamColumnsToDepartmentController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + + [HttpPost("DepartmentFilter")] + public async Task GetWindreamColumnsToDepartmentListAsync([FromBody] DepartmentFilter filter) + { + try + { + var list = await ((WindreamColumnsToDepartmentRepository)EntityRepository).GetListByFilterAsync(filter); + return new OkObjectResult(list); + } + catch (Exception ex) + { + this.WriteLogException(ex); + return StatusCode(StatusCodes.Status400BadRequest, $"Cann't get the filtered list of {typeof(WindreamColumnsToDepartment).Name}"); + } + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/WindreamIndexController.cs b/StaffDBServer/Controllers/WindreamIndexController.cs new file mode 100644 index 0000000..f390310 --- /dev/null +++ b/StaffDBServer/Controllers/WindreamIndexController.cs @@ -0,0 +1,36 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using DAL.Repositories; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class WindreamIndexController : BaseController + { + public WindreamIndexController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + + [HttpPost("ClientIdFilter")] + public async Task GetWindreamIndexListAsync([FromBody] ClientIdFilter filter) + { + try + { + var list = await ((WindreamIndexRepository)EntityRepository).GetListByFilterAsync(filter); + return new OkObjectResult(list); + } + catch (Exception ex) + { + this.WriteLogException(ex); + return StatusCode(StatusCodes.Status400BadRequest, $"Cann't get the filtered list of {typeof(WindreamIndex).Name}"); + } + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/WindreamIndexToWindreamSearchToDepartmentController.cs b/StaffDBServer/Controllers/WindreamIndexToWindreamSearchToDepartmentController.cs new file mode 100644 index 0000000..793a1d1 --- /dev/null +++ b/StaffDBServer/Controllers/WindreamIndexToWindreamSearchToDepartmentController.cs @@ -0,0 +1,36 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using DAL.Repositories; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class WindreamIndexToWindreamSearchToDepartmentController : BaseController + { + public WindreamIndexToWindreamSearchToDepartmentController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + + [HttpPost("WindreamSearchToDepartmentFilter")] + public async Task GetWindreamIndexToWindreamSearchToDepartmentListAsync([FromBody] WindreamSearchToDepartmentFilter filter) + { + try + { + var list = await ((WindreamIndexToWindreamSearchToDepartmentRepository)EntityRepository).GetListByFilterAsync(filter); + return new OkObjectResult(list); + } + catch (Exception ex) + { + this.WriteLogException(ex); + return StatusCode(StatusCodes.Status400BadRequest, $"Cann't get the filtered list of {typeof(WindreamIndexToWindreamSearchToDepartment).Name}"); + } + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/WindreamInputFolderController.cs b/StaffDBServer/Controllers/WindreamInputFolderController.cs new file mode 100644 index 0000000..8d89ca1 --- /dev/null +++ b/StaffDBServer/Controllers/WindreamInputFolderController.cs @@ -0,0 +1,36 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using DAL.Repositories; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class WindreamInputFolderController : BaseController + { + public WindreamInputFolderController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + + [HttpPost("WindreamInputFolderFilter")] + public async Task GetWindreamInputFolderListAsync([FromBody] WindreamInputFolderFilter filter) + { + try + { + var list = await ((WindreamInputFolderRepository)EntityRepository).GetListByFilterAsync(filter); + return new OkObjectResult(list); + } + catch (Exception ex) + { + this.WriteLogException(ex); + return StatusCode(StatusCodes.Status400BadRequest, $"Cann't get the filtered list of {typeof(WindreamInputFolder).Name}"); + } + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/WindreamSearchController.cs b/StaffDBServer/Controllers/WindreamSearchController.cs new file mode 100644 index 0000000..50776e3 --- /dev/null +++ b/StaffDBServer/Controllers/WindreamSearchController.cs @@ -0,0 +1,36 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using DAL.Repositories; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class WindreamSearchController : BaseController + { + public WindreamSearchController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + + [HttpPost("ClientIdFilter")] + public async Task GetWindreamSearchListAsync([FromBody] ClientIdFilter filter) + { + try + { + var list = await ((WindreamSearchRepository)EntityRepository).GetListByFilterAsync(filter); + return new OkObjectResult(list); + } + catch (Exception ex) + { + this.WriteLogException(ex); + return StatusCode(StatusCodes.Status400BadRequest, $"Cann't get the filtered list of {typeof(WindreamSearch).Name}"); + } + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/WindreamSearchItemController.cs b/StaffDBServer/Controllers/WindreamSearchItemController.cs new file mode 100644 index 0000000..1885bcb --- /dev/null +++ b/StaffDBServer/Controllers/WindreamSearchItemController.cs @@ -0,0 +1,36 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using DAL.Repositories; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class WindreamSearchItemController : BaseController + { + public WindreamSearchItemController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + + [HttpPost("ClientIdFilter")] + public async Task GetWindreamSearchItemListAsync([FromBody] ClientIdFilter filter) + { + try + { + var list = await ((WindreamSearchItemRepository)EntityRepository).GetListByFilterAsync(filter); + return new OkObjectResult(list); + } + catch (Exception ex) + { + this.WriteLogException(ex); + return StatusCode(StatusCodes.Status400BadRequest, $"Cann't get the filtered list of {typeof(WindreamSearchItem).Name}"); + } + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/WindreamSearchItemToWindreamSearchToDepartmentController.cs b/StaffDBServer/Controllers/WindreamSearchItemToWindreamSearchToDepartmentController.cs new file mode 100644 index 0000000..3d2bc11 --- /dev/null +++ b/StaffDBServer/Controllers/WindreamSearchItemToWindreamSearchToDepartmentController.cs @@ -0,0 +1,36 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using DAL.Repositories; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class WindreamSearchItemToWindreamSearchToDepartmentController : BaseController + { + public WindreamSearchItemToWindreamSearchToDepartmentController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + + [HttpPost("WindreamSearchToDepartmentFilter")] + public async Task GetWindreamSearchItemToWindreamSearchToDepartmentListAsync([FromBody] WindreamSearchToDepartmentFilter filter) + { + try + { + var list = await ((WindreamSearchItemToWindreamSearchToDepartmentRepository)EntityRepository).GetListByFilterAsync(filter); + return new OkObjectResult(list); + } + catch (Exception ex) + { + this.WriteLogException(ex); + return StatusCode(StatusCodes.Status400BadRequest, $"Cann't get the filtered list of {typeof(WindreamSearchItemToWindreamSearchToDepartment).Name}"); + } + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Controllers/WindreamSearchToDepartmentController.cs b/StaffDBServer/Controllers/WindreamSearchToDepartmentController.cs new file mode 100644 index 0000000..48a046a --- /dev/null +++ b/StaffDBServer/Controllers/WindreamSearchToDepartmentController.cs @@ -0,0 +1,54 @@ +using DAL.Models.Entities; +using DAL.Models.Filters; +using DAL.Repositories; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using HRD.WebApi.Repositories; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace StaffDBServer.Controllers +{ + [JWTAuthorize] + public class WindreamSearchToDepartmentController : BaseController + { + public WindreamSearchToDepartmentController(IBaseRepository repositoryBase) : base(repositoryBase) + { + } + + [HttpPost("DepartmentFilter")] + public async Task GetWindreamSearchToDepartmentListAsync([FromBody] DepartmentFilter filter) + { + try + { + var list = await ((WindreamSearchToDepartmentRepository)EntityRepository).GetListByFilterAsync(filter); + return new OkObjectResult(list); + } + catch (Exception ex) + { + this.WriteLogException(ex); + return StatusCode(StatusCodes.Status400BadRequest, $"Cann't get the filtered list of {typeof(WindreamSearchToDepartment).Name}"); + } + } + + [HttpPut("CopyWindreamTile/{WindreamSearchToDepartmentId}")] + public async Task GetVisitorListAsync(int WindreamSearchToDepartmentId, [FromBody] List trgDepartmentIds) + { + var strTrgDepartmentIds = string.Join(",", trgDepartmentIds); + try + { + await ((WindreamSearchToDepartmentRepository)EntityRepository).AddWindreamTile(WindreamSearchToDepartmentId, strTrgDepartmentIds); + this.WriteLogWarn($"Windream Search Tile Id={WindreamSearchToDepartmentId} is added to Departments wit Ids={strTrgDepartmentIds}"); + return new OkObjectResult(true); + } + catch (Exception ex) + { + this.WriteLogException(ex); + return StatusCode(StatusCodes.Status400BadRequest, $"Cann't add Windream Search Tile Id={WindreamSearchToDepartmentId} to Departments wit Ids={strTrgDepartmentIds}"); + } + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Extends/JwtMiddlewareOptionsHelper.cs b/StaffDBServer/Extends/JwtMiddlewareOptionsHelper.cs new file mode 100644 index 0000000..bd8fb56 --- /dev/null +++ b/StaffDBServer/Extends/JwtMiddlewareOptionsHelper.cs @@ -0,0 +1,37 @@ +using HRD.LDAPService; +using HRD.LDAPService.JWT; +using HRD.WebApi; +using System.Collections.Generic; + +namespace StaffDBServer.Extends + +{ + public static class JwtMiddlewareOptionsHelper + { + public static JwtMiddlewareOptions GetJwtMiddlewareOptions() + { + var list = new List(); + var ADGroupPrefix = WebApiConfig.IsLive ? "" : "__Test"; + + //Admin Role + list.Add(new JwtRole(JwtGlobals.ROLE_ADMIN, "GG_WebApp" + ADGroupPrefix + "_StaffDB_Admin")); + + //Core RoleList + list.Add(new JwtRole(JwtGlobals.ROLE_USER, "GG_WebApp" + ADGroupPrefix + "_StaffDB_User")); //(RO) nur eigene + list.Add(new JwtRole(JwtGlobals.ROLE_MASTER, "GG_WebApp" + ADGroupPrefix + "_StaffDB_Master")); //RW ALLE Abteilungen + list.Add(new JwtRole(JwtGlobals.ROLE_DEPARTMENTUSER, "GG_WebApp" + ADGroupPrefix + "_StaffDB_DepartmentUser")); //(RW) auch andere aus eigener Abteilung + list.Add(new JwtRole(JwtGlobals.ROLE_DEPARTMENTMASTER, "GG_WebApp" + ADGroupPrefix + "_StaffDB_DepartmentMaster")); //(RW) auch andere aus eigener Abteilung + + JwtMiddlewareOptions options = new JwtMiddlewareOptions() + { + Secret = "12345678901234567809_MY_VERY_LONG_SECRET", + JwtRoleList = list, + ExpirationInMin = 60 * 24 * 30 * 1, //1 Month + AktivateAuthorizationFilter = true, + AuthorizationFilterWhitelistPath = new List() { "api/WebAppUser/LoginWithNameAndPassword", "api/Info" }, + AuthorizationFilterBlacklistPath = new List() { "api/WebAppUser/all" } + }; + return options; + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Extends/ServiceExtensions4BaseRepository.cs b/StaffDBServer/Extends/ServiceExtensions4BaseRepository.cs new file mode 100644 index 0000000..37c1117 --- /dev/null +++ b/StaffDBServer/Extends/ServiceExtensions4BaseRepository.cs @@ -0,0 +1,47 @@ +using DAL._Shared.SharedModels; +using DAL._Shared.SharedRepositories; +using DAL.Models.Entities; +using DAL.Repositories; +using HRD.WebApi.Repositories; +using Microsoft.Extensions.DependencyInjection; + +namespace StaffDBServer.Extends +{ + public static class ServiceExtensions4BaseRepository + { + public static void ConfigureRepositoryWrapper(this IServiceCollection services) + { + services.AddScoped(typeof(IBaseRepository), typeof(SubsidiaryRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(WindreamInputFolderRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(WindreamSearchToDepartmentRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(WindreamSearchItemToWindreamSearchToDepartmentRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(WindreamSearchItemRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(WindreamSearchRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(WindreamIndexToWindreamSearchToDepartmentRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(WindreamIndexRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(WindreamColumnsToDepartmentRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(WebAppToWebAppRoleRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(WebAppToWebAppAdditionalRoleRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(WebAppToDepartmentRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(WebAppAdditionalRoleRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(EmployeeToWebAppRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(EmployeeToDepartmentRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(EmployeeToAttributeRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(EmployeeRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(DocumentArtToDepartmentRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(DepartmentToWebAppToEmployeeForWindreamRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(WebAppRoleRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(WebAppRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(RangRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(ProjectRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(EmployeeStatusRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(EmployeeAttributeRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(DocumentArtRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(DepartmentRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(CostCentreRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(AdWebAppToWebAppRoleRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(WebAppUserRepository)); + services.AddScoped(typeof(IBaseRepository), typeof(WebAppEmployeeInfo)); + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Nuget.config b/StaffDBServer/Nuget.config new file mode 100644 index 0000000..4e0ab30 --- /dev/null +++ b/StaffDBServer/Nuget.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/StaffDBServer/Program.cs b/StaffDBServer/Program.cs new file mode 100644 index 0000000..f25da92 --- /dev/null +++ b/StaffDBServer/Program.cs @@ -0,0 +1,67 @@ +using HRD.AppLogger; +using HRD.WebApi; +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using NLog.Web; +using System; +using System.Reflection; + +namespace StaffDBServer +{ + public class Program + { + public static void Main(string[] args) + + { + AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException; + + IConfiguration configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json", true, true).Build(); + + WebApiConfig.Init(configuration, Assembly.GetExecutingAssembly().GetName()); + + ILoggerManager logger = new LoggerManager(); + logger.LogWarn($"[Start WebApi Server] BaseDirectory: {AppDomain.CurrentDomain.BaseDirectory}; TargetFrameworkName: {AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName}"); + + try + { + CreateWebHostBuilder(args) + .Build() + .Run(); + } + catch (Exception ex) + { + logger.LogException(ex, "Stopped program because of exception"); + throw; + } + finally + { + // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux) + NLog.LogManager.Flush(); + NLog.LogManager.Shutdown(); + } + } + + public static IWebHostBuilder CreateWebHostBuilder(string[] args) => + + WebHost.CreateDefaultBuilder(args) + + .ConfigureLogging(options => options.ClearProviders()) + .UseStartup().ConfigureLogging(logging => + { + logging.ClearProviders(); + logging.SetMinimumLevel(LogLevel.Warning); + }) + .UseNLog(); + + private static void CurrentDomainOnUnhandledException(object sender, UnhandledExceptionEventArgs unhandledExceptionEventArgs) + + { + ILoggerManager logger = new LoggerManager(); + logger.LogException((Exception)unhandledExceptionEventArgs.ExceptionObject, "Application closed due to exception."); + NLog.LogManager.Flush(); + } + } +} \ No newline at end of file diff --git a/StaffDBServer/Properties/launchSettings.json b/StaffDBServer/Properties/launchSettings.json new file mode 100644 index 0000000..500661c --- /dev/null +++ b/StaffDBServer/Properties/launchSettings.json @@ -0,0 +1,13 @@ +{ + "profiles": { + "StaffDBServer": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:54305;http://localhost:54306", + "sqlDebugging": true + } + } +} \ No newline at end of file diff --git a/StaffDBServer/StaffDBServer.csproj b/StaffDBServer/StaffDBServer.csproj new file mode 100644 index 0000000..a8c47a2 --- /dev/null +++ b/StaffDBServer/StaffDBServer.csproj @@ -0,0 +1,25 @@ + + + + netcoreapp7.0 + 1.0.0 + 1.0.0.0 + 1.0.0.0 + + + + 1701;1702;$(NoWarn);1591 + + Auto + + + + + + + + + + + + \ No newline at end of file diff --git a/StaffDBServer/Startup.cs b/StaffDBServer/Startup.cs new file mode 100644 index 0000000..6a4a0cd --- /dev/null +++ b/StaffDBServer/Startup.cs @@ -0,0 +1,69 @@ +using DAL; +using HRD.LDAPService.JWT; +using HRD.WebApi; +using HRD.WebApi.DAL.Middleware; +using HRD.WebApi.Helpers; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using NLog.Web; +using StaffDBServer.Extends; +using StaffDBServer.SharedExtensions; +using System; + +namespace StaffDBServer +{ + public class Startup + { + public void ConfigureServices(IServiceCollection services) + { + services.ConfigureWebApiExtensionsAtFirst(); //at first + + services.ConfigureRepositoryWrapper(); //add repos + + services.AddDbContext(options => + { + const int dbTimeoutInMin = 5; + options + .UseSqlServer(WebApiConfig.ConnectionString(EN_ConnectionType.SQLServer), + opts => opts.CommandTimeout((int)TimeSpan.FromMinutes(dbTimeoutInMin).TotalSeconds)); + }); + + services.ConfigureWebApiExtensionsEnd(); //should come last + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + app.ApplicationServices.SetupNLogServiceLocator(); + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + else + { + app.UseHsts(); + } + app.AddCustomExceptionHandling(); + + app.UseHttpsRedirection(); + + app.UseRouting(); + + app.UseCors("AllowAllOrigins"); + + app.UseOpenApi(); + + app.UseDALMiddleware(); + app.UseJwtMiddleware(); + app.ConfigureSwagger(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + } + } +} \ No newline at end of file diff --git a/StaffDBServer/_Shared/SharedControllers/InfoController.cs b/StaffDBServer/_Shared/SharedControllers/InfoController.cs new file mode 100644 index 0000000..88b5c26 --- /dev/null +++ b/StaffDBServer/_Shared/SharedControllers/InfoController.cs @@ -0,0 +1,16 @@ +using DAL; +using HRD.WebApi.Controllers; +using Microsoft.AspNetCore.Mvc; + +namespace StaffDBServer.SharedExtensions +{ + [Route("api/[controller]")] + [Produces("application/json")] + [ApiController] + public class InfoController : InfoBaseController + { + public InfoController() : base(new WebApiContext()) + { + } + } +} \ No newline at end of file diff --git a/StaffDBServer/_Shared/SharedControllers/WebAppUserController.cs b/StaffDBServer/_Shared/SharedControllers/WebAppUserController.cs new file mode 100644 index 0000000..bd00ea3 --- /dev/null +++ b/StaffDBServer/_Shared/SharedControllers/WebAppUserController.cs @@ -0,0 +1,99 @@ +using DAL; +using DAL._Shared.SharedModels; +using DAL._Shared.SharedRepositories; +using HRD.LDAPService.JWT; +using HRD.WebApi.Controllers; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Net.Http.Headers; +using System; +using System.Threading.Tasks; + +namespace StaffDBServer.SharedControllers +{ + [JWTAuthorizeAttribute] + public class WebAppUserController : BaseMiniController + { + public WebAppUserController() : base(new WebApiContext()) + { + } + + [HttpPost("Culture")] + public async Task UpdateCultureAsync([FromBody] WebAppUser userFromClient) + { + try + { + //User Should by in the DB + WebAppUserRepository webAppUserRepository = new WebAppUserRepository(); + WebAppUser userFromDB = await webAppUserRepository.GetByAsync(u => u.LoginName == userFromClient.LoginName, false); + + if (userFromDB != default) //first login, get User from WebAppEmployeeInfo + { + userFromDB.Language = userFromClient.Language; + userFromDB.Culture = userFromClient.Culture; + if (!await webAppUserRepository.UpdateAsync(userFromDB)) + { + return StatusCode(StatusCodes.Status400BadRequest, $"Cannot set User's language/culture"); + } + } + return new OkObjectResult(userFromClient); + } + catch (Exception ex) + { + WriteLogException(ex, ex.Message); + return StatusCode(StatusCodes.Status400BadRequest, $"Cannot set User's language/culture"); + } + } + + [HttpPost("LoginWithJWT")] + public async Task LoginWithAuthorizationAsync([FromBody] WebAppUser userFromClient) + { + try + { + var accessToken = Request.Headers[HeaderNames.Authorization]; + WebAppUserHelper webAppUserHelper = new WebAppUserHelper(); + WebAppUser result = await webAppUserHelper.CheckLoginWithJWTAsync(accessToken, userFromClient.ClientVersion); + return new OkObjectResult(result); + } + catch (Exception ex) + { + WriteLogException(ex, ex.Message); + return Unauthorized(ex.Message); + } + } + + [HttpPost("LoginWithNameAndPassword/{webApiId}"),] + [Microsoft.AspNetCore.Authorization.AllowAnonymous] + public async Task LoginWithNameAndPasswordAsync([FromBody] WebAppUser userFromClient, int webApiId) + { + try + { + WebAppUserHelper webAppUserHelper = new WebAppUserHelper(); + var result = await webAppUserHelper.CheckLoginWithNameAndPasswordAsync(userFromClient, webApiId); + return new OkObjectResult(result); + } + catch (Exception ex) + { + WriteLogException(ex, ex.Message); + return NotFound(ex.Message); + } + } + + [HttpPost("LoginWithNameAndPassword")] + [Microsoft.AspNetCore.Authorization.AllowAnonymous] + public async Task LoginWithNameAndPasswordAsync([FromBody] WebAppUser userFromClient) + { + try + { + WebAppUserHelper webAppUserHelper = new WebAppUserHelper(); + var result = await webAppUserHelper.CheckLoginWithNameAndPasswordAsync(userFromClient); + return new OkObjectResult(result); + } + catch (Exception ex) + { + WriteLogException(ex, ex.Message); + return NotFound(ex.Message); + } + } + } +} \ No newline at end of file diff --git a/StaffDBServer/_Shared/SharedControllers/WebAppUserHelper.cs b/StaffDBServer/_Shared/SharedControllers/WebAppUserHelper.cs new file mode 100644 index 0000000..45039bb --- /dev/null +++ b/StaffDBServer/_Shared/SharedControllers/WebAppUserHelper.cs @@ -0,0 +1,204 @@ +using DAL._Shared.SharedModels; +using DAL._Shared.SharedRepositories; +using HRD.LDAPService; +using HRD.LDAPService.JWT; +using Microsoft.Extensions.Primitives; +using System; +using System.Threading.Tasks; + +namespace StaffDBServer.SharedControllers +{ + public class WebAppUserHelper + { + private const int GLB_LOGIN_LOCK_TIME_IN_MIN = 5; + + public int GlbWebApiIdStaffDB { get; private set; } = 2; + + public async Task CheckLoginWithJWTAsync(StringValues accessToken, string clientVersion) + { + WebAppUserRepository webAppUserRepository = new WebAppUserRepository(); + if (!JwtManager.IsValidatJwtTokenSubject(accessToken)) + { + throw new UnauthorizedAccessException($"Not valid JWT"); + } + + var ldapUser = JwtManager.DecryptTokenAsLdapUser(accessToken); + if (ldapUser == null) + { + throw new UnauthorizedAccessException($"Unable to decrypt JWT"); + } + + WebAppEmployeeInfoRepository webAppEmployeeInfoRepository = new WebAppEmployeeInfoRepository(); + WebAppEmployeeInfo webAppEmployeeInfo = await webAppEmployeeInfoRepository.GetByAsync(x => x.LoginName == ldapUser.LoginName); + if (webAppEmployeeInfo == default) + { + throw new UnauthorizedAccessException($"User '{ldapUser.LoginName}' cannot be found in StaffDB."); + } + + var userFromDB = await webAppUserRepository.GetByAsync(u => u.LoginName == ldapUser.LoginName, false); + if (userFromDB == default) + { + throw new UnauthorizedAccessException($"Unable to load WebApiUser:{ldapUser.LoginName}"); + } + + if (userFromDB.JwtExpiredOn == null) + { + throw new UnauthorizedAccessException($"User have to relogin; LoginName: {ldapUser.LoginName}"); + } + + userFromDB.RoleList = ldapUser.RoleListAsString(EN_LdapRoleListFilter.OnlyRoleList); + userFromDB.WebAppRoleList = ldapUser.RoleListAsString(EN_LdapRoleListFilter.OnlyWebAppRoleList); + userFromDB.Token = ldapUser.Token; + userFromDB.JwtExpiredOn = ldapUser.JwtExpiredOn; + userFromDB.LastLogin = DateTime.Now; + userFromDB.ClientVersion = clientVersion; + + if (await webAppUserRepository.SaveChangesAsync()) + { + return userFromDB; + } + return (default); + } + + public async Task CheckLoginWithNameAndPasswordAsync(WebAppUser userFromClient, int webAppId) + { + try + { + WebAppEmployeeInfoRepository webAppEmployeeInfoRepository = new WebAppEmployeeInfoRepository(); + WebAppEmployeeInfo webAppEmployeeInfo = await webAppEmployeeInfoRepository.GetByAsync(x => x.LoginName == userFromClient.LoginName && x.WebAppId == webAppId); + WebAppUserRepository webAppUserRepository = new WebAppUserRepository(); + return await DoCheckLoginWithNameAndPasswordAsync(userFromClient, webAppUserRepository, webAppEmployeeInfoRepository); + } + catch (Exception ex) + { + throw ex; + } + } + + public async Task CheckLoginWithNameAndPasswordAsync(WebAppUser userFromClient) + { + try + { + WebAppEmployeeInfoRepository webAppEmployeeInfoRepository = new WebAppEmployeeInfoRepository(); + WebAppEmployeeInfo webAppEmployeeInfo = await webAppEmployeeInfoRepository.GetByAsync(x => x.LoginName == userFromClient.LoginName && x.WebAppId == GlbWebApiIdStaffDB); + WebAppUserRepository webAppUserRepository = new WebAppUserRepository(); + return await DoCheckLoginWithNameAndPasswordAsync(userFromClient, webAppUserRepository, webAppEmployeeInfoRepository); + } + catch (Exception ex) + { + throw ex; + } + } + + private static async Task DoCheckLoginWithNameAndPasswordAsync(WebAppUser userFromClient, WebAppUserRepository webAppUserRepository, WebAppEmployeeInfoRepository webAppEmployeeInfoRepository) + { + try + { + WebAppEmployeeInfo webAppEmployeeInfo = await webAppEmployeeInfoRepository.GetByAsync(x => x.LoginName == userFromClient.LoginName); + if (webAppEmployeeInfo == default) + { + if (userFromClient.IsGermanCulture()) + { + throw new UnauthorizedAccessException($"Benutzer '{userFromClient.LoginName}' wurde in der StaffDB nicht freigeschaltet."); + } + else + { + throw new UnauthorizedAccessException($"User '{userFromClient.LoginName}' was not set in der StaffDB."); + } + } + + LdapUser ldapUser = new LdapUser(userFromClient.LoginName, webAppEmployeeInfo.EmployeeId, userFromClient.Password, webAppEmployeeInfo.DepartmentId, webAppEmployeeInfo.ExtendedDepartmentIdList); + if (!JwtManager.GenerateLdapUserWithJwtToken(ldapUser)) + { + if (ldapUser == default) + { + if (userFromClient.IsGermanCulture()) + { + throw new UnauthorizedAccessException($"Mit den Anmeldeinformationen (Loginname: '{userFromClient.LoginName}') konnte keine Verbindung hergestellt werden"); + } + else + { + throw new UnauthorizedAccessException($"With login data (Loginname: '{userFromClient.LoginName}') cannot be logged"); + } + } + + if (ldapUser.IsAccountLockedOut) + { + System.Globalization.CultureInfo cultureinfo = new System.Globalization.CultureInfo(userFromClient.Culture); + var lastBadPasswordAttemptLocalTime = ldapUser.AccountLockoutTime - TimeSpan.FromMinutes(userFromClient.TimeZoneOffsetInMin); + var waitTillTime = lastBadPasswordAttemptLocalTime?.AddMinutes(GLB_LOGIN_LOCK_TIME_IN_MIN + 1); + + if (userFromClient.IsGermanCulture()) + { + throw new UnauthorizedAccessException($"Der Benutzer mit Loginnamen '{ldapUser.LoginName}' wurde am {lastBadPasswordAttemptLocalTime?.ToString(cultureinfo)} gesperrt!\nVersuchen Sie sich um {waitTillTime?.ToString(cultureinfo.DateTimeFormat.ShortTimePattern)} neuanzumelden."); + } + else + { + throw new UnauthorizedAccessException($"The user with the loginname '{ldapUser.LoginName}' was locked on {lastBadPasswordAttemptLocalTime?.ToString(cultureinfo)}!\nTry to log again at {waitTillTime?.ToString(cultureinfo.DateTimeFormat.ShortTimePattern)}."); + } + } + + if (!ldapUser.Enabled) + { + if (userFromClient.IsGermanCulture()) + { + throw new UnauthorizedAccessException($"Der Benutzer mit Loginnamen '{userFromClient.LoginName}' ist deaktiviert!"); + } + else + { + throw new UnauthorizedAccessException($"The user with loginname '{userFromClient.LoginName}' is inactive!"); + } + } + + if (!ldapUser.IsValidatCredentials) + { + if (userFromClient.IsGermanCulture()) + { + throw new UnauthorizedAccessException($"Sie haben Ihren Loginnamen '{userFromClient.LoginName}' oder Ihr Passwort falsch eingegeben.\nAchtung, das Passwort wurde {ldapUser.BadLogonCount} Mal falsch eingegeben!"); + } + else + { + throw new UnauthorizedAccessException($"Your loginname '{userFromClient.LoginName}' or password is wrong.\nAttention, you have input wrong password {ldapUser.BadLogonCount} times!"); + } + } + } + + WebAppUser userFromDB = await webAppUserRepository.GetByAsync(u => u.LoginName == userFromClient.LoginName, false); + if (userFromDB == default) //get the WebAppUser data from LDAP & StaffDB + { + userFromDB = new WebAppUser(ldapUser.LoginName, webAppEmployeeInfo.ShortName, ldapUser.RoleListAsString(), $"{webAppEmployeeInfo.FirstName} {webAppEmployeeInfo.LastName}"); + userFromDB.Language = userFromClient.Language; + userFromDB.Culture = userFromClient.Culture; + if (!await webAppUserRepository.AddAsync(userFromDB)) + { + if (userFromClient.IsGermanCulture()) + { + throw new UnauthorizedAccessException($"Benutzer '{userFromClient.LoginName}' konnte nicht automatisch erstellt werden."); + } + else + { + throw new UnauthorizedAccessException($"User '{userFromClient.LoginName}' cannot be created automatically."); + } + } + } + + userFromDB.RoleList = ldapUser.RoleListAsString(EN_LdapRoleListFilter.OnlyRoleList); + userFromDB.WebAppRoleList = ldapUser.RoleListAsString(EN_LdapRoleListFilter.OnlyWebAppRoleList); + userFromDB.Token = ldapUser.Token; + userFromDB.JwtExpiredOn = ldapUser.JwtExpiredOn; + userFromDB.LastLogin = DateTime.Now; + userFromDB.ClientVersion = userFromClient.ClientVersion; + + if (await webAppUserRepository.SaveChangesAsync()) + { + return userFromDB; + } + return (default); + } + catch (Exception ex) + { + throw ex; + } + } + } +} \ No newline at end of file diff --git a/StaffDBServer/_Shared/SharedExtensions/ServiceExtensions.cs b/StaffDBServer/_Shared/SharedExtensions/ServiceExtensions.cs new file mode 100644 index 0000000..a8f1e3b --- /dev/null +++ b/StaffDBServer/_Shared/SharedExtensions/ServiceExtensions.cs @@ -0,0 +1,49 @@ +using HRD.AppLogger; +using HRD.LDAPService.JWT; +using HRD.WebApi.DAL.Middleware; +using HRD.WebApi.Helpers; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Server.IISIntegration; +using Microsoft.Extensions.DependencyInjection; + +namespace StaffDBServer.SharedExtensions +{ + public static class ServiceExtensions + { + public static void ConfigureWebApiExtensionsAtFirst(this IServiceCollection services) + { + //services.AddCors(); + services.AddCustomCors("AllowAllOrigins"); + + services.Configure(options => + { + options.AuthenticationDisplayName = "Windows"; + options.ForwardClientCertificate = true; + options.AutomaticAuthentication = true; + }); + services.AddAuthentication(IISDefaults.AuthenticationScheme); + + services.ConfigureJWT(Extends.JwtMiddlewareOptionsHelper.GetJwtMiddlewareOptions()); ; + + services.ConfigureDAL(WebApiMiddlewareOptionsHelper.GetWebApiMiddlewareOptions()); + + services.AddSingleton(); + + services.ConfigureSwagger(); + } + + public static void ConfigureWebApiExtensionsEnd(this IServiceCollection services) + { + services.AddMvc() + .ConfigureApiBehaviorOptions(options => + { + options.InvalidModelStateResponseFactory = context => + { + var errors = new HRD.WebApi.Helpers.HttpErrorDetails(context); + return new BadRequestObjectResult(errors); + }; + }); + } + } +} \ No newline at end of file diff --git a/StaffDBServer/_Shared/SharedExtensions/ServiceSwaggerExtensions.cs b/StaffDBServer/_Shared/SharedExtensions/ServiceSwaggerExtensions.cs new file mode 100644 index 0000000..af1378f --- /dev/null +++ b/StaffDBServer/_Shared/SharedExtensions/ServiceSwaggerExtensions.cs @@ -0,0 +1,59 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.PlatformAbstractions; +using NSwag; +using NSwag.Generation.Processors.Security; +using System.Linq; + +namespace StaffDBServer.SharedExtensions +{ + public static class ServiceSwaggerExtensions + { + public static void ConfigureSwagger(this IApplicationBuilder app) + { + app.UseSwaggerUi(cfg => + cfg.DocExpansion = "none" //"list" + ); + } + + public static void ConfigureSwagger(this IServiceCollection services) + { + services.AddSwaggerDocument(config => + { + #region add Bearer Authorization + + config.AddSecurity("JWT", Enumerable.Empty(), new OpenApiSecurityScheme + { + Type = OpenApiSecuritySchemeType.ApiKey, + Name = "Authorization", + In = OpenApiSecurityApiKeyLocation.Header, + Description = "Bearer JWT token." + }); + + config.OperationProcessors.Add( + new AspNetCoreOperationSecurityScopeProcessor("JWT")); + + #endregion add Bearer Authorization + + config.PostProcess = document => + { + document.Info.Version = "V." + PlatformServices.Default.Application.ApplicationVersion + "; " + PlatformServices.Default.Application.RuntimeFramework; + document.Info.Title = $" {PlatformServices.Default.Application.ApplicationName} API"; + document.Info.Description = $" {PlatformServices.Default.Application.ApplicationName} Backend "; + document.Info.TermsOfService = "None"; + document.Info.Contact = new NSwag.OpenApiContact + { + Name = "IT", + Email = string.Empty, + Url = "https://hensel-recycling.com" + }; + document.Info.License = new NSwag.OpenApiLicense + { + Name = "Commercial License", + Url = "https://hensel-recycling.com" + }; + }; + }); + } + } +} \ No newline at end of file diff --git a/StaffDBServer/_Shared/SharedExtensions/WebApiMiddlewareOptionsHelper.cs b/StaffDBServer/_Shared/SharedExtensions/WebApiMiddlewareOptionsHelper.cs new file mode 100644 index 0000000..23d90c0 --- /dev/null +++ b/StaffDBServer/_Shared/SharedExtensions/WebApiMiddlewareOptionsHelper.cs @@ -0,0 +1,26 @@ +using HRD.WebApi; +using HRD.WebApi.DAL.Middleware; + +namespace StaffDBServer.SharedExtensions +{ + public static class WebApiMiddlewareOptionsHelper + { + public static WebApiMiddlewareOptions GetWebApiMiddlewareOptions() + { + WebApiMiddlewareOptions options = new WebApiMiddlewareOptions + { + AssemblyVersion = WebApiConfig.AssemblyVersion, + AssemblyName = WebApiConfig.AssemblyName, + ClientVersion = WebApiConfig.ClientVersion, + + Connectionstring = WebApiConfig.Connectionstring, + + NlogConnectionstring = WebApiConfig.NlogConnectionstring, + NlogDBLogLevel = WebApiConfig.NlogDBLogLevel, + NlogFileLogLevel = WebApiConfig.NlogFileLogLevel, + NlogLogDirectory = WebApiConfig.NlogLogDirectory + }; + return options; + } + } +} \ No newline at end of file diff --git a/StaffDBServer/appsettings.json b/StaffDBServer/appsettings.json new file mode 100644 index 0000000..5f1071a --- /dev/null +++ b/StaffDBServer/appsettings.json @@ -0,0 +1,30 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Warning" + } + }, + + "ConnectionStrings": { + "sqlConnection": "server=DHDEAB-S883-2\\Dev2; database=DDStaffDB; TrustServerCertificate=True; Encrypt=False; MultipleActiveResultSets=True; User Id=webApiUser; Password=webApiUserPWD!" + }, + "AppConfig": { + "LDAP_WebAppGroup_Is_Live": "false", + "ClientVersion": "1.6.8", + "OfficeFileServerUrl": "" + }, + + "Nlog": { + "NlogConnectionstring": "%sqlConnection%", + "NlogDBLogLevel": "Warn", + "NlogFileLogLevel": "Warn", + "NlogLogDirectory": "c:\\temp\\_logs\\", + "NlogSentryDSN": "", + "NlogSentryIsEnable": "false" + }, + + "CustomConfig": { + }, + + "AllowedHosts": "*" +} \ No newline at end of file diff --git a/XUnitDAL.Test/Test_Controller_Entity.cs b/XUnitDAL.Test/Test_Controller_Entity.cs new file mode 100644 index 0000000..eb1b945 --- /dev/null +++ b/XUnitDAL.Test/Test_Controller_Entity.cs @@ -0,0 +1,730 @@ +using DAL.Repositories; +using Microsoft.AspNetCore.Http; +using NLog.Filters; +using StaffDBServer.Controllers; +using Xunit; +using XUnitWebApi.SharedConfig; + +namespace XUnitWebApi.Controller +{ + public class Test_Controller_Entity + { + //----Check_GetEntityController + + [Fact] + public async Task Check_GetSubsidiaryController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 1; + SubsidiaryRepository repository = new SubsidiaryRepository(); + SubsidiaryController controller = new SubsidiaryController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.SubsidiaryId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetWindreamInputFolderController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 49; + WindreamInputFolderRepository repository = new WindreamInputFolderRepository(); + WindreamInputFolderController controller = new WindreamInputFolderController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.WindreamInputFolderId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetWindreamSearchToDepartmentController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 1; + WindreamSearchToDepartmentRepository repository = new WindreamSearchToDepartmentRepository(); + WindreamSearchToDepartmentController controller = new WindreamSearchToDepartmentController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.WindreamSearchToDepartmentId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetWindreamSearchItemToWindreamSearchToDepartmentController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 1; + WindreamSearchItemToWindreamSearchToDepartmentRepository repository = new WindreamSearchItemToWindreamSearchToDepartmentRepository(); + WindreamSearchItemToWindreamSearchToDepartmentController controller = new WindreamSearchItemToWindreamSearchToDepartmentController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.WindreamSearchItemToWindreamSearchToDepartmentId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetWindreamSearchItemController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 1; + WindreamSearchItemRepository repository = new WindreamSearchItemRepository(); + WindreamSearchItemController controller = new WindreamSearchItemController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.WindreamSearchItemId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetWindreamSearchController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 1; + WindreamSearchRepository repository = new WindreamSearchRepository(); + WindreamSearchController controller = new WindreamSearchController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.WindreamSearchId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetWindreamIndexToWindreamSearchToDepartmentController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 1; + WindreamIndexToWindreamSearchToDepartmentRepository repository = new WindreamIndexToWindreamSearchToDepartmentRepository(); + WindreamIndexToWindreamSearchToDepartmentController controller = new WindreamIndexToWindreamSearchToDepartmentController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.WindreamIndexToWindreamSearchToDepartmentId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetWindreamIndexController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 1; + WindreamIndexRepository repository = new WindreamIndexRepository(); + WindreamIndexController controller = new WindreamIndexController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.WindreamIndexId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetWindreamColumnsToDepartmentController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 1; + WindreamColumnsToDepartmentRepository repository = new WindreamColumnsToDepartmentRepository(); + WindreamColumnsToDepartmentController controller = new WindreamColumnsToDepartmentController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.WindreamColumnsToDepartmentId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetWebAppToWebAppRoleController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 2; + WebAppToWebAppRoleRepository repository = new WebAppToWebAppRoleRepository(); + WebAppToWebAppRoleController controller = new WebAppToWebAppRoleController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.WebAppToWebAppRoleId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetWebAppToWebAppAdditionalRoleController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 70; + WebAppToWebAppAdditionalRoleRepository repository = new WebAppToWebAppAdditionalRoleRepository(); + WebAppToWebAppAdditionalRoleController controller = new WebAppToWebAppAdditionalRoleController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.WebAppToWebAppAdditionalRoleId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetWebAppToDepartmentController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 100; + WebAppToDepartmentRepository repository = new WebAppToDepartmentRepository(); + WebAppToDepartmentController controller = new WebAppToDepartmentController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.WebAppToDepartmentId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetWebAppAdditionalRoleController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 1; + WebAppAdditionalRoleRepository repository = new WebAppAdditionalRoleRepository(); + WebAppAdditionalRoleController controller = new WebAppAdditionalRoleController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.WebAppAdditionalRoleId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetEmployeeToWebAppController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 300; + EmployeeToWebAppRepository repository = new EmployeeToWebAppRepository(); + EmployeeToWebAppController controller = new EmployeeToWebAppController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.EmployeeToWebAppId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetEmployeeToDepartmentController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 1; + EmployeeToDepartmentRepository repository = new EmployeeToDepartmentRepository(); + EmployeeToDepartmentController controller = new EmployeeToDepartmentController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.EmployeeToDepartmentId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetEmployeeToAttributeController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 100; + EmployeeToAttributeRepository repository = new EmployeeToAttributeRepository(); + EmployeeToAttributeController controller = new EmployeeToAttributeController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.EmployeeToAttributeId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetEmployeeController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 1; + EmployeeRepository repository = new EmployeeRepository(); + EmployeeController controller = new EmployeeController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.EmployeeId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetDocumentArtToDepartmentController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 1; + DocumentArtToDepartmentRepository repository = new DocumentArtToDepartmentRepository(); + DocumentArtToDepartmentController controller = new DocumentArtToDepartmentController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.DocumentArtToDepartmentId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetDepartmentToWebAppToEmployeeForWindreamController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 1; + DepartmentToWebAppToEmployeeForWindreamRepository repository = new DepartmentToWebAppToEmployeeForWindreamRepository(); + DepartmentToWebAppToEmployeeForWindreamController controller = new DepartmentToWebAppToEmployeeForWindreamController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.DepartmentToWebAppToEmployeeForWindreamId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetWebAppRoleController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 10; + WebAppRoleRepository repository = new WebAppRoleRepository(); + WebAppRoleController controller = new WebAppRoleController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.WebAppRoleId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetWebAppController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 1; + WebAppRepository repository = new WebAppRepository(); + WebAppController controller = new WebAppController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.WebAppId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetRangController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 1; + RangRepository repository = new RangRepository(); + RangController controller = new RangController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.RangId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetProjectController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 1; + ProjectRepository repository = new ProjectRepository(); + ProjectController controller = new ProjectController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.ProjectId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetEmployeeStatusController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 1; + EmployeeStatusRepository repository = new EmployeeStatusRepository(); + EmployeeStatusController controller = new EmployeeStatusController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.EmployeeStatusId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetEmployeeAttributeController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 1; + EmployeeAttributeRepository repository = new EmployeeAttributeRepository(); + EmployeeAttributeController controller = new EmployeeAttributeController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.EmployeeAttributeId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetDocumentArtController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 1; + DocumentArtRepository repository = new DocumentArtRepository(); + DocumentArtController controller = new DocumentArtController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.DocumentArtId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetDepartmentController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 1; + DepartmentRepository repository = new DepartmentRepository(); + DepartmentController controller = new DepartmentController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.DepartmentId); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetCostCentreController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 100; + CostCentreRepository repository = new CostCentreRepository(); + CostCentreController controller = new CostCentreController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.CostCentreId); + } + catch (Exception ex) + { + throw ex; + } + } + + + [Fact] + public async Task Check_Employee() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 272; + var repo = new EmployeeRepository(); + var entity= await repo.GetByIdAsync(entityId); + entity.PhoneNo = "1234"; + await repo.SaveChangesAsync(); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetAdWebAppToWebAppRoleController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + int entityId = 1; + AdWebAppToWebAppRoleRepository repository = new AdWebAppToWebAppRoleRepository(); + AdWebAppToWebAppRoleController controller = new AdWebAppToWebAppRoleController(repository); + dynamic result = await controller.GetEntityAsync(entityId); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.Result.StatusCode); + + var entity = result.Result.Value; + Assert.NotNull(entity); + if (entityId > 0) Assert.Equal(entityId, entity.AdWebAppToWebAppRoleId); + } + catch (Exception ex) + { + throw ex; + } + } + } +} \ No newline at end of file diff --git a/XUnitDAL.Test/Test_Controller_Filter.cs b/XUnitDAL.Test/Test_Controller_Filter.cs new file mode 100644 index 0000000..2d2de34 --- /dev/null +++ b/XUnitDAL.Test/Test_Controller_Filter.cs @@ -0,0 +1,534 @@ +using DAL.Models.Filters; +using DAL.Repositories; +using Microsoft.AspNetCore.Http; +using StaffDBServer.Controllers; +using Xunit; +using XUnitWebApi.SharedConfig; + +namespace XUnitWebApi.Controller +{ + public class Test_Controller_Filter + { + //----Check_GetEntityFilteredListController + + [Fact] + public async Task Check_GetWindreamInputFolderFilteredListController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + WindreamInputFolderFilter filter = new WindreamInputFolderFilter(); + filter.ClientId = 24110; + WindreamInputFolderRepository repository = new WindreamInputFolderRepository(); + WindreamInputFolderController controller = new WindreamInputFolderController(repository); + dynamic result = await controller.GetWindreamInputFolderListAsync(filter); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.StatusCode); + + var entity = result.Value; + Assert.NotNull(entity); + + Assert.NotEqual(entity.Count, 0); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetWindreamSearchToDepartmentFilteredListController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + DepartmentFilter filter = new DepartmentFilter(); + filter.DepartmentId = 16; + WindreamSearchToDepartmentRepository repository = new WindreamSearchToDepartmentRepository(); + WindreamSearchToDepartmentController controller = new WindreamSearchToDepartmentController(repository); + dynamic result = await controller.GetWindreamSearchToDepartmentListAsync(filter); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.StatusCode); + + var entity = result.Value; + Assert.NotNull(entity); + + Assert.NotEqual(entity.Count, 0); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetWindreamSearchItemToWindreamSearchToDepartmentFilteredListController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + WindreamSearchToDepartmentFilter filter = new WindreamSearchToDepartmentFilter(); + filter.DepartmentId = 16; + WindreamSearchItemToWindreamSearchToDepartmentRepository repository = new WindreamSearchItemToWindreamSearchToDepartmentRepository(); + WindreamSearchItemToWindreamSearchToDepartmentController controller = new WindreamSearchItemToWindreamSearchToDepartmentController(repository); + dynamic result = await controller.GetWindreamSearchItemToWindreamSearchToDepartmentListAsync(filter); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.StatusCode); + + var entity = result.Value; + Assert.NotNull(entity); + + Assert.NotEqual(entity.Count, 0); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetWindreamSearchItemFilteredListController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + ClientIdFilter filter = new ClientIdFilter(); + filter.ClientId = 24110; + WindreamSearchItemRepository repository = new WindreamSearchItemRepository(); + WindreamSearchItemController controller = new WindreamSearchItemController(repository); + dynamic result = await controller.GetWindreamSearchItemListAsync(filter); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.StatusCode); + + var entity = result.Value; + Assert.NotNull(entity); + + Assert.NotEqual(entity.Count, 0); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetWindreamSearchFilteredListController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + ClientIdFilter filter = new ClientIdFilter(); + filter.ClientId = 24110; + WindreamSearchRepository repository = new WindreamSearchRepository(); + WindreamSearchController controller = new WindreamSearchController(repository); + dynamic result = await controller.GetWindreamSearchListAsync(filter); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.StatusCode); + + var entity = result.Value; + Assert.NotNull(entity); + + Assert.NotEqual(entity.Count, 0); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetWindreamIndexToWindreamSearchToDepartmentFilteredListController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + WindreamSearchToDepartmentFilter filter = new WindreamSearchToDepartmentFilter(); + filter.DepartmentId = 16; + WindreamIndexToWindreamSearchToDepartmentRepository repository = new WindreamIndexToWindreamSearchToDepartmentRepository(); + WindreamIndexToWindreamSearchToDepartmentController controller = new WindreamIndexToWindreamSearchToDepartmentController(repository); + dynamic result = await controller.GetWindreamIndexToWindreamSearchToDepartmentListAsync(filter); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.StatusCode); + + var entity = result.Value; + Assert.NotNull(entity); + + Assert.NotEqual(entity.Count, 0); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetWindreamIndexFilteredListController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + ClientIdFilter filter = new ClientIdFilter(); + filter.ClientId = 24110; + WindreamIndexRepository repository = new WindreamIndexRepository(); + WindreamIndexController controller = new WindreamIndexController(repository); + dynamic result = await controller.GetWindreamIndexListAsync(filter); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.StatusCode); + + var entity = result.Value; + Assert.NotNull(entity); + + Assert.NotEqual(entity.Count, 0); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetWindreamColumnsToDepartmentFilteredListController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + DepartmentFilter filter = new DepartmentFilter(); + filter.DepartmentId = 16; + WindreamColumnsToDepartmentRepository repository = new WindreamColumnsToDepartmentRepository(); + WindreamColumnsToDepartmentController controller = new WindreamColumnsToDepartmentController(repository); + dynamic result = await controller.GetWindreamColumnsToDepartmentListAsync(filter); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.StatusCode); + + var entity = result.Value; + Assert.NotNull(entity); + + Assert.NotEqual(entity.Count, 0); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetWebAppToWebAppRoleFilteredListController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + WebAppFilter filter = new WebAppFilter(); + filter.WebAppId = 1; + WebAppToWebAppRoleRepository repository = new WebAppToWebAppRoleRepository(); + WebAppToWebAppRoleController controller = new WebAppToWebAppRoleController(repository); + dynamic result = await controller.GetWebAppToWebAppRoleListAsync(filter); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.StatusCode); + + var entity = result.Value; + Assert.NotNull(entity); + + Assert.NotEqual(entity.Count, 0); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetWebAppToWebAppAdditionalRoleFilteredListController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + EmployeeToWebAppFilter filter = new EmployeeToWebAppFilter(); + filter.EmployeeToWebAppId = 73; + WebAppToWebAppAdditionalRoleRepository repository = new WebAppToWebAppAdditionalRoleRepository(); + WebAppToWebAppAdditionalRoleController controller = new WebAppToWebAppAdditionalRoleController(repository); + dynamic result = await controller.GetWebAppToWebAppAdditionalRoleListAsync(filter); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.StatusCode); + + var entity = result.Value; + Assert.NotNull(entity); + + Assert.NotEqual(entity.Count, 0); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetWebAppToDepartmentFilteredListController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + EmployeeToWebAppFilter filter = new EmployeeToWebAppFilter(); + filter.EmployeeToWebAppId = 39; + WebAppToDepartmentRepository repository = new WebAppToDepartmentRepository(); + WebAppToDepartmentController controller = new WebAppToDepartmentController(repository); + dynamic result = await controller.GetWebAppToDepartmentListAsync(filter); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.StatusCode); + + var entity = result.Value; + Assert.NotNull(entity); + + Assert.NotEqual(entity.Count, 0); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetWebAppAdditionalRoleFilteredListController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + WebAppFilter filter = new WebAppFilter(); + filter.WebAppId = 3; + WebAppAdditionalRoleRepository repository = new WebAppAdditionalRoleRepository(); + WebAppAdditionalRoleController controller = new WebAppAdditionalRoleController(repository); + dynamic result = await controller.GetWebAppAdditionalRoleListAsync(filter); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.StatusCode); + + var entity = result.Value; + Assert.NotNull(entity); + + Assert.NotEqual(entity.Count, 0); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetEmployeeToWebAppFilteredListController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + EmployeeFilter filter = new EmployeeFilter(); + filter.LoginName = "y.kochetenko"; + EmployeeToWebAppRepository repository = new EmployeeToWebAppRepository(); + EmployeeToWebAppController controller = new EmployeeToWebAppController(repository); + dynamic result = await controller.GetEmployeeToWebAppListAsync(filter); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.StatusCode); + + var entity = result.Value; + Assert.NotNull(entity); + + Assert.NotEqual(entity.Count, 0); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetEmployeeToDepartmentFilteredListController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + EmployeeFilter filter = new EmployeeFilter(); + filter.EmployeeId = 29; + EmployeeToDepartmentRepository repository = new EmployeeToDepartmentRepository(); + EmployeeToDepartmentController controller = new EmployeeToDepartmentController(repository); + dynamic result = await controller.GetEmployeeToDepartmentListAsync(filter); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.StatusCode); + + var entity = result.Value; + Assert.NotNull(entity); + + Assert.NotEqual(entity.Count, 0); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetEmployeeToAttributeFilteredListController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + EmployeeFilter filter = new EmployeeFilter(); + filter.EmployeeId = 29; + EmployeeToAttributeRepository repository = new EmployeeToAttributeRepository(); + EmployeeToAttributeController controller = new EmployeeToAttributeController(repository); + dynamic result = await controller.GetEmployeeToAttributeListAsync(filter); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.StatusCode); + + var entity = result.Value; + Assert.NotNull(entity); + + Assert.NotEqual(entity.Count, 0); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetEmployeeFilteredClientIdController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + EmployeeFullFilter filter = new EmployeeFullFilter(); + filter.ClientId = 24110; + EmployeeRepository repository = new EmployeeRepository(); + EmployeeController controller = new EmployeeController(repository); + dynamic result = await controller.GetEmployeeListAsync(filter); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.StatusCode); + + var entity = result.Value; + Assert.NotNull(entity); + + Assert.NotEqual(entity.Count, 0); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetEmployeeFilteredisActive() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + EmployeeFullFilter filter = new EmployeeFullFilter(); + filter.IsActive = false; + EmployeeRepository repository = new EmployeeRepository(); + EmployeeController controller = new EmployeeController(repository); + dynamic result = await controller.GetEmployeeListAsync(filter); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.StatusCode); + + var entity = result.Value; + Assert.NotNull(entity); + + Assert.NotEqual(entity.Count, 0); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetEmployeeFilteredListController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + EmployeeFullFilter filter = new EmployeeFullFilter(); + filter.Name = ""; + EmployeeRepository repository = new EmployeeRepository(); + EmployeeController controller = new EmployeeController(repository); + dynamic result = await controller.GetEmployeeListAsync(filter); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.StatusCode); + + var entity = result.Value; + Assert.NotNull(entity); + + Assert.NotEqual(entity.Count, 0); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetDocumentArtToDepartmentFilteredListController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + DepartmentFilter filter = new DepartmentFilter(); + filter.DepartmentId = 16; + DocumentArtToDepartmentRepository repository = new DocumentArtToDepartmentRepository(); + DocumentArtToDepartmentController controller = new DocumentArtToDepartmentController(repository); + dynamic result = await controller.GetDocumentArtToDepartmentListAsync(filter); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.StatusCode); + + var entity = result.Value; + Assert.NotNull(entity); + + Assert.NotEqual(entity.Count, 0); + } + catch (Exception ex) + { + throw ex; + } + } + + [Fact] + public async Task Check_GetDepartmentToWebAppToEmployeeForWindreamFilteredListController() + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + EmployeeFilter filter = new EmployeeFilter(); + filter.EmployeeId = 29; + DepartmentToWebAppToEmployeeForWindreamRepository repository = new DepartmentToWebAppToEmployeeForWindreamRepository(); + DepartmentToWebAppToEmployeeForWindreamController controller = new DepartmentToWebAppToEmployeeForWindreamController(repository); + dynamic result = await controller.GetDepartmentToWebAppToEmployeeForWindreamListAsync(filter); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.StatusCode); + + var entity = result.Value; + Assert.NotNull(entity); + + Assert.NotEqual(entity.Count, 0); + } + catch (Exception ex) + { + throw ex; + } + } + } +} \ No newline at end of file diff --git a/XUnitDAL.Test/XUnitWebApi.Test.csproj b/XUnitDAL.Test/XUnitWebApi.Test.csproj new file mode 100644 index 0000000..88e3eae --- /dev/null +++ b/XUnitDAL.Test/XUnitWebApi.Test.csproj @@ -0,0 +1,27 @@ + + + + netcoreapp7.0 + enable + + false + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/XUnitDAL.Test/_Shared/Shared_Test_Controller_Generic.cs b/XUnitDAL.Test/_Shared/Shared_Test_Controller_Generic.cs new file mode 100644 index 0000000..7d8f4fb --- /dev/null +++ b/XUnitDAL.Test/_Shared/Shared_Test_Controller_Generic.cs @@ -0,0 +1,89 @@ +using Microsoft.AspNetCore.Http; +using Xunit; +using XUnitWebApi.SharedConfig; +using XUnitWebApi.SharedUtils; + +namespace XUnitWebApi.SharedController +{ + public class Shared_Test_Controller_Generic + { + [Theory()] + [InlineData("")] + [InlineData("AdWebAppToWebAppRole")] + [InlineData("CostCentre")] + [InlineData("Department")] + [InlineData("DocumentArt")] + [InlineData("EmployeeAttribute")] + [InlineData("EmployeeStatus")] + [InlineData("Project")] + [InlineData("Rang")] + [InlineData("WebApp")] + [InlineData("WebAppRole")] + [InlineData("DepartmentToWebAppToEmployeeForWindream")] + [InlineData("DocumentArtToDepartment")] + [InlineData("Employee")] + [InlineData("EmployeeToAttribute")] + [InlineData("EmployeeToDepartment")] + [InlineData("EmployeeToWebApp")] + [InlineData("WebAppAdditionalRole")] + [InlineData("WebAppToDepartment")] + [InlineData("WebAppToWebAppAdditionalRole")] + [InlineData("WebAppToWebAppRole")] + [InlineData("WindreamColumnsToDepartment")] + [InlineData("WindreamIndex")] + [InlineData("WindreamIndexToWindreamSearchToDepartment")] + [InlineData("WindreamSearch")] + [InlineData("WindreamSearchItem")] + [InlineData("WindreamSearchItemToWindreamSearchToDepartment")] + [InlineData("WindreamSearchToDepartment")] + [InlineData("WindreamInputFolder")] + [InlineData("Subsidiary")] + public async Task Check_Dynamic_EntityControllers(string entityName = "", int entityId = 0) + { + Shared_Test_Config.Init_Webapi_Context(); + string actualEntity = ""; + List ExceptionList = new List(); + + var typeList = TestHelper.GetAllRepositories().Select(t => t.Name.Replace("Repository", "")); + + foreach (var item in typeList) + { + try + { + actualEntity = item; + if (entityName == "" || item == entityName) + { + dynamic repository = TestHelper.GetRepository_BasedOn_BaseRepository(item); + if (repository == null) continue; + dynamic controller = TestHelper.GetApiController_BasedOn_BaseController(item, repository); + if (controller == null) continue; + dynamic result; + if (entityId > 0) + { + result = await controller.GetEntityAsync(entityId); + result = result?.Result; + } + else result = await controller.GetAllAsync(); + Assert.NotNull(result); + Assert.Equal(StatusCodes.Status200OK, result.StatusCode); + + var entity = result.Value; + Assert.NotNull(entity); + + if (entityId > 0) Assert.Equal(entityId, entity.GetEntityId()); + else Assert.NotEqual(entity.Count, 0); + } + } + catch (Exception ex) + { + //throw new Exception(actualEntity, ex); + Console.WriteLine(ex.Message); + ExceptionList.Add($"Entity: {actualEntity} " + ex.Message + " " + ex.InnerException); + } + } + var errList = ""; + foreach (var item in ExceptionList) errList += "\r\n -- " + item; + if (ExceptionList.Count > 0) throw new Exception(errList); + } + } +} \ No newline at end of file diff --git a/XUnitDAL.Test/_Shared/Shared_Test_DAL.cs b/XUnitDAL.Test/_Shared/Shared_Test_DAL.cs new file mode 100644 index 0000000..97c5945 --- /dev/null +++ b/XUnitDAL.Test/_Shared/Shared_Test_DAL.cs @@ -0,0 +1,88 @@ +using DAL; +using DAL._Shared.SharedRepositories; +using HRD.WebApi; +using System.Reflection; +using Xunit; +using XUnitWebApi.SharedConfig; +using XUnitWebApi.SharedUtils; + +namespace XUnitWebApi.SahredDAL +{ + public class Shared_Test_DAL + { + [Fact] + public async System.Threading.Tasks.Task Check_Repository_XXXAsync() + { + Shared_Test_Config.Init_Webapi_Context(); + WebAppUserRepository webAppUserRepository = new WebAppUserRepository(); + + var res = await webAppUserRepository.TakeListAsync(2); + Assert.NotEmpty(res); + } + + [Fact] + public void Check_Repository_By_Name() + { + var res = Check_Repositories(0, true, "Case"); + Assert.True(res); + } + + [Fact] + public void Check_All_Repositories() + { + var res = Check_Repositories(0, true); + Assert.True(res); + } + + [Fact] + public void Check_All_Repositories_With_Values() + { + var res = Check_Repositories(1, true); + Assert.True(res); + } + + private bool Check_Repositories(int count = 0, bool raiseRepositoryExceptions = false, string repositoryName = "", string namespaceName = "DAL.Repositories") + { + Shared_Test_Config.Init_Webapi_Context(); + + WebApiConfig.RaiseRepositoryExceptions = raiseRepositoryExceptions; + + string entityName = string.Empty; + + List ExceptionList = new List(); + + using WebApiContext ctx = new WebApiContext(); + { + Assert.True(ctx.Database.CanConnect()); + var typeList = TestHelper.GetAllRepositories(namespaceName); + + foreach (var item in typeList) + { + try + { + if (repositoryName == "" || item.Name.Contains(repositoryName)) + { + Type type = item as Type; + entityName = type.Name; + object instance = Activator.CreateInstance(type); + MethodInfo takeListMethod = type.GetMethod("TakeList"); + dynamic list = takeListMethod.Invoke(instance, new object[] { count, true }); + System.Diagnostics.Debug.WriteLine(entityName); + Assert.NotNull(list); + Assert.Equal(count, list.Count); + } + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + ExceptionList.Add($"Entity: {entityName} " + ex.Message + " " + ex.InnerException); + } + } + } + var errList = ""; + foreach (var item in ExceptionList) errList += "\r\n -- " + item; + if (ExceptionList.Count > 0) throw new Exception(errList); + return true; + } + } +} \ No newline at end of file diff --git a/XUnitDAL.Test/_Shared/Shared_Test_LDAP.cs b/XUnitDAL.Test/_Shared/Shared_Test_LDAP.cs new file mode 100644 index 0000000..6493872 --- /dev/null +++ b/XUnitDAL.Test/_Shared/Shared_Test_LDAP.cs @@ -0,0 +1,98 @@ +using DAL._Shared.SharedModels; +using DAL._Shared.SharedRepositories; +using HRD.LDAPService; +using HRD.LDAPService.JWT; +using StaffDBServer.SharedControllers; +using Xunit; +using XUnitWebApi.SharedConfig; + +namespace XUnitWebApi.SharedLDAP +{ + public class Shared_Test_LDAP + { + [Theory] + [InlineData("user", "pwd")] + [InlineData("user2", "pwd")] + public async System.Threading.Tasks.Task Validate_Credentials_WebAppUser(string login, string passwort) + { + Shared_Test_Config.Init_Webapi_Context(); + + try + { + WebAppUser userFromClient = new WebAppUser( + login, + login, + "User", + login); + userFromClient.Password = passwort; + + WebAppEmployeeInfoRepository webAppEmployeeInfoRepository = new WebAppEmployeeInfoRepository(); + WebAppEmployeeInfo webAppEmployeeInfo = await webAppEmployeeInfoRepository.GetByAsync(x => x.LoginName == userFromClient.LoginName); + Assert.NotNull(webAppEmployeeInfo); + + WebAppUserHelper webAppUserHelper = new WebAppUserHelper(); + LdapUser ldapUserFromClient = new LdapUser(userFromClient.LoginName, webAppEmployeeInfo.EmployeeId, userFromClient.Password, webAppEmployeeInfo.DepartmentId, webAppEmployeeInfo.ExtendedDepartmentIdList); + Assert.NotNull(ldapUserFromClient); + + bool ldapUserOk = JwtManager.GenerateLdapUserWithJwtToken(ldapUserFromClient); + Assert.True(ldapUserOk); + + WebAppUser newUser = await webAppUserHelper.CheckLoginWithNameAndPasswordAsync(userFromClient); + + Assert.NotNull(newUser); + } + catch (Exception) + { + throw; + } + } + + + [Theory] + [InlineData("visitoripad", "pwd")] + public void Validate_Credentials_with_password(string login, string passwort) + { + try + { + LdapUser ldapUser = new LdapUser(login, 0, passwort); + var result = LdapAuthenticationService.CheckAndUpdateIdentityWithPassword(ldapUser); + + Assert.True(result); + } + catch (Exception) + { + throw; + } + } + + [Theory] + [MemberData(nameof(GetLdapUsers))] + public void Validate_Credentials_with_password_Version2(LdapUser ldapUser) + { + try + { + var result = LdapAuthenticationService.CheckAndUpdateIdentityWithPassword(ldapUser); + + Assert.True(result); + } + catch (Exception) + { + throw; + } + } + + public static IEnumerable GetLdapUsers() + { + LdapUser ldapUser = new LdapUser("user1", 0, "pwd"); + LdapUser ldapUser2 = new LdapUser("Error", 0, "pwd"); + + var allData = new List + { + new object[] { ldapUser }, + new object[] { ldapUser2 } + }; + + return allData; + } + } +} \ No newline at end of file diff --git a/XUnitDAL.Test/_Shared/Shared_Utils.cs b/XUnitDAL.Test/_Shared/Shared_Utils.cs new file mode 100644 index 0000000..e665cb7 --- /dev/null +++ b/XUnitDAL.Test/_Shared/Shared_Utils.cs @@ -0,0 +1,46 @@ +namespace XUnitWebApi.SharedUtils +{ + public static class TestHelper + { + public static IEnumerable GetAllRepositories(string namespaceName = "DAL.Repositories") + { + var types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(t => t.GetTypes()) + .Where(t => t.IsClass && !t.Name.StartsWith("<") + && (t.Namespace == namespaceName || t.Namespace == "DAL.SharedRepositories") + ); + return types; + } + + public static dynamic GetApiController_BasedOn_BaseController(string controllerName, dynamic repository) + { + var typeList = AppDomain.CurrentDomain.GetAssemblies().SelectMany(t => t.GetTypes()) + .Where(t => t.IsClass && !t.Name.StartsWith("<")) + .Where(t => t.Name.Contains("Controller")) + .Where(t => t.BaseType.Name.StartsWith("BaseController")) + .Where(t => controllerName == "" || t.Name == controllerName + "Controller"); + //var entityTypes = typeList.ToList(); + //var entityType = entityTypes.Where(t => controllerName == "" || t.Name.Contains(controllerName)).FirstOrDefault(); + var entityType = typeList.FirstOrDefault(); + if (entityType == default) return default; + Type type = entityType as Type; + dynamic instance = Activator.CreateInstance(type, new object[] { repository }); + + return instance; + } + + public static dynamic GetRepository_BasedOn_BaseRepository(string repositoryName) + { + var typeList = AppDomain.CurrentDomain.GetAssemblies().SelectMany(t => t.GetTypes()) + .Where(t => t.IsClass && !t.Name.StartsWith("<")) + .Where(t => repositoryName == "" || t.Name == repositoryName + "Repository") + .Where(t => t.Name.Contains("Repository")) + .Where(t => t.BaseType.Name.StartsWith("BaseRepository")); + var entityType = typeList.FirstOrDefault(); + if (entityType == default) return default; + Type type = entityType as Type; + dynamic instance = Activator.CreateInstance(type); + + return instance; + } + } +} \ No newline at end of file diff --git a/XUnitDAL.Test/_Shared/Shared_test_config.cs b/XUnitDAL.Test/_Shared/Shared_test_config.cs new file mode 100644 index 0000000..cc47d61 --- /dev/null +++ b/XUnitDAL.Test/_Shared/Shared_test_config.cs @@ -0,0 +1,41 @@ +using HRD.AppLogger; +using HRD.LDAPService; +using HRD.LDAPService.JWT; +using HRD.WebApi; +using Microsoft.Extensions.Configuration; + +namespace XUnitWebApi.SharedConfig +{ + public static class Shared_Test_Config + { + public static void Init_Webapi_Context() + { + if (WebApiConfig.Connectionstring != default) return; //all test are running simultain using the same WebApiConfig, therefore it must be initialised only one time + var app_path = Directory.GetCurrentDirectory(); + var pos = app_path.IndexOf("XUnitDAL.Test"); + if (pos >= 0) app_path = app_path.Remove(pos); + app_path += "StaffDBServer\\appsettings.json"; + + IConfiguration configuration = new ConfigurationBuilder().AddJsonFile(app_path, true, true).Build(); + WebApiConfig.Init(configuration); + + WebApiConfig.AssemblyName = "KabionlineServer_test"; + WebApiConfig.AssemblyVersion = "xxx.xx"; + //WebApiConfig.Connectionstring = Config_ConnectionString; + //WebApiConfig.NlogConnectionstring = Config_ConnectionString; + WebApiConfig.NlogDBLogLevel = EN_LoggingLevel.Error; + WebApiConfig.NlogFileLogLevel = EN_LoggingLevel.Off; + WebApiConfig.RaiseRepositoryExceptions = false; + + //JWT#1 + var jwtRoleList = new List(); + var ADGroupPrefix = WebApiConfig.IsLive ? "" : "__Test"; + //jwtRoleList.Add(new JwtRole(JwtGlobals.ROLE_USER, "GG_WebApp" + ADGroupPrefix + "_Kabionline_User")); //(RO) nur eigene + //jwtRoleList.Add(new JwtRole(JwtGlobals.ROLE_MASTER, "GG_WebApp" + ADGroupPrefix + "_Kabionline_Master")); //RW ALLE Abteilungen + //jwtRoleList.Add(new JwtRole(JwtGlobals.ROLE_DEPARTMENTUSER, "GG_WebApp" + ADGroupPrefix + "_Kabionline_DepartmentUser")); //(RW) auch andere aus eigener Abteilung + //jwtRoleList.Add(new JwtRole(JwtGlobals.ROLE_DEPARTMENTMASTER, "GG_WebApp" + ADGroupPrefix + "_Kabionline_DepartmentMaster")); //(RW) auch andere aus eigener Abteilung + + JwtTokenConfig.JwtRoleList = jwtRoleList; + } + } +} \ No newline at end of file