From 7d760b589e8418d3b49407a6affa74b3d0675378 Mon Sep 17 00:00:00 2001 From: Sergio Matias Urquin Date: Tue, 29 Apr 2025 18:56:29 -0600 Subject: [PATCH] Add project files. --- .gitignore | 367 +++++++++++++++ .pipelines/GitVersion.yml | 59 +++ .pipelines/templated-pipeline.yml | 57 +++ .../Core.Cerberos.Application.csproj | 20 + .../UseCases/Modules/Adapter/ModulePort.cs | 19 + .../Input/ChangeModuleStatusRequest.cs | 16 + .../Modules/Input/CreateModuleRequest.cs | 20 + .../Input/GetAllModulesByListRequest.cs | 14 + .../Modules/Input/GetAllModulesRequest.cs | 12 + .../Modules/Input/GetModuleRequest.cs | 13 + .../Modules/Input/UpdateModuleRequest.cs | 21 + .../UseCases/Modules/ModuleHandler.cs | 219 +++++++++ .../UseCases/Modules/Ports/IModulePort.cs | 13 + .../Validator/ChangeModuleStatusValidator.cs | 14 + .../Validator/CreateModuleValidator.cs | 15 + .../Validator/GetAllModulesByListValidator.cs | 14 + .../Validator/UpdateModuleValidator.cs | 15 + .../Permissions/Adapter/PermissionPort.cs | 19 + .../Input/ChangePermissionStatusRequest.cs | 16 + .../Input/CreatePermissionRequest.cs | 17 + .../Input/GetAllPermissionsByListRequest.cs | 14 + .../Input/GetAllPermissionsRequest.cs | 12 + .../Permissions/Input/GetPermissionRequest.cs | 13 + .../Input/UpdatePermissionRequest.cs | 19 + .../UseCases/Permissions/PermissionHandler.cs | 204 ++++++++ .../Permissions/Ports/IPermissionPort.cs | 13 + .../ChangePermissionStatusValidator.cs | 15 + .../Validator/CreatePermissionValidator.cs | 15 + .../Validator/UpdatePermissionValidator.cs | 14 + .../UseCases/Roles/Adapter/RolePort.cs | 19 + .../Input/AddApplicationToRoleRequest.cs | 15 + .../Roles/Input/ChangeRoleStatusRequest.cs | 15 + .../UseCases/Roles/Input/CreateRoleRequest.cs | 22 + .../Roles/Input/GetAllRolesRequest.cs | 12 + .../UseCases/Roles/Input/GetRoleRequest.cs | 13 + .../Input/RemoveApplicationFromRoleRequest.cs | 15 + .../UseCases/Roles/Input/UpdateRoleRequest.cs | 24 + .../UseCases/Roles/Ports/IRolePort.cs | 12 + .../UseCases/Roles/RoleHandler.cs | 235 ++++++++++ .../Validator/ChangeRoleStatusValidator.cs | 16 + .../Roles/Validator/CreateRoleValidator.cs | 16 + .../Roles/Validator/UpdateRoleValidator.cs | 16 + .../UseCases/Users/Adapter/UserPort.cs | 33 ++ .../Input/AcceptUserConsentFormRequest.cs | 12 + .../Users/Input/AddCompanyToUserRequest.cs | 14 + .../Users/Input/AddProjectToUserRequest.cs | 14 + .../Users/Input/ChangeUserStatusRequest.cs | 16 + .../UseCases/Users/Input/CreateUserRequest.cs | 21 + .../Users/Input/GetAllUsersRequest.cs | 12 + .../Users/Input/GetConsentFormPDFRequest.cs | 12 + .../Users/Input/GetTokenAdapterRequest.cs | 13 + .../Users/Input/GetUserByEmailRequest.cs | 13 + .../UseCases/Users/Input/GetUserRequest.cs | 13 + .../UseCases/Users/Input/LoginUserRequest.cs | 13 + .../UseCases/Users/Input/LogoutUserRequest.cs | 13 + .../Input/RemoveCompanyFromUserRequest.cs | 14 + .../Input/RemoveProjectFromUserRequest.cs | 14 + .../UseCases/Users/Input/UpdateUserRequest.cs | 20 + .../Input/ValidateUserExistenceRequest.cs | 13 + .../UseCases/Users/Ports/IUserPort.cs | 17 + .../UseCases/Users/UserHandler.cs | 439 ++++++++++++++++++ .../Validator/ChangeUserStatusValidator.cs | 15 + .../Users/Validator/CreateUserValidator.cs | 17 + .../Users/Validator/UpdateUserValidator.cs | 17 + .../RegisterClientConfiguration.cs | 59 +++ .../Clients/ICerberosServiceClient.cs | 118 +++++ .../Clients/Requests/ModuleRequest.cs | 16 + .../Clients/Requests/PermissionRequest.cs | 12 + .../Clients/Requests/RoleRequest.cs | 16 + .../Clients/Requests/UserRequest.cs | 13 + .../Core.Cerberos.External.csproj | 16 + .../GatewayConfiguration.cs | 19 + .../GatewaySettingsConfigurations.cs | 48 ++ .../Token/AuthenticatedHttpClientHandler.cs | 32 ++ .../Helpers/Token/HttpContextTokenProvider.cs | 31 ++ .../Helpers/Token/ITokenProvider.cs | 19 + Core.Cerberos.Service.API.sln | 46 ++ .../Cerberos.Service.API.http | 6 + .../Controllers/ModuleController.cs | 200 ++++++++ .../Controllers/PermissionController.cs | 200 ++++++++ .../Controllers/RoleController.cs | 208 +++++++++ .../Controllers/UserController.cs | 432 +++++++++++++++++ .../Core.Cerberos.Service.API.csproj | 27 ++ .../Extensions/SwaggerExtensions.cs | 99 ++++ Core.Cerberos.Service.API/Program.cs | 170 +++++++ .../Properties/launchSettings.json | 41 ++ .../appsettings.Development.json | 9 + .../appsettings.Local.json | 12 + Core.Cerberos.Service.API/appsettings.json | 12 + .../sample.settings.Development.json | 30 ++ README.md | 1 + 91 files changed, 4366 insertions(+) create mode 100644 .gitignore create mode 100644 .pipelines/GitVersion.yml create mode 100644 .pipelines/templated-pipeline.yml create mode 100644 Core.Cerberos.Application/Core.Cerberos.Application.csproj create mode 100644 Core.Cerberos.Application/UseCases/Modules/Adapter/ModulePort.cs create mode 100644 Core.Cerberos.Application/UseCases/Modules/Input/ChangeModuleStatusRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Modules/Input/CreateModuleRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Modules/Input/GetAllModulesByListRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Modules/Input/GetAllModulesRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Modules/Input/GetModuleRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Modules/Input/UpdateModuleRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Modules/ModuleHandler.cs create mode 100644 Core.Cerberos.Application/UseCases/Modules/Ports/IModulePort.cs create mode 100644 Core.Cerberos.Application/UseCases/Modules/Validator/ChangeModuleStatusValidator.cs create mode 100644 Core.Cerberos.Application/UseCases/Modules/Validator/CreateModuleValidator.cs create mode 100644 Core.Cerberos.Application/UseCases/Modules/Validator/GetAllModulesByListValidator.cs create mode 100644 Core.Cerberos.Application/UseCases/Modules/Validator/UpdateModuleValidator.cs create mode 100644 Core.Cerberos.Application/UseCases/Permissions/Adapter/PermissionPort.cs create mode 100644 Core.Cerberos.Application/UseCases/Permissions/Input/ChangePermissionStatusRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Permissions/Input/CreatePermissionRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Permissions/Input/GetAllPermissionsByListRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Permissions/Input/GetAllPermissionsRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Permissions/Input/GetPermissionRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Permissions/Input/UpdatePermissionRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Permissions/PermissionHandler.cs create mode 100644 Core.Cerberos.Application/UseCases/Permissions/Ports/IPermissionPort.cs create mode 100644 Core.Cerberos.Application/UseCases/Permissions/Validator/ChangePermissionStatusValidator.cs create mode 100644 Core.Cerberos.Application/UseCases/Permissions/Validator/CreatePermissionValidator.cs create mode 100644 Core.Cerberos.Application/UseCases/Permissions/Validator/UpdatePermissionValidator.cs create mode 100644 Core.Cerberos.Application/UseCases/Roles/Adapter/RolePort.cs create mode 100644 Core.Cerberos.Application/UseCases/Roles/Input/AddApplicationToRoleRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Roles/Input/ChangeRoleStatusRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Roles/Input/CreateRoleRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Roles/Input/GetAllRolesRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Roles/Input/GetRoleRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Roles/Input/RemoveApplicationFromRoleRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Roles/Input/UpdateRoleRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Roles/Ports/IRolePort.cs create mode 100644 Core.Cerberos.Application/UseCases/Roles/RoleHandler.cs create mode 100644 Core.Cerberos.Application/UseCases/Roles/Validator/ChangeRoleStatusValidator.cs create mode 100644 Core.Cerberos.Application/UseCases/Roles/Validator/CreateRoleValidator.cs create mode 100644 Core.Cerberos.Application/UseCases/Roles/Validator/UpdateRoleValidator.cs create mode 100644 Core.Cerberos.Application/UseCases/Users/Adapter/UserPort.cs create mode 100644 Core.Cerberos.Application/UseCases/Users/Input/AcceptUserConsentFormRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Users/Input/AddCompanyToUserRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Users/Input/AddProjectToUserRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Users/Input/ChangeUserStatusRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Users/Input/CreateUserRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Users/Input/GetAllUsersRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Users/Input/GetConsentFormPDFRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Users/Input/GetTokenAdapterRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Users/Input/GetUserByEmailRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Users/Input/GetUserRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Users/Input/LoginUserRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Users/Input/LogoutUserRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Users/Input/RemoveCompanyFromUserRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Users/Input/RemoveProjectFromUserRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Users/Input/UpdateUserRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Users/Input/ValidateUserExistenceRequest.cs create mode 100644 Core.Cerberos.Application/UseCases/Users/Ports/IUserPort.cs create mode 100644 Core.Cerberos.Application/UseCases/Users/UserHandler.cs create mode 100644 Core.Cerberos.Application/UseCases/Users/Validator/ChangeUserStatusValidator.cs create mode 100644 Core.Cerberos.Application/UseCases/Users/Validator/CreateUserValidator.cs create mode 100644 Core.Cerberos.Application/UseCases/Users/Validator/UpdateUserValidator.cs create mode 100644 Core.Cerberos.External/ClientConfiguration/RegisterClientConfiguration.cs create mode 100644 Core.Cerberos.External/Clients/ICerberosServiceClient.cs create mode 100644 Core.Cerberos.External/Clients/Requests/ModuleRequest.cs create mode 100644 Core.Cerberos.External/Clients/Requests/PermissionRequest.cs create mode 100644 Core.Cerberos.External/Clients/Requests/RoleRequest.cs create mode 100644 Core.Cerberos.External/Clients/Requests/UserRequest.cs create mode 100644 Core.Cerberos.External/Core.Cerberos.External.csproj create mode 100644 Core.Cerberos.External/GatewayConfigurations/GatewayConfiguration.cs create mode 100644 Core.Cerberos.External/GatewayConfigurations/GatewaySettingsConfigurations.cs create mode 100644 Core.Cerberos.External/Helpers/Token/AuthenticatedHttpClientHandler.cs create mode 100644 Core.Cerberos.External/Helpers/Token/HttpContextTokenProvider.cs create mode 100644 Core.Cerberos.External/Helpers/Token/ITokenProvider.cs create mode 100644 Core.Cerberos.Service.API.sln create mode 100644 Core.Cerberos.Service.API/Cerberos.Service.API.http create mode 100644 Core.Cerberos.Service.API/Controllers/ModuleController.cs create mode 100644 Core.Cerberos.Service.API/Controllers/PermissionController.cs create mode 100644 Core.Cerberos.Service.API/Controllers/RoleController.cs create mode 100644 Core.Cerberos.Service.API/Controllers/UserController.cs create mode 100644 Core.Cerberos.Service.API/Core.Cerberos.Service.API.csproj create mode 100644 Core.Cerberos.Service.API/Extensions/SwaggerExtensions.cs create mode 100644 Core.Cerberos.Service.API/Program.cs create mode 100644 Core.Cerberos.Service.API/Properties/launchSettings.json create mode 100644 Core.Cerberos.Service.API/appsettings.Development.json create mode 100644 Core.Cerberos.Service.API/appsettings.Local.json create mode 100644 Core.Cerberos.Service.API/appsettings.json create mode 100644 Core.Cerberos.Service.API/sample.settings.Development.json create mode 100644 README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..79957db --- /dev/null +++ b/.gitignore @@ -0,0 +1,367 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +CerberosServiceSettings.development.json +/Core.Cerberos.Service.API/cerberosprivkey.pem +/Core.Cerberos.Service.API/cerberospubkey.pem diff --git a/.pipelines/GitVersion.yml b/.pipelines/GitVersion.yml new file mode 100644 index 0000000..f5867a9 --- /dev/null +++ b/.pipelines/GitVersion.yml @@ -0,0 +1,59 @@ +mode: mainline +assembly-versioning-scheme: MajorMinorPatch +tag-prefix: '[vV]' +major-version-bump-message: '\+semver:\s?(breaking|major)' +minor-version-bump-message: '\+semver:\s?(feature|minor)' +patch-version-bump-message: '\+semver:\s?(fix|patch)' +no-bump-message: '\+semver:\s?(none|skip)' +legacy-semver-padding: 4 +build-metadata-padding: 4 +commits-since-version-source-padding: 4 +commit-message-incrementing: Enabled +branches: + main: + regex: ^master$|^main$ + tag: '' + increment: Patch + prevent-increment-of-merged-branch-version: true + track-merge-target: false + source-branches: [ 'develop', 'release' ] + tracks-release-branches: false + is-release-branch: false + is-mainline: true + pre-release-weight: 55000 + feature: + regex: ^features?[/-] + tag: useBranchName + increment: Inherit + prevent-increment-of-merged-branch-version: false + track-merge-target: false + source-branches: [ 'develop', 'main', 'release', 'feature', 'support', 'hotfix' ] + tracks-release-branches: false + is-release-branch: false + is-mainline: false + pre-release-weight: 30000 + release: + regex: ^releases?[/-] + tag: beta + increment: None + is-mainline: true + regex: ^releases?[/-] + prevent-increment-of-merged-branch-version: true + track-merge-target: false + source-branches: [ 'develop', 'main', 'support', 'release' ] + tracks-release-branches: false + is-release-branch: true + is-mainline: false + pre-release-weight: 30000 + hotfix: + regex: ^hotfix(es)?[/-] + increment: Patch + prevent-increment-of-merged-branch-version: false + track-merge-target: false + source-branches: [ 'develop', 'main', 'support' ] + tracks-release-branches: false + is-release-branch: false + is-mainline: false + pre-release-weight: 30000 +ignore: + sha: [] \ No newline at end of file diff --git a/.pipelines/templated-pipeline.yml b/.pipelines/templated-pipeline.yml new file mode 100644 index 0000000..47c9493 --- /dev/null +++ b/.pipelines/templated-pipeline.yml @@ -0,0 +1,57 @@ +pool: + vmImage: 'windows-latest' + +trigger: + branches: + include: + - release/* + - feature/* + - hotfix/* + - bugfix/* + - development + +variables: + project: 'Core.Cerberos.Service.API/Core.Cerberos.Service.API.csproj' + solution: 'Core.Cerberos.Service.API.sln' + buildConfiguration: 'Release' + artifactName: 'drop' + snykConnectionEndpoint: 'SnykConnection' + projectNameOnSonar: 'Core.Cerberos.Service.API' + projectKeyOnSonar: 'heathpbu_Core.Cerberos.Service.API' + feed: '1b3770f1-17db-4bf2-a43d-49f305aa7a22' + projectFileName: 'Core.Cerberos.Service.API.csproj' + projectPath: 'Core.Cerberos.Service.API/' + +resources: + repositories: + - repository: templates + name: "Template.DevOps.Pipelines" + type: "git" + project: "SharedLibs" + +jobs: +- job: CI + steps: + - template: templates/dotnet/v1/step1_setup.yml@templates + - template: templates/dotnet/v1/step2_versioning.yml@templates + parameters: + projectFileName: '$(projectFileName)' + path: '$(projectPath)' + - template: templates/dotnet/v1/step3_restore_and_build.yml@templates + parameters: + project: '$(project)' + solution: '$(solution)' + buildConfiguration: '$(buildConfiguration)' + projectNameOnSonar: '$(projectNameOnSonar)' + projectKeyOnSonar: '$(projectKeyOnSonar)' + feed: '$(feed)' + + - template: templates/dotnet/v1/step5_snyk_analysis.yml@templates + parameters: + snykConnectionEndpoint: '$(snykConnectionEndpoint)' + solutionToScan: '$(solution)' + + - template: templates/dotnet/v1/step6_release.yml@templates + parameters: + artifactName: '$(artifactName)' + project: '$(project)' \ No newline at end of file diff --git a/Core.Cerberos.Application/Core.Cerberos.Application.csproj b/Core.Cerberos.Application/Core.Cerberos.Application.csproj new file mode 100644 index 0000000..c9ab0b4 --- /dev/null +++ b/Core.Cerberos.Application/Core.Cerberos.Application.csproj @@ -0,0 +1,20 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + + diff --git a/Core.Cerberos.Application/UseCases/Modules/Adapter/ModulePort.cs b/Core.Cerberos.Application/UseCases/Modules/Adapter/ModulePort.cs new file mode 100644 index 0000000..f178d8d --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Modules/Adapter/ModulePort.cs @@ -0,0 +1,19 @@ +using Core.Cerberos.Adapters; +using Core.Cerberos.Application.UseCases.Modules.Ports; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Mvc; + +namespace Core.Cerberos.Application.UseCases.Modules.Adapter +{ + public class ModulePort : BasePresenter, IModulePort + { + public void Success(ModuleAdapter output) + { + ViewModel = new OkObjectResult(output); + } + public void Success(List output) + { + ViewModel = new OkObjectResult(output); + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Modules/Input/ChangeModuleStatusRequest.cs b/Core.Cerberos.Application/UseCases/Modules/Input/ChangeModuleStatusRequest.cs new file mode 100644 index 0000000..fdd176d --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Modules/Input/ChangeModuleStatusRequest.cs @@ -0,0 +1,16 @@ +using Core.Cerberos.Adapters.Common.Enums; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Modules.Input +{ + public class ChangeModuleStatusRequest : Notificator, ICommand + { + public string Id { get; set; } + public StatusEnum Status { get; set; } + + public bool Validate() + { + return Id != null; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Modules/Input/CreateModuleRequest.cs b/Core.Cerberos.Application/UseCases/Modules/Input/CreateModuleRequest.cs new file mode 100644 index 0000000..546d8e2 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Modules/Input/CreateModuleRequest.cs @@ -0,0 +1,20 @@ +using Core.Cerberos.Adapters.Common.Enums; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Modules.Input +{ + public class CreateModuleRequest : Notificator, ICommand + { + public string Name { get; set; } = null!; + public string? Description { get; set; } + public string? Icon { get; set; } + public string? Route { get; set; } + public int? Order { get; set; } + public ApplicationsEnum? Application { get; set; } = null!; + + public bool Validate() + { + return Name != null; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Modules/Input/GetAllModulesByListRequest.cs b/Core.Cerberos.Application/UseCases/Modules/Input/GetAllModulesByListRequest.cs new file mode 100644 index 0000000..849ca56 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Modules/Input/GetAllModulesByListRequest.cs @@ -0,0 +1,14 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Modules.Input +{ + public class GetAllModulesByListRequest : Notificator, ICommand + { + public string[] Modules { get; set; } + + public bool Validate() + { + return Modules != null; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Modules/Input/GetAllModulesRequest.cs b/Core.Cerberos.Application/UseCases/Modules/Input/GetAllModulesRequest.cs new file mode 100644 index 0000000..cb56ec3 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Modules/Input/GetAllModulesRequest.cs @@ -0,0 +1,12 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Modules.Input +{ + public class GetAllModulesRequest : ICommand + { + public bool Validate() + { + return true; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Modules/Input/GetModuleRequest.cs b/Core.Cerberos.Application/UseCases/Modules/Input/GetModuleRequest.cs new file mode 100644 index 0000000..7547375 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Modules/Input/GetModuleRequest.cs @@ -0,0 +1,13 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Modules.Input +{ + public class GetModuleRequest : Notificator, ICommand + { + public string Id { get; set; } + public bool Validate() + { + return Id != null; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Modules/Input/UpdateModuleRequest.cs b/Core.Cerberos.Application/UseCases/Modules/Input/UpdateModuleRequest.cs new file mode 100644 index 0000000..ff2c676 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Modules/Input/UpdateModuleRequest.cs @@ -0,0 +1,21 @@ +using Core.Cerberos.Adapters.Common.Enums; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Modules.Input +{ + public class UpdateModuleRequest : Notificator, ICommand + { + public string Id { get; set; } = null!; + public string Name { get; set; } = null!; + public string? Description { get; set; } + public string? Icon { get; set; } + public string Route { get; set; } = null!; + public int? Order { get; set; } + public ApplicationsEnum? Application { get; set; } = null!; + public StatusEnum Status { get; set; } + public bool Validate() + { + return Id != null; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Modules/ModuleHandler.cs b/Core.Cerberos.Application/UseCases/Modules/ModuleHandler.cs new file mode 100644 index 0000000..7703e4a --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Modules/ModuleHandler.cs @@ -0,0 +1,219 @@ +using Core.Cerberos.Adapters; +using Core.Cerberos.Application.UseCases.Modules.Input; +using Core.Cerberos.Application.UseCases.Modules.Ports; +using Core.Cerberos.External.Clients; +using Core.Cerberos.External.Clients.Requests; +using FluentValidation; +using Lib.Architecture.BuildingBlocks; +using Lib.Architecture.BuildingBlocks.Helpers; + +namespace Core.Cerberos.Application.UseCases.Modules +{ + public class ModuleHandler : + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler + { + private readonly IModulePort _port; + private readonly IValidator _changeModuleStatusValidator; + private readonly IValidator _registerModuleValidator; + private readonly IValidator _updateModuleValidator; + private readonly IValidator _modulesByListValidator; + private readonly ICerberosServiceClient _cerberosDALService; + + public ModuleHandler( + IModulePort port, + IValidator changeModuleStatusValidator, + IValidator registerModuleValidator, + IValidator updateModuleValidator, + IValidator modulesByListValidator, + ICerberosServiceClient cerberosDALService) + { + _port = port ?? throw new ArgumentNullException(nameof(port)); + _changeModuleStatusValidator = changeModuleStatusValidator ?? throw new ArgumentNullException(nameof(changeModuleStatusValidator)); + _registerModuleValidator = registerModuleValidator ?? throw new ArgumentNullException(nameof(registerModuleValidator)); + _updateModuleValidator = updateModuleValidator ?? throw new ArgumentNullException(nameof(updateModuleValidator)); + _cerberosDALService = cerberosDALService ?? throw new ArgumentNullException(nameof(cerberosDALService)); + _modulesByListValidator = modulesByListValidator ?? throw new ArgumentNullException(nameof(modulesByListValidator)); + } + + public async ValueTask ExecuteAsync(GetModuleRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var result = await _cerberosDALService.GetModuleByIdAsync(command.Id, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(GetAllModulesRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var _result = await _cerberosDALService.GetAllModulesAsync().ConfigureAwait(false); + if (!_result.Any()) + { + _port.NoContentSuccess(); + return; + } + _port.Success(_result.ToList()); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(GetAllModulesByListRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_modulesByListValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var _result = await _cerberosDALService.GetAllModulesByListAsync(command.Modules, cancellationToken).ConfigureAwait(false); + if (!_result.Any()) + { + _port.NoContentSuccess(); + return; + } + _port.Success(_result.ToList()); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(ChangeModuleStatusRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_changeModuleStatusValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var result = await _cerberosDALService.ChangeStatusModuleAsync(command.Id, command.Status, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(CreateModuleRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_registerModuleValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var request = new ModuleRequest + { + Name = command.Name, + Description = command.Description, + Icon = command.Icon, + Route = command.Route, + Order = command.Order, + Application = command.Application, + }; + + var result = await _cerberosDALService.CreateModuleAsync(request, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(UpdateModuleRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_updateModuleValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var request = new ModuleAdapter + { + Id = command.Id, + Name = command.Name, + Description = command.Description, + Application = command.Application, + Route = command.Route, + Order = command.Order, + Icon = command.Icon, + Status = command.Status + }; + + string id = command.Id; + + var result = await _cerberosDALService.UpdateModuleAsync(request, id, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Modules/Ports/IModulePort.cs b/Core.Cerberos.Application/UseCases/Modules/Ports/IModulePort.cs new file mode 100644 index 0000000..dfe9fbf --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Modules/Ports/IModulePort.cs @@ -0,0 +1,13 @@ +using Core.Cerberos.Adapters; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Modules.Ports +{ + public interface IModulePort : IBasePort, + ICommandSuccessPort, + ICommandSuccessPort>, + INoContentPort, IBusinessErrorPort, ITimeoutPort, IValidationErrorPort, + INotFoundPort, IForbiddenPort, IUnauthorizedPort, IInternalServerErrorPort + { + } +} diff --git a/Core.Cerberos.Application/UseCases/Modules/Validator/ChangeModuleStatusValidator.cs b/Core.Cerberos.Application/UseCases/Modules/Validator/ChangeModuleStatusValidator.cs new file mode 100644 index 0000000..63009b6 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Modules/Validator/ChangeModuleStatusValidator.cs @@ -0,0 +1,14 @@ +using Core.Cerberos.Application.UseCases.Modules.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.Modules.Validator +{ + public class ChangeModuleStatusValidator : AbstractValidator + { + public ChangeModuleStatusValidator() + { + RuleFor(i => i.Id).NotEmpty().NotNull().OverridePropertyName(x => x.Id).WithName("Module ID").WithMessage("Module ID is Obligatory."); + RuleFor(i => i.Status).NotNull().OverridePropertyName(x => x.Status).WithName("Status").WithMessage("Status is Obligatory."); + } + } +} \ No newline at end of file diff --git a/Core.Cerberos.Application/UseCases/Modules/Validator/CreateModuleValidator.cs b/Core.Cerberos.Application/UseCases/Modules/Validator/CreateModuleValidator.cs new file mode 100644 index 0000000..ca2f49d --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Modules/Validator/CreateModuleValidator.cs @@ -0,0 +1,15 @@ +using Core.Cerberos.Application.UseCases.Modules.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.Modules.Validator +{ + public class CreateModuleValidator : AbstractValidator + { + public CreateModuleValidator() + { + RuleFor(i => i.Name).NotEmpty().NotNull().OverridePropertyName(x => x.Name).WithName("Module Name").WithMessage("Module Name is Obligatory."); + RuleFor(i => i.Route).NotEmpty().NotNull().OverridePropertyName(x => x.Route).WithName("Module Route").WithMessage("Module Route is Obligatory."); + RuleFor(i => i.Application).NotEmpty().NotNull().OverridePropertyName(x => x.Application).WithName("Application").WithMessage("Application is Obligatory."); + } + } +} \ No newline at end of file diff --git a/Core.Cerberos.Application/UseCases/Modules/Validator/GetAllModulesByListValidator.cs b/Core.Cerberos.Application/UseCases/Modules/Validator/GetAllModulesByListValidator.cs new file mode 100644 index 0000000..9b85fe1 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Modules/Validator/GetAllModulesByListValidator.cs @@ -0,0 +1,14 @@ +using Core.Cerberos.Application.UseCases.Modules.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.Modules.Validator +{ + public class GetAllModulesByListValidator : AbstractValidator + { + public GetAllModulesByListValidator() + { + RuleFor(i => i.Modules).NotEmpty().NotNull().OverridePropertyName(x => x.Modules).WithName("Modules").WithMessage("Modules are Obligatory."); + } + + } +} \ No newline at end of file diff --git a/Core.Cerberos.Application/UseCases/Modules/Validator/UpdateModuleValidator.cs b/Core.Cerberos.Application/UseCases/Modules/Validator/UpdateModuleValidator.cs new file mode 100644 index 0000000..325c0d2 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Modules/Validator/UpdateModuleValidator.cs @@ -0,0 +1,15 @@ +using Core.Cerberos.Application.UseCases.Modules.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.Modules.Validator +{ + public class UpdateModuleValidator : AbstractValidator + { + public UpdateModuleValidator() + { + RuleFor(i => i.Name).NotEmpty().NotNull().OverridePropertyName(x => x.Name).WithName("Module Name").WithMessage("Module Name is Obligatory."); + RuleFor(i => i.Application).NotEmpty().NotNull().OverridePropertyName(x => x.Application).WithName("Application").WithMessage("Application is Obligatory."); + RuleFor(i => i.Route).NotEmpty().NotNull().OverridePropertyName(x => x.Route).WithName("Module Route").WithMessage("Module Route is Obligatory."); + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Permissions/Adapter/PermissionPort.cs b/Core.Cerberos.Application/UseCases/Permissions/Adapter/PermissionPort.cs new file mode 100644 index 0000000..02eece0 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Permissions/Adapter/PermissionPort.cs @@ -0,0 +1,19 @@ +using Core.Cerberos.Adapters; +using Core.Cerberos.Application.UseCases.Permissions.Ports; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Mvc; + +namespace Core.Cerberos.Application.UseCases.Permissions.Adapter +{ + public class PermissionPort : BasePresenter, IPermissionPort + { + public void Success(PermissionAdapter output) + { + ViewModel = new OkObjectResult(output); + } + public void Success(List output) + { + ViewModel = new OkObjectResult(output); + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Permissions/Input/ChangePermissionStatusRequest.cs b/Core.Cerberos.Application/UseCases/Permissions/Input/ChangePermissionStatusRequest.cs new file mode 100644 index 0000000..50cecf4 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Permissions/Input/ChangePermissionStatusRequest.cs @@ -0,0 +1,16 @@ +using Core.Cerberos.Adapters.Common.Enums; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Permissions.Input +{ + public class ChangePermissionStatusRequest : Notificator, ICommand + { + public string Id { get; set; } + public StatusEnum Status { get; set; } + + public bool Validate() + { + return Id != null; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Permissions/Input/CreatePermissionRequest.cs b/Core.Cerberos.Application/UseCases/Permissions/Input/CreatePermissionRequest.cs new file mode 100644 index 0000000..a50103a --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Permissions/Input/CreatePermissionRequest.cs @@ -0,0 +1,17 @@ +using Core.Cerberos.Adapters.Common.Constants; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Permissions.Input +{ + public class CreatePermissionRequest : Notificator, ICommand + { + public string Name { get; set; } = null!; + public string Description { get; set; } = null!; + public AccessLevelEnum? AccessLevel { get; set; } = null!; + + public bool Validate() + { + return Name != null; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Permissions/Input/GetAllPermissionsByListRequest.cs b/Core.Cerberos.Application/UseCases/Permissions/Input/GetAllPermissionsByListRequest.cs new file mode 100644 index 0000000..e730af6 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Permissions/Input/GetAllPermissionsByListRequest.cs @@ -0,0 +1,14 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Permissions.Input +{ + public class GetAllPermissionsByListRequest : ICommand + { + public string[]? Permissions { get; set; } + + public bool Validate() + { + return Permissions != null; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Permissions/Input/GetAllPermissionsRequest.cs b/Core.Cerberos.Application/UseCases/Permissions/Input/GetAllPermissionsRequest.cs new file mode 100644 index 0000000..6ba5b74 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Permissions/Input/GetAllPermissionsRequest.cs @@ -0,0 +1,12 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Permissions.Input +{ + public class GetAllPermissionsRequest : ICommand + { + public bool Validate() + { + return true; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Permissions/Input/GetPermissionRequest.cs b/Core.Cerberos.Application/UseCases/Permissions/Input/GetPermissionRequest.cs new file mode 100644 index 0000000..d95b10e --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Permissions/Input/GetPermissionRequest.cs @@ -0,0 +1,13 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Permissions.Input +{ + public class GetPermissionRequest : Notificator, ICommand + { + public string Id { get; set; } + public bool Validate() + { + return Id != null; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Permissions/Input/UpdatePermissionRequest.cs b/Core.Cerberos.Application/UseCases/Permissions/Input/UpdatePermissionRequest.cs new file mode 100644 index 0000000..987a27a --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Permissions/Input/UpdatePermissionRequest.cs @@ -0,0 +1,19 @@ +using Core.Cerberos.Adapters.Common.Constants; +using Core.Cerberos.Adapters.Common.Enums; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Permissions.Input +{ + public class UpdatePermissionRequest : Notificator, ICommand + { + public string Id { get; set; } = null!; + public string Name { get; set; } = null!; + public string? Description { get; set; } + public AccessLevelEnum? AccessLevel { get; set; } = null!; + public StatusEnum Status { get; set; } + public bool Validate() + { + return Id != null; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Permissions/PermissionHandler.cs b/Core.Cerberos.Application/UseCases/Permissions/PermissionHandler.cs new file mode 100644 index 0000000..9fd7c07 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Permissions/PermissionHandler.cs @@ -0,0 +1,204 @@ +using Core.Cerberos.Adapters; +using Core.Cerberos.Application.UseCases.Permissions.Input; +using Core.Cerberos.Application.UseCases.Permissions.Ports; +using Core.Cerberos.External.Clients; +using Core.Cerberos.External.Clients.Requests; +using FluentValidation; +using Lib.Architecture.BuildingBlocks; +using Lib.Architecture.BuildingBlocks.Helpers; + +namespace Core.Cerberos.Application.UseCases.Permissions +{ + public class PermissionHandler : + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler + { + private readonly IPermissionPort _port; + private readonly IValidator _changePermissionStatusValidator; + private readonly IValidator _registerPermissionValidator; + private readonly IValidator _updatePermissionValidator; + private readonly ICerberosServiceClient _cerberosDALService; + + public PermissionHandler( + IPermissionPort port, + IValidator changePermissionStatusValidator, + IValidator registerPermissionValidator, + IValidator updatePermissionValidator, + ICerberosServiceClient cerberosDALService) + { + _port = port ?? throw new ArgumentNullException(nameof(port)); + _changePermissionStatusValidator = changePermissionStatusValidator ?? throw new ArgumentNullException(nameof(changePermissionStatusValidator)); + _registerPermissionValidator = registerPermissionValidator ?? throw new ArgumentNullException(nameof(registerPermissionValidator)); + _updatePermissionValidator = updatePermissionValidator ?? throw new ArgumentNullException(nameof(updatePermissionValidator)); + _cerberosDALService = cerberosDALService ?? throw new ArgumentNullException(nameof(cerberosDALService)); + } + + public async ValueTask ExecuteAsync(GetPermissionRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var result = await _cerberosDALService.GetPermissionByIdAsync(command.Id, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(GetAllPermissionsRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var _result = await _cerberosDALService.GetAllPermissionsAsync().ConfigureAwait(false); + if (!_result.Any()) + { + _port.NoContentSuccess(); + return; + } + _port.Success(_result.ToList()); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(GetAllPermissionsByListRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var _result = await _cerberosDALService.GetAllPermissionsByListAsync(command.Permissions, cancellationToken).ConfigureAwait(false); + if (!_result.Any()) + { + _port.NoContentSuccess(); + return; + } + _port.Success(_result.ToList()); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(ChangePermissionStatusRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_changePermissionStatusValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var result = await _cerberosDALService.ChangeStatusPermissionAsync(command.Id, command.Status, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(CreatePermissionRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_registerPermissionValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var request = new PermissionRequest + { + Name = command.Name, + Description = command.Description, + AccessLevel = command.AccessLevel + }; + + var result = await _cerberosDALService.CreatePermissionAsync(request, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(UpdatePermissionRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_updatePermissionValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var request = new PermissionAdapter + { + Id = command.Id, + Name = command.Name, + Description = command.Description, + AccessLevel = command.AccessLevel, + Status = command.Status + }; + + string id = command.Id; + + var result = await _cerberosDALService.UpdatePermissionAsync(request, id, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Permissions/Ports/IPermissionPort.cs b/Core.Cerberos.Application/UseCases/Permissions/Ports/IPermissionPort.cs new file mode 100644 index 0000000..e65abc9 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Permissions/Ports/IPermissionPort.cs @@ -0,0 +1,13 @@ +using Core.Cerberos.Adapters; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Permissions.Ports +{ + public interface IPermissionPort : IBasePort, + ICommandSuccessPort, + ICommandSuccessPort>, + INoContentPort, IBusinessErrorPort, ITimeoutPort, IValidationErrorPort, + INotFoundPort, IForbiddenPort, IUnauthorizedPort, IInternalServerErrorPort + { + } +} diff --git a/Core.Cerberos.Application/UseCases/Permissions/Validator/ChangePermissionStatusValidator.cs b/Core.Cerberos.Application/UseCases/Permissions/Validator/ChangePermissionStatusValidator.cs new file mode 100644 index 0000000..a60b37b --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Permissions/Validator/ChangePermissionStatusValidator.cs @@ -0,0 +1,15 @@ +using Core.Cerberos.Application.UseCases.Permissions.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.Permissions.Validator +{ + public class ChangePermissionStatusValidator : AbstractValidator + { + public ChangePermissionStatusValidator() + { + RuleFor(i => i.Id).NotEmpty().NotNull().OverridePropertyName(x => x.Id).WithName("Permission ID").WithMessage("Permission ID is Obligatory."); + RuleFor(i => i.Status).NotNull().OverridePropertyName(x => x.Status).WithName("Status").WithMessage("Status is Obligatory."); + } + + } +} \ No newline at end of file diff --git a/Core.Cerberos.Application/UseCases/Permissions/Validator/CreatePermissionValidator.cs b/Core.Cerberos.Application/UseCases/Permissions/Validator/CreatePermissionValidator.cs new file mode 100644 index 0000000..eba98c0 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Permissions/Validator/CreatePermissionValidator.cs @@ -0,0 +1,15 @@ +using Core.Cerberos.Application.UseCases.Permissions.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.Permissions.Validator +{ + public class CreatePermissionValidator : AbstractValidator + { + public CreatePermissionValidator() + { + RuleFor(i => i.Name).NotEmpty().NotNull().OverridePropertyName(x => x.Name).WithName("Permission Name").WithMessage("Permission Name is Obligatory."); + RuleFor(i => i.Description).NotEmpty().NotNull().OverridePropertyName(x => x.Description).WithName("Permission Description").WithMessage("Permission Description is Obligatory."); + RuleFor(i => i.AccessLevel).NotEmpty().NotNull().OverridePropertyName(x => x.AccessLevel).WithName("AccesLevel").WithMessage("AccesLevel is Obligatory."); + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Permissions/Validator/UpdatePermissionValidator.cs b/Core.Cerberos.Application/UseCases/Permissions/Validator/UpdatePermissionValidator.cs new file mode 100644 index 0000000..d516e16 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Permissions/Validator/UpdatePermissionValidator.cs @@ -0,0 +1,14 @@ +using Core.Cerberos.Application.UseCases.Permissions.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.Permissions.Validator +{ + public class UpdatePermissionValidator : AbstractValidator + { + public UpdatePermissionValidator() + { + RuleFor(i => i.Name).NotEmpty().NotNull().OverridePropertyName(x => x.Name).WithName("Permission Name").WithMessage("Permission Name is Obligatory."); + RuleFor(i => i.Description).NotEmpty().NotNull().OverridePropertyName(x => x.Description).WithName("Permission Description").WithMessage("Permission Description is Obligatory."); + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Roles/Adapter/RolePort.cs b/Core.Cerberos.Application/UseCases/Roles/Adapter/RolePort.cs new file mode 100644 index 0000000..5806076 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Roles/Adapter/RolePort.cs @@ -0,0 +1,19 @@ +using Core.Cerberos.Adapters; +using Core.Cerberos.Application.UseCases.Roles.Ports; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Mvc; + +namespace Core.Cerberos.Application.UseCases.Roles.Adapter +{ + public class RolePort : BasePresenter, IRolePort + { + public void Success(RoleAdapter output) + { + ViewModel = new OkObjectResult(output); + } + public void Success(List output) + { + ViewModel = new OkObjectResult(output); + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Roles/Input/AddApplicationToRoleRequest.cs b/Core.Cerberos.Application/UseCases/Roles/Input/AddApplicationToRoleRequest.cs new file mode 100644 index 0000000..49c2bd0 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Roles/Input/AddApplicationToRoleRequest.cs @@ -0,0 +1,15 @@ +using Core.Cerberos.Adapters.Common.Enums; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Roles.Input +{ + public class AddApplicationToRoleRequest : Notificator, ICommand + { + public string RoleId { get; set; } + public ApplicationsEnum Application { get; set; } + public bool Validate() + { + return true; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Roles/Input/ChangeRoleStatusRequest.cs b/Core.Cerberos.Application/UseCases/Roles/Input/ChangeRoleStatusRequest.cs new file mode 100644 index 0000000..7133d04 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Roles/Input/ChangeRoleStatusRequest.cs @@ -0,0 +1,15 @@ +using Core.Cerberos.Adapters.Common.Enums; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Roles.Input +{ + public class ChangeRoleStatusRequest : Notificator, ICommand + { + public string Id { get; set; } + public StatusEnum Status { get; set; } + public bool Validate() + { + return Id != null; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Roles/Input/CreateRoleRequest.cs b/Core.Cerberos.Application/UseCases/Roles/Input/CreateRoleRequest.cs new file mode 100644 index 0000000..b0edcd7 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Roles/Input/CreateRoleRequest.cs @@ -0,0 +1,22 @@ +using Core.Cerberos.Adapters.Common.Enums; +using Lib.Architecture.BuildingBlocks; +using System.Text.Json.Serialization; + +namespace Core.Cerberos.Application.UseCases.Roles.Input +{ + public class CreateRoleRequest : Notificator, ICommand + { + public string Name { get; set; } = null!; + public string Description { get; set; } = null!; + + [JsonConverter(typeof(EnumArrayJsonConverter))] + public ApplicationsEnum[]? Applications { get; set; } = null!; + public string[] Modules { get; set; } = null!; + public string[] Permissions { get; set; } = null!; + + public bool Validate() + { + return Name != null; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Roles/Input/GetAllRolesRequest.cs b/Core.Cerberos.Application/UseCases/Roles/Input/GetAllRolesRequest.cs new file mode 100644 index 0000000..23e7dc5 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Roles/Input/GetAllRolesRequest.cs @@ -0,0 +1,12 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Roles.Input +{ + public class GetAllRolesRequest : ICommand + { + public bool Validate() + { + return true; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Roles/Input/GetRoleRequest.cs b/Core.Cerberos.Application/UseCases/Roles/Input/GetRoleRequest.cs new file mode 100644 index 0000000..7f424c8 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Roles/Input/GetRoleRequest.cs @@ -0,0 +1,13 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Roles.Input +{ + public class GetRoleRequest : Notificator, ICommand + { + public string Id { get; set; } + public bool Validate() + { + return Id != null; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Roles/Input/RemoveApplicationFromRoleRequest.cs b/Core.Cerberos.Application/UseCases/Roles/Input/RemoveApplicationFromRoleRequest.cs new file mode 100644 index 0000000..ffe3863 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Roles/Input/RemoveApplicationFromRoleRequest.cs @@ -0,0 +1,15 @@ +using Core.Cerberos.Adapters.Common.Enums; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Roles.Input +{ + public class RemoveApplicationFromRoleRequest : Notificator, ICommand + { + public string RoleId { get; set; } + public ApplicationsEnum Application { get; set; } + public bool Validate() + { + return true; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Roles/Input/UpdateRoleRequest.cs b/Core.Cerberos.Application/UseCases/Roles/Input/UpdateRoleRequest.cs new file mode 100644 index 0000000..bce0c1d --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Roles/Input/UpdateRoleRequest.cs @@ -0,0 +1,24 @@ +using Core.Cerberos.Adapters.Common.Enums; +using Lib.Architecture.BuildingBlocks; +using System.Text.Json.Serialization; + +namespace Core.Cerberos.Application.UseCases.Roles.Input +{ + public class UpdateRoleRequest : Notificator, ICommand + { + public string Id { get; set; } = null!; + public string Name { get; set; } = null!; + public string? Description { get; set; } + + [JsonConverter(typeof(EnumArrayJsonConverter))] + public ApplicationsEnum[]? Applications { get; set; } + public string[] Modules { get; set; } = null!; + public string[] Permissions { get; set; } = null!; + public StatusEnum Status { get; set; } + + public bool Validate() + { + return Id != null; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Roles/Ports/IRolePort.cs b/Core.Cerberos.Application/UseCases/Roles/Ports/IRolePort.cs new file mode 100644 index 0000000..bc1a929 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Roles/Ports/IRolePort.cs @@ -0,0 +1,12 @@ +using Core.Cerberos.Adapters; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Roles.Ports +{ + public interface IRolePort : IBasePort, + ICommandSuccessPort, ICommandSuccessPort>, + INoContentPort, IBusinessErrorPort, ITimeoutPort, IValidationErrorPort, + INotFoundPort, IForbiddenPort, IUnauthorizedPort, IInternalServerErrorPort + { + } +} diff --git a/Core.Cerberos.Application/UseCases/Roles/RoleHandler.cs b/Core.Cerberos.Application/UseCases/Roles/RoleHandler.cs new file mode 100644 index 0000000..5bd131b --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Roles/RoleHandler.cs @@ -0,0 +1,235 @@ +using Core.Cerberos.Adapters; +using Core.Cerberos.Application.UseCases.Roles.Input; +using Core.Cerberos.Application.UseCases.Roles.Ports; +using Core.Cerberos.External.Clients; +using Core.Cerberos.External.Clients.Requests; +using FluentValidation; +using Lib.Architecture.BuildingBlocks; +using Lib.Architecture.BuildingBlocks.Helpers; + +namespace Core.Cerberos.Application.UseCases.Role +{ + public class RoleHandler : + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler + + { + private readonly IRolePort _port; + private readonly IValidator _changeRoleStatusValidator; + private readonly IValidator _registerRoleValidator; + private readonly IValidator _updateRoleValidator; + private readonly ICerberosServiceClient _cerberosDALService; + + public RoleHandler( + IRolePort port, + IValidator changeRoleStatusValidator, + IValidator registerRoleValidator, + IValidator updateRoleValidator, + ICerberosServiceClient cerberosDALService) + { + _port = port ?? throw new ArgumentNullException(nameof(port)); + _changeRoleStatusValidator = changeRoleStatusValidator ?? throw new ArgumentNullException(nameof(changeRoleStatusValidator)); + _registerRoleValidator = registerRoleValidator ?? throw new ArgumentNullException(nameof(registerRoleValidator)); + _updateRoleValidator = updateRoleValidator ?? throw new ArgumentNullException(nameof(updateRoleValidator)); + _cerberosDALService = cerberosDALService ?? throw new ArgumentNullException(nameof(cerberosDALService)); + } + + public async ValueTask ExecuteAsync(GetRoleRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var result = await _cerberosDALService.GetRoleByIdAsync(command.Id, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(GetAllRolesRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var _result = await _cerberosDALService.GetAllRolesAsync().ConfigureAwait(false); + if (!_result.Any()) + { + _port.NoContentSuccess(); + return; + } + _port.Success(_result.ToList()); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(ChangeRoleStatusRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_changeRoleStatusValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var result = await _cerberosDALService.ChangeRoleStatusAsync(command.Id, command.Status, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(CreateRoleRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_registerRoleValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var request = new RoleRequest + { + Name = command.Name, + Description = command.Description, + Applications = command.Applications, + Modules = command.Modules, + Permissions = command.Permissions + + }; + + var result = await _cerberosDALService.CreateRoleAsync(request, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(UpdateRoleRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_updateRoleValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var request = new RoleAdapter + { + Id = command.Id, + Name = command.Name, + Description = command.Description, + Applications = command.Applications, + Modules = command.Modules, + Permissions = command.Permissions, + Status = command.Status + }; + + string id = command.Id; + + var result = await _cerberosDALService.UpdateRoleAsync(request, id, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(AddApplicationToRoleRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var result = await _cerberosDALService.AddApplicationToRoleAsync(command.RoleId, command.Application, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(RemoveApplicationFromRoleRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var result = await _cerberosDALService.RemoveApplicationToRoleAsync(command.RoleId, command.Application, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Roles/Validator/ChangeRoleStatusValidator.cs b/Core.Cerberos.Application/UseCases/Roles/Validator/ChangeRoleStatusValidator.cs new file mode 100644 index 0000000..02d5831 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Roles/Validator/ChangeRoleStatusValidator.cs @@ -0,0 +1,16 @@ +using Core.Cerberos.Application.UseCases.Roles.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.Roles.Validator +{ + public class ChangeRoleStatusValidator : AbstractValidator + { + public ChangeRoleStatusValidator() + { + RuleFor(i => i.Id).NotEmpty().NotNull().OverridePropertyName(x => x.Id).WithName("Role ID").WithMessage("Role ID is Obligatory."); + RuleFor(i => i.Status).NotNull().OverridePropertyName(x => x.Status).WithName("Status").WithMessage("Status is Obligatory."); + + } + + } +} diff --git a/Core.Cerberos.Application/UseCases/Roles/Validator/CreateRoleValidator.cs b/Core.Cerberos.Application/UseCases/Roles/Validator/CreateRoleValidator.cs new file mode 100644 index 0000000..0469039 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Roles/Validator/CreateRoleValidator.cs @@ -0,0 +1,16 @@ +using Core.Cerberos.Application.UseCases.Roles.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.Roles.Validator +{ + public class CreateRoleValidator : AbstractValidator + { + public CreateRoleValidator() + { + RuleFor(i => i.Name).NotEmpty().NotNull().OverridePropertyName(x => x.Name).WithName("Role Name").WithMessage("Role Name is Obligatory."); + RuleFor(i => i.Description).NotEmpty().NotNull().OverridePropertyName(x => x.Description).WithName("Role Description").WithMessage("Role Description is Obligatory."); + RuleFor(i => i.Applications).NotNull().OverridePropertyName(x => x.Applications).WithName("AccesLevel").WithMessage("Role must have at least one application."); + RuleFor(i => i.Permissions).NotEmpty().NotNull().OverridePropertyName(x => x.Applications).WithName("Role permissions").WithMessage("Role Permissions are Obligatory."); + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Roles/Validator/UpdateRoleValidator.cs b/Core.Cerberos.Application/UseCases/Roles/Validator/UpdateRoleValidator.cs new file mode 100644 index 0000000..91a860f --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Roles/Validator/UpdateRoleValidator.cs @@ -0,0 +1,16 @@ +using Core.Cerberos.Application.UseCases.Roles.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.Roles.Validator +{ + public class UpdateRoleValidator : AbstractValidator + { + public UpdateRoleValidator() + { + RuleFor(i => i.Name).NotEmpty().NotNull().OverridePropertyName(x => x.Name).WithName("Role Name").WithMessage("Role Name is Obligatory."); + RuleFor(i => i.Description).NotEmpty().NotNull().OverridePropertyName(x => x.Description).WithName("Role Description").WithMessage("Role Description is Obligatory."); + RuleFor(i => i.Applications).NotEmpty().NotNull().OverridePropertyName(x => x.Applications).WithName("Role applications").WithMessage("Role Applications are Obligatory."); + RuleFor(i => i.Permissions).NotEmpty().NotNull().OverridePropertyName(x => x.Applications).WithName("Role permissions").WithMessage("Role Permissions are Obligatory."); + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Users/Adapter/UserPort.cs b/Core.Cerberos.Application/UseCases/Users/Adapter/UserPort.cs new file mode 100644 index 0000000..8e78581 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Users/Adapter/UserPort.cs @@ -0,0 +1,33 @@ +using Core.Blueprint.Storage.Adapters; +using Core.Cerberos.Adapters; +using Core.Cerberos.Application.UseCases.Users.Ports; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Mvc; + +namespace Core.Cerberos.Application.UseCases.Users.Adapter +{ + public class UserPort : BasePresenter, IUserPort + { + public void Success(UserAdapter output) + { + ViewModel = new OkObjectResult(output); + } + public void Success(List output) + { + ViewModel = new OkObjectResult(output); + } + + public void Success(UserExistenceAdapter output) + { + ViewModel = new OkObjectResult(output); + } + public void Success(TokenAdapter output) + { + ViewModel = new OkObjectResult(output); + } + public void Success(BlobDownloadUriAdapter output) + { + ViewModel = new OkObjectResult(output); + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Users/Input/AcceptUserConsentFormRequest.cs b/Core.Cerberos.Application/UseCases/Users/Input/AcceptUserConsentFormRequest.cs new file mode 100644 index 0000000..8602422 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Users/Input/AcceptUserConsentFormRequest.cs @@ -0,0 +1,12 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Users.Input +{ + public class AcceptUserConsentFormRequest : ICommand + { + public bool Validate() + { + return true; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Users/Input/AddCompanyToUserRequest.cs b/Core.Cerberos.Application/UseCases/Users/Input/AddCompanyToUserRequest.cs new file mode 100644 index 0000000..d049e1e --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Users/Input/AddCompanyToUserRequest.cs @@ -0,0 +1,14 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Users.Input +{ + public class AddCompanyToUserRequest : Notificator, ICommand + { + public string UserId { get; set; } + public string CompanyId { get; set; } + public bool Validate() + { + return true; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Users/Input/AddProjectToUserRequest.cs b/Core.Cerberos.Application/UseCases/Users/Input/AddProjectToUserRequest.cs new file mode 100644 index 0000000..73888fa --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Users/Input/AddProjectToUserRequest.cs @@ -0,0 +1,14 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Users.Input +{ + public class AddProjectToUserRequest : Notificator, ICommand + { + public string UserId { get; set; } + public string ProjectId { get; set; } + public bool Validate() + { + return true; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Users/Input/ChangeUserStatusRequest.cs b/Core.Cerberos.Application/UseCases/Users/Input/ChangeUserStatusRequest.cs new file mode 100644 index 0000000..51deae5 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Users/Input/ChangeUserStatusRequest.cs @@ -0,0 +1,16 @@ +using Core.Cerberos.Adapters.Common.Enums; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Users.Input +{ + public class ChangeUserStatusRequest : Notificator, ICommand + { + public string Id { get; set; } + public StatusEnum Status { get; set; } + + public bool Validate() + { + return Id != null; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Users/Input/CreateUserRequest.cs b/Core.Cerberos.Application/UseCases/Users/Input/CreateUserRequest.cs new file mode 100644 index 0000000..9e8c6f7 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Users/Input/CreateUserRequest.cs @@ -0,0 +1,21 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Users.Input +{ + public class CreateUserRequest : Notificator, ICommand + { + public string Email { get; set; } = null!; + public string Name { get; set; } = null!; + public string MiddleName { get; set; } = null!; + public string LastName { get; set; } = null!; + public string RoleId { get; set; } = null!; + public string[] Companies { get; set; } = null!; + public string[]? Projects { get; set; } + public bool SendInvitation { get; set; } + + public bool Validate() + { + return Name != null; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Users/Input/GetAllUsersRequest.cs b/Core.Cerberos.Application/UseCases/Users/Input/GetAllUsersRequest.cs new file mode 100644 index 0000000..3a8eb34 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Users/Input/GetAllUsersRequest.cs @@ -0,0 +1,12 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Users.Input +{ + public class GetAllUsersRequest : ICommand + { + public bool Validate() + { + return true; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Users/Input/GetConsentFormPDFRequest.cs b/Core.Cerberos.Application/UseCases/Users/Input/GetConsentFormPDFRequest.cs new file mode 100644 index 0000000..f2123cf --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Users/Input/GetConsentFormPDFRequest.cs @@ -0,0 +1,12 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Users.Input +{ + public class GetConsentFormPDFRequest : ICommand + { + public bool Validate() + { + return true; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Users/Input/GetTokenAdapterRequest.cs b/Core.Cerberos.Application/UseCases/Users/Input/GetTokenAdapterRequest.cs new file mode 100644 index 0000000..c5c5810 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Users/Input/GetTokenAdapterRequest.cs @@ -0,0 +1,13 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Users.Input +{ + public class GetTokenAdapterRequest : Notificator, ICommand + { + public string Email { get; set; } + public bool Validate() + { + return Email != null; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Users/Input/GetUserByEmailRequest.cs b/Core.Cerberos.Application/UseCases/Users/Input/GetUserByEmailRequest.cs new file mode 100644 index 0000000..7f7590d --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Users/Input/GetUserByEmailRequest.cs @@ -0,0 +1,13 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Users.Input +{ + public class GetUserByEmailRequest : Notificator, ICommand + { + public string Email { get; set; } + public bool Validate() + { + return Email != null; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Users/Input/GetUserRequest.cs b/Core.Cerberos.Application/UseCases/Users/Input/GetUserRequest.cs new file mode 100644 index 0000000..a138d98 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Users/Input/GetUserRequest.cs @@ -0,0 +1,13 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Users.Input +{ + public class GetUserRequest : Notificator, ICommand + { + public string Id { get; set; } + public bool Validate() + { + return Id != null; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Users/Input/LoginUserRequest.cs b/Core.Cerberos.Application/UseCases/Users/Input/LoginUserRequest.cs new file mode 100644 index 0000000..914f00b --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Users/Input/LoginUserRequest.cs @@ -0,0 +1,13 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Users.Input +{ + public class LoginUserRequest : Notificator, ICommand + { + public string Email { get; set; } + public bool Validate() + { + return Email != null; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Users/Input/LogoutUserRequest.cs b/Core.Cerberos.Application/UseCases/Users/Input/LogoutUserRequest.cs new file mode 100644 index 0000000..a73132f --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Users/Input/LogoutUserRequest.cs @@ -0,0 +1,13 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Users.Input +{ + public class LogoutUserRequest : Notificator, ICommand + { + public string Email { get; set; } + public bool Validate() + { + return Email != null; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Users/Input/RemoveCompanyFromUserRequest.cs b/Core.Cerberos.Application/UseCases/Users/Input/RemoveCompanyFromUserRequest.cs new file mode 100644 index 0000000..cb0b276 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Users/Input/RemoveCompanyFromUserRequest.cs @@ -0,0 +1,14 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Users.Input +{ + public class RemoveCompanyFromUserRequest : Notificator, ICommand + { + public string UserId { get; set; } + public string CompanyId { get; set; } + public bool Validate() + { + return true; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Users/Input/RemoveProjectFromUserRequest.cs b/Core.Cerberos.Application/UseCases/Users/Input/RemoveProjectFromUserRequest.cs new file mode 100644 index 0000000..74a82d4 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Users/Input/RemoveProjectFromUserRequest.cs @@ -0,0 +1,14 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Users.Input +{ + public class RemoveProjectFromUserRequest : Notificator, ICommand + { + public string UserId { get; set; } + public string ProjectId { get; set; } + public bool Validate() + { + return true; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Users/Input/UpdateUserRequest.cs b/Core.Cerberos.Application/UseCases/Users/Input/UpdateUserRequest.cs new file mode 100644 index 0000000..96f8bb2 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Users/Input/UpdateUserRequest.cs @@ -0,0 +1,20 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Users.Input +{ + public class UpdateUserRequest : Notificator, ICommand + { + public string Id { get; set; } = null!; + public string Email { get; set; } = null!; + public string Name { get; set; } = null!; + public string? MiddleName { get; set; } + public string LastName { get; set; } = null!; + public string RoleId { get; set; } = null!; + public string[] Companies { get; set; } = null!; + public string[]? Projects { get; set; } + public bool Validate() + { + return Email != null; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Users/Input/ValidateUserExistenceRequest.cs b/Core.Cerberos.Application/UseCases/Users/Input/ValidateUserExistenceRequest.cs new file mode 100644 index 0000000..aabe8c6 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Users/Input/ValidateUserExistenceRequest.cs @@ -0,0 +1,13 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Users.Input +{ + public class ValidateUserExistenceRequest : Notificator, ICommand + { + public string Email { get; set; } + public bool Validate() + { + return Email != null; + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Users/Ports/IUserPort.cs b/Core.Cerberos.Application/UseCases/Users/Ports/IUserPort.cs new file mode 100644 index 0000000..551c6f3 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Users/Ports/IUserPort.cs @@ -0,0 +1,17 @@ +using Core.Blueprint.Storage.Adapters; +using Core.Cerberos.Adapters; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Cerberos.Application.UseCases.Users.Ports +{ + public interface IUserPort : IBasePort, + ICommandSuccessPort, + ICommandSuccessPort, + ICommandSuccessPort>, + ICommandSuccessPort, + ICommandSuccessPort, + INoContentPort, IBusinessErrorPort, ITimeoutPort, IValidationErrorPort, + INotFoundPort, IForbiddenPort, IUnauthorizedPort, IInternalServerErrorPort + { + } +} diff --git a/Core.Cerberos.Application/UseCases/Users/UserHandler.cs b/Core.Cerberos.Application/UseCases/Users/UserHandler.cs new file mode 100644 index 0000000..436c245 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Users/UserHandler.cs @@ -0,0 +1,439 @@ +using Core.Cerberos.Adapters; +using Core.Cerberos.Application.UseCases.Users.Input; +using Core.Cerberos.Application.UseCases.Users.Ports; +using Core.Cerberos.External.Clients; +using Core.Cerberos.External.Clients.Requests; +using FluentValidation; +using Lib.Architecture.BuildingBlocks; +using Lib.Architecture.BuildingBlocks.Helpers; +namespace Core.Cerberos.Application.UseCases.Users +{ + public class UserHandler : + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler + { + private readonly IUserPort _port; + private readonly IValidator _changeUserStatusValidator; + private readonly IValidator _registerUserValidator; + private readonly IValidator _updateUserValidator; + private readonly ICerberosServiceClient _cerberosDALService; + + public UserHandler( + IUserPort port, + IValidator changeUserStatusValidator, + IValidator registerUserValidator, + IValidator updateUserValidator, + ICerberosServiceClient cerberosDALService) + { + _port = port ?? throw new ArgumentNullException(nameof(port)); + _changeUserStatusValidator = changeUserStatusValidator ?? throw new ArgumentNullException(nameof(changeUserStatusValidator)); + _registerUserValidator = registerUserValidator ?? throw new ArgumentNullException(nameof(registerUserValidator)); + _updateUserValidator = updateUserValidator ?? throw new ArgumentNullException(nameof(updateUserValidator)); + _cerberosDALService = cerberosDALService ?? throw new ArgumentNullException(nameof(cerberosDALService)); + } + + public async ValueTask ExecuteAsync(GetUserRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var result = await _cerberosDALService.GetUserByIdAsync(command.Id, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(GetUserByEmailRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var result = await _cerberosDALService.GetUserByEmailAsync(command.Email, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(ValidateUserExistenceRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var result = await _cerberosDALService.ValidateUserExistence(command.Email, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(GetAllUsersRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var _result = await _cerberosDALService.GetAllUsersAsync().ConfigureAwait(false); + if (!_result.Any()) + { + _port.NoContentSuccess(); + return; + } + _port.Success(_result.ToList()); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(ChangeUserStatusRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_changeUserStatusValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var result = await _cerberosDALService.ChangeUserStatusAsync(command.Id, command.Status, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(CreateUserRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_registerUserValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var request = new UserRequest + { + Email = command.Email, + Name = command.Name, + MiddleName = command.MiddleName, + LastName = command.LastName, + RoleId = command.RoleId, + Companies = command.Companies, + Projects = command.Projects, + }; + + var result = await _cerberosDALService.CreateUserAsync(request, command.SendInvitation, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(UpdateUserRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_updateUserValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var request = new UserAdapter + { + Id = command.Id, + Email = command.Email, + Name = command.Name, + MiddleName = command.MiddleName, + LastName = command.LastName, + RoleId = command.RoleId, + Companies = command.Companies, + Projects = command.Projects + }; + + var result = await _cerberosDALService.UpdateUserAsync(request, request.Id, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(LoginUserRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var result = await _cerberosDALService.LoginUserAsync(command.Email, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(LogoutUserRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var result = await _cerberosDALService.LogoutUserAsync(command.Email, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(AddCompanyToUserRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var result = await _cerberosDALService.AddCompanyToUserAsync(command.UserId, command.CompanyId, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(RemoveCompanyFromUserRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var result = await _cerberosDALService.RemoveCompanyToUserAsync(command.UserId, command.CompanyId, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(AddProjectToUserRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var result = await _cerberosDALService.AddProjectToUserAsync(command.UserId, command.ProjectId, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(RemoveProjectFromUserRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var result = await _cerberosDALService.RemoveProjectToUserAsync(command.UserId, command.ProjectId, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(GetTokenAdapterRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var result = await _cerberosDALService.GetTokenAdapter(command.Email, cancellationToken).ConfigureAwait(false); + + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(GetConsentFormPDFRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var _result = await _cerberosDALService.GetConsentFormPDFAsync(cancellationToken).ConfigureAwait(false); + if (_result == null) + { + _port.NoContentSuccess(); + return; + } + _port.Success(_result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(AcceptUserConsentFormRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var result = await _cerberosDALService.AcceptUserConsentFormAsync(cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + } +} \ No newline at end of file diff --git a/Core.Cerberos.Application/UseCases/Users/Validator/ChangeUserStatusValidator.cs b/Core.Cerberos.Application/UseCases/Users/Validator/ChangeUserStatusValidator.cs new file mode 100644 index 0000000..abaf7cf --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Users/Validator/ChangeUserStatusValidator.cs @@ -0,0 +1,15 @@ +using Core.Cerberos.Application.UseCases.Users.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.Users.Validator +{ + public class ChangeUserStatusValidator : AbstractValidator + { + public ChangeUserStatusValidator() + { + RuleFor(i => i.Id).NotEmpty().NotNull().OverridePropertyName(x => x.Id).WithName("User ID").WithMessage("User ID is Obligatory."); + RuleFor(i => i.Status).NotNull().NotNull().OverridePropertyName(x => x.Status).WithName("Status").WithMessage("Status is Obligatory."); + } + + } +} \ No newline at end of file diff --git a/Core.Cerberos.Application/UseCases/Users/Validator/CreateUserValidator.cs b/Core.Cerberos.Application/UseCases/Users/Validator/CreateUserValidator.cs new file mode 100644 index 0000000..a91305b --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Users/Validator/CreateUserValidator.cs @@ -0,0 +1,17 @@ +using Core.Cerberos.Application.UseCases.Users.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.Users.Validator +{ + public class CreateUserValidator : AbstractValidator + { + public CreateUserValidator() + { + RuleFor(i => i.Email).NotEmpty().NotNull().OverridePropertyName(x => x.Email).WithName("User Email").WithMessage("Email is Obligatory."); + RuleFor(i => i.Name).NotEmpty().NotNull().OverridePropertyName(x => x.Name).WithName("User Name").WithMessage("User Name is Obligatory."); + RuleFor(i => i.LastName).NotEmpty().NotNull().OverridePropertyName(x => x.LastName).WithName("User LastName").WithMessage("User LastName is Obligatory."); + RuleFor(i => i.RoleId).NotEmpty().NotNull().OverridePropertyName(x => x.RoleId).WithName("Role Id").WithMessage("Role Id is Obligatory."); + RuleFor(i => i.Companies).NotEmpty().NotNull().OverridePropertyName(x => x.Companies).WithName("Companies").WithMessage("Companies is Obligatory."); + } + } +} diff --git a/Core.Cerberos.Application/UseCases/Users/Validator/UpdateUserValidator.cs b/Core.Cerberos.Application/UseCases/Users/Validator/UpdateUserValidator.cs new file mode 100644 index 0000000..1723ae0 --- /dev/null +++ b/Core.Cerberos.Application/UseCases/Users/Validator/UpdateUserValidator.cs @@ -0,0 +1,17 @@ +using Core.Cerberos.Application.UseCases.Users.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.Users.Validator +{ + public class UpdateUserValidator : AbstractValidator + { + public UpdateUserValidator() + { + RuleFor(i => i.Email).NotEmpty().NotNull().OverridePropertyName(x => x.Email).WithName("User Email").WithMessage("Email is Obligatory."); + RuleFor(i => i.Name).NotEmpty().NotNull().OverridePropertyName(x => x.Name).WithName("User Name").WithMessage("User Name is Obligatory."); + RuleFor(i => i.LastName).NotEmpty().NotNull().OverridePropertyName(x => x.LastName).WithName("User LastName").WithMessage("User LastName is Obligatory."); + RuleFor(i => i.RoleId).NotEmpty().NotNull().OverridePropertyName(x => x.RoleId).WithName("Role Id").WithMessage("Role Id is Obligatory."); + RuleFor(i => i.Companies).NotEmpty().NotNull().OverridePropertyName(x => x.Companies).WithName("Companies").WithMessage("Companies is Obligatory."); + } + } +} diff --git a/Core.Cerberos.External/ClientConfiguration/RegisterClientConfiguration.cs b/Core.Cerberos.External/ClientConfiguration/RegisterClientConfiguration.cs new file mode 100644 index 0000000..1f8e097 --- /dev/null +++ b/Core.Cerberos.External/ClientConfiguration/RegisterClientConfiguration.cs @@ -0,0 +1,59 @@ +using Core.Cerberos.External.Clients; +using Core.Cerberos.External.GatewayConfigurations; +using Core.Cerberos.External.Helpers.Token; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Refit; + +namespace Core.Cerberos.External.ClientConfiguration +{ + public static class RegisterClientConfiguration + { + public static IServiceCollection RegisterExternalLayer(this IServiceCollection services, IConfiguration configuration) + { + var gatewayConfiguration = new GatewayConfiguration(); + var gatewaySettingsConfiguration = new GatewaySettingsConfigurations(configuration); + + // Register GatewayConfiguration as a singleton + services.AddSingleton(gatewayConfiguration); + + // Register IHttpContextAccessor + services.AddSingleton(); + + // Register ITokenProvider + services.AddSingleton(); + + // Register the custom AuthenticatedHttpClientHandler + services.AddTransient(provider => + { + var tokenProvider = provider.GetRequiredService(); + var handler = new AuthenticatedHttpClientHandler(tokenProvider) + { + InnerHandler = new HttpClientHandler() // Setting the InnerHandler manually + }; + return handler; + }); + + var cerberosServiceApiUrl = GatewaySettingsConfigurations.GetCerberosServiceAPIEndpoint().Endpoint.Url; + + // Register ICerberosServiceClient with the manually created HttpClient + services.AddScoped(provider => + { + var handler = provider.GetRequiredService(); + var httpClient = new HttpClient(handler) + { + BaseAddress = new Uri(cerberosServiceApiUrl), + Timeout = TimeSpan.FromMinutes(1) + }; + return RestService.For(httpClient); + }); + + services.AddScoped(); + + return services; + } + } +} diff --git a/Core.Cerberos.External/Clients/ICerberosServiceClient.cs b/Core.Cerberos.External/Clients/ICerberosServiceClient.cs new file mode 100644 index 0000000..9c8717c --- /dev/null +++ b/Core.Cerberos.External/Clients/ICerberosServiceClient.cs @@ -0,0 +1,118 @@ +using Core.Blueprint.Storage.Adapters; +using Core.Cerberos.Adapters; +using Core.Cerberos.Adapters.Common.Constants; +using Core.Cerberos.Adapters.Common.Enums; +using Core.Cerberos.External.Clients.Requests; +using Microsoft.AspNetCore.Mvc; +using Refit; + +namespace Core.Cerberos.External.Clients +{ + public interface ICerberosServiceClient + { + [Get("/v1/User")] + Task> GetAllUsersAsync(CancellationToken cancellationToken = default); + + [Get("/v1/User/" + Routes.Id)] + Task GetUserByIdAsync([FromRoute] string id, CancellationToken cancellationToken = default); + + [Get("/v1/User/" + Routes.Email)] + Task GetUserByEmailAsync([FromRoute] string email, CancellationToken cancellationToken = default); + + [Get("/v1/User/{email}/ValidateExistence")] + Task ValidateUserExistence([FromRoute] string email, CancellationToken cancellationToken = default); + + [Post("/v1/User/" + Routes.Register)] + Task CreateUserAsync([FromBody] UserRequest newUser, [FromRoute] bool sendInvitation, CancellationToken cancellationToken = default); + + [Put("/v1/User/" + Routes.Id)] + Task UpdateUserAsync([FromBody] UserAdapter entity, [FromRoute] string id, CancellationToken cancellationToken = default); + + [Patch("/v1/User/" + Routes.LogIn)] + Task LoginUserAsync([FromRoute] string email, CancellationToken cancellationToken = default); + + [Patch("/v1/User/" + Routes.LogOut)] + Task LogoutUserAsync([FromRoute] string email, CancellationToken cancellationToken = default); + + [Patch("/v1/User/" + Routes.ChangeStatus)] + Task ChangeUserStatusAsync([FromRoute] string id, StatusEnum newStatus, CancellationToken cancellationToken = default); + + [Get("/v1/User/{email}/GetTokenAdapter")] + Task GetTokenAdapter([FromRoute] string email, CancellationToken cancellationToken = default); + + [Post("/v1/User/" + Routes.AddCompany)] + Task AddCompanyToUserAsync([FromRoute] string userId, [FromRoute] string companyId, CancellationToken cancellationToken = default); + + [Delete("/v1/User/" + Routes.RemoveCompany)] + Task RemoveCompanyToUserAsync([FromRoute] string userId, [FromRoute] string companyId, CancellationToken cancellationToken = default); + + [Post("/v1/User/" + Routes.AddProject)] + Task AddProjectToUserAsync([FromRoute] string userId, [FromRoute] string projectId, CancellationToken cancellationToken = default); + + [Delete("/v1/User/" + Routes.RemoveProject)] + Task RemoveProjectToUserAsync([FromRoute] string userId, [FromRoute] string projectId, CancellationToken cancellationToken = default); + + [Get("/v1/User/GetConsentFormPDF")] + Task GetConsentFormPDFAsync(CancellationToken cancellationToken = default); + + [Patch("/v1/User/AcceptUserConsentForm")] + Task AcceptUserConsentFormAsync(CancellationToken cancellationToken = default); + + [Get("/v1/Role")] + Task> GetAllRolesAsync(CancellationToken cancellationToken = default); + + [Get("/v1/Role/" + Routes.Id)] + Task GetRoleByIdAsync([FromRoute] string id, CancellationToken cancellationToken = default); + + [Post("/v1/Role")] + Task CreateRoleAsync([FromBody] RoleRequest newRole, CancellationToken cancellationToken = default); + + [Put("/v1/Role/" + Routes.Id)] + Task UpdateRoleAsync([FromBody] RoleAdapter entity, [FromRoute] string id, CancellationToken cancellationToken = default); + + [Patch("/v1/Role/" + Routes.ChangeStatus)] + Task ChangeRoleStatusAsync([FromRoute] string id, [FromRoute] StatusEnum newStatus, CancellationToken cancellationToken = default); + + [Post("/v1/Role/" + Routes.AddApplication)] + Task AddApplicationToRoleAsync([FromRoute] string RoleId, [FromRoute] ApplicationsEnum application, CancellationToken cancellationToken = default); + + [Delete("/v1/Role/" + Routes.RemoveApplication)] + Task RemoveApplicationToRoleAsync([FromRoute] string RoleId, [FromRoute] ApplicationsEnum application, CancellationToken cancellationToken = default); + + [Get("/v1/Permission")] + Task> GetAllPermissionsAsync(CancellationToken cancellationToken = default); + + [Post("/v1/Permission/" + Routes.GetPermissionList)] + Task> GetAllPermissionsByListAsync([FromBody] string[] request, CancellationToken cancellationToken = default); + + [Get("/v1/Permission/" + Routes.Id)] + Task GetPermissionByIdAsync([FromRoute] string id, CancellationToken cancellationToken = default); + + [Post("/v1/Permission")] + Task CreatePermissionAsync([FromBody] PermissionRequest newPermission, CancellationToken cancellationToken = default); + + [Put("/v1/Permission/" + Routes.Id)] + Task UpdatePermissionAsync([FromBody] PermissionAdapter entity, [FromRoute] string id, CancellationToken cancellationToken = default); + + [Patch("/v1/Permission/" + Routes.ChangeStatus)] + Task ChangeStatusPermissionAsync([FromRoute] string id, [FromRoute] StatusEnum newStatus, CancellationToken cancellationToken = default); + + [Get("/v1/Module")] + Task> GetAllModulesAsync(CancellationToken cancellationToken = default); + + [Post("/v1/Module/" + Routes.GetModuleList)] + Task> GetAllModulesByListAsync([FromBody] string[] request, CancellationToken cancellationToken = default); + + [Get("/v1/Module/" + Routes.Id)] + Task GetModuleByIdAsync([FromRoute] string id, CancellationToken cancellationToken = default); + + [Post("/v1/Module")] + Task CreateModuleAsync([FromBody] ModuleRequest newModule, CancellationToken cancellationToken = default); + + [Put("/v1/Module/" + Routes.Id)] + Task UpdateModuleAsync([FromBody] ModuleAdapter entity, [FromRoute] string id, CancellationToken cancellationToken = default); + + [Patch("/v1/Module/" + Routes.ChangeStatus)] + Task ChangeStatusModuleAsync([FromRoute] string id, [FromRoute] StatusEnum newStatus, CancellationToken cancellationToken = default); + } +} diff --git a/Core.Cerberos.External/Clients/Requests/ModuleRequest.cs b/Core.Cerberos.External/Clients/Requests/ModuleRequest.cs new file mode 100644 index 0000000..2aaaece --- /dev/null +++ b/Core.Cerberos.External/Clients/Requests/ModuleRequest.cs @@ -0,0 +1,16 @@ +using Core.Cerberos.Adapters.Common.Enums; +using System.Text.Json.Serialization; + +namespace Core.Cerberos.External.Clients.Requests +{ + public class ModuleRequest + { + public string Name { get; set; } = null!; + public string? Description { get; set; } + public string? Icon { get; set; } + public string? Route { get; set; } + public int? Order { get; set; } + [JsonConverter(typeof(JsonStringEnumConverter))] + public ApplicationsEnum? Application { get; set; } = null!; + } +} diff --git a/Core.Cerberos.External/Clients/Requests/PermissionRequest.cs b/Core.Cerberos.External/Clients/Requests/PermissionRequest.cs new file mode 100644 index 0000000..8049d4c --- /dev/null +++ b/Core.Cerberos.External/Clients/Requests/PermissionRequest.cs @@ -0,0 +1,12 @@ +using Core.Cerberos.Adapters.Common.Constants; + +namespace Core.Cerberos.External.Clients.Requests +{ + public class PermissionRequest + { + public string Name { get; set; } = null!; + public string? Description { get; set; } + public string? RoleId { get; set; } + public AccessLevelEnum? AccessLevel { get; set; } = null!; + } +} diff --git a/Core.Cerberos.External/Clients/Requests/RoleRequest.cs b/Core.Cerberos.External/Clients/Requests/RoleRequest.cs new file mode 100644 index 0000000..11ad9dc --- /dev/null +++ b/Core.Cerberos.External/Clients/Requests/RoleRequest.cs @@ -0,0 +1,16 @@ +using Core.Cerberos.Adapters.Common.Enums; +using System.Text.Json.Serialization; + +namespace Core.Cerberos.External.Clients.Requests +{ + public class RoleRequest + { + public string Name { get; set; } = null!; + public string? Description { get; set; } + [JsonConverter(typeof(EnumArrayJsonConverter))] + public ApplicationsEnum[]? Applications { get; set; } + public string[] Modules { get; set; } = null!; + public string[] Permissions { get; set; } = null!; + + } +} diff --git a/Core.Cerberos.External/Clients/Requests/UserRequest.cs b/Core.Cerberos.External/Clients/Requests/UserRequest.cs new file mode 100644 index 0000000..8fe46d0 --- /dev/null +++ b/Core.Cerberos.External/Clients/Requests/UserRequest.cs @@ -0,0 +1,13 @@ +namespace Core.Cerberos.External.Clients.Requests +{ + public class UserRequest + { + public string Email { get; set; } = null!; + public string Name { get; set; } = null!; + public string? MiddleName { get; set; } + public string LastName { get; set; } = null!; + public string RoleId { get; set; } = null!; + public string[] Companies { get; set; } = null!; + public string[]? Projects { get; set; } + } +} diff --git a/Core.Cerberos.External/Core.Cerberos.External.csproj b/Core.Cerberos.External/Core.Cerberos.External.csproj new file mode 100644 index 0000000..327e206 --- /dev/null +++ b/Core.Cerberos.External/Core.Cerberos.External.csproj @@ -0,0 +1,16 @@ + + + + net8.0 + enable + enable + + + + + + + + + + diff --git a/Core.Cerberos.External/GatewayConfigurations/GatewayConfiguration.cs b/Core.Cerberos.External/GatewayConfigurations/GatewayConfiguration.cs new file mode 100644 index 0000000..3ff78d2 --- /dev/null +++ b/Core.Cerberos.External/GatewayConfigurations/GatewayConfiguration.cs @@ -0,0 +1,19 @@ +using Core.Blueprint.External; + +namespace Core.Cerberos.External.GatewayConfigurations +{ + public record GatewayConfiguration + { + public GatewayConfiguration() + { + CerberosService = new CerberosServiceAPI(); + } + + public CerberosServiceAPI CerberosService { get; set; } + } + public record CerberosServiceAPI + { + public string Channel { get; set; } + public BaseEndpoint Endpoint { get; set; } + } +} diff --git a/Core.Cerberos.External/GatewayConfigurations/GatewaySettingsConfigurations.cs b/Core.Cerberos.External/GatewayConfigurations/GatewaySettingsConfigurations.cs new file mode 100644 index 0000000..97fdda0 --- /dev/null +++ b/Core.Cerberos.External/GatewayConfigurations/GatewaySettingsConfigurations.cs @@ -0,0 +1,48 @@ +using Core.Blueprint.External; +using Microsoft.Extensions.Configuration; + +namespace Core.Cerberos.External.GatewayConfigurations +{ + public class GatewaySettingsConfigurations + { + private static GatewayConfiguration GatewayConfigurations { get; set; } = new GatewayConfiguration(); + private readonly IConfiguration _configuration; + + public GatewaySettingsConfigurations(IConfiguration configuration) + { + _configuration = configuration; + this.SetCerberosServiceAPIEndpoint(); + } + public static CerberosServiceAPI GetCerberosServiceAPIEndpoint() + { + return GatewayConfigurations.CerberosService; + } + private GatewayConfiguration SetCerberosServiceAPIEndpoint() + { + IConfigurationSection source; + var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? string.Empty; + + if (environment == "Local") + source = _configuration.GetSection("LocalGateways"); + else + source = _configuration.GetSection("Gateways"); + + var endpoint = source["CerberosDAL"] ?? string.Empty; + + if (string.IsNullOrEmpty(endpoint)) throw new Exception("Cerberos DAL endpoint is empty or null"); + + GatewayConfigurations.CerberosService = new CerberosServiceAPI() + { + Endpoint = new BaseEndpoint() + { + Uri = new Uri(endpoint), + Url = endpoint, + Token = string.Empty, + APIName = "Cerberos Service" + } + }; + + return GatewayConfigurations; + } + } +} diff --git a/Core.Cerberos.External/Helpers/Token/AuthenticatedHttpClientHandler.cs b/Core.Cerberos.External/Helpers/Token/AuthenticatedHttpClientHandler.cs new file mode 100644 index 0000000..28d2178 --- /dev/null +++ b/Core.Cerberos.External/Helpers/Token/AuthenticatedHttpClientHandler.cs @@ -0,0 +1,32 @@ +// *********************************************************************** +// +// Heath +// +// *********************************************************************** + +namespace Core.Cerberos.External.Helpers.Token +{ + /// + /// Class to inject the token in all requests. + /// + public class AuthenticatedHttpClientHandler : DelegatingHandler + { + private readonly ITokenProvider _tokenProvider; + + public AuthenticatedHttpClientHandler(ITokenProvider tokenProvider) + { + _tokenProvider = tokenProvider; + } + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + var token = _tokenProvider.GetToken(); + if (!string.IsNullOrEmpty(token)) + { + request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token); + } + + return await base.SendAsync(request, cancellationToken); + } + } +} diff --git a/Core.Cerberos.External/Helpers/Token/HttpContextTokenProvider.cs b/Core.Cerberos.External/Helpers/Token/HttpContextTokenProvider.cs new file mode 100644 index 0000000..55845e3 --- /dev/null +++ b/Core.Cerberos.External/Helpers/Token/HttpContextTokenProvider.cs @@ -0,0 +1,31 @@ +// *********************************************************************** +// +// Heath +// +// *********************************************************************** + +using Microsoft.AspNetCore.Http; + +namespace Core.Cerberos.External.Helpers.Token +{ + /// + /// Class to return the access token to controllers. + /// + public class HttpContextTokenProvider : ITokenProvider + { + private readonly IHttpContextAccessor _httpContextAccessor; + + public HttpContextTokenProvider(IHttpContextAccessor httpContextAccessor) + { + _httpContextAccessor = httpContextAccessor; + } + + /// + /// Get token from headers. + /// + public string GetToken() + { + return _httpContextAccessor.HttpContext?.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last(); + } + } +} diff --git a/Core.Cerberos.External/Helpers/Token/ITokenProvider.cs b/Core.Cerberos.External/Helpers/Token/ITokenProvider.cs new file mode 100644 index 0000000..b3f5b4b --- /dev/null +++ b/Core.Cerberos.External/Helpers/Token/ITokenProvider.cs @@ -0,0 +1,19 @@ +// *********************************************************************** +// +// Heath +// +// *********************************************************************** + +namespace Core.Cerberos.External.Helpers.Token +{ + /// + /// Interface for token provider. + /// + public interface ITokenProvider + { + /// + /// Get token from headers. + /// + string GetToken(); + } +} diff --git a/Core.Cerberos.Service.API.sln b/Core.Cerberos.Service.API.sln new file mode 100644 index 0000000..9c79e7f --- /dev/null +++ b/Core.Cerberos.Service.API.sln @@ -0,0 +1,46 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.10.34928.147 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Cerberos.Service.API", "Core.Cerberos.Service.API\Core.Cerberos.Service.API.csproj", "{00F5B578-77EE-44A9-A611-5D753FDF158D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Application", "Application", "{F33D7786-EFE5-4618-9D47-C0272227C095}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Presentation", "Presentation", "{685F19C0-CE60-4BFB-9EDB-6834D01A6161}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Cerberos.External", "Core.Cerberos.External\Core.Cerberos.External.csproj", "{52EB3BBE-DACB-4EE5-8FFA-B8DBE34BA137}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core.Cerberos.Application", "Core.Cerberos.Application\Core.Cerberos.Application.csproj", "{F1980B4D-35C3-4495-84CF-09E1D3822CDA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {00F5B578-77EE-44A9-A611-5D753FDF158D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {00F5B578-77EE-44A9-A611-5D753FDF158D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {00F5B578-77EE-44A9-A611-5D753FDF158D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {00F5B578-77EE-44A9-A611-5D753FDF158D}.Release|Any CPU.Build.0 = Release|Any CPU + {52EB3BBE-DACB-4EE5-8FFA-B8DBE34BA137}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {52EB3BBE-DACB-4EE5-8FFA-B8DBE34BA137}.Debug|Any CPU.Build.0 = Debug|Any CPU + {52EB3BBE-DACB-4EE5-8FFA-B8DBE34BA137}.Release|Any CPU.ActiveCfg = Release|Any CPU + {52EB3BBE-DACB-4EE5-8FFA-B8DBE34BA137}.Release|Any CPU.Build.0 = Release|Any CPU + {F1980B4D-35C3-4495-84CF-09E1D3822CDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F1980B4D-35C3-4495-84CF-09E1D3822CDA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F1980B4D-35C3-4495-84CF-09E1D3822CDA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F1980B4D-35C3-4495-84CF-09E1D3822CDA}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {00F5B578-77EE-44A9-A611-5D753FDF158D} = {685F19C0-CE60-4BFB-9EDB-6834D01A6161} + {52EB3BBE-DACB-4EE5-8FFA-B8DBE34BA137} = {F33D7786-EFE5-4618-9D47-C0272227C095} + {F1980B4D-35C3-4495-84CF-09E1D3822CDA} = {F33D7786-EFE5-4618-9D47-C0272227C095} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8FA6398B-A66F-49A1-AB06-EDCEA5A4715E} + EndGlobalSection +EndGlobal diff --git a/Core.Cerberos.Service.API/Cerberos.Service.API.http b/Core.Cerberos.Service.API/Cerberos.Service.API.http new file mode 100644 index 0000000..ec0c9c4 --- /dev/null +++ b/Core.Cerberos.Service.API/Cerberos.Service.API.http @@ -0,0 +1,6 @@ +@Core.Cerberos.Service.API_HostAddress = http://localhost:5145 + +GET {{Core.Cerberos.Service.API_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/Core.Cerberos.Service.API/Controllers/ModuleController.cs b/Core.Cerberos.Service.API/Controllers/ModuleController.cs new file mode 100644 index 0000000..4bf1450 --- /dev/null +++ b/Core.Cerberos.Service.API/Controllers/ModuleController.cs @@ -0,0 +1,200 @@ +using Asp.Versioning; +using Core.Cerberos.Adapters; +using Core.Cerberos.Adapters.Attributes; +using Core.Cerberos.Adapters.Common.Constants; +using Core.Cerberos.Application.UseCases.Modules.Input; +using Core.Cerberos.Application.UseCases.Modules.Ports; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Core.Cerberos.Service.API.Controllers +{ + /// + /// Handles all services and business rules related to . + /// + [ApiVersion("1.0")] + [Route("api/v{api-version:apiVersion}/[controller]")] + [Produces("application/json")] + [ApiController] + public class ModuleController : ControllerBase + { + private readonly IComponentHandler getModuleHandler; + private readonly IComponentHandler getAllModulesHandler; + private readonly IComponentHandler getAllModulesByListHandler; + private readonly IComponentHandler createModuleHandler; + private readonly IComponentHandler updateModuleHandler; + private readonly IComponentHandler changeModuleStatusHandler; + private readonly IModulePort port; + + /// + /// Handles all services and business rules related to . + /// + public ModuleController( + IComponentHandler getModuleHandler, + IComponentHandler getAllModulesHandler, + IComponentHandler getAllModulesByListHandler, + IComponentHandler createModuleHandler, + IComponentHandler updateModuleHandler, + IComponentHandler changeModuleStatusHandler, + IModulePort port + ) + { + this.createModuleHandler = createModuleHandler; + this.updateModuleHandler = updateModuleHandler; + this.changeModuleStatusHandler = changeModuleStatusHandler; + this.getAllModulesHandler = getAllModulesHandler; + this.getModuleHandler = getModuleHandler; + this.getAllModulesByListHandler = getAllModulesByListHandler; + this.port = port; + } + + /// + /// Gets all the modules. + /// + [HttpGet("GetAll")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("ModuleManagement.Read, RoleManagement.Read")] + public async Task GetAllModulesAsync(CancellationToken cancellationToken) + { + await getAllModulesHandler.ExecuteAsync(new GetAllModulesRequest { }, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Gets all the modules by module identifiers. + /// + /// The request containing the list of module identifiers. + /// Cancellation token for the asynchronous operation. + /// The representing the result of the service call. + /// The modules found. + /// No content if no modules are found. + /// Bad request if the module identifiers are missing or invalid. + /// Unauthorized if the user is not authenticated. + /// Precondition failed if the request does not meet expected conditions. + /// Unprocessable entity if the request cannot be processed. + /// Internal server error if an unexpected error occurs. + [HttpPost] + [Route(Routes.GetModuleList)] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("ModuleManagement.Read")] + public async Task GetAllModulesByListAsync([FromBody] GetAllModulesByListRequest request, CancellationToken cancellationToken) + { + + if (request == null || request.Modules == null || !request.Modules.Any()) + { + return BadRequest("Module identifiers are required."); + } + + await getAllModulesByListHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Gets the module by identifier. + /// + [HttpPost] + [Route("GetById")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("ModuleManagement.Read")] + public async Task GetModuleById([FromBody] GetModuleRequest request, CancellationToken cancellationToken) + { + + if (request.Id == null || !request.Id.Any()) + { + return BadRequest("Invalid Module Id"); + } + + await getModuleHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Creates a new module. + /// + [HttpPost("Create")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("ModuleManagement.Write")] + public async Task CreateModuleAsync([FromBody] CreateModuleRequest newModule, CancellationToken cancellationToken = default) + { + await createModuleHandler.ExecuteAsync(newModule, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Updates a full module by identifier. + /// + [HttpPut("Update")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("ModuleManagement.Write")] + public async Task UpdateModuleAsync([FromBody] UpdateModuleRequest request, CancellationToken cancellationToken = default) + { + await updateModuleHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Changes the status of the module. + /// + [HttpPatch] + [Route("ChangeStatus")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("ModuleManagement.Write")] + public async Task ChangeModuleStatusAsync([FromBody] ChangeModuleStatusRequest request, + CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(request.Id)) { return BadRequest("Invalid module identifier"); } + + await changeModuleStatusHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + } +} diff --git a/Core.Cerberos.Service.API/Controllers/PermissionController.cs b/Core.Cerberos.Service.API/Controllers/PermissionController.cs new file mode 100644 index 0000000..0c43203 --- /dev/null +++ b/Core.Cerberos.Service.API/Controllers/PermissionController.cs @@ -0,0 +1,200 @@ +using Asp.Versioning; +using Core.Cerberos.Adapters; +using Core.Cerberos.Adapters.Attributes; +using Core.Cerberos.Adapters.Common.Constants; +using Core.Cerberos.Application.UseCases.Permissions.Input; +using Core.Cerberos.Application.UseCases.Permissions.Ports; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Core.Cerberos.Service.API.Controllers +{ + /// + /// Handles all services and business rules related to . + /// + [ApiVersion("1.0")] + [Route("api/v{api-version:apiVersion}/[controller]")] + [Produces("application/json")] + [ApiController] + public class PermissionController : ControllerBase + { + private readonly IComponentHandler getPermissionHandler; + private readonly IComponentHandler getAllPermissionsHandler; + private readonly IComponentHandler getAllPermissionsByListHandler; + private readonly IComponentHandler createPermissionHandler; + private readonly IComponentHandler updatePermissionHandler; + private readonly IComponentHandler changePermissionStatusHandler; + private readonly IPermissionPort port; + + /// + /// Handles all services and business rules related to . + /// + public PermissionController( + IComponentHandler getPermissionHandler, + IComponentHandler getAllPermissionsHandler, + IComponentHandler getAllPermissionsByListHandler, + IComponentHandler createPermissionHandler, + IComponentHandler updatePermissionHandler, + IComponentHandler changePermissionStatusHandler, + IPermissionPort port + ) + { + this.createPermissionHandler = createPermissionHandler; + this.updatePermissionHandler = updatePermissionHandler; + this.changePermissionStatusHandler = changePermissionStatusHandler; + this.getAllPermissionsHandler = getAllPermissionsHandler; + this.getPermissionHandler = getPermissionHandler; + this.getAllPermissionsByListHandler = getAllPermissionsByListHandler; + this.port = port; + } + + /// + /// Gets all the permissions. + /// + [HttpGet("GetAll")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("PermissionManagement.Read, RoleManagement.Read")] + public async Task GetAllPermissionsAsync(CancellationToken cancellationToken) + { + await getAllPermissionsHandler.ExecuteAsync(new GetAllPermissionsRequest { }, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Gets all the permissions by permission identifiers. + /// + /// The request containing the list of permission identifiers. + /// Cancellation token for the asynchronous operation. + /// The representing the result of the service call. + /// The permissions found. + /// No content if no permissions are found. + /// Bad request if the permission identifiers are missing or invalid. + /// Unauthorized if the user is not authenticated. + /// Precondition failed if the request does not meet expected conditions. + /// Unprocessable entity if the request cannot be processed. + /// Internal server error if an unexpected error occurs. + [HttpPost] + [Route(Routes.GetPermissionList)] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("PermissionManagement.Read")] + public async Task GetAllPermissionsByListAsync([FromBody] GetAllPermissionsByListRequest request, CancellationToken cancellationToken) + { + + if (request == null || request.Permissions == null || !request.Permissions.Any()) + { + return BadRequest("Permission identifiers are required."); + } + + await getAllPermissionsByListHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Gets the permission by identifier. + /// + [HttpPost] + [Route("GetById")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("PermissionManagement.Read")] + public async Task GetPermissionById([FromBody] GetPermissionRequest request, CancellationToken cancellationToken) + { + + if (request.Id == null || !request.Id.Any()) + { + return BadRequest("Invalid Permission Id"); + } + + await getPermissionHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Creates a new permission. + /// + [HttpPost("Create")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("PermissionManagement.Write")] + public async Task CreatePermissionAsync([FromBody] CreatePermissionRequest newPermission, CancellationToken cancellationToken = default) + { + await createPermissionHandler.ExecuteAsync(newPermission, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Updates a full permission by identifier. + /// + [HttpPut("Update")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("PermissionManagement.Write")] + public async Task UpdatePermissionAsync([FromBody] UpdatePermissionRequest request, CancellationToken cancellationToken = default) + { + await updatePermissionHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Changes the status of the permission. + /// + [HttpPatch] + [Route("ChangeStatus")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("PermissionManagement.Write")] + public async Task ChangePermissionStatusAsync([FromBody] ChangePermissionStatusRequest request, + CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(request.Id)) { return BadRequest("Invalid permission identifier"); } + + await changePermissionStatusHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + } +} diff --git a/Core.Cerberos.Service.API/Controllers/RoleController.cs b/Core.Cerberos.Service.API/Controllers/RoleController.cs new file mode 100644 index 0000000..32d6a14 --- /dev/null +++ b/Core.Cerberos.Service.API/Controllers/RoleController.cs @@ -0,0 +1,208 @@ +using Asp.Versioning; +using Core.Cerberos.Adapters.Attributes; +using Core.Cerberos.Adapters.Common.Constants; +using Core.Cerberos.Application.UseCases.Roles.Input; +using Core.Cerberos.Application.UseCases.Roles.Ports; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Core.Cerberos.Service.API.Controllers +{ + /// + /// Handles all requests for role authentication. + /// + [ApiVersion("1.0")] + [Route("api/v{api-version:apiVersion}/[controller]")] + [Produces("application/json")] + [ApiController] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + public class RoleController : ControllerBase + { + private readonly IComponentHandler getRoleHandler; + private readonly IComponentHandler getAllRolesHandler; + private readonly IComponentHandler createRoleHandler; + private readonly IComponentHandler updateRoleHandler; + private readonly IComponentHandler changeStatusRoleHandler; + private readonly IComponentHandler addApplicationToRoleHandler; + private readonly IComponentHandler removeApplicationToRoleHandler; + private readonly IRolePort port; + + /// + /// Handles all requests for role authentication. + /// + public RoleController( + IComponentHandler getRoleHandler, + IComponentHandler getAllRolesHandler, + IComponentHandler createRoleHandler, + IComponentHandler updateRoleHandler, + IComponentHandler changeRoleStatusHandler, + IComponentHandler addApplicationToRoleHandler, + IComponentHandler removeApplicationToRoleHandler, + IRolePort port + ) + { + this.createRoleHandler = createRoleHandler; + this.updateRoleHandler = updateRoleHandler; + this.changeStatusRoleHandler = changeRoleStatusHandler; + this.getAllRolesHandler = getAllRolesHandler; + this.getRoleHandler = getRoleHandler; + this.addApplicationToRoleHandler = addApplicationToRoleHandler; + this.removeApplicationToRoleHandler = removeApplicationToRoleHandler; + this.port = port; + } + + /// + /// Gets all the roles. + /// + [HttpGet("GetAll")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("RoleManagement.Read")] + public async Task GetAllRolesAsync(CancellationToken cancellationToken) + { + await getAllRolesHandler.ExecuteAsync(new GetAllRolesRequest { }, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Gets the role by identifier. + /// + [HttpPost] + [Route("GetById")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("RoleManagement.Read")] + public async Task GetRoleById([FromBody] GetRoleRequest request, CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(request.Id)) { return BadRequest("Invalid role identifier"); } + + await getRoleHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Creates a new role. + /// + [HttpPost("Create")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("RoleManagement.Write")] + public async Task CreateRoleAsync([FromBody] CreateRoleRequest newRole, CancellationToken cancellationToken = default) + { + await createRoleHandler.ExecuteAsync(newRole, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Updates a full role by identifier. + /// + [HttpPut("Update")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("RoleManagement.Write")] + public async Task UpdateRoleAsync([FromBody] UpdateRoleRequest entity, CancellationToken cancellationToken = default) + { + await updateRoleHandler.ExecuteAsync(entity, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Changes the status of the role. + /// + [HttpPatch] + [Route("ChangeStatus")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("RoleManagement.Write")] + public async Task ChageRoleStatusAsync(ChangeRoleStatusRequest request, CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(request.Id)) { return BadRequest("Invalid role identifier"); } + + await changeStatusRoleHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Adds an application to the role's list of applications. + /// + [HttpPost] + [Route("AddApplication")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("RoleManagement.Write")] + public async Task AddApplicationToRoleAsync(AddApplicationToRoleRequest request, CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(request.RoleId)) { return BadRequest("Invalid role identifier"); } + + await addApplicationToRoleHandler.ExecuteAsync(request, cancellationToken); + + return port.ViewModel; + } + + /// + /// Removes an application from the role's list of applications. + /// + [HttpDelete] + [Route("RemoveApplication")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("RoleManagement.Write")] + public async Task RemoveApplicationToRoleAsync(RemoveApplicationFromRoleRequest request, + CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(request.RoleId)) { return BadRequest("Invalid role identifier"); } + + await removeApplicationToRoleHandler.ExecuteAsync(request, cancellationToken); + + return port.ViewModel; + } + } +} diff --git a/Core.Cerberos.Service.API/Controllers/UserController.cs b/Core.Cerberos.Service.API/Controllers/UserController.cs new file mode 100644 index 0000000..4fc4314 --- /dev/null +++ b/Core.Cerberos.Service.API/Controllers/UserController.cs @@ -0,0 +1,432 @@ +using Asp.Versioning; +using Core.Cerberos.Adapters; +using Core.Cerberos.Adapters.Attributes; +using Core.Cerberos.Adapters.Common.Constants; +using Core.Cerberos.Application.UseCases.Users.Input; +using Core.Cerberos.Application.UseCases.Users.Ports; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Core.Cerberos.Service.API.Controllers +{ + /// + /// Handles all requests for user. + /// + [ApiVersion("1.0")] + [Route("api/v{api-version:apiVersion}/[controller]")] + [Produces("application/json")] + [ApiController] + public class UserController : ControllerBase + { + private readonly IComponentHandler getUserHandler; + private readonly IComponentHandler getUserByEmailHandler; + private readonly IComponentHandler getAllUsersHandler; + private readonly IComponentHandler createUserHandler; + private readonly IComponentHandler updateUserHandler; + private readonly IComponentHandler ChangeUserStatusHandler; + private readonly IComponentHandler addCompanyToUserHandler; + private readonly IComponentHandler removeCompanyFromUserHandler; + private readonly IComponentHandler addProjectToUserHandler; + private readonly IComponentHandler removeProjectFromUserHandler; + private readonly IComponentHandler loginUserHandler; + private readonly IComponentHandler logoutUserHandler; + private readonly IComponentHandler validateUserHandler; + private readonly IComponentHandler getTokenAdapterHandler; + private readonly IComponentHandler getConsentFormPDFHandler; + private readonly IComponentHandler acceptUserConsentFormHandler; + private readonly IUserPort port; + + /// + /// Creates a new instance of UserController. + /// + public UserController( + IComponentHandler getUserHandler, + IComponentHandler getUserByEmailHandler, + IComponentHandler getAllUsersHandler, + IComponentHandler createUserHandler, + IComponentHandler updateUserHandler, + IComponentHandler changeUserStatusHandler, + IComponentHandler addCompanyToUserHandler, + IComponentHandler removeCompanyFromUserHandler, + IComponentHandler addProjectToUserHandler, + IComponentHandler removeProjectFromUserHandler, + IComponentHandler loginUserHandler, + IComponentHandler logoutUserHandler, + IComponentHandler validateUserHandler, + IComponentHandler getTokenAdapterHandler, + IComponentHandler getConsentFormPDFHandler, + IComponentHandler acceptUserConsentFormHandler, + IUserPort port + ) + { + this.createUserHandler = createUserHandler; + this.updateUserHandler = updateUserHandler; + this.ChangeUserStatusHandler = changeUserStatusHandler; + this.getAllUsersHandler = getAllUsersHandler; + this.getUserHandler = getUserHandler; + this.getUserByEmailHandler = getUserByEmailHandler; + this.addCompanyToUserHandler = addCompanyToUserHandler; + this.removeCompanyFromUserHandler = removeCompanyFromUserHandler; + this.addProjectToUserHandler = addProjectToUserHandler; + this.removeProjectFromUserHandler = removeProjectFromUserHandler; + this.loginUserHandler = loginUserHandler; + this.logoutUserHandler = logoutUserHandler; + this.validateUserHandler = validateUserHandler; + this.getTokenAdapterHandler = getTokenAdapterHandler; + this.getConsentFormPDFHandler = getConsentFormPDFHandler; + this.acceptUserConsentFormHandler = acceptUserConsentFormHandler; + this.port = port; + } + /// + /// Gets all the users. + /// + [HttpGet] + [Route("GetAll")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("UserManagement.Read")] + public async Task GetAllUsersAsync(CancellationToken cancellationToken) + { + await getAllUsersHandler.ExecuteAsync(new GetAllUsersRequest { }, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Gets the user by identifier. + /// + [HttpPost] + [Route("GetById")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("UserManagement.Read")] + public async Task GetUserById([FromBody] GetUserRequest request, CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(request.Id)) { return BadRequest("Invalid user identifier"); } + + await getUserHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Gets the user by email. + /// + [HttpPost] + [Route("GetByEmail")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [Authorize(AuthenticationSchemes = $"{Schemes.HeathScheme}, {Schemes.AzureScheme}")] + public async Task GetUserByEmail([FromBody] GetUserByEmailRequest request, CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(request.Email)) { return BadRequest("Invalid user email"); } + + await getUserByEmailHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Creates a new user. + /// + [HttpPost] + [Route("Create")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("UserManagement.Write")] + public async Task CreateUserAsync([FromBody] CreateUserRequest newUser, CancellationToken cancellationToken = default) + { + await createUserHandler.ExecuteAsync(newUser, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Updates a full user by identifier. + /// + [HttpPut("Update")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("UserManagement.Write")] + public async Task UpdateUserAsync([FromBody] UpdateUserRequest request, + CancellationToken cancellationToken = default) + { + await updateUserHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Logs in the user. + /// + [HttpPatch("LoginUser")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [Authorize(AuthenticationSchemes = $"{Schemes.HeathScheme}, {Schemes.AzureScheme}")] + public async Task LoginUserAsync([FromBody] LoginUserRequest request, CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(request.Email)) { return BadRequest("Invalid user email"); } + + await loginUserHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Logs in the user. + /// + [HttpPatch("LogOutUser")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task LogOutUserSessionAsync([FromBody] LogoutUserRequest request, CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(request.Email)) { return BadRequest("Invalid user email"); } + + await logoutUserHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Changes the status of the user. + /// + [HttpPatch] + [Route("ChangeStatus")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("UserManagement.Write")] + public async Task ChangeUserStatusAsync([FromBody] ChangeUserStatusRequest request, CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(request.Id)) { return BadRequest("Invalid user identifier"); } + + await ChangeUserStatusHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Adds a company to the user's list of companies. + /// + [HttpPost] + [Route("AddCompany")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("UserManagement.Write")] + public async Task AddCompanyToUserAsync([FromBody] AddCompanyToUserRequest request, + CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(request.UserId)) { return BadRequest("Invalid user identifier"); } + if (string.IsNullOrEmpty(request.CompanyId)) { return BadRequest("Invalid company identifier"); } + + await addCompanyToUserHandler.ExecuteAsync(request, cancellationToken); + + return port.ViewModel; + } + + /// + /// Removes a company from the user's list of companies. + /// + [HttpDelete] + [Route("RemoveCompany")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("UserManagement.Write")] + public async Task RemoveCompanyFromUserAsync([FromBody] RemoveCompanyFromUserRequest request, + CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(request.UserId)) { return BadRequest("Invalid user identifier"); } + if (string.IsNullOrEmpty(request.CompanyId)) { return BadRequest("Invalid company identifier"); } + + await removeCompanyFromUserHandler.ExecuteAsync(request, cancellationToken); + + return port.ViewModel; + } + + /// + /// Adds a project to the user's list of projects. + /// + [HttpPost] + [Route("AddProject")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("UserManagement.Write")] + public async Task AddProjectToUserAsync([FromBody] AddProjectToUserRequest request, + CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(request.UserId)) { return BadRequest("Invalid user identifier"); } + if (string.IsNullOrEmpty(request.ProjectId)) { return BadRequest("Invalid project identifier"); } + + await addProjectToUserHandler.ExecuteAsync(request, cancellationToken); + + return port.ViewModel; + } + + /// + /// Removes a project from the user's list of projects. + /// + [HttpDelete] + [Route("RemoveProject")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("UserManagement.Write")] + public async Task RemoveProjectFromUserAsync([FromBody] RemoveProjectFromUserRequest request, + CancellationToken cancellationToken) + { + + if (string.IsNullOrEmpty(request.UserId)) { return BadRequest("Invalid user identifier"); } + if (string.IsNullOrEmpty(request.ProjectId)) { return BadRequest("Invalid project identifier"); } + + await removeProjectFromUserHandler.ExecuteAsync(request, cancellationToken); + + return port.ViewModel; + } + + /// + /// Validates if a user exists on the database. + /// + [HttpPost] + [Route("ValidateExistence")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [AllowAnonymous] + public async Task ValidateUserExistenceAsync([FromBody] ValidateUserExistenceRequest request, CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(request.Email)) { return BadRequest("Invalid user email"); } + + await validateUserHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Gets a token for the user, including roles, permissions, and modules. + /// + [HttpPost] + [Route("GetTokenAdapter")] + [ProducesResponseType(typeof(TokenAdapter), StatusCodes.Status200OK)] + [Authorize(AuthenticationSchemes = $"{Schemes.HeathScheme}, {Schemes.AzureScheme}")] + public async Task GetTokenAdapter([FromBody] GetTokenAdapterRequest request, CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(request.Email)) { return BadRequest("Invalid user email"); } + + await getTokenAdapterHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Get Consent Form PDF. + /// + [HttpGet] + [Route("GetConsentFormPDF")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [Authorize(AuthenticationSchemes = Schemes.HeathScheme)] + [Permission("UserManagement.Read")] + public async Task GetConsentFormPDFAsync(CancellationToken cancellationToken) + { + await getConsentFormPDFHandler.ExecuteAsync(new GetConsentFormPDFRequest { }, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Accept user consent form. + /// + [HttpPatch("AcceptUserConsentForm")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [Authorize(AuthenticationSchemes = $"{Schemes.HeathScheme}, {Schemes.AzureScheme}")] + public async Task AcceptUserConsentFormAsync(CancellationToken cancellationToken) + { + await acceptUserConsentFormHandler.ExecuteAsync(new AcceptUserConsentFormRequest { }, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + } +} diff --git a/Core.Cerberos.Service.API/Core.Cerberos.Service.API.csproj b/Core.Cerberos.Service.API/Core.Cerberos.Service.API.csproj new file mode 100644 index 0000000..890870e --- /dev/null +++ b/Core.Cerberos.Service.API/Core.Cerberos.Service.API.csproj @@ -0,0 +1,27 @@ + + + + net8.0 + enable + enable + True + + + + + + + + + + + + + + PreserveNewest + true + PreserveNewest + + + + diff --git a/Core.Cerberos.Service.API/Extensions/SwaggerExtensions.cs b/Core.Cerberos.Service.API/Extensions/SwaggerExtensions.cs new file mode 100644 index 0000000..e505236 --- /dev/null +++ b/Core.Cerberos.Service.API/Extensions/SwaggerExtensions.cs @@ -0,0 +1,99 @@ +using Asp.Versioning.ApiExplorer; +using Microsoft.Extensions.Options; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; +using Swashbuckle.AspNetCore.SwaggerUI; + +namespace Core.Cerberos.Service.API.Extensions +{ + public static class SwaggerExtensions + { + public static void AddSwagger(this IServiceCollection services, IConfiguration configuration) + { + services.AddEndpointsApiExplorer(); + AddSwaggerGen(services, configuration); + services.AddTransient, ConfigureSwaggerOptions>(); + } + + /// + /// Configures Swagger generation with OAuth2 security and XML comments. + /// + /// The to add the services to. + /// The containing Swagger and OAuth2 configuration settings. + public static void AddSwaggerGen(this IServiceCollection services, IConfiguration configuration) + { + services.AddSwaggerGen(c => + { + c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme + { + Description = "JWT Authorization header using the Bearer scheme", + Name = "Authorization", + In = ParameterLocation.Header, + Type = SecuritySchemeType.Http, + Scheme = "bearer", + BearerFormat = "JWT" + }); + + c.AddSecurityRequirement(new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = "Bearer" + } + }, + Array.Empty() + } + }); + }); + } + public static void ConfigureSwagger(this WebApplication app) + { + //Swagger Stuff Goes Here + + app.UseSwagger(); + app.UseSwaggerUI(options => + { + foreach (var version in app.DescribeApiVersions().Select(version => version.GroupName)) + options.SwaggerEndpoint($"/swagger/{version}/swagger.json", version); + + options.DisplayRequestDuration(); + options.EnableTryItOutByDefault(); + options.DocExpansion(DocExpansion.None); + }); + + // app.MapGet("/", () => Results.Redirect("/swagger/index.html")).WithTags(string.Empty); + } + public static IServiceCollection AddVersioning(this IServiceCollection services) + { + services.AddApiVersioning(options => options.ReportApiVersions = true) + .AddApiExplorer(options => + { + options.GroupNameFormat = "'v'VVV"; + options.SubstituteApiVersionInUrl = true; + }); + + return services; + } + } + public class ConfigureSwaggerOptions(IApiVersionDescriptionProvider provider) : IConfigureOptions + { + private readonly IApiVersionDescriptionProvider _provider = provider; + + public void Configure(SwaggerGenOptions options) + { + foreach (var description in _provider.ApiVersionDescriptions) + options.SwaggerDoc(description.GroupName, new() + { + Title = AppDomain.CurrentDomain.FriendlyName, + Version = description.ApiVersion.ToString() + }); + + + options.CustomSchemaIds(type => type.ToString().Replace("+", ".")); + } + } +} diff --git a/Core.Cerberos.Service.API/Program.cs b/Core.Cerberos.Service.API/Program.cs new file mode 100644 index 0000000..f1c9758 --- /dev/null +++ b/Core.Cerberos.Service.API/Program.cs @@ -0,0 +1,170 @@ +using Core.Cerberos.Adapters.Extensions; +using Core.Cerberos.Adapters.Helpers; +using Core.Cerberos.Application.UseCases.Modules; +using Core.Cerberos.Application.UseCases.Modules.Adapter; +using Core.Cerberos.Application.UseCases.Modules.Input; +using Core.Cerberos.Application.UseCases.Modules.Ports; +using Core.Cerberos.Application.UseCases.Modules.Validator; +using Core.Cerberos.Application.UseCases.Permissions; +using Core.Cerberos.Application.UseCases.Permissions.Adapter; +using Core.Cerberos.Application.UseCases.Permissions.Input; +using Core.Cerberos.Application.UseCases.Permissions.Ports; +using Core.Cerberos.Application.UseCases.Permissions.Validator; +using Core.Cerberos.Application.UseCases.Role; +using Core.Cerberos.Application.UseCases.Roles.Adapter; +using Core.Cerberos.Application.UseCases.Roles.Input; +using Core.Cerberos.Application.UseCases.Roles.Ports; +using Core.Cerberos.Application.UseCases.Roles.Validator; +using Core.Cerberos.Application.UseCases.Users; +using Core.Cerberos.Application.UseCases.Users.Adapter; +using Core.Cerberos.Application.UseCases.Users.Input; +using Core.Cerberos.Application.UseCases.Users.Ports; +using Core.Cerberos.Application.UseCases.Users.Validator; +using Core.Cerberos.External.ClientConfiguration; +using Core.Cerberos.Service.API.Extensions; +using FluentValidation; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.ResponseCompression; +using System.IO.Compression; + +var builder = WebApplication.CreateBuilder(args); + +var authSettings = AuthHelper.GetAuthSettings(builder, "cerberos_service"); + +builder.Services.ConfigureAuthentication(builder.Configuration, authSettings); + +builder.Host.ConfigureServices((context, services) => +{ + services.AddCors(options => + { + options.AddPolicy("AllowAll", policyBuilder => + policyBuilder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()); + }); + services.AddMvc().AddJsonOptions(options => + { + options.JsonSerializerOptions.WriteIndented = true; + options.JsonSerializerOptions.MaxDepth = 20; + options.JsonSerializerOptions.NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals; + }); + services.Configure(options => + { + options.Level = CompressionLevel.SmallestSize; + }); + services.Configure(options => + { + options.Level = CompressionLevel.SmallestSize; + }); + services.AddResponseCompression(options => + { + options.EnableForHttps = true; + options.Providers.Add(); + options.Providers.Add(); + }); + + services.AddResponseCaching(); + services.AddControllers(); + services.AddEndpointsApiExplorer(); + builder.Services.AddSwagger(builder.Configuration, "Core.Cerberos.Service.API.xml", authSettings); + builder.Services.AddVersioning(builder.Configuration); + services.AddLogging(); + services.AddProblemDetails(); + + //Register Stuff + services.RegisterExternalLayer(builder.Configuration); + + services.AddScoped(); + services.AddScoped, UserHandler>(); + services.AddScoped, UserHandler>(); + services.AddScoped, UserHandler>(); + services.AddScoped, UserHandler>(); + services.AddScoped, UserHandler>(); + services.AddScoped, UserHandler>(); + services.AddScoped, UserHandler>(); + services.AddScoped, UserHandler>(); + services.AddScoped, UserHandler>(); + services.AddScoped, UserHandler>(); + services.AddScoped, UserHandler>(); + services.AddScoped, UserHandler>(); + services.AddScoped, UserHandler>(); + + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, CreateUserValidator>(); + services.AddScoped, UserHandler>(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, UpdateUserValidator>(); + services.AddScoped, UserHandler>(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, ChangeUserStatusValidator>(); + services.AddScoped, UserHandler>(); + + services.AddScoped(); + services.AddScoped, RoleHandler>(); + services.AddScoped, RoleHandler>(); + services.AddScoped, RoleHandler>(); + services.AddScoped, RoleHandler>(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, CreateRoleValidator>(); + services.AddScoped, RoleHandler>(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, UpdateRoleValidator>(); + services.AddScoped, RoleHandler>(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, ChangeRoleStatusValidator>(); + services.AddScoped, RoleHandler>(); + + services.AddScoped(); + services.AddScoped, PermissionHandler>(); + services.AddScoped, PermissionHandler>(); + services.AddScoped, PermissionHandler>(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, CreatePermissionValidator>(); + services.AddScoped, PermissionHandler>(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, UpdatePermissionValidator>(); + services.AddScoped, PermissionHandler>(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, ChangePermissionStatusValidator>(); + services.AddScoped, PermissionHandler>(); + + services.AddScoped(); + services.AddScoped, ModuleHandler>(); + services.AddScoped, ModuleHandler>(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, GetAllModulesByListValidator>(); + services.AddScoped, ModuleHandler>(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, CreateModuleValidator>(); + services.AddScoped, ModuleHandler>(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, UpdateModuleValidator>(); + services.AddScoped, ModuleHandler>(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, ChangeModuleStatusValidator>(); + services.AddScoped, ModuleHandler>(); +}); + +var app = builder.Build(); +app.UseSwaggerUI(builder.Configuration, authSettings); +app.ConfigureSwagger(builder.Configuration); +app.UseResponseCompression(); +app.UseResponseCaching(); +app.UseHttpsRedirection(); +app.UseCors("AllowAll"); +app.UseAuthorization(); +app.MapControllers(); + +app.Run(); + diff --git a/Core.Cerberos.Service.API/Properties/launchSettings.json b/Core.Cerberos.Service.API/Properties/launchSettings.json new file mode 100644 index 0000000..a1f3921 --- /dev/null +++ b/Core.Cerberos.Service.API/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:56379", + "sslPort": 44312 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5145", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Local" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7253;http://localhost:5145", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Local" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Local" + } + } + } +} diff --git a/Core.Cerberos.Service.API/appsettings.Development.json b/Core.Cerberos.Service.API/appsettings.Development.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/Core.Cerberos.Service.API/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/Core.Cerberos.Service.API/appsettings.Local.json b/Core.Cerberos.Service.API/appsettings.Local.json new file mode 100644 index 0000000..25ca5e4 --- /dev/null +++ b/Core.Cerberos.Service.API/appsettings.Local.json @@ -0,0 +1,12 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "LocalGateways": { + "CerberosDAL": "https://localhost:7031/api" + } +} diff --git a/Core.Cerberos.Service.API/appsettings.json b/Core.Cerberos.Service.API/appsettings.json new file mode 100644 index 0000000..d321977 --- /dev/null +++ b/Core.Cerberos.Service.API/appsettings.json @@ -0,0 +1,12 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "Endpoints": { + "AppConfigurationURI": "https://sandbox-hci-usc-appcg.azconfig.io" + } +} diff --git a/Core.Cerberos.Service.API/sample.settings.Development.json b/Core.Cerberos.Service.API/sample.settings.Development.json new file mode 100644 index 0000000..3d612f0 --- /dev/null +++ b/Core.Cerberos.Service.API/sample.settings.Development.json @@ -0,0 +1,30 @@ +{ + "Gateways": { + "CerberosDAL": "" // Data access layer endpoint + }, + "ConnectionStrings": { + "KeyVault": "" //KeyVault Uri + }, + "JwtIssuerOptions": { + "Audience": "", // Audience for token creation, specifies intended recipients + "Issuer": "" // Issuer for token creation, identifies the issuer of the token + }, + "AzureAdB2C": { + "Instance": "", // Azure AD instance URL (STORED IN KEY VAULT) + "TenantId": "", // Azure AD tenant ID (STORED IN KEY VAULT) + "ClientId": "", // Azure AD application client ID (STORED IN KEY VAULT) + "ClientSecret": "", // Azure AD application client secret (STORED IN KEY VAULT) + "CallbackPath": "", // Path for redirect after authentication + "Scopes": "" // Access scopes for user permissions + }, + "HeathCerberosApp": { + "AuthorizationUrl": "", // URL for authorization endpoint (STORED IN KEY VAULT) + "TokenUrl": "", // URL for token endpoint (STORED IN KEY VAULT) + "Scope": "", // Scope for application permissions (STORED IN KEY VAULT) + "ClientId": "" // Client ID for Cerberos application (STORED IN KEY VAULT) + }, + "MicrosoftGraph": { + "Scopes": "", // Scopes for Microsoft Graph API access + "BaseUrl": "" // Base URL for Microsoft Graph API + } +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..e074419 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +SharedApplications \ No newline at end of file