From c44014b458c8024104761549f5e19b40a9c58217 Mon Sep 17 00:00:00 2001 From: luismd98 Date: Wed, 2 Nov 2022 11:31:23 -0500 Subject: [PATCH] Primer commit --- .gitattributes | 63 +++ .gitignore | 363 ++++++++++++++++++ ApiGateway/.config/dotnet-tools.json | 12 + ApiGateway/ApiGateway.csproj | 37 ++ ApiGateway/Config/AlterUpstream.cs | 15 + ApiGateway/CustomLogic.cs | 228 +++++++++++ ApiGateway/Loggin.cs | 73 ++++ ApiGateway/OcelotJwtMiddleware.cs | 110 ++++++ ApiGateway/OcelotResponseMiddleware.cs | 67 ++++ ApiGateway/Program.cs | 145 +++++++ ApiGateway/Properties/launchSettings.json | 31 ++ .../Routes/ocelot.SwaggerEndPoints.json | 88 +++++ ApiGateway/Routes/ocelot.adminusuarios.json | 319 +++++++++++++++ ApiGateway/Routes/ocelot.afiliados.json | 306 +++++++++++++++ ApiGateway/Routes/ocelot.apitest.json | 56 +++ ApiGateway/Routes/ocelot.contratos.json | 45 +++ ApiGateway/Routes/ocelot.datosmaestros.json | 23 ++ ApiGateway/Routes/ocelot.externo.json | 39 ++ ApiGateway/Routes/ocelot.global.json | 9 + ApiGateway/Trash/ocelot - Copy.json | 105 +++++ ApiGateway/Trash/ocelot2.json | 19 + ApiGateway/appsettings.Development.json | 8 + ApiGateway/appsettings.json | 9 + ApiGateway/ocelot.json | 1 + Auth/Auth.csproj | 13 + Auth/Security.cs | 179 +++++++++ AuthWebApi/AuthWebApi.csproj | 13 + AuthWebApi/Controllers/AccountController.cs | 31 ++ AuthWebApi/Program.cs | 18 + AuthWebApi/Properties/launchSettings.json | 30 ++ AuthWebApi/appsettings.Development.json | 8 + AuthWebApi/appsettings.json | 9 + BackApiGateway.sln | 48 +++ IntegradorBE/.config/dotnet-tools.json | 12 + IntegradorBE/Controllers/AuthController.cs | 97 +++++ IntegradorBE/Controllers/UPCController.cs | 72 ++++ IntegradorBE/IntegradorBE.csproj | 18 + IntegradorBE/IntegradorBE.sln | 31 ++ IntegradorBE/Program.cs | 42 ++ IntegradorBE/Properties/launchSettings.json | 32 ++ IntegradorBE/appsettings.Development.json | 8 + IntegradorBE/appsettings.json | 9 + JwtAuthManager/CustomJwtAuthExtension.cs | 40 ++ JwtAuthManager/JwtAuthManager.csproj | 16 + JwtAuthManager/JwtTokenHandler.cs | 81 ++++ JwtAuthManager/Models/AuthRequest.cs | 14 + JwtAuthManager/Models/AuthResponse.cs | 15 + JwtAuthManager/Models/UserAccount.cs | 17 + TestApi1/.config/dotnet-tools.json | 12 + .../Controllers/WeatherForecastController.cs | 45 +++ TestApi1/Program.cs | 25 ++ TestApi1/Properties/launchSettings.json | 31 ++ TestApi1/TestApi1.csproj | 13 + TestApi1/WeatherForecast.cs | 13 + TestApi1/appsettings.Development.json | 8 + TestApi1/appsettings.json | 9 + TestApi2/.config/dotnet-tools.json | 12 + TestApi2/Controllers/ContratosController.cs | 28 ++ .../Controllers/WeatherForecastController.cs | 45 +++ TestApi2/Program.cs | 28 ++ TestApi2/Properties/launchSettings.json | 31 ++ TestApi2/TestApi2.csproj | 17 + TestApi2/WeatherForecast.cs | 13 + TestApi2/appsettings.Development.json | 8 + TestApi2/appsettings.json | 9 + .../Visualizers/attribcache140.bin | Bin 0 -> 8152 bytes ocelot.json | 0 67 files changed, 3371 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 ApiGateway/.config/dotnet-tools.json create mode 100644 ApiGateway/ApiGateway.csproj create mode 100644 ApiGateway/Config/AlterUpstream.cs create mode 100644 ApiGateway/CustomLogic.cs create mode 100644 ApiGateway/Loggin.cs create mode 100644 ApiGateway/OcelotJwtMiddleware.cs create mode 100644 ApiGateway/OcelotResponseMiddleware.cs create mode 100644 ApiGateway/Program.cs create mode 100644 ApiGateway/Properties/launchSettings.json create mode 100644 ApiGateway/Routes/ocelot.SwaggerEndPoints.json create mode 100644 ApiGateway/Routes/ocelot.adminusuarios.json create mode 100644 ApiGateway/Routes/ocelot.afiliados.json create mode 100644 ApiGateway/Routes/ocelot.apitest.json create mode 100644 ApiGateway/Routes/ocelot.contratos.json create mode 100644 ApiGateway/Routes/ocelot.datosmaestros.json create mode 100644 ApiGateway/Routes/ocelot.externo.json create mode 100644 ApiGateway/Routes/ocelot.global.json create mode 100644 ApiGateway/Trash/ocelot - Copy.json create mode 100644 ApiGateway/Trash/ocelot2.json create mode 100644 ApiGateway/appsettings.Development.json create mode 100644 ApiGateway/appsettings.json create mode 100644 ApiGateway/ocelot.json create mode 100644 Auth/Auth.csproj create mode 100644 Auth/Security.cs create mode 100644 AuthWebApi/AuthWebApi.csproj create mode 100644 AuthWebApi/Controllers/AccountController.cs create mode 100644 AuthWebApi/Program.cs create mode 100644 AuthWebApi/Properties/launchSettings.json create mode 100644 AuthWebApi/appsettings.Development.json create mode 100644 AuthWebApi/appsettings.json create mode 100644 BackApiGateway.sln create mode 100644 IntegradorBE/.config/dotnet-tools.json create mode 100644 IntegradorBE/Controllers/AuthController.cs create mode 100644 IntegradorBE/Controllers/UPCController.cs create mode 100644 IntegradorBE/IntegradorBE.csproj create mode 100644 IntegradorBE/IntegradorBE.sln create mode 100644 IntegradorBE/Program.cs create mode 100644 IntegradorBE/Properties/launchSettings.json create mode 100644 IntegradorBE/appsettings.Development.json create mode 100644 IntegradorBE/appsettings.json create mode 100644 JwtAuthManager/CustomJwtAuthExtension.cs create mode 100644 JwtAuthManager/JwtAuthManager.csproj create mode 100644 JwtAuthManager/JwtTokenHandler.cs create mode 100644 JwtAuthManager/Models/AuthRequest.cs create mode 100644 JwtAuthManager/Models/AuthResponse.cs create mode 100644 JwtAuthManager/Models/UserAccount.cs create mode 100644 TestApi1/.config/dotnet-tools.json create mode 100644 TestApi1/Controllers/WeatherForecastController.cs create mode 100644 TestApi1/Program.cs create mode 100644 TestApi1/Properties/launchSettings.json create mode 100644 TestApi1/TestApi1.csproj create mode 100644 TestApi1/WeatherForecast.cs create mode 100644 TestApi1/appsettings.Development.json create mode 100644 TestApi1/appsettings.json create mode 100644 TestApi2/.config/dotnet-tools.json create mode 100644 TestApi2/Controllers/ContratosController.cs create mode 100644 TestApi2/Controllers/WeatherForecastController.cs create mode 100644 TestApi2/Program.cs create mode 100644 TestApi2/Properties/launchSettings.json create mode 100644 TestApi2/TestApi2.csproj create mode 100644 TestApi2/WeatherForecast.cs create mode 100644 TestApi2/appsettings.Development.json create mode 100644 TestApi2/appsettings.json create mode 100644 Visual Studio 2022/Visualizers/attribcache140.bin create mode 100644 ocelot.json diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9491a2f --- /dev/null +++ b/.gitignore @@ -0,0 +1,363 @@ +## 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 \ No newline at end of file diff --git a/ApiGateway/.config/dotnet-tools.json b/ApiGateway/.config/dotnet-tools.json new file mode 100644 index 0000000..b8c6c1f --- /dev/null +++ b/ApiGateway/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "dotnet-ef": { + "version": "6.0.9", + "commands": [ + "dotnet-ef" + ] + } + } +} \ No newline at end of file diff --git a/ApiGateway/ApiGateway.csproj b/ApiGateway/ApiGateway.csproj new file mode 100644 index 0000000..bd93d7f --- /dev/null +++ b/ApiGateway/ApiGateway.csproj @@ -0,0 +1,37 @@ + + + + net6.0 + enable + enable + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ApiGateway/Config/AlterUpstream.cs b/ApiGateway/Config/AlterUpstream.cs new file mode 100644 index 0000000..bb5f71c --- /dev/null +++ b/ApiGateway/Config/AlterUpstream.cs @@ -0,0 +1,15 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace ApiGateway.Config +{ + public class AlterUpstream + { + public static string AlterUpstreamSwaggerJson(HttpContext context, string swaggerJson) + { + var swagger = JObject.Parse(swaggerJson); + // ... alter upstream json + return swagger.ToString(Formatting.Indented); + } + } +} diff --git a/ApiGateway/CustomLogic.cs b/ApiGateway/CustomLogic.cs new file mode 100644 index 0000000..496546b --- /dev/null +++ b/ApiGateway/CustomLogic.cs @@ -0,0 +1,228 @@ +using JwtAuthManager; +using Microsoft.IdentityModel.Tokens; +using Ocelot.Configuration; +using Ocelot.Middleware; +using Security; +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Text; +using System.Text.RegularExpressions; + +namespace ApiGateway +{ + public static class CustomLogic + { + //private static readonly int _SEMILLA = 1262; + private static readonly Encripter _encript = new(); + + public static bool Authorize(HttpContext ctx) + { + // Solo para test + string seguimiento = ctx.Request.Headers["Potato"]; + var route2 = ctx.Items.DownstreamRequest(); //Solo el path del request + var route3 = ctx.Items.DownstreamRoute(); //Datos full del request + var calledUrl = ctx.Items.DownstreamRoute().UpstreamPathTemplate.OriginalValue; + + var isLogin = calledUrl == "/Ext/Login" ; + var isExtLogin = calledUrl == "/Auth/Login"; + + // Excepcion para login, no requiere token + if (String.Equals(calledUrl, "/Ext/Login") || + String.Equals(calledUrl, "/Auth/Login")) + return true; + + //if (isLogin == true || isExtLogin == true) return true; + + try + { + string path = ctx.Request.Path; + + string authString = ctx.Request.Headers["Authorization"]; + + //Perfil seleccionado, no obligatorio para login + string? signature = ctx.Request.Headers["Signature"]; + signature = Base64Decode(signature); + + + if (authString.IsNullOrEmpty()) throw new Exception("Nel wey, no hay token"); + + + string? jwtDescifrado = DesCifrar(authString.Replace("Bearer ", "")); + if (jwtDescifrado.IsNullOrEmpty()) throw new Exception("Nel wey, token inválido"); + + + var jwtToken = new JwtSecurityToken(jwtDescifrado); + if (VerifyToken(jwtToken.RawData) == false) throw new Exception("Firma inválida"); + + + //Claims dentro del .json + DownstreamRoute? route = (DownstreamRoute?)ctx.Items["DownstreamRoute"]; + if (route == null || route.RouteClaimsRequirement.Count == 0) return true; + + //flag for authorization // Para iterar multples roles, no usados ya que se usa solo con 1 + //bool auth = false; + + //where are stored the claims of the jwt token + + //Claims del token + Claim[] claims = jwtToken.Claims.ToArray(); + + //where are stored the required claims for the route + Dictionary required = route.RouteClaimsRequirement; + Regex reor = new Regex(@"[^,\s+$ ][^\,]*[^,\s+$ ]"); + MatchCollection matches; + + Regex reand = new Regex(@"[^&\s+$ ][^\&]*[^&\s+$ ]"); + MatchCollection matchesand; + //int cont = 0; + foreach (KeyValuePair claim in required) + { + matches = reor.Matches(claim.Value); + foreach (Match match in matches) + { + matchesand = reand.Matches(match.Value); + //cont = 0; + foreach (Match m in matchesand) //m = claim dentro dle json (value) + { + //Si permite cualquier permiso + if (String.Equals("any", m.Value)) return true; + + + foreach (Claim cl in claims) // Claim (key:value) desde el token + { + + if (cl.Type == claim.Key && String.Equals(claim.Key, "permisos")) + { + string separador = "::"; + + int index = cl.Value.LastIndexOf(separador); + string newPermiso = cl.Value; + string permisoRoles = cl.Value; + if (index >= 0) + newPermiso = cl.Value[..index]; + + permisoRoles = cl.Value.Substring(index + separador.Length); + + var rolesLst = permisoRoles.Split(','); + + // Excepcion de rol Seleccionado para Externo + if(String.Equals(newPermiso, m.Value) && + String.Equals(_encript.DecryptHashTkn(newPermiso), "externo")) + { + return true; + } + + //Si no hay perfil seleccionado + if (signature.IsNullOrEmpty()) + throw new Exception("Falta el perfil, no mames"); + + bool aplicaRolSeleccionado = rolesLst.Any(signature!.Contains); + + //Aqui remuevo los :: teniendo en cuenta key == permisos cl.Value + //if (cl.Value == m.Value) + if (String.Equals(newPermiso, m.Value) && aplicaRolSeleccionado == true) + { + return true; + //cont++; //NO NECESARIO porque solo hay 1 permiso por request + } + } + } + } + //if (cont == matchesand.Count) + //{ + // return true; + // // break; + //} + } + } + return false; + } + catch (Exception e) + { + ctx.Items.SetError(new UnauthenticatedError(e.Message)); + return false; + } + + /// + //return true; + /// + + } + + + public static bool VerifyToken(string token) + { + if(_encript.IsValid == false) return false; + + var validationParameters = new TokenValidationParameters() + { + ValidateIssuer = false, + ValidateAudience = false, + ValidateIssuerSigningKey = true, + //IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(JwtTokenHandler.JWT_SECURITY_KEY)) + IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Encripter.HashKey)) + }; + + var tokenHandler = new JwtSecurityTokenHandler(); + SecurityToken validatedToken = null; + + try + { + tokenHandler.ValidateToken(token, validationParameters, out validatedToken); + } + catch (SecurityTokenException) + { + return false; + } + catch (Exception e) + { + var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()); + var logger = loggerFactory.CreateLogger(""); + //something else happened + logger.LogInformation(e.ToString()); + + return false; + //throw; + } + //... manual validations return false if anything untoward is discovered + return validatedToken != null; + } + + public static string? DesCifrar(string value) + { + if (_encript.IsValid == false) return null; + try + { + string? b64Decrypted = Base64Decode(value); + if (b64Decrypted.IsNullOrEmpty()) return null; + + string decryptedText = ""; + for (int i = 0; i < b64Decrypted!.Length; i++) + { + int encrypted = (int)b64Decrypted[i]; + int decryption = encrypted - _encript.getSemilla(); + decryptedText += Char.ConvertFromUtf32(decryption); + } + return decryptedText; + } + catch (Exception) + { + return null; + } + } + + public static string? Base64Decode(string base64EncodedData) + { + try + { + var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData); + return System.Text.Encoding.UTF8.GetString(base64EncodedBytes); + } + catch (Exception) + { + return null; + } + } + + } +} diff --git a/ApiGateway/Loggin.cs b/ApiGateway/Loggin.cs new file mode 100644 index 0000000..a213791 --- /dev/null +++ b/ApiGateway/Loggin.cs @@ -0,0 +1,73 @@ +using Kros.Extensions; +using Microsoft.Extensions.Primitives; + +namespace ApiGateway +{ + public class Loggin + { + //public string GetRequestIP(HttpContext ctx, bool tryUseXForwardHeader = true) + //{ + // string ip = null; + + // // todo support new "Forwarded" header (2014) https://en.wikipedia.org/wiki/X-Forwarded-For + + // // X-Forwarded-For (csv list): Using the First entry in the list seems to work + // // for 99% of cases however it has been suggested that a better (although tedious) + // // approach might be to read each IP from right to left and use the first public IP. + // // http://stackoverflow.com/a/43554000/538763 + // // + // if (tryUseXForwardHeader) + // { + // ip = GetHeaderValueAs(ctx, "X-Forwarded-For"); + // ip = SplitCsv(ip).FirstOrDefault(); + + // } + + // // RemoteIpAddress is always null in DNX RC1 Update1 (bug). + // if (IsNullOrWhitespace(ip) && ctx?.Connection?.RemoteIpAddress != null) + // ip = ctx.Connection.RemoteIpAddress.ToString(); + + // if (IsNullOrWhitespace(ip)) + // ip = GetHeaderValueAs(ctx, "REMOTE_ADDR"); + + // // _httpContextAccessor.HttpContext?.Request?.Host this is the local host. + + // if (IsNullOrWhitespace(ip)) + // throw new Exception("Unable to determine caller's IP."); + + // return ip; + //} + + //public T GetHeaderValueAs(HttpContext ctx, string headerName) + //{ + // StringValues values; + + // if (ctx?.Request?.Headers?.TryGetValue(headerName, out values) ?? false) + // { + // string rawValues = values.ToString(); // writes out as Csv when there are multiple. + + // if (!IsNullOrWhitespace(rawValues)) + // return (T)Convert.ChangeType(values.ToString(), typeof(T)); + // } + // return default(T); + //} + + //public List SplitCsv(string csvList, bool nullOrWhitespaceInputReturnsNull = false) + //{ + // if (string.IsNullOrWhiteSpace(csvList)) + // return nullOrWhitespaceInputReturnsNull ? null : new List(); + + // return csvList + // .TrimEnd(',') + // .Split(',') + // .AsEnumerable() + // .Select(s => s.Trim()) + // .ToList(); + //} + + //public bool IsNullOrWhitespace(string s) + //{ + // return String.IsNullOrWhiteSpace(s); + //} + } +} diff --git a/ApiGateway/OcelotJwtMiddleware.cs b/ApiGateway/OcelotJwtMiddleware.cs new file mode 100644 index 0000000..9a13dd7 --- /dev/null +++ b/ApiGateway/OcelotJwtMiddleware.cs @@ -0,0 +1,110 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using Microsoft.Net.Http.Headers; +using Ocelot.Middleware; +using Ocelot.RequestId; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Security.Claims; +using System.Threading.Tasks; +using Microsoft.Net.Http.Headers; + + +namespace ApiGateway +{ + public class OcelotJwtMiddleware : OcelotPipelineConfiguration + { + private static readonly string RoleSeparator = ","; + + + + public OcelotJwtMiddleware() + { + PreAuthorizationMiddleware = async (ctx, next) => + { + await ProcessRequest(ctx, next); + }; + } + + public async Task ProcessRequest(HttpContext context, System.Func next) + { + //var _bearer_token = context.Request.Headers[HeaderNames.Authorization].ToString().Replace("Bearer ", ""); + + + context.Request.Headers[HeaderNames.Authorization] = "Reemplazo el token"; + + var _bearer_token = context.Request.Headers[HeaderNames.Authorization].ToString(); + + var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole().AddDebug()); + var logger = loggerFactory.CreateLogger(""); + + + logger.LogInformation("Potato 3"); + logger.LogInformation("Bearer:"); + logger.LogInformation(_bearer_token); + logger.LogDebug("Potato 4"); + + // Get the the any service object, if required + //var anyService = context.RequestServices.GetService(typeof()); + + var user = ((DefaultHttpContext)context)?.User; + var email = user.Claims.Where(y => y.Type.Contains("email")).FirstOrDefault()?.Value; + + + if (!string.IsNullOrWhiteSpace(email) && email.Equals("BobSmith66@email.com", StringComparison.CurrentCultureIgnoreCase)) + { + // Example 1 : adding extra claims + EnrichClaim(user); + } + // Call the underline service + await next.Invoke(); + } + + private void EnrichClaim(ClaimsPrincipal claims) + { + var listOfClaims = new List + { + new Claim("CustomClaimName", "CustomClaimValue") + }; + + claims.AddIdentity(new ClaimsIdentity(listOfClaims)); + } + + private static async Task ReturnStatus(HttpContext context, HttpStatusCode statusCode, string msg) + { + context.Response.StatusCode = (int)statusCode; + await context.Response.WriteAsync(msg); + } + + //public static Func< DownstreamContext, Func, Task> CreateAuthorizationFilter + // => async (downStreamContext, next) => + // { + // HttpContext httpContext = downStreamContext.HttpContext; + // var token = httpContext.Request.Cookies[JwtManager.AuthorizationTokenKey]; + // if (token != null && AuthorizeIfValidToken(downStreamContext, token)) + // { + // await next.Invoke(); + // } + // else + // { + // downStreamContext.DownstreamResponse = + // new DownstreamResponse(new HttpResponseMessage(HttpStatusCode.Unauthorized)); + // } + // }; + + //private static bool AuthorizeIfValidToken(DownstreamContext downStreamContext, string jwtToken) + //{ + // IIdentityProvider decodedObject = new JwtManager().Decode(jwtToken); + // if (decodedObject != null) + // { + // return downStreamContext.DownstreamReRoute.RouteClaimsRequirement["Role"] + // ?.Split(RoleSeparator) + // .FirstOrDefault(role => role.Trim() == decodedObject.GetRole()) != default; + // } + + // return false; + //} + } +} diff --git a/ApiGateway/OcelotResponseMiddleware.cs b/ApiGateway/OcelotResponseMiddleware.cs new file mode 100644 index 0000000..0f9f8c9 --- /dev/null +++ b/ApiGateway/OcelotResponseMiddleware.cs @@ -0,0 +1,67 @@ +using Ocelot.Infrastructure.Extensions; +using Ocelot.Logging; +using Ocelot.Middleware; +using Ocelot.Responder; + + +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Authentication; +using Microsoft.Extensions.Caching.Memory; +using Ocelot.Authorization; +using System.Text.RegularExpressions; + +namespace ApiGateway +{ + public class OcelotResponseMiddleware : Ocelot.Middleware.OcelotMiddleware + { + private readonly RequestDelegate _next; + private readonly IHttpResponder _responder; + private readonly IErrorsToHttpStatusCodeMapper _codeMapper; + + public OcelotResponseMiddleware( + RequestDelegate next, + IHttpResponder responder, + IErrorsToHttpStatusCodeMapper codeMapper, + IOcelotLoggerFactory loggerFactory) + : base(loggerFactory.CreateLogger()) + { + _next = next; + _responder = responder; + _codeMapper = codeMapper; + } + + public async Task Invoke(HttpContext httpContext) + { + //var x = CustomLogic.Authorize(httpContext); + + await _next.Invoke(httpContext); + if (httpContext.Response.HasStarted) + return; + + var errors = httpContext.Items.Errors(); + if (errors.Count > 0) + { + Logger.LogWarning($"{errors.ToErrorString()} errors found in {MiddlewareName}. Setting error response for request path:{httpContext.Request.Path}, request method: {httpContext.Request.Method}"); + + var statusCode = _codeMapper.Map(errors); + var error = string.Join(",", errors.Select(x => x.Message)); + httpContext.Response.StatusCode = statusCode; + // output error + await httpContext.Response.WriteAsync(error); + } + else + { + Logger.LogDebug("no pipeline errors, setting and returning completed response"); + + var downstreamResponse = httpContext.Items.DownstreamResponse(); + + await _responder.SetResponseOnHttpContext(httpContext, downstreamResponse); + } + } + } + + + +} diff --git a/ApiGateway/Program.cs b/ApiGateway/Program.cs new file mode 100644 index 0000000..ddf8b33 --- /dev/null +++ b/ApiGateway/Program.cs @@ -0,0 +1,145 @@ +using ApiGateway; +using JwtAuthManager; +using Microsoft.Net.Http.Headers; +using Ocelot.Authorization; +using Ocelot.DependencyInjection; +using Ocelot.Middleware; +using MMLib.SwaggerForOcelot.DependencyInjection; +using Ocelot.Provider.Polly; +using ApiGateway.Config; +using System.Net; +using Microsoft.AspNetCore.Http; + +var builder = WebApplication.CreateBuilder(args); + + +builder.Configuration.AddOcelotWithSwaggerSupport(options => +{ + options.Folder = "Routes"; +}); + + +var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()); +var logger = loggerFactory.CreateLogger(""); + +builder.Configuration.SetBasePath(builder.Environment.ContentRootPath) + .AddJsonFile("ocelot.json", optional: false, reloadOnChange: true) + .AddEnvironmentVariables(); + +var pipeConfig = new OcelotPipelineConfiguration +{ + + AuthorizationMiddleware = async (downStreamContext, next) => + { + //Authorize(downStreamContext); + + var _bearer_token = downStreamContext.Request.Headers[HeaderNames.Authorization].ToString(); + + + logger.LogInformation("Bearer 2:"); + logger.LogInformation(_bearer_token); + //await next.Invoke(); + + //downStreamContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized; + //await downStreamContext.Response.WriteAsync("Nel wey "); + //downStreamContext.Items.SetError(new UnauthenticatedError("Ni modo, wey")); + //return; + + //var cifrado = Encipher(_bearer_token, cipherKey); + + //var descifrado = Decipher(cifrado, cipherKey); + bool isAuthorized = CustomLogic.Authorize(downStreamContext); + if (isAuthorized) + { + await next.Invoke(); + } + else + { + //downStreamContext.Items.SetError(new UnauthenticatedError("Nel wey, no estas autorizado")); + return; + } + } +}; + + + +builder.Services.AddCors(options => +{ + options.AddPolicy(name: "MyCors", builder => + { + builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod(); + }); +}); + +builder.Services.AddOcelot(builder.Configuration).AddPolly(); +builder.Services.AddSwaggerForOcelot(builder.Configuration); + +builder.Services.AddCustomJwtAuthentication(); + +var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"); + +builder.Configuration.SetBasePath(Directory.GetCurrentDirectory()) + .AddOcelot("Routes", builder.Environment) + .AddEnvironmentVariables(); + + +// Add services to the container. + +builder.Services.AddControllers(); +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); + +// Swagger for ocelot +builder.Services.AddSwaggerGen(); + +builder.Services.AddAuthorization(); +builder.Services.AddAuthentication(); + + + +var app = builder.Build(); + + + +app.UseCors("MyCors"); + +//app.UseCors("widthoutCors"); +app.UseSwagger(); +//Configure the HTTP request pipeline. +//if (app.Environment.IsDevelopment() || app.Environment.IsProduction()) +//{ +//} +if (app.Environment.IsDevelopment()) +{ + Environment.SetEnvironmentVariable("Mode", "Dev"); +} +else +{ + Environment.SetEnvironmentVariable("Mode", "Prod"); +} + + +//IApplicationBuilder config2 = new IApplicationBuilder + + +// Cargue de Ocelot +app.UseMiddleware(); +app.UseSwaggerForOcelotUI(options => +{ + options.PathToSwaggerGenerator = "/swagger/docs"; + options.ReConfigureUpstreamSwaggerJson = AlterUpstream.AlterUpstreamSwaggerJson; + +}).UseOcelot(pipeConfig).Wait(); + + +app.UseAuthorization(); +app.UseAuthentication(); + +app.MapControllers(); + +app.MapGet("/", () => "Hello World!"); + + +app.Run(); + + diff --git a/ApiGateway/Properties/launchSettings.json b/ApiGateway/Properties/launchSettings.json new file mode 100644 index 0000000..fa51e06 --- /dev/null +++ b/ApiGateway/Properties/launchSettings.json @@ -0,0 +1,31 @@ +{ + "profiles": { + "ApiGateway": { + "commandName": "Project", + "launchBrowser": false, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "MySecretKey": "_ll@v3Segur1d4d!123" + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5042" + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + }, + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:9939", + "sslPort": 0 + } + } +} \ No newline at end of file diff --git a/ApiGateway/Routes/ocelot.SwaggerEndPoints.json b/ApiGateway/Routes/ocelot.SwaggerEndPoints.json new file mode 100644 index 0000000..36a4778 --- /dev/null +++ b/ApiGateway/Routes/ocelot.SwaggerEndPoints.json @@ -0,0 +1,88 @@ +{ + "SwaggerEndPoints": [ + { + "Key": "ApiGetway", + "TransformByOcelotConfig": false, + "Config": [ + { + "Name": "ApiGetway", + "Version": "1.0", + "Url": "http://localhost:80/api/swagger/v1/swagger.json" + } + ] + }, + + { + "Key": "DatosMaestros", + "TransformByOcelotConfig": true, + "Config": [ + { + "Name": "DatosMaestros", + "Version": "1.0", + "Url": "http://localhost:8146/swagger/v1/swagger.json" + } + ] + }, + + { + "Key": "MsAdminUsuarios", + "TransformByOcelotConfig": true, + "Config": [ + { + "Name": "MsAdminUsuarios", + "Version": "1.0", + "Url": "http://localhost:8151/swagger/v1/swagger.json" + } + ] + }, + + { + "Key": "Afiliados", + "TransformByOcelotConfig": true, + "Config": [ + { + "Name": "Afiliados", + "Version": "1.0", + "Url": "http://localhost:8145/swagger/v1/swagger.json" + } + ] + }, + + { + "Key": "Externo", + "TransformByOcelotConfig": true, + "Config": [ + { + "Name": "Externo", + "Version": "1.0", + "Url": "http://localhost:8199/swagger/v1/swagger.json" + } + ] + } + + //{ + // "Key": "MsContratos", + // "TransformByOcelotConfig": true, + // "Config": [ + // { + // "Name": "MsContratos", + // "Version": "1.0", + // "Url": "http://localhost:5102/swagger/v1/swagger.json" + // } + // ] + //}, + + //{ + // "Key": "apitest", + // "TransformByOcelotConfig": true, + // "Config": [ + // { + // "Name": "ApiTest", + // "Version": "1.0", + // "Url": "http://localhost:5041/swagger/v1/swagger.json" + // } + // ] + + + ] +} diff --git a/ApiGateway/Routes/ocelot.adminusuarios.json b/ApiGateway/Routes/ocelot.adminusuarios.json new file mode 100644 index 0000000..d6b2598 --- /dev/null +++ b/ApiGateway/Routes/ocelot.adminusuarios.json @@ -0,0 +1,319 @@ +{ + "Routes": [ + + { + "SwaggerKey": "MsAdminUsuarios", + + "UpstreamPathTemplate": "/Auth/Login", + "UpstreamHttpMethod": [ "POST" ], + + "DownstreamPathTemplate": "/Auth/Login", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8151 + } + ], + + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + + + + + + { + "SwaggerKey": "MsAdminUsuarios", + + "UpstreamPathTemplate": "/Microservicios", + "UpstreamHttpMethod": [ "GET" ], + + "DownstreamPathTemplate": "/Microservicios", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8151 + } + ], + + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + { + "SwaggerKey": "MsAdminUsuarios", + + "UpstreamPathTemplate": "/Microservicios", + "UpstreamHttpMethod": [ "POST" ], + + "DownstreamPathTemplate": "/Microservicios", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8151 + } + ], + + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + + + + { + "SwaggerKey": "MsAdminUsuarios", + "UpstreamPathTemplate": "/Perfiles", + "UpstreamHttpMethod": [ "GET" ], + + "DownstreamPathTemplate": "/Perfiles", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8151 + } + ], + + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + { + "SwaggerKey": "MsAdminUsuarios", + "UpstreamPathTemplate": "/Perfiles", + "UpstreamHttpMethod": [ "POST" ], + + "DownstreamPathTemplate": "/Perfiles", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8151 + } + ], + + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + { + "SwaggerKey": "MsAdminUsuarios", + "UpstreamPathTemplate": "/Perfiles", + "UpstreamHttpMethod": [ "PATCH" ], + + "DownstreamPathTemplate": "/Perfiles", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8151 + } + ], + + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + + + + { + "SwaggerKey": "MsAdminUsuarios", + "UpstreamPathTemplate": "/Permisos", + "UpstreamHttpMethod": [ "GET" ], + + "DownstreamPathTemplate": "/Permisos", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8151 + } + ], + + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + + { + "SwaggerKey": "MsAdminUsuarios", + "UpstreamPathTemplate": "/Permisos", + "UpstreamHttpMethod": [ "POST" ], + + "DownstreamPathTemplate": "/Permisos", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8151 + } + ], + + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + + + + + + { + "SwaggerKey": "MsAdminUsuarios", + "UpstreamPathTemplate": "/PerfilesPorUsuario", + "UpstreamHttpMethod": [ "GET" ], + + "DownstreamPathTemplate": "/PerfilesPorUsuario", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8151 + } + ], + + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + + { + "SwaggerKey": "MsAdminUsuarios", + "UpstreamPathTemplate": "/PerfilesPorUsuario", + "UpstreamHttpMethod": [ "POST" ], + + "DownstreamPathTemplate": "/PerfilesPorUsuario", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8151 + } + ], + + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + + + + + + + { + "SwaggerKey": "MsAdminUsuarios", + "UpstreamPathTemplate": "/Usuarios/Iniciales", + "UpstreamHttpMethod": [ "GET" ], + + "DownstreamPathTemplate": "/Usuarios/Iniciales", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8151 + } + ], + + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + + + { + "SwaggerKey": "MsAdminUsuarios", + "UpstreamPathTemplate": "/Usuarios", + "UpstreamHttpMethod": [ "GET" ], + + "DownstreamPathTemplate": "/Usuarios", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8151 + } + ], + + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + + + + + { + "SwaggerKey": "MsAdminUsuarios", + "UpstreamPathTemplate": "/Usuarios", + "UpstreamHttpMethod": [ "POST" ], + + "DownstreamPathTemplate": "/Usuarios", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8151 + } + ], + + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + + { + "SwaggerKey": "MsAdminUsuarios", + "UpstreamPathTemplate": "/Usuarios", + "UpstreamHttpMethod": [ "PATCH" ], + + "DownstreamPathTemplate": "/Usuarios", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8151 + } + ], + + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + + + + { + "SwaggerKey": "MsAdminUsuarios", + "UpstreamPathTemplate": "/TESTERROR", + "UpstreamHttpMethod": [ "PATCH" ], + + "DownstreamPathTemplate": "/Usuarios/TESTERROR", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8151 + } + ], + + "RouteClaimsRequirement": { + "permisos": "any" + } + } + + + + + + + + ] +} diff --git a/ApiGateway/Routes/ocelot.afiliados.json b/ApiGateway/Routes/ocelot.afiliados.json new file mode 100644 index 0000000..61277fc --- /dev/null +++ b/ApiGateway/Routes/ocelot.afiliados.json @@ -0,0 +1,306 @@ +{ + "Routes": [ + { + "SwaggerKey": "Afiliados", + "UpstreamPathTemplate": "/Afiliados", + "UpstreamHttpMethod": [ "Get" ], + + "DownstreamPathTemplate": "/Afiliados", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8145 + } + ], + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + + + { + "SwaggerKey": "Afiliados", + "UpstreamPathTemplate": "/Afiliados", + "UpstreamHttpMethod": [ "Post" ], + + "DownstreamPathTemplate": "/Afiliados", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8145 + } + ], + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + + + { + "SwaggerKey": "Afiliados", + "UpstreamPathTemplate": "/Afiliados/Documento", + "UpstreamHttpMethod": [ "Get" ], + + "DownstreamPathTemplate": "/Afiliados/Documento", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8145 + } + ], + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + + + { + "SwaggerKey": "Afiliados", + "UpstreamPathTemplate": "/Afiliados/Aceptar", + "UpstreamHttpMethod": [ "Post" ], + + "DownstreamPathTemplate": "/Afiliados/Aceptar", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8145 + } + ], + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + + + { + "SwaggerKey": "Afiliados", + "UpstreamPathTemplate": "/Afiliados/SubirSoporte", + "UpstreamHttpMethod": [ "Post" ], + + "DownstreamPathTemplate": "/Afiliados/SubirSoporte", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8145 + } + ], + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + + + { + "SwaggerKey": "Afiliados", + "UpstreamPathTemplate": "/Afiliados/CheckDocumento", + "UpstreamHttpMethod": [ "Get" ], + + "DownstreamPathTemplate": "/Afiliados/CheckDocumento", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8145 + } + ], + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + + + { + "SwaggerKey": "Afiliados", + "UpstreamPathTemplate": "/Afiliados/Rechazar", + "UpstreamHttpMethod": [ "Post" ], + + "DownstreamPathTemplate": "/Afiliados/Rechazar", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8145 + } + ], + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + + + { + "SwaggerKey": "Afiliados", + "UpstreamPathTemplate": "/Afiliados/Aprobar", + "UpstreamHttpMethod": [ "Post" ], + + "DownstreamPathTemplate": "/Afiliados/Aprobar", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8145 + } + ], + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + + + { + "SwaggerKey": "Afiliados", + "UpstreamPathTemplate": "/Afiliados/Generar", + "UpstreamHttpMethod": [ "Patch" ], + + "DownstreamPathTemplate": "/Afiliados/Generar", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8145 + } + ], + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + + + { + "SwaggerKey": "Afiliados", + "UpstreamPathTemplate": "/Afiliados/AfiliadosUsuario", + "UpstreamHttpMethod": [ "Get" ], + + "DownstreamPathTemplate": "/Afiliados/AfiliadosUsuario", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8145 + } + ], + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + + + { + "SwaggerKey": "Afiliados", + "UpstreamPathTemplate": "/Archivos", + "UpstreamHttpMethod": [ "Get" ], + + "DownstreamPathTemplate": "/Archivos", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8145 + } + ], + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + + + { + "SwaggerKey": "Afiliados", + "UpstreamPathTemplate": "/DeclaratoriasPorAfiliado", + "UpstreamHttpMethod": [ "Get" ], + + "DownstreamPathTemplate": "/DeclaratoriasPorAfiliado", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8145 + } + ], + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + + + { + "SwaggerKey": "Afiliados", + "UpstreamPathTemplate": "/PreguntasDeclaratorias", + "UpstreamHttpMethod": [ "Get" ], + + "DownstreamPathTemplate": "/PreguntasDeclaratorias", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8145 + } + ], + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + + + { + "SwaggerKey": "Afiliados", + "UpstreamPathTemplate": "/UPCAdicional", + "UpstreamHttpMethod": [ "Get" ], + + "DownstreamPathTemplate": "/UPCAdicional", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8145 + } + ], + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + + + { + "SwaggerKey": "Afiliados", + "UpstreamPathTemplate": "/UPCAdicional", + "UpstreamHttpMethod": [ "Post" ], + + "DownstreamPathTemplate": "/UPCAdicional", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8145 + } + ], + "RouteClaimsRequirement": { + "permisos": "any" + } + }, + + + { + "SwaggerKey": "Afiliados", + "UpstreamPathTemplate": "/UPCAdicional", + "UpstreamHttpMethod": [ "Patch" ], + + "DownstreamPathTemplate": "/UPCAdicional", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8145 + } + ], + "RouteClaimsRequirement": { + "permisos": "any" + } + } + ] +} diff --git a/ApiGateway/Routes/ocelot.apitest.json b/ApiGateway/Routes/ocelot.apitest.json new file mode 100644 index 0000000..cf2cc40 --- /dev/null +++ b/ApiGateway/Routes/ocelot.apitest.json @@ -0,0 +1,56 @@ +{ + "Routes": [ + { + "SwaggerKey": "apitest", + //Incoming + "UpstreamPathTemplate": "/Test", + "UpstreamHttpMethod": [ "GET", "POST" ], + + //Routed + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5041 + } + ], + "DownstreamPathTemplate": "/ApiTest", + + //Auth + "AuthenticationOptions": { + //"AuthenticationProviderKey": "Bearer", + "AllowedScopes": [] // Ejemplo: "api.portfolio.manager.v1" + }, + "RouteClaimsRequirement": { + "permisos": "nuepDLYs7n8=" + } + }, + + + { + "SwaggerKey": "apitest", + + "UpstreamPathTemplate": "/Test/{id}", + "UpstreamHttpMethod": [ "DELETE" ], + + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5041 + } + ], + "DownstreamPathTemplate": "/ApiTest/{id}", + + // + "RateLimitOptions": { + "ClientWhiteList": [], + "EnableRateLimiting": true, + "Period": "5s", //s =sec, m = min, h = hour, d = day // Solo puede hacer request en x tiempo + "PeriodTimespan": 10, // reintentar luego de x tiempo si entra en el error del period + "Limit": 1 //Request que puede hacer 1 cliente + } + + } + ] +} diff --git a/ApiGateway/Routes/ocelot.contratos.json b/ApiGateway/Routes/ocelot.contratos.json new file mode 100644 index 0000000..353ef2a --- /dev/null +++ b/ApiGateway/Routes/ocelot.contratos.json @@ -0,0 +1,45 @@ +{ + "Routes": [ + { + "SwaggerKey": "MsContratos", + //Incoming + "UpstreamPathTemplate": "/Contratos", + "UpstreamHttpMethod": [ "GET", "POST" ], + + //Routed + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5102 + } + ], + "DownstreamPathTemplate": "/api/Contratos" + //"AuthenticationOptions": { + // //"AuthenticationProviderKey": "Bearer", + // "AllowedScopes": [ "0kmmpshnyd.execute-api.us-east-2.amazonaws.com/" ] // Ejemplo: "api.portfolio.manager.v1" + //} + }, + { + "SwaggerKey": "MsContratos", + //Incoming + "UpstreamPathTemplate": "/Contratos/asdasd/potato", + "UpstreamHttpMethod": [ "GET", "POST" ], + + //Routed + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5102 + } + ], + "DownstreamPathTemplate": "/api/Contratos" + //"AuthenticationOptions": { + // //"AuthenticationProviderKey": "Bearer", + // "AllowedScopes": [ "0kmmpshnyd.execute-api.us-east-2.amazonaws.com/" ] // Ejemplo: "api.portfolio.manager.v1" + //} + } + ] + +} diff --git a/ApiGateway/Routes/ocelot.datosmaestros.json b/ApiGateway/Routes/ocelot.datosmaestros.json new file mode 100644 index 0000000..c13dd12 --- /dev/null +++ b/ApiGateway/Routes/ocelot.datosmaestros.json @@ -0,0 +1,23 @@ +{ + "Routes": [ + { + "SwaggerKey": "DatosMaestros", + + "UpstreamPathTemplate": "/DatosMaestros", + "UpstreamHttpMethod": [ "GET" ], + + "DownstreamPathTemplate": "/DatosMaestros", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8146 + } + ], + + "RouteClaimsRequirement": { + "permisos": "any" + } + } + ] +} diff --git a/ApiGateway/Routes/ocelot.externo.json b/ApiGateway/Routes/ocelot.externo.json new file mode 100644 index 0000000..9115eb8 --- /dev/null +++ b/ApiGateway/Routes/ocelot.externo.json @@ -0,0 +1,39 @@ +{ + "Routes": [ + + { + "SwaggerKey": "Externo", + "UpstreamPathTemplate": "/Ext/Login", + "UpstreamHttpMethod": [ "POST" ], + + "DownstreamPathTemplate": "/Auth/Login", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8199 + } + ] + }, + + + { + "SwaggerKey": "Externo", + "UpstreamPathTemplate": "/UPC", + "UpstreamHttpMethod": [ "Get" ], + + "DownstreamPathTemplate": "/UPC", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 8199 + } + ], + "RouteClaimsRequirement": { + "permisos": "W3Y9E3ioiao=" + //"permisos": "8IF4fbgkEP0=" // => Dev + } + } + ] +} diff --git a/ApiGateway/Routes/ocelot.global.json b/ApiGateway/Routes/ocelot.global.json new file mode 100644 index 0000000..1de75c8 --- /dev/null +++ b/ApiGateway/Routes/ocelot.global.json @@ -0,0 +1,9 @@ +{ + "GlobalConfiguration": { + //"BaseUrl": "https://localhost:8021", + "RateLimitOptions": { + "QuotaExceededMessage": "Request excedidos", + "HttpStatusCode": 909 //429 default + } + } +} diff --git a/ApiGateway/Trash/ocelot - Copy.json b/ApiGateway/Trash/ocelot - Copy.json new file mode 100644 index 0000000..07bf6c3 --- /dev/null +++ b/ApiGateway/Trash/ocelot - Copy.json @@ -0,0 +1,105 @@ +{ + "Routes": [ + + { + //Incoming + "UpstreamPathTemplate": "/api/Account", + "UpstreamHttpMethod": [ "POST" ], + + //Routed + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5151 + } + ], + "DownstreamPathTemplate": "/api/Account" + }, + + + { + //Incoming + "UpstreamPathTemplate": "/Contratos", + "UpstreamHttpMethod": [ "GET", "POST" ], + + //Routed + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5102 + } + ], + "DownstreamPathTemplate": "/api/Contratos", + "AuthenticationOptions": { + //"AuthenticationProviderKey": "Bearer", + "AllowedScopes": ["0kmmpshnyd.execute-api.us-east-2.amazonaws.com/"] // Ejemplo: "api.portfolio.manager.v1" + } + }, + + + + { + //Incoming + "UpstreamPathTemplate": "/Test", + "UpstreamHttpMethod": [ "GET", "POST" ], + + //Routed + "DownstreamScheme": "https", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 7041 + } + ], + "DownstreamPathTemplate": "/ApiTest", + + //Auth + "AuthenticationOptions": { + //"AuthenticationProviderKey": "Bearer", + "AllowedScopes": [] // Ejemplo: "api.portfolio.manager.v1" + }, + "RouteClaimsRequirement": { + "permiso": "nuepDLYs7n8=" + } + }, + + + + { + "UpstreamPathTemplate": "/Test/{id}", + "UpstreamHttpMethod": [ "DELETE" ], + + "DownstreamScheme": "https", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 7041 + } + ], + "DownstreamPathTemplate": "/ApiTest/{id}", + + // + "RateLimitOptions": { + "ClientWhiteList": [], + "EnableRateLimiting": true, + "Period": "5s", //s =sec, m = min, h = hour, d = day // Solo puede hacer request en x tiempo + "PeriodTimespan": 10, // reintentar luego de x tiempo si entra en el error del period + "Limit": 1 //Request que puede hacer 1 cliente + } + + } + ], + + + + "GlobalConfiguration": { + "BaseUrl": "https://localhost:7041", + "RateLimitOptions": { + "QuotaExceededMessage": "Request excedidos", + "HttpStatusCode": 909 //429 default + } + } + +} \ No newline at end of file diff --git a/ApiGateway/Trash/ocelot2.json b/ApiGateway/Trash/ocelot2.json new file mode 100644 index 0000000..54ce45e --- /dev/null +++ b/ApiGateway/Trash/ocelot2.json @@ -0,0 +1,19 @@ +{ + "Routes": [ + { + "UpstreamPathTemplate": "/ApiTest", + "UpstreamHttpMethod": [ "GET", "POST" ], + + "DownstreamScheme": "https", + "DownstreamHostAndPorts": [ + "Host": "localhost", + "Port" : 7041 + ] + } + ], + + "GlobalConfiguration": { + "BaseUrl": "https://localhost:7041" + } + +} \ No newline at end of file diff --git a/ApiGateway/appsettings.Development.json b/ApiGateway/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/ApiGateway/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/ApiGateway/appsettings.json b/ApiGateway/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/ApiGateway/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/ApiGateway/ocelot.json b/ApiGateway/ocelot.json new file mode 100644 index 0000000..045373e --- /dev/null +++ b/ApiGateway/ocelot.json @@ -0,0 +1 @@ +{"Routes":[{"DownstreamPathTemplate":"/Auth/Login","UpstreamPathTemplate":"/Auth/Login","UpstreamHttpMethod":["GET"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8151}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/Microservicios","UpstreamPathTemplate":"/Microservicios","UpstreamHttpMethod":["GET"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8151}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/Microservicios","UpstreamPathTemplate":"/Microservicios","UpstreamHttpMethod":["POST"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8151}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/Perfiles","UpstreamPathTemplate":"/Perfiles","UpstreamHttpMethod":["GET"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8151}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/Perfiles","UpstreamPathTemplate":"/Perfiles","UpstreamHttpMethod":["POST"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8151}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/Perfiles","UpstreamPathTemplate":"/Perfiles","UpstreamHttpMethod":["PATCH"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8151}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/Permisos","UpstreamPathTemplate":"/Permisos","UpstreamHttpMethod":["GET"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8151}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/Permisos","UpstreamPathTemplate":"/Permisos","UpstreamHttpMethod":["POST"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8151}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/PerfilesPorUsuario","UpstreamPathTemplate":"/PerfilesPorUsuario","UpstreamHttpMethod":["GET"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8151}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/PerfilesPorUsuario","UpstreamPathTemplate":"/PerfilesPorUsuario","UpstreamHttpMethod":["POST"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8151}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/Usuarios/Iniciales","UpstreamPathTemplate":"/Usuarios/Iniciales","UpstreamHttpMethod":["GET"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8151}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/Usuarios","UpstreamPathTemplate":"/Usuarios","UpstreamHttpMethod":["GET"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8151}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/Usuarios","UpstreamPathTemplate":"/Usuarios","UpstreamHttpMethod":["POST"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8151}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/Usuarios","UpstreamPathTemplate":"/Usuarios","UpstreamHttpMethod":["PATCH"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8151}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/Usuarios/TESTERROR","UpstreamPathTemplate":"/TESTERROR","UpstreamHttpMethod":["PATCH"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8151}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/Afiliados","UpstreamPathTemplate":"/Afiliados","UpstreamHttpMethod":["Get"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8145}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/Afiliados","UpstreamPathTemplate":"/Afiliados","UpstreamHttpMethod":["Post"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8145}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/Afiliados/Documento","UpstreamPathTemplate":"/Afiliados/Documento","UpstreamHttpMethod":["Get"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8145}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/Afiliados/Aceptar","UpstreamPathTemplate":"/Afiliados/Aceptar","UpstreamHttpMethod":["Post"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8145}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/Afiliados/SubirSoporte","UpstreamPathTemplate":"/Afiliados/SubirSoporte","UpstreamHttpMethod":["Post"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8145}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/Afiliados/CheckDocumento","UpstreamPathTemplate":"/Afiliados/CheckDocumento","UpstreamHttpMethod":["Get"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8145}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/Afiliados/Rechazar","UpstreamPathTemplate":"/Afiliados/Rechazar","UpstreamHttpMethod":["Post"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8145}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/Afiliados/Aprobar","UpstreamPathTemplate":"/Afiliados/Aprobar","UpstreamHttpMethod":["Post"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8145}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/Afiliados/Generar","UpstreamPathTemplate":"/Afiliados/Generar","UpstreamHttpMethod":["Patch"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8145}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/Afiliados/AfiliadosUsuario","UpstreamPathTemplate":"/Afiliados/AfiliadosUsuario","UpstreamHttpMethod":["Get"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8145}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/Archivos","UpstreamPathTemplate":"/Archivos","UpstreamHttpMethod":["Get"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8145}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/DeclaratoriasPorAfiliado","UpstreamPathTemplate":"/DeclaratoriasPorAfiliado","UpstreamHttpMethod":["Get"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8145}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/PreguntasDeclaratorias","UpstreamPathTemplate":"/PreguntasDeclaratorias","UpstreamHttpMethod":["Get"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8145}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/UPCAdicional","UpstreamPathTemplate":"/UPCAdicional","UpstreamHttpMethod":["Get"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8145}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/UPCAdicional","UpstreamPathTemplate":"/UPCAdicional","UpstreamHttpMethod":["Post"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8145}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/UPCAdicional","UpstreamPathTemplate":"/UPCAdicional","UpstreamHttpMethod":["Patch"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8145}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/ApiTest","UpstreamPathTemplate":"/Test","UpstreamHttpMethod":["GET","POST"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"nuepDLYs7n8="},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":5041}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/ApiTest/{id}","UpstreamPathTemplate":"/Test/{id}","UpstreamHttpMethod":["DELETE"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":true,"Period":"5s","PeriodTimespan":10.0,"Limit":1},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":5041}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/api/Contratos","UpstreamPathTemplate":"/Contratos","UpstreamHttpMethod":["GET","POST"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":5102}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/api/Contratos","UpstreamPathTemplate":"/Contratos/asdasd/potato","UpstreamHttpMethod":["GET","POST"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":5102}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/DatosMaestros","UpstreamPathTemplate":"/DatosMaestros","UpstreamHttpMethod":["GET"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"any"},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8146}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/Ext/Login","UpstreamPathTemplate":"/Ext/Login","UpstreamHttpMethod":["Get"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8199}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null},{"DownstreamPathTemplate":"/UPC","UpstreamPathTemplate":"/UPC","UpstreamHttpMethod":["Get"],"DownstreamHttpMethod":null,"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{"permisos":"8IF4fbgkEP0="},"AddQueriesToRequest":{},"ChangeDownstreamPathTemplate":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"RouteIsCaseSensitive":false,"ServiceName":null,"ServiceNamespace":null,"DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHostAndPorts":[{"Host":"localhost","Port":8199}],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false,"SecurityOptions":{"IPAllowedList":[],"IPBlockedList":[]},"DownstreamHttpVersion":null}],"DynamicRoutes":[],"Aggregates":[],"GlobalConfiguration":{"RequestIdKey":null,"ServiceDiscoveryProvider":{"Scheme":null,"Host":null,"Port":0,"Type":null,"Token":null,"ConfigurationKey":null,"PollingInterval":0,"Namespace":null},"RateLimitOptions":{"ClientIdHeader":"ClientId","QuotaExceededMessage":"Request excedidos","RateLimitCounterPrefix":"ocelot","DisableRateLimitHeaders":false,"HttpStatusCode":909},"QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"BaseUrl":null,"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"DownstreamScheme":null,"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true,"MaxConnectionsPerServer":2147483647},"DownstreamHttpVersion":null}} \ No newline at end of file diff --git a/Auth/Auth.csproj b/Auth/Auth.csproj new file mode 100644 index 0000000..0caf158 --- /dev/null +++ b/Auth/Auth.csproj @@ -0,0 +1,13 @@ + + + + net6.0 + enable + enable + + + + + + + diff --git a/Auth/Security.cs b/Auth/Security.cs new file mode 100644 index 0000000..c298c8b --- /dev/null +++ b/Auth/Security.cs @@ -0,0 +1,179 @@ +using Nini.Config; +using System.Security.Cryptography; +using System.Text; +using System.Text.Json; + +namespace Security +{ + public class Encripter + { + public static int _SEMILLA { get; private set; } = -1; + public static string? HashKey { get; private set; } + private static string? PwdKey { get; set; } + + public Encripter() + { + string? mode = Environment.GetEnvironmentVariable("Mode"); + + if (mode == "Prod") + { + ReadCredentials(); + } + else + { + string DevKey = Environment.GetEnvironmentVariable("MySecretKey")!; + HashKey = DevKey; + PwdKey = DevKey; + _SEMILLA = 1262; + } + } + + public bool IsValid + { + get + { + return HashKey != null && PwdKey != null && _SEMILLA != -1; + } + } + + public int getSemilla() + { + return _SEMILLA; + } + + private void ReadCredentials() + { + try + { + + //var folder = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + + var filePath = Path.Combine("C:\\Users\\Administrator", ".hims", "info"); + //var filePath = Path.Combine("C:\\Users\\Admin\\Desktop\\sqsas\\usuarios", "info"); + + //Validacion manual antes de leer + if (!File.Exists(filePath)) //Exist = false + { + //Devolver error + HashKey = null; + PwdKey = null; + _SEMILLA = -1; + return; + } + + IConfigSource source = new IniConfigSource(filePath); + var security = source.Configs["hash"]; + var defecto = source.Configs["default"]; + + HashKey = security.Get("tkn_key"); + PwdKey = security.Get("hash_key"); + _SEMILLA = Int32.Parse(defecto.Get("seed")); + + Console.WriteLine(); + + } + catch (IOException ioEx) + { + Console.WriteLine(ioEx.Message); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + } + + public string EncryptPwd(string text) + { + return Encrypt(text, PwdKey); + } + public string DecryptPwd(string text) + { + return Decrypt(text, PwdKey); + } + + public string EncryptHashTkn(string text) + { + return Encrypt(text, HashKey); + } + public string DecryptHashTkn(string text) + { + return Decrypt(text, HashKey); + } + + private static string Encrypt(string text, string hash) + { + try + { + byte[] bytesHash = UTF8Encoding.UTF8.GetBytes(hash); + byte[] bytes = UTF8Encoding.UTF8.GetBytes(text); + + MD5 md5 = MD5.Create(); + TripleDES trpl = TripleDES.Create(); + + trpl.Key = md5.ComputeHash(bytesHash); + trpl.Mode = CipherMode.ECB; + + ICryptoTransform transformer = trpl.CreateEncryptor(); + byte[] res = transformer.TransformFinalBlock(bytes, 0, bytes.Length); + + + return Convert.ToBase64String(res); + } + catch (Exception ex) + { + return ex.Message; + } + } + + private static string Decrypt(string encText, string hash) + { + try + { + + //string hash = Environment.GetEnvironmentVariable("MySecretKey")!; + + byte[] bytesHash = UTF8Encoding.UTF8.GetBytes(hash); + byte[] bytes = Convert.FromBase64String(encText); + + MD5 md5 = MD5.Create(); + TripleDES trpl = TripleDES.Create(); + + trpl.Key = md5.ComputeHash(bytesHash); + trpl.Mode = CipherMode.ECB; + + ICryptoTransform transformer = trpl.CreateDecryptor(); + byte[] res = transformer.TransformFinalBlock(bytes, 0, bytes.Length); + + return UTF8Encoding.UTF8.GetString(res); + } + catch (Exception ex) + { + return ex.Message; + } + } + + public static string Cypher(string value) + { + string encryptedText = ""; + for (int i = 0; i < value.Length; i++) + { + int txtUser = (int)value[i]; + int encryption = txtUser + _SEMILLA; + encryptedText += Char.ConvertFromUtf32(encryption); + } + return Base64Encode(encryptedText); + } + + + public static string Base64Decode(string base64EncodedData) + { + var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData); + return System.Text.Encoding.UTF8.GetString(base64EncodedBytes); + } + public static string Base64Encode(string plainText) + { + var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText); + return System.Convert.ToBase64String(plainTextBytes); + } + } +} \ No newline at end of file diff --git a/AuthWebApi/AuthWebApi.csproj b/AuthWebApi/AuthWebApi.csproj new file mode 100644 index 0000000..40b6173 --- /dev/null +++ b/AuthWebApi/AuthWebApi.csproj @@ -0,0 +1,13 @@ + + + + net6.0 + enable + enable + + + + + + + diff --git a/AuthWebApi/Controllers/AccountController.cs b/AuthWebApi/Controllers/AccountController.cs new file mode 100644 index 0000000..105ca80 --- /dev/null +++ b/AuthWebApi/Controllers/AccountController.cs @@ -0,0 +1,31 @@ +using JwtAuthManager; +using JwtAuthManager.Models; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; + +namespace AuthWebApi.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class AccountController : ControllerBase + { + private readonly JwtTokenHandler _jwtTokenHandler; + + public AccountController(JwtTokenHandler jwtTokenHandler) + { + _jwtTokenHandler = jwtTokenHandler; + } + + [HttpPost] + public ActionResult Authenticate([FromBody] AuthRequest authRequest) + { + var authResponse = _jwtTokenHandler.GenerateJwtToken(authRequest); + if(authResponse == null) return Unauthorized(); + return Ok(authResponse); + } + + +// https://localhost:7041/ApiTest post get +//https://localhost:7041/ApiTest/{id} delete + } +} diff --git a/AuthWebApi/Program.cs b/AuthWebApi/Program.cs new file mode 100644 index 0000000..191eac7 --- /dev/null +++ b/AuthWebApi/Program.cs @@ -0,0 +1,18 @@ +using JwtAuthManager; + +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. + +builder.Services.AddControllers(); +builder.Services.AddSingleton(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. + +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); diff --git a/AuthWebApi/Properties/launchSettings.json b/AuthWebApi/Properties/launchSettings.json new file mode 100644 index 0000000..874525c --- /dev/null +++ b/AuthWebApi/Properties/launchSettings.json @@ -0,0 +1,30 @@ +{ + "profiles": { + "AuthWebApi": { + "commandName": "Project", + "launchUrl": "weatherforecast", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5151" + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "weatherforecast", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + }, + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:33553", + "sslPort": 0 + } + } +} \ No newline at end of file diff --git a/AuthWebApi/appsettings.Development.json b/AuthWebApi/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/AuthWebApi/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/AuthWebApi/appsettings.json b/AuthWebApi/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/AuthWebApi/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/BackApiGateway.sln b/BackApiGateway.sln new file mode 100644 index 0000000..9739c13 --- /dev/null +++ b/BackApiGateway.sln @@ -0,0 +1,48 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.32328.378 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ApiGateway", "ApiGateway", "{9F5D8D1C-CF99-4BDD-8497-0123656B8A48}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApiGateway", "ApiGateway\ApiGateway.csproj", "{AC631810-7FAF-4C9A-A35D-3EC538A49810}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JwtAuthManager", "JwtAuthManager\JwtAuthManager.csproj", "{787DFE08-2E54-4833-AF3E-5979B676B042}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Auth", "Auth\Auth.csproj", "{76522272-9D28-4168-8296-AFC933D22650}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IntegradorBE", "IntegradorBE\IntegradorBE.csproj", "{9562FA86-4AEF-43E2-A6F6-D60AF09BCA12}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {AC631810-7FAF-4C9A-A35D-3EC538A49810}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AC631810-7FAF-4C9A-A35D-3EC538A49810}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AC631810-7FAF-4C9A-A35D-3EC538A49810}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AC631810-7FAF-4C9A-A35D-3EC538A49810}.Release|Any CPU.Build.0 = Release|Any CPU + {787DFE08-2E54-4833-AF3E-5979B676B042}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {787DFE08-2E54-4833-AF3E-5979B676B042}.Debug|Any CPU.Build.0 = Debug|Any CPU + {787DFE08-2E54-4833-AF3E-5979B676B042}.Release|Any CPU.ActiveCfg = Release|Any CPU + {787DFE08-2E54-4833-AF3E-5979B676B042}.Release|Any CPU.Build.0 = Release|Any CPU + {76522272-9D28-4168-8296-AFC933D22650}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {76522272-9D28-4168-8296-AFC933D22650}.Debug|Any CPU.Build.0 = Debug|Any CPU + {76522272-9D28-4168-8296-AFC933D22650}.Release|Any CPU.ActiveCfg = Release|Any CPU + {76522272-9D28-4168-8296-AFC933D22650}.Release|Any CPU.Build.0 = Release|Any CPU + {9562FA86-4AEF-43E2-A6F6-D60AF09BCA12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9562FA86-4AEF-43E2-A6F6-D60AF09BCA12}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9562FA86-4AEF-43E2-A6F6-D60AF09BCA12}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9562FA86-4AEF-43E2-A6F6-D60AF09BCA12}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {AC631810-7FAF-4C9A-A35D-3EC538A49810} = {9F5D8D1C-CF99-4BDD-8497-0123656B8A48} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {EC576D5A-ADE3-40CC-BF55-7E52E6F18AC4} + EndGlobalSection +EndGlobal diff --git a/IntegradorBE/.config/dotnet-tools.json b/IntegradorBE/.config/dotnet-tools.json new file mode 100644 index 0000000..53c8226 --- /dev/null +++ b/IntegradorBE/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "dotnet-ef": { + "version": "6.0.10", + "commands": [ + "dotnet-ef" + ] + } + } +} \ No newline at end of file diff --git a/IntegradorBE/Controllers/AuthController.cs b/IntegradorBE/Controllers/AuthController.cs new file mode 100644 index 0000000..16ad9a4 --- /dev/null +++ b/IntegradorBE/Controllers/AuthController.cs @@ -0,0 +1,97 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.IdentityModel.Tokens; +using Security; +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Text; +using System.Web; + +namespace IntegradorBE.Controllers +{ + [ApiController] + [Route("[controller]")] + public class AuthController : ControllerBase + { + private static readonly Encripter _encript = new(); + + [HttpPost("Login")] + public IActionResult Login() + { + try + { + var ip = ""; + + if (HttpContext?.Connection?.RemoteIpAddress != null) + ip = HttpContext.Connection.RemoteIpAddress.ToString(); + + + if (String.IsNullOrWhiteSpace(ip)) + ip = HttpContext?.Request.Headers["REMOTE_ADDR"]; + + + if (!_encript.IsValid) return BadRequest("Lectura inválida"); + if (String.IsNullOrWhiteSpace(ip)) return Unauthorized("Acceso no autorizado."); + + //Security key debe ser un environment variable seguro + var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Encripter.HashKey)); + var signingCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256); + + ClaimsIdentity claims = new ClaimsIdentity(new List + { + new Claim("IP", ip), + new Claim("permisos", _encript.EncryptHashTkn("externo") + "::-1") + }); + + + var securityTokenDescriptor = new SecurityTokenDescriptor + { + Subject = claims, + Expires = DateTime.Now.AddDays(20), + SigningCredentials = signingCredentials + }; + + var jwtSecurityTokenHandler = new JwtSecurityTokenHandler(); + var securityToken = jwtSecurityTokenHandler.CreateToken(securityTokenDescriptor); + var token = jwtSecurityTokenHandler.WriteToken(securityToken); + + return Ok(new { + token = Encripter.Cypher(token) + }); + + } catch (Exception e) + { + return BadRequest(e.Message); + } + + } + + + [HttpGet("Encriptar")] + public IActionResult Encriptar(string text, int tipo) + { + if (!_encript.IsValid) return BadRequest("Lectura inválida"); + + if (tipo == 0) return Ok(_encript.EncryptPwd(text)); + + return Ok(_encript.EncryptHashTkn(text)); + } + + [HttpGet("Desencriptar")] + public IActionResult Desencriptar(string text, int tipo) + { + if (!_encript.IsValid) return BadRequest("Lectura inválida"); + + if (tipo == 0) return Ok(_encript.DecryptPwd(text)); + + return Ok(_encript.DecryptHashTkn(text)); + } + + } + + public class LoginModel + { + public string? TX_CORREO_USUMS { get; set; } + public string? TX_PASSWORD_USUMS { get; set; } + } + +} \ No newline at end of file diff --git a/IntegradorBE/Controllers/UPCController.cs b/IntegradorBE/Controllers/UPCController.cs new file mode 100644 index 0000000..febdfc0 --- /dev/null +++ b/IntegradorBE/Controllers/UPCController.cs @@ -0,0 +1,72 @@ +using Microsoft.AspNetCore.Mvc; + +namespace IntegradorBE.Controllers +{ + [ApiController] + [Route("[controller]")] + public class UPCController : ControllerBase + { + + [HttpGet] + public IActionResult UPC(string TX_DOC_AFIL) + { + try{ + + if (TX_DOC_AFIL == null) return Conflict("Introduzca un valor para consultar"); + + UPCModel[] upc = new UPCModel[5]; + + upc[0] = new UPCModel + { + TX_DOC_AFIL = "7818322", + NU_VALORUPC_UPC = 300000, + }; + + upc[1] = new UPCModel + { + TX_DOC_AFIL = "234wert", + NU_VALORUPC_UPC = 20000, + }; + + upc[2] = new UPCModel + { + TX_DOC_AFIL = "900578105", + NU_VALORUPC_UPC = 10000, + }; + + upc[3] = new UPCModel + { + TX_DOC_AFIL = "1452145", + NU_VALORUPC_UPC = 50000, + }; + + upc[4] = new UPCModel + { + TX_DOC_AFIL = "127647831", + NU_VALORUPC_UPC = 70000, + }; + + var existe = upc.FirstOrDefault(x => x.TX_DOC_AFIL == TX_DOC_AFIL)?.NU_VALORUPC_UPC; + + if (existe != null) + { + return Ok(existe); + } + + return Ok("El documento no existe"); + } + catch(Exception ex) + { + return BadRequest(ex); + } + } + + } + + public class UPCModel + { + public string? TX_DOC_AFIL { get; set; } + public decimal? NU_VALORUPC_UPC { get; set; } + } + +} \ No newline at end of file diff --git a/IntegradorBE/IntegradorBE.csproj b/IntegradorBE/IntegradorBE.csproj new file mode 100644 index 0000000..36ecd2d --- /dev/null +++ b/IntegradorBE/IntegradorBE.csproj @@ -0,0 +1,18 @@ + + + + net6.0 + enable + enable + + + + + + + + + + + + diff --git a/IntegradorBE/IntegradorBE.sln b/IntegradorBE/IntegradorBE.sln new file mode 100644 index 0000000..ed48996 --- /dev/null +++ b/IntegradorBE/IntegradorBE.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.2.32519.379 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IntegradorBE", "IntegradorBE.csproj", "{494E091E-7088-418E-A823-D313FC51D4CE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Auth", "..\Auth\Auth.csproj", "{D7302A1B-4C0E-4FF4-83FC-4DB768976A2A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {494E091E-7088-418E-A823-D313FC51D4CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {494E091E-7088-418E-A823-D313FC51D4CE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {494E091E-7088-418E-A823-D313FC51D4CE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {494E091E-7088-418E-A823-D313FC51D4CE}.Release|Any CPU.Build.0 = Release|Any CPU + {D7302A1B-4C0E-4FF4-83FC-4DB768976A2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D7302A1B-4C0E-4FF4-83FC-4DB768976A2A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D7302A1B-4C0E-4FF4-83FC-4DB768976A2A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D7302A1B-4C0E-4FF4-83FC-4DB768976A2A}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {9C57CBEF-459D-496E-986C-9242C9201016} + EndGlobalSection +EndGlobal diff --git a/IntegradorBE/Program.cs b/IntegradorBE/Program.cs new file mode 100644 index 0000000..a75248e --- /dev/null +++ b/IntegradorBE/Program.cs @@ -0,0 +1,42 @@ +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. + +builder.Services.AddControllers(); +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); + +// Enable Cors +builder.Services.AddCors(options => { + options.AddPolicy(name: "widthoutCors", + builder => { + builder.AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader(); + }); +}); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +app.UseSwagger(); +app.UseSwaggerUI(); +app.UseCors("widthoutCors"); + +if (app.Environment.IsDevelopment()) +{ + Environment.SetEnvironmentVariable("Mode", "Dev"); +} +else +{ + Environment.SetEnvironmentVariable("Mode", "Prod"); +} + +app.UseHttpsRedirection(); + +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); diff --git a/IntegradorBE/Properties/launchSettings.json b/IntegradorBE/Properties/launchSettings.json new file mode 100644 index 0000000..20b9edb --- /dev/null +++ b/IntegradorBE/Properties/launchSettings.json @@ -0,0 +1,32 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:18821", + "sslPort": 44327 + } + }, + "profiles": { + "IntegradorBE": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7082;http://localhost:5082", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "MySecretKey": "_ll@v3Segur1d4d!123" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/IntegradorBE/appsettings.Development.json b/IntegradorBE/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/IntegradorBE/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/IntegradorBE/appsettings.json b/IntegradorBE/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/IntegradorBE/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/JwtAuthManager/CustomJwtAuthExtension.cs b/JwtAuthManager/CustomJwtAuthExtension.cs new file mode 100644 index 0000000..08cb353 --- /dev/null +++ b/JwtAuthManager/CustomJwtAuthExtension.cs @@ -0,0 +1,40 @@ +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.IdentityModel.Tokens; +using System.Text; + +namespace JwtAuthManager +{ + public static class CustomJwtAuthExtension + { + + //private readonly ILogger _logger; + + //public CustomJwtAuthExtension(ILogger<> logger) + //{ + // _logger = (ILogger?)logger; + //} + + public static void AddCustomJwtAuthentication(this IServiceCollection services) + { + + services.AddAuthentication(options => + { + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + }).AddJwtBearer(options => + { + options.IncludeErrorDetails = true; + options.RequireHttpsMetadata = true; + options.SaveToken = true; + options.TokenValidationParameters = new TokenValidationParameters + { + ValidateIssuer = false, + ValidateAudience = false, + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(JwtTokenHandler.JWT_SECURITY_KEY)) + }; + }); + } + } +} diff --git a/JwtAuthManager/JwtAuthManager.csproj b/JwtAuthManager/JwtAuthManager.csproj new file mode 100644 index 0000000..02c9b0f --- /dev/null +++ b/JwtAuthManager/JwtAuthManager.csproj @@ -0,0 +1,16 @@ + + + + net6.0 + enable + enable + + + + + + + + + + diff --git a/JwtAuthManager/JwtTokenHandler.cs b/JwtAuthManager/JwtTokenHandler.cs new file mode 100644 index 0000000..8484262 --- /dev/null +++ b/JwtAuthManager/JwtTokenHandler.cs @@ -0,0 +1,81 @@ +using JwtAuthManager.Models; +using Microsoft.IdentityModel.Tokens; +using System; +using System.Collections.Generic; +using System.IdentityModel.Tokens.Jwt; +using System.Linq; +using System.Security.Claims; +using System.Text; +using System.Threading.Tasks; + +namespace JwtAuthManager +{ + public class JwtTokenHandler + { + public const string JWT_SECURITY_KEY = "_ll@v3Segur1d4d!123"; + private const int JWT_TOKEN_VALIDITY_MINS = 20; + + private readonly List _userLsist; + + public JwtTokenHandler() + { + _userLsist = new List + { + new UserAccount{UserName = "admin", Password = "admin123", Roles = new string [] { "MUJi4t5UCmA=", "LtMPr37abss=", } }, + new UserAccount{UserName = "user1", Password = "user1", Roles = new string [] { "nuepDLYs7n8=", "adnfaIJMvtc=" } }, + }; + } + + + public AuthResponse? GenerateJwtToken(AuthRequest authRequest) + { + if (string.IsNullOrWhiteSpace(authRequest.UserName) || string.IsNullOrWhiteSpace(authRequest.Password)) return null; + + // Validation + var userAcc = _userLsist.Where(x => x.UserName == authRequest.UserName && + x.Password == authRequest.Password).FirstOrDefault(); + + if (userAcc == null) return null; + + var tokenExpiryTimeStamp = DateTime.UtcNow.AddDays(JWT_TOKEN_VALIDITY_MINS); + //var tokenExpiryTimeStamp = DateTime.UtcNow.AddMinutes(JWT_TOKEN_VALIDITY_MINS); + var tokenKey = Encoding.ASCII.GetBytes(JWT_SECURITY_KEY); + + var claimsIdentity = new ClaimsIdentity(new List + { + new Claim(JwtRegisteredClaimNames.Name, authRequest.UserName), + }); + + foreach(var role in userAcc.Roles) + { + claimsIdentity.AddClaim(new Claim("permiso", role)); + } + + var signingCredentials = new SigningCredentials( + new SymmetricSecurityKey(tokenKey), + SecurityAlgorithms.HmacSha256Signature); + + var securityTokenDescriptor = new SecurityTokenDescriptor + { + Subject = claimsIdentity, + Expires = tokenExpiryTimeStamp, + SigningCredentials = signingCredentials + }; + + var jwtSecurityTokenHandler = new JwtSecurityTokenHandler(); + var securityToken = jwtSecurityTokenHandler.CreateToken(securityTokenDescriptor); + var token = jwtSecurityTokenHandler.WriteToken(securityToken); + + return new AuthResponse + { + UserName = userAcc.UserName, + ExpiresIn = (int)tokenExpiryTimeStamp.Subtract(DateTime.UtcNow).TotalSeconds, + JwtToken = token + }; + + + + } + + } +} diff --git a/JwtAuthManager/Models/AuthRequest.cs b/JwtAuthManager/Models/AuthRequest.cs new file mode 100644 index 0000000..2af324e --- /dev/null +++ b/JwtAuthManager/Models/AuthRequest.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JwtAuthManager.Models +{ + public class AuthRequest + { + public string UserName { get; set; } + public string Password { get; set; } + } +} diff --git a/JwtAuthManager/Models/AuthResponse.cs b/JwtAuthManager/Models/AuthResponse.cs new file mode 100644 index 0000000..5551be0 --- /dev/null +++ b/JwtAuthManager/Models/AuthResponse.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JwtAuthManager.Models +{ + public class AuthResponse + { + public string UserName { get; set; } + public string JwtToken { get; set; } + public int ExpiresIn { get; set; } + } +} diff --git a/JwtAuthManager/Models/UserAccount.cs b/JwtAuthManager/Models/UserAccount.cs new file mode 100644 index 0000000..05ed833 --- /dev/null +++ b/JwtAuthManager/Models/UserAccount.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JwtAuthManager.Models +{ + public class UserAccount + { + public string UserName { get; set; } + public string Password { get; set; } + //public List Role { get; set; } + public string[] Roles { get; set; } + + } +} diff --git a/TestApi1/.config/dotnet-tools.json b/TestApi1/.config/dotnet-tools.json new file mode 100644 index 0000000..b8c6c1f --- /dev/null +++ b/TestApi1/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "dotnet-ef": { + "version": "6.0.9", + "commands": [ + "dotnet-ef" + ] + } + } +} \ No newline at end of file diff --git a/TestApi1/Controllers/WeatherForecastController.cs b/TestApi1/Controllers/WeatherForecastController.cs new file mode 100644 index 0000000..1d47c99 --- /dev/null +++ b/TestApi1/Controllers/WeatherForecastController.cs @@ -0,0 +1,45 @@ +using Microsoft.AspNetCore.Mvc; + +namespace TestApi1.Controllers +{ + [ApiController] + [Route("ApiTest")] + public class WeatherForecastController : ControllerBase + { + private static readonly string[] Summaries = new[] + { + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" + }; + + private readonly ILogger _logger; + + public WeatherForecastController(ILogger logger) + { + _logger = logger; + } + + [HttpGet(Name = "GetWeatherForecast")] + public IEnumerable Get() + { + return Enumerable.Range(1, 5).Select(index => new WeatherForecast + { + Date = DateTime.Now.AddDays(index), + TemperatureC = Random.Shared.Next(-20, 55), + Summary = Summaries[Random.Shared.Next(Summaries.Length)] + }) + .ToArray(); + } + + [HttpPost] + public string post() + { + return "Ingresa al post"; + } + + [HttpDelete("{id}")] + public string delete(int id) + { + return "Elimina: "+ id; + } + } +} \ No newline at end of file diff --git a/TestApi1/Program.cs b/TestApi1/Program.cs new file mode 100644 index 0000000..faa2d9c --- /dev/null +++ b/TestApi1/Program.cs @@ -0,0 +1,25 @@ +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. + +builder.Services.AddControllers(); +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. + app.UseSwagger(); + app.UseSwaggerUI(); +//if (app.Environment.IsDevelopment()) +//{ +//} + +//app.UseHttpsRedirection(); + +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); diff --git a/TestApi1/Properties/launchSettings.json b/TestApi1/Properties/launchSettings.json new file mode 100644 index 0000000..24ceeaf --- /dev/null +++ b/TestApi1/Properties/launchSettings.json @@ -0,0 +1,31 @@ +{ + "profiles": { + "TestApi1": { + "commandName": "Project", + "launchBrowser": false, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7041;http://localhost:5041" + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + }, + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:9982", + "sslPort": 44313 + } + } +} \ No newline at end of file diff --git a/TestApi1/TestApi1.csproj b/TestApi1/TestApi1.csproj new file mode 100644 index 0000000..60bf9ea --- /dev/null +++ b/TestApi1/TestApi1.csproj @@ -0,0 +1,13 @@ + + + + net6.0 + enable + enable + + + + + + + diff --git a/TestApi1/WeatherForecast.cs b/TestApi1/WeatherForecast.cs new file mode 100644 index 0000000..8d1e1b4 --- /dev/null +++ b/TestApi1/WeatherForecast.cs @@ -0,0 +1,13 @@ +namespace TestApi1 +{ + public class WeatherForecast + { + public DateTime Date { get; set; } + + public int TemperatureC { get; set; } + + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); + + public string? Summary { get; set; } + } +} \ No newline at end of file diff --git a/TestApi1/appsettings.Development.json b/TestApi1/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/TestApi1/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/TestApi1/appsettings.json b/TestApi1/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/TestApi1/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/TestApi2/.config/dotnet-tools.json b/TestApi2/.config/dotnet-tools.json new file mode 100644 index 0000000..b8c6c1f --- /dev/null +++ b/TestApi2/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "dotnet-ef": { + "version": "6.0.9", + "commands": [ + "dotnet-ef" + ] + } + } +} \ No newline at end of file diff --git a/TestApi2/Controllers/ContratosController.cs b/TestApi2/Controllers/ContratosController.cs new file mode 100644 index 0000000..5381b2d --- /dev/null +++ b/TestApi2/Controllers/ContratosController.cs @@ -0,0 +1,28 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; + +namespace TestApi2.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class ContratosController : ControllerBase + { + + // Admin: Consulta (1) Crear (0) + // Doctor: Permiso 1, 0 + [HttpGet] + //[Authorize(Roles = "Doctor,admin")] + public string get() + { + return "Get Contratos Admin y user"; + } + + [HttpPost] + //[Authorize(Roles = "Admin")] + public string post() + { + return "POST Contratos Solo ADMIN"; + } + } +} diff --git a/TestApi2/Controllers/WeatherForecastController.cs b/TestApi2/Controllers/WeatherForecastController.cs new file mode 100644 index 0000000..02508c7 --- /dev/null +++ b/TestApi2/Controllers/WeatherForecastController.cs @@ -0,0 +1,45 @@ +using Microsoft.AspNetCore.Mvc; + +namespace TestApi2.Controllers +{ + [ApiController] + [Route("ApiTest")] + public class WeatherForecastController : ControllerBase + { + private static readonly string[] Summaries = new[] + { + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" + }; + + private readonly ILogger _logger; + + public WeatherForecastController(ILogger logger) + { + _logger = logger; + } + + [HttpGet(Name = "GetWeatherForecast")] + public IEnumerable Get() + { + return Enumerable.Range(1, 5).Select(index => new WeatherForecast + { + Date = DateTime.Now.AddDays(index), + TemperatureC = Random.Shared.Next(-20, 55), + Summary = Summaries[Random.Shared.Next(Summaries.Length)] + }) + .ToArray(); + } + + [HttpPost] + public string post() + { + return "Ingresa al post"; + } + + [HttpDelete("{id}")] + public string delete(int id) + { + return "Elimina: " + id; + } + } +} \ No newline at end of file diff --git a/TestApi2/Program.cs b/TestApi2/Program.cs new file mode 100644 index 0000000..6a5f708 --- /dev/null +++ b/TestApi2/Program.cs @@ -0,0 +1,28 @@ +using JwtAuthManager; + +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. + +builder.Services.AddControllers(); +builder.Services.AddCustomJwtAuthentication(); // <========= + +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. + app.UseSwagger(); + app.UseSwaggerUI(); +//if (app.Environment.IsDevelopment()) +//{ +//} + +app.UseAuthentication(); // <========= +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); diff --git a/TestApi2/Properties/launchSettings.json b/TestApi2/Properties/launchSettings.json new file mode 100644 index 0000000..758f3f1 --- /dev/null +++ b/TestApi2/Properties/launchSettings.json @@ -0,0 +1,31 @@ +{ + "profiles": { + "TestApi2": { + "commandName": "Project", + "launchBrowser": false, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5102" + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + }, + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:22994", + "sslPort": 0 + } + } +} \ No newline at end of file diff --git a/TestApi2/TestApi2.csproj b/TestApi2/TestApi2.csproj new file mode 100644 index 0000000..2b222da --- /dev/null +++ b/TestApi2/TestApi2.csproj @@ -0,0 +1,17 @@ + + + + net6.0 + enable + enable + + + + + + + + + + + diff --git a/TestApi2/WeatherForecast.cs b/TestApi2/WeatherForecast.cs new file mode 100644 index 0000000..4cb7e49 --- /dev/null +++ b/TestApi2/WeatherForecast.cs @@ -0,0 +1,13 @@ +namespace TestApi2 +{ + public class WeatherForecast + { + public DateTime Date { get; set; } + + public int TemperatureC { get; set; } + + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); + + public string? Summary { get; set; } + } +} \ No newline at end of file diff --git a/TestApi2/appsettings.Development.json b/TestApi2/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/TestApi2/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/TestApi2/appsettings.json b/TestApi2/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/TestApi2/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/Visual Studio 2022/Visualizers/attribcache140.bin b/Visual Studio 2022/Visualizers/attribcache140.bin new file mode 100644 index 0000000000000000000000000000000000000000..0f575020a076c021fb2a3dcafd621a5d326c6e83 GIT binary patch literal 8152 zcmeGhU60$wkt&kHaFW)s9mjS)%D8FTBp20piR-|~p*VfrvC&sW>F%5`X((!?+Z;tI zOY-g%Rp@hp{*b;D=v!Y3N;NWkT`@< ztEg3-U`&|Vx5+oVUv|Ixyg@DIdhXCK9#bzcZQTzB)Gby>KNyV&ixY$h^!rt_MvQq3 zx2Nr>$Aozx$Nui);zRuHsO7-+14i~868Oxtchq*!x2g3xnReZC;_UYyems0Md_3IU z9Xxtyer&z~8~fuHh1K1FS!9?kve-S*>40oQ_&c#>)P-tbOUg^aSl#J_D24ZoS<@U7 zbzkMrxmpWsTh2&$K1V|3{Twrc8jnpoAZ?SfZ}ybJJ!AIe3?_G+@8&z|jK4$ptB}z%^Jk>%n=dmy&;eeCKE7}iDfy+65F7lfx*A>`4V z0lC_64{{C7xiD=yD4X79x^0kgpRfbV0<-1{C3oE*{+T=2fZ#2$3$$8?3<)ESm2U@0 zq5GzF-nt-cXuFrWLfsK-gpXWQ>3Mjj>aH2L!0R!$elkM@JY6Xd*ILCIwev|4Ax0Y6 zF(l2feRAa#`A1@Npga+>iwiJg8_TEj9jP8-1&sRBqAq}3P5oR@RftVSrVkP5wgJZ; z&5kiBgg`qoN>xnXjIzxOJlouoEZ|iU-|NILuM5-yZxIS5c192Lr1CuD;J&ng&~D5SFP%_l;9hzq(<9e*fB5wHAHQopD)59L zQ=!0stHgvrb>mpmR{vYLk9@W+_MS|JT}H?v6^N?|-aJm1Uv4ie{NewXEFSB*GYVDp zm*tG3ZsSsM>!e*%QBg6o{7i-=W?oWfbnTzN|I=Sy{m=C$*YU!jM5#J_TdcW`uN2-) z-#K(p^!^P0MO}0+$(7U9%rUj6O5sL|I=oQaOi{E6Tq$lEGq{qv3@Zx`2=-Ad6=Jnr zigE$^DWaav)u;G;D$t|67e}wH#+TJ#Mc{Y92jQMzL$UM8(h}+k9r$Os90%s=5uu|q zA16X+g-Rl(AjpsBnl=#HKqPR2Z1(ckhZk$!Udzm0`Dx_eAk7YPe?!V zwO6>Wsf#zoo>l~eGI$$vZLe4gd>^lv;5uD$#dV8Mq1h;Wkbau5ZuW`2itd-I7d(P8 zpVg^zzKT{}CPB*dn&mTMotNAzuEm77Dt|?Ip)5eLgIAaL_0LTqdb;oe;>9I8mlmTjC5lEg>;*pAGK1I?KPzGMLhm^T{G zZ#f_&ke3~y?Ik9nS0xxLh5N=#bD(`CbrlT+zhAEr3h53QF}Vw8O7xpG9Qd}7&1x1q zo3L0o6Eu2KlB{;8-)_P>;aHn;m+?ZT>YB^OUUa{EkUYp?!iV4wIK@~Kh@Xt=6TTzA!7z( z2ge~aS3B+{4&foBirhG{Gs!?2Vqvj z?qSFY0Kp>)iwUKLJRqmVIMkLns7-Pi#U}}aQUeC9JwJLAAB$CGA1dkN(0Y!ocgMh9 zH2NjVEI>j3o(y&gsR5_Wux+_eW5@*5!RtvtKrmN*nBL0Jx;{^+4-PuMK!-+YBrG_| zR%miN8%Bw2T_7=DSK zUP3+gV|_ncSorh+J^zKh9zgYP(@9h)ql}3OA!<}OCPZyBcZ3e`Ooud^bs}?aUXra~ zMy<0ou`xRbLJT5!N&4EDmGG;9$8E@=xq9NVbGXi75rfmQ;aqJqIyTu9=LI-dE98P& zygiN6i;+-qw!y+$5x(m1uP8iDLE2>eRB&LfRvljL!b5P%&VxF9Ao6_z;j|7}6bEhB zqxiuH#Ys#+IHm9z2|fYhD+%*iyu66X*j+R`KFAeg{suJ=pXDbcgyt%L^4nwxiEU(` z@-=pppOTWHp-bURDFuisngc3;IFEafaIV_A48DatlY?iQ1A7EbcK}&GJ6UIE#p7qp ziUp`1|6W+vQHgyRjrDsnXFtlEh5Onznkj!SKQY>!)?w$Mq1Lo|RW}-1xzo~HwXS-s z>Ai!xs&{)8t!3;z+}ktCtwy8Q)VfbO)M`F9v`SUL)zfaZscWsKZnWzM-CC>DFe=qj Z@9?nNfluVkUZdJMDAlVWTkVT#=YRc-#;E`R literal 0 HcmV?d00001 diff --git a/ocelot.json b/ocelot.json new file mode 100644 index 0000000..e69de29