From a636309b5a285d85cfc00410db50a0d91f2f3f80 Mon Sep 17 00:00:00 2001 From: Tyler Wise Date: Sat, 12 Aug 2023 20:46:56 -0400 Subject: [PATCH] Initial Commit from Swagger-Gen --- .swagger-codegen-ignore | 23 + .swagger-codegen/VERSION | 1 + IO.Swagger.sln | 25 + NuGet.Config | 8 + README.md | 25 +- aspnetcore-server-generated.zip | Bin 0 -> 29696 bytes build.bat | 9 + build.sh | 8 + src/IO.Swagger/.gitignore | 208 ++++++++ .../Attributes/ValidateModelStateAttribute.cs | 61 +++ src/IO.Swagger/Controllers/AuthApi.cs | 97 ++++ src/IO.Swagger/Controllers/CurrencyApi.cs | 134 +++++ src/IO.Swagger/Controllers/WalletApi.cs | 103 ++++ src/IO.Swagger/Dockerfile | 19 + src/IO.Swagger/Filters/BasePathFilter.cs | 51 ++ .../GeneratePathParamsValidationFilter.cs | 96 ++++ src/IO.Swagger/IO.Swagger.csproj | 21 + src/IO.Swagger/Models/AuthLoginBody.cs | 135 +++++ src/IO.Swagger/Models/AuthRegisterBody.cs | 167 +++++++ src/IO.Swagger/Models/CurrencyAddAssetBody.cs | 151 ++++++ src/IO.Swagger/Models/CurrencyCreateBody.cs | 137 +++++ .../Models/CurrencyCreateCollectionBody.cs | 120 +++++ src/IO.Swagger/Models/CurrencyMintBody.cs | 135 +++++ .../Models/WalletTransferDigitalBody.cs | 135 +++++ .../Models/WalletTransferPhysicalBody.cs | 150 ++++++ src/IO.Swagger/Program.cs | 29 ++ src/IO.Swagger/Properties/launchSettings.json | 36 ++ .../Security/BearerAuthenticationHandler.cs | 58 +++ src/IO.Swagger/Startup.cs | 146 ++++++ src/IO.Swagger/appsettings.json | 10 + src/IO.Swagger/web.config | 24 + src/IO.Swagger/wwwroot/README.md | 42 ++ src/IO.Swagger/wwwroot/index.html | 1 + src/IO.Swagger/wwwroot/swagger-original.json | 471 ++++++++++++++++++ src/IO.Swagger/wwwroot/web.config | 9 + 35 files changed, 2844 insertions(+), 1 deletion(-) create mode 100644 .swagger-codegen-ignore create mode 100644 .swagger-codegen/VERSION create mode 100644 IO.Swagger.sln create mode 100644 NuGet.Config create mode 100644 aspnetcore-server-generated.zip create mode 100644 build.bat create mode 100644 build.sh create mode 100644 src/IO.Swagger/.gitignore create mode 100644 src/IO.Swagger/Attributes/ValidateModelStateAttribute.cs create mode 100644 src/IO.Swagger/Controllers/AuthApi.cs create mode 100644 src/IO.Swagger/Controllers/CurrencyApi.cs create mode 100644 src/IO.Swagger/Controllers/WalletApi.cs create mode 100644 src/IO.Swagger/Dockerfile create mode 100644 src/IO.Swagger/Filters/BasePathFilter.cs create mode 100644 src/IO.Swagger/Filters/GeneratePathParamsValidationFilter.cs create mode 100644 src/IO.Swagger/IO.Swagger.csproj create mode 100644 src/IO.Swagger/Models/AuthLoginBody.cs create mode 100644 src/IO.Swagger/Models/AuthRegisterBody.cs create mode 100644 src/IO.Swagger/Models/CurrencyAddAssetBody.cs create mode 100644 src/IO.Swagger/Models/CurrencyCreateBody.cs create mode 100644 src/IO.Swagger/Models/CurrencyCreateCollectionBody.cs create mode 100644 src/IO.Swagger/Models/CurrencyMintBody.cs create mode 100644 src/IO.Swagger/Models/WalletTransferDigitalBody.cs create mode 100644 src/IO.Swagger/Models/WalletTransferPhysicalBody.cs create mode 100644 src/IO.Swagger/Program.cs create mode 100644 src/IO.Swagger/Properties/launchSettings.json create mode 100644 src/IO.Swagger/Security/BearerAuthenticationHandler.cs create mode 100644 src/IO.Swagger/Startup.cs create mode 100644 src/IO.Swagger/appsettings.json create mode 100644 src/IO.Swagger/web.config create mode 100644 src/IO.Swagger/wwwroot/README.md create mode 100644 src/IO.Swagger/wwwroot/index.html create mode 100644 src/IO.Swagger/wwwroot/swagger-original.json create mode 100644 src/IO.Swagger/wwwroot/web.config diff --git a/.swagger-codegen-ignore b/.swagger-codegen-ignore new file mode 100644 index 0000000..c5fa491 --- /dev/null +++ b/.swagger-codegen-ignore @@ -0,0 +1,23 @@ +# Swagger Codegen Ignore +# Generated by swagger-codegen https://github.com/swagger-api/swagger-codegen + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell Swagger Codgen to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/.swagger-codegen/VERSION b/.swagger-codegen/VERSION new file mode 100644 index 0000000..1617617 --- /dev/null +++ b/.swagger-codegen/VERSION @@ -0,0 +1 @@ +3.0.46 \ No newline at end of file diff --git a/IO.Swagger.sln b/IO.Swagger.sln new file mode 100644 index 0000000..b815e98 --- /dev/null +++ b/IO.Swagger.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.34003.232 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IO.Swagger", "src\IO.Swagger\IO.Swagger.csproj", "{DE0790AC-036E-402C-BB2D-6FF54543B851}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DE0790AC-036E-402C-BB2D-6FF54543B851}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DE0790AC-036E-402C-BB2D-6FF54543B851}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DE0790AC-036E-402C-BB2D-6FF54543B851}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DE0790AC-036E-402C-BB2D-6FF54543B851}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {C5D6DB47-4B18-4926-A927-0313EB9C300D} + EndGlobalSection +EndGlobal diff --git a/NuGet.Config b/NuGet.Config new file mode 100644 index 0000000..5db080c --- /dev/null +++ b/NuGet.Config @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/README.md b/README.md index 4e75b2b..ecaec9a 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,25 @@ -# bank-backend +# IO.Swagger - ASP.NET Core 2.0 Server +API documentation for T&J Central Bank's digital wallets + +## Run + +Linux/OS X: + +``` +sh build.sh +``` + +Windows: + +``` +build.bat +``` + +## Run in Docker + +``` +cd src/IO.Swagger +docker build -t io.swagger . +docker run -p 5000:5000 io.swagger +``` diff --git a/aspnetcore-server-generated.zip b/aspnetcore-server-generated.zip new file mode 100644 index 0000000000000000000000000000000000000000..56bc5d560c84560203f6c06db442574bdcd81c9c GIT binary patch literal 29696 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 I-u?Ce0E)r`zW@LL literal 0 HcmV?d00001 diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..2e04123 --- /dev/null +++ b/build.bat @@ -0,0 +1,9 @@ +:: Generated by: https://github.com/swagger-api/swagger-codegen.git +:: + +@echo off + +dotnet restore src\IO.Swagger +dotnet build src\IO.Swagger +echo Now, run the following to start the project: dotnet run -p src\IO.Swagger\IO.Swagger.csproj --launch-profile web. +echo. diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..ce6063a --- /dev/null +++ b/build.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +# +# Generated by: https://github.com/swagger-api/swagger-codegen.git +# + +dotnet restore src/IO.Swagger/ && \ + dotnet build src/IO.Swagger/ && \ + echo "Now, run the following to start the project: dotnet run -p src/IO.Swagger/IO.Swagger.csproj --launch-profile web" diff --git a/src/IO.Swagger/.gitignore b/src/IO.Swagger/.gitignore new file mode 100644 index 0000000..cd9b840 --- /dev/null +++ b/src/IO.Swagger/.gitignore @@ -0,0 +1,208 @@ +PID + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Visual Studio 2015 cache/options directory +.vs/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml + +# 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 +# TODO: 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 + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# 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/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +bower_components/ +orleans.codegen.cs + +# 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 + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt diff --git a/src/IO.Swagger/Attributes/ValidateModelStateAttribute.cs b/src/IO.Swagger/Attributes/ValidateModelStateAttribute.cs new file mode 100644 index 0000000..07cfabe --- /dev/null +++ b/src/IO.Swagger/Attributes/ValidateModelStateAttribute.cs @@ -0,0 +1,61 @@ +using System.ComponentModel.DataAnnotations; +using System.Reflection; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Controllers; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.AspNetCore.Mvc.ModelBinding; + +namespace IO.Swagger.Attributes +{ + /// + /// Model state validation attribute + /// + public class ValidateModelStateAttribute : ActionFilterAttribute + { + /// + /// Called before the action method is invoked + /// + /// + public override void OnActionExecuting(ActionExecutingContext context) + { + // Per https://blog.markvincze.com/how-to-validate-action-parameters-with-dataannotation-attributes/ + var descriptor = context.ActionDescriptor as ControllerActionDescriptor; + if (descriptor != null) + { + foreach (var parameter in descriptor.MethodInfo.GetParameters()) + { + object args = null; + if (context.ActionArguments.ContainsKey(parameter.Name)) + { + args = context.ActionArguments[parameter.Name]; + } + + ValidateAttributes(parameter, args, context.ModelState); + } + } + + if (!context.ModelState.IsValid) + { + context.Result = new BadRequestObjectResult(context.ModelState); + } + } + + private void ValidateAttributes(ParameterInfo parameter, object args, ModelStateDictionary modelState) + { + foreach (var attributeData in parameter.CustomAttributes) + { + var attributeInstance = parameter.GetCustomAttribute(attributeData.AttributeType); + + var validationAttribute = attributeInstance as ValidationAttribute; + if (validationAttribute != null) + { + var isValid = validationAttribute.IsValid(args); + if (!isValid) + { + modelState.AddModelError(parameter.Name, validationAttribute.FormatErrorMessage(parameter.Name)); + } + } + } + } + } +} diff --git a/src/IO.Swagger/Controllers/AuthApi.cs b/src/IO.Swagger/Controllers/AuthApi.cs new file mode 100644 index 0000000..d7766cb --- /dev/null +++ b/src/IO.Swagger/Controllers/AuthApi.cs @@ -0,0 +1,97 @@ +/* + * T&J Central Bank API + * + * API documentation for T&J Central Bank's digital wallets + * + * OpenAPI spec version: 1.0.0 + * + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ +using System; +using System.Collections.Generic; +using Microsoft.AspNetCore.Mvc; +using Swashbuckle.AspNetCore.Annotations; +using Swashbuckle.AspNetCore.SwaggerGen; +using Newtonsoft.Json; +using System.ComponentModel.DataAnnotations; +using IO.Swagger.Attributes; +using IO.Swagger.Security; +using Microsoft.AspNetCore.Authorization; +using IO.Swagger.Models; + +namespace IO.Swagger.Controllers +{ + /// + /// + /// + [ApiController] + public class AuthApiController : ControllerBase + { + /// + /// Get user details + /// + /// Successful response + /// Unauthorized + [HttpGet] + [Route("/v1/api/auth/details")] + [Authorize(AuthenticationSchemes = BearerAuthenticationHandler.SchemeName)] + [ValidateModelState] + [SwaggerOperation("GetUserDetails")] + public virtual IActionResult GetUserDetails() + { + //TODO: Uncomment the next line to return response 200 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(200); + + //TODO: Uncomment the next line to return response 401 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(401); + + throw new NotImplementedException(); + } + + /// + /// Log in with email and password + /// + /// + /// Logged in successfully + /// Unauthorized + [HttpPost] + [Route("/v1/api/auth/login")] + [ValidateModelState] + [SwaggerOperation("LoginUser")] + public virtual IActionResult LoginUser([FromBody]AuthLoginBody body) + { + //TODO: Uncomment the next line to return response 200 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(200); + + //TODO: Uncomment the next line to return response 401 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(401); + + throw new NotImplementedException(); + } + + /// + /// Register a new user + /// + /// + /// User registered successfully + /// Bad Request + /// Conflict (user with provided email already exists) + [HttpPost] + [Route("/v1/api/auth/register")] + [ValidateModelState] + [SwaggerOperation("RegisterUser")] + public virtual IActionResult RegisterUser([FromBody]AuthRegisterBody body) + { + //TODO: Uncomment the next line to return response 201 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(201); + + //TODO: Uncomment the next line to return response 400 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(400); + + //TODO: Uncomment the next line to return response 409 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(409); + + throw new NotImplementedException(); + } + } +} diff --git a/src/IO.Swagger/Controllers/CurrencyApi.cs b/src/IO.Swagger/Controllers/CurrencyApi.cs new file mode 100644 index 0000000..1279c00 --- /dev/null +++ b/src/IO.Swagger/Controllers/CurrencyApi.cs @@ -0,0 +1,134 @@ +/* + * T&J Central Bank API + * + * API documentation for T&J Central Bank's digital wallets + * + * OpenAPI spec version: 1.0.0 + * + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ +using System; +using System.Collections.Generic; +using Microsoft.AspNetCore.Mvc; +using Swashbuckle.AspNetCore.Annotations; +using Swashbuckle.AspNetCore.SwaggerGen; +using Newtonsoft.Json; +using System.ComponentModel.DataAnnotations; +using IO.Swagger.Attributes; +using IO.Swagger.Security; +using Microsoft.AspNetCore.Authorization; +using IO.Swagger.Models; + +namespace IO.Swagger.Controllers +{ + /// + /// + /// + [ApiController] + public class CurrencyApiController : ControllerBase + { + /// + /// Add a digital asset to the user's collection + /// + /// + /// Successful asset addition + /// Bad Request + /// Unauthorized + [HttpPost] + [Route("/v1/api/currency/addAsset")] + [Authorize(AuthenticationSchemes = BearerAuthenticationHandler.SchemeName)] + [ValidateModelState] + [SwaggerOperation("AddDigitalAssetToCollection")] + public virtual IActionResult AddDigitalAssetToCollection([FromBody]CurrencyAddAssetBody body) + { + //TODO: Uncomment the next line to return response 201 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(201); + + //TODO: Uncomment the next line to return response 400 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(400); + + //TODO: Uncomment the next line to return response 401 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(401); + + throw new NotImplementedException(); + } + + /// + /// Create a new collection of digital assets owned by the user + /// + /// + /// Successful collection creation + /// Bad Request + /// Unauthorized + [HttpPost] + [Route("/v1/api/currency/createCollection")] + [Authorize(AuthenticationSchemes = BearerAuthenticationHandler.SchemeName)] + [ValidateModelState] + [SwaggerOperation("CreateAssetCollection")] + public virtual IActionResult CreateAssetCollection([FromBody]CurrencyCreateCollectionBody body) + { + //TODO: Uncomment the next line to return response 201 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(201); + + //TODO: Uncomment the next line to return response 400 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(400); + + //TODO: Uncomment the next line to return response 401 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(401); + + throw new NotImplementedException(); + } + + /// + /// Create a new currency type + /// + /// + /// Currency type created successfully + /// Bad Request + /// Unauthorized + [HttpPost] + [Route("/v1/api/currency/create")] + [Authorize(AuthenticationSchemes = BearerAuthenticationHandler.SchemeName)] + [ValidateModelState] + [SwaggerOperation("CreateCurrency")] + public virtual IActionResult CreateCurrency([FromBody]CurrencyCreateBody body) + { + //TODO: Uncomment the next line to return response 201 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(201); + + //TODO: Uncomment the next line to return response 400 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(400); + + //TODO: Uncomment the next line to return response 401 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(401); + + throw new NotImplementedException(); + } + + /// + /// Mint additional units of a currency + /// + /// + /// Successful minting + /// Bad Request + /// Unauthorized + [HttpPost] + [Route("/v1/api/currency/mint")] + [Authorize(AuthenticationSchemes = BearerAuthenticationHandler.SchemeName)] + [ValidateModelState] + [SwaggerOperation("MintCurrency")] + public virtual IActionResult MintCurrency([FromBody]CurrencyMintBody body) + { + //TODO: Uncomment the next line to return response 200 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(200); + + //TODO: Uncomment the next line to return response 400 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(400); + + //TODO: Uncomment the next line to return response 401 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(401); + + throw new NotImplementedException(); + } + } +} diff --git a/src/IO.Swagger/Controllers/WalletApi.cs b/src/IO.Swagger/Controllers/WalletApi.cs new file mode 100644 index 0000000..6c8c07e --- /dev/null +++ b/src/IO.Swagger/Controllers/WalletApi.cs @@ -0,0 +1,103 @@ +/* + * T&J Central Bank API + * + * API documentation for T&J Central Bank's digital wallets + * + * OpenAPI spec version: 1.0.0 + * + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ +using System; +using System.Collections.Generic; +using Microsoft.AspNetCore.Mvc; +using Swashbuckle.AspNetCore.Annotations; +using Swashbuckle.AspNetCore.SwaggerGen; +using Newtonsoft.Json; +using System.ComponentModel.DataAnnotations; +using IO.Swagger.Attributes; +using IO.Swagger.Security; +using Microsoft.AspNetCore.Authorization; +using IO.Swagger.Models; + +namespace IO.Swagger.Controllers +{ + /// + /// + /// + [ApiController] + public class WalletApiController : ControllerBase + { + /// + /// Get user's wallet + /// + /// Successful response + /// Unauthorized + [HttpGet] + [Route("/v1/api/wallet")] + [Authorize(AuthenticationSchemes = BearerAuthenticationHandler.SchemeName)] + [ValidateModelState] + [SwaggerOperation("GetUserWallet")] + public virtual IActionResult GetUserWallet() + { + //TODO: Uncomment the next line to return response 200 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(200); + + //TODO: Uncomment the next line to return response 401 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(401); + + throw new NotImplementedException(); + } + + /// + /// Transfer digital asset to another user + /// + /// + /// Successful transfer + /// Bad Request + /// Unauthorized + [HttpPost] + [Route("/v1/api/wallet/transferDigital")] + [Authorize(AuthenticationSchemes = BearerAuthenticationHandler.SchemeName)] + [ValidateModelState] + [SwaggerOperation("TransferDigitalAsset")] + public virtual IActionResult TransferDigitalAsset([FromBody]WalletTransferDigitalBody body) + { + //TODO: Uncomment the next line to return response 200 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(200); + + //TODO: Uncomment the next line to return response 400 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(400); + + //TODO: Uncomment the next line to return response 401 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(401); + + throw new NotImplementedException(); + } + + /// + /// Transfer physical currency to another user + /// + /// + /// Successful transfer + /// Bad Request + /// Unauthorized + [HttpPost] + [Route("/v1/api/wallet/transferPhysical")] + [Authorize(AuthenticationSchemes = BearerAuthenticationHandler.SchemeName)] + [ValidateModelState] + [SwaggerOperation("TransferPhysicalCurrency")] + public virtual IActionResult TransferPhysicalCurrency([FromBody]WalletTransferPhysicalBody body) + { + //TODO: Uncomment the next line to return response 200 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(200); + + //TODO: Uncomment the next line to return response 400 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(400); + + //TODO: Uncomment the next line to return response 401 or use other options such as return this.NotFound(), return this.BadRequest(..), ... + // return StatusCode(401); + + throw new NotImplementedException(); + } + } +} diff --git a/src/IO.Swagger/Dockerfile b/src/IO.Swagger/Dockerfile new file mode 100644 index 0000000..a22c4e1 --- /dev/null +++ b/src/IO.Swagger/Dockerfile @@ -0,0 +1,19 @@ +FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-env +WORKDIR /app + +ENV DOTNET_CLI_TELEMETRY_OPTOUT 1 + +# copy csproj and restore as distinct layers +COPY *.csproj ./ +RUN dotnet restore + +# copy everything else and build +COPY . ./ +RUN dotnet publish -c Release -o out + +# build runtime image +FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 +WORKDIR /app +COPY --from=build-env /app/out . + +ENTRYPOINT ["dotnet", "IO.Swagger.dll"] diff --git a/src/IO.Swagger/Filters/BasePathFilter.cs b/src/IO.Swagger/Filters/BasePathFilter.cs new file mode 100644 index 0000000..c9d95d6 --- /dev/null +++ b/src/IO.Swagger/Filters/BasePathFilter.cs @@ -0,0 +1,51 @@ +using System.Linq; +using System.Text.RegularExpressions; +using Swashbuckle.AspNetCore.Swagger; +using Swashbuckle.AspNetCore.SwaggerGen; +using Microsoft.OpenApi.Models; + +namespace IO.Swagger.Filters +{ + /// + /// BasePath Document Filter sets BasePath property of Swagger and removes it from the individual URL paths + /// + public class BasePathFilter : IDocumentFilter + { + /// + /// Constructor + /// + /// BasePath to remove from Operations + public BasePathFilter(string basePath) + { + BasePath = basePath; + } + + /// + /// Gets the BasePath of the Swagger Doc + /// + /// The BasePath of the Swagger Doc + public string BasePath { get; } + + /// + /// Apply the filter + /// + /// OpenApiDocument + /// FilterContext + public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) + { + swaggerDoc.Servers.Add(new OpenApiServer() { Url = this.BasePath }); + + var pathsToModify = swaggerDoc.Paths.Where(p => p.Key.StartsWith(this.BasePath)).ToList(); + + foreach (var path in pathsToModify) + { + if (path.Key.StartsWith(this.BasePath)) + { + string newKey = Regex.Replace(path.Key, $"^{this.BasePath}", string.Empty); + swaggerDoc.Paths.Remove(path.Key); + swaggerDoc.Paths.Add(newKey, path.Value); + } + } + } + } +} diff --git a/src/IO.Swagger/Filters/GeneratePathParamsValidationFilter.cs b/src/IO.Swagger/Filters/GeneratePathParamsValidationFilter.cs new file mode 100644 index 0000000..1845e56 --- /dev/null +++ b/src/IO.Swagger/Filters/GeneratePathParamsValidationFilter.cs @@ -0,0 +1,96 @@ +using System.ComponentModel.DataAnnotations; +using System.Linq; +using Microsoft.AspNetCore.Mvc.Controllers; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace IO.Swagger.Filters +{ + /// + /// Path Parameter Validation Rules Filter + /// + public class GeneratePathParamsValidationFilter : IOperationFilter + { + /// + /// Constructor + /// + /// Operation + /// OperationFilterContext + public void Apply(OpenApiOperation operation, OperationFilterContext context) + { + var pars = context.ApiDescription.ParameterDescriptions; + + foreach (var par in pars) + { + var swaggerParam = operation.Parameters.SingleOrDefault(p => p.Name == par.Name); + + var attributes = ((ControllerParameterDescriptor)par.ParameterDescriptor).ParameterInfo.CustomAttributes; + + if (attributes != null && attributes.Count() > 0 && swaggerParam != null) + { + // Required - [Required] + var requiredAttr = attributes.FirstOrDefault(p => p.AttributeType == typeof(RequiredAttribute)); + if (requiredAttr != null) + { + swaggerParam.Required = true; + } + + // Regex Pattern [RegularExpression] + var regexAttr = attributes.FirstOrDefault(p => p.AttributeType == typeof(RegularExpressionAttribute)); + if (regexAttr != null) + { + string regex = (string)regexAttr.ConstructorArguments[0].Value; + if (swaggerParam is OpenApiParameter) + { + ((OpenApiParameter)swaggerParam).Schema.Pattern = regex; + } + } + + // String Length [StringLength] + int? minLenght = null, maxLength = null; + var stringLengthAttr = attributes.FirstOrDefault(p => p.AttributeType == typeof(StringLengthAttribute)); + if (stringLengthAttr != null) + { + if (stringLengthAttr.NamedArguments.Count == 1) + { + minLenght = (int)stringLengthAttr.NamedArguments.Single(p => p.MemberName == "MinimumLength").TypedValue.Value; + } + maxLength = (int)stringLengthAttr.ConstructorArguments[0].Value; + } + + var minLengthAttr = attributes.FirstOrDefault(p => p.AttributeType == typeof(MinLengthAttribute)); + if (minLengthAttr != null) + { + minLenght = (int)minLengthAttr.ConstructorArguments[0].Value; + } + + var maxLengthAttr = attributes.FirstOrDefault(p => p.AttributeType == typeof(MaxLengthAttribute)); + if (maxLengthAttr != null) + { + maxLength = (int)maxLengthAttr.ConstructorArguments[0].Value; + } + + if (swaggerParam is OpenApiParameter) + { + ((OpenApiParameter)swaggerParam).Schema.MinLength = minLenght; + ((OpenApiParameter)swaggerParam).Schema.MaxLength = maxLength; + } + + // Range [Range] + var rangeAttr = attributes.FirstOrDefault(p => p.AttributeType == typeof(RangeAttribute)); + if (rangeAttr != null) + { + int rangeMin = (int)rangeAttr.ConstructorArguments[0].Value; + int rangeMax = (int)rangeAttr.ConstructorArguments[1].Value; + + if (swaggerParam is OpenApiParameter) + { + ((OpenApiParameter)swaggerParam).Schema.Minimum = rangeMin; + ((OpenApiParameter)swaggerParam).Schema.Maximum = rangeMax; + } + } + } + } + } + } +} diff --git a/src/IO.Swagger/IO.Swagger.csproj b/src/IO.Swagger/IO.Swagger.csproj new file mode 100644 index 0000000..77cf8af --- /dev/null +++ b/src/IO.Swagger/IO.Swagger.csproj @@ -0,0 +1,21 @@ + + + IO.Swagger + IO.Swagger + net7.0 + true + true + IO.Swagger + IO.Swagger + + + + + + + + + + + + diff --git a/src/IO.Swagger/Models/AuthLoginBody.cs b/src/IO.Swagger/Models/AuthLoginBody.cs new file mode 100644 index 0000000..f821de0 --- /dev/null +++ b/src/IO.Swagger/Models/AuthLoginBody.cs @@ -0,0 +1,135 @@ +/* + * T&J Central Bank API + * + * API documentation for T&J Central Bank's digital wallets + * + * OpenAPI spec version: 1.0.0 + * + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ +using System; +using System.Linq; +using System.IO; +using System.Text; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel.DataAnnotations; +using System.Runtime.Serialization; +using Newtonsoft.Json; + +namespace IO.Swagger.Models +{ + /// + /// + /// + [DataContract] + public partial class AuthLoginBody : IEquatable + { + /// + /// Gets or Sets Email + /// + + [DataMember(Name="email")] + public string Email { get; set; } + + /// + /// Gets or Sets Password + /// + + [DataMember(Name="password")] + public string Password { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append("class AuthLoginBody {\n"); + sb.Append(" Email: ").Append(Email).Append("\n"); + sb.Append(" Password: ").Append(Password).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public string ToJson() + { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj.GetType() == GetType() && Equals((AuthLoginBody)obj); + } + + /// + /// Returns true if AuthLoginBody instances are equal + /// + /// Instance of AuthLoginBody to be compared + /// Boolean + public bool Equals(AuthLoginBody other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + + return + ( + Email == other.Email || + Email != null && + Email.Equals(other.Email) + ) && + ( + Password == other.Password || + Password != null && + Password.Equals(other.Password) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + var hashCode = 41; + // Suitable nullity checks etc, of course :) + if (Email != null) + hashCode = hashCode * 59 + Email.GetHashCode(); + if (Password != null) + hashCode = hashCode * 59 + Password.GetHashCode(); + return hashCode; + } + } + + #region Operators + #pragma warning disable 1591 + + public static bool operator ==(AuthLoginBody left, AuthLoginBody right) + { + return Equals(left, right); + } + + public static bool operator !=(AuthLoginBody left, AuthLoginBody right) + { + return !Equals(left, right); + } + + #pragma warning restore 1591 + #endregion Operators + } +} diff --git a/src/IO.Swagger/Models/AuthRegisterBody.cs b/src/IO.Swagger/Models/AuthRegisterBody.cs new file mode 100644 index 0000000..1374ecf --- /dev/null +++ b/src/IO.Swagger/Models/AuthRegisterBody.cs @@ -0,0 +1,167 @@ +/* + * T&J Central Bank API + * + * API documentation for T&J Central Bank's digital wallets + * + * OpenAPI spec version: 1.0.0 + * + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ +using System; +using System.Linq; +using System.IO; +using System.Text; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel.DataAnnotations; +using System.Runtime.Serialization; +using Newtonsoft.Json; + +namespace IO.Swagger.Models +{ + /// + /// + /// + [DataContract] + public partial class AuthRegisterBody : IEquatable + { + /// + /// Gets or Sets FirstName + /// + + [StringLength(32, MinimumLength=3)] + [DataMember(Name="firstName")] + public string FirstName { get; set; } + + /// + /// Gets or Sets LastName + /// + + [StringLength(32, MinimumLength=3)] + [DataMember(Name="lastName")] + public string LastName { get; set; } + + /// + /// Gets or Sets Email + /// + + [DataMember(Name="email")] + public string Email { get; set; } + + /// + /// Gets or Sets Password + /// + + [DataMember(Name="password")] + public string Password { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append("class AuthRegisterBody {\n"); + sb.Append(" FirstName: ").Append(FirstName).Append("\n"); + sb.Append(" LastName: ").Append(LastName).Append("\n"); + sb.Append(" Email: ").Append(Email).Append("\n"); + sb.Append(" Password: ").Append(Password).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public string ToJson() + { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj.GetType() == GetType() && Equals((AuthRegisterBody)obj); + } + + /// + /// Returns true if AuthRegisterBody instances are equal + /// + /// Instance of AuthRegisterBody to be compared + /// Boolean + public bool Equals(AuthRegisterBody other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + + return + ( + FirstName == other.FirstName || + FirstName != null && + FirstName.Equals(other.FirstName) + ) && + ( + LastName == other.LastName || + LastName != null && + LastName.Equals(other.LastName) + ) && + ( + Email == other.Email || + Email != null && + Email.Equals(other.Email) + ) && + ( + Password == other.Password || + Password != null && + Password.Equals(other.Password) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + var hashCode = 41; + // Suitable nullity checks etc, of course :) + if (FirstName != null) + hashCode = hashCode * 59 + FirstName.GetHashCode(); + if (LastName != null) + hashCode = hashCode * 59 + LastName.GetHashCode(); + if (Email != null) + hashCode = hashCode * 59 + Email.GetHashCode(); + if (Password != null) + hashCode = hashCode * 59 + Password.GetHashCode(); + return hashCode; + } + } + + #region Operators + #pragma warning disable 1591 + + public static bool operator ==(AuthRegisterBody left, AuthRegisterBody right) + { + return Equals(left, right); + } + + public static bool operator !=(AuthRegisterBody left, AuthRegisterBody right) + { + return !Equals(left, right); + } + + #pragma warning restore 1591 + #endregion Operators + } +} diff --git a/src/IO.Swagger/Models/CurrencyAddAssetBody.cs b/src/IO.Swagger/Models/CurrencyAddAssetBody.cs new file mode 100644 index 0000000..db780c8 --- /dev/null +++ b/src/IO.Swagger/Models/CurrencyAddAssetBody.cs @@ -0,0 +1,151 @@ +/* + * T&J Central Bank API + * + * API documentation for T&J Central Bank's digital wallets + * + * OpenAPI spec version: 1.0.0 + * + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ +using System; +using System.Linq; +using System.IO; +using System.Text; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel.DataAnnotations; +using System.Runtime.Serialization; +using Newtonsoft.Json; + +namespace IO.Swagger.Models +{ + /// + /// + /// + [DataContract] + public partial class CurrencyAddAssetBody : IEquatable + { + /// + /// Gets or Sets CollectionId + /// + + [DataMember(Name="collectionId")] + public int? CollectionId { get; set; } + + /// + /// Gets or Sets AssetName + /// + + [StringLength(32, MinimumLength=1)] + [DataMember(Name="assetName")] + public string AssetName { get; set; } + + /// + /// Gets or Sets AssetLink + /// + [RegularExpression("/^(https?|ftp)://[^\\s/$.?#].[^\\s]*$/")] + [DataMember(Name="assetLink")] + public string AssetLink { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append("class CurrencyAddAssetBody {\n"); + sb.Append(" CollectionId: ").Append(CollectionId).Append("\n"); + sb.Append(" AssetName: ").Append(AssetName).Append("\n"); + sb.Append(" AssetLink: ").Append(AssetLink).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public string ToJson() + { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj.GetType() == GetType() && Equals((CurrencyAddAssetBody)obj); + } + + /// + /// Returns true if CurrencyAddAssetBody instances are equal + /// + /// Instance of CurrencyAddAssetBody to be compared + /// Boolean + public bool Equals(CurrencyAddAssetBody other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + + return + ( + CollectionId == other.CollectionId || + CollectionId != null && + CollectionId.Equals(other.CollectionId) + ) && + ( + AssetName == other.AssetName || + AssetName != null && + AssetName.Equals(other.AssetName) + ) && + ( + AssetLink == other.AssetLink || + AssetLink != null && + AssetLink.Equals(other.AssetLink) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + var hashCode = 41; + // Suitable nullity checks etc, of course :) + if (CollectionId != null) + hashCode = hashCode * 59 + CollectionId.GetHashCode(); + if (AssetName != null) + hashCode = hashCode * 59 + AssetName.GetHashCode(); + if (AssetLink != null) + hashCode = hashCode * 59 + AssetLink.GetHashCode(); + return hashCode; + } + } + + #region Operators + #pragma warning disable 1591 + + public static bool operator ==(CurrencyAddAssetBody left, CurrencyAddAssetBody right) + { + return Equals(left, right); + } + + public static bool operator !=(CurrencyAddAssetBody left, CurrencyAddAssetBody right) + { + return !Equals(left, right); + } + + #pragma warning restore 1591 + #endregion Operators + } +} diff --git a/src/IO.Swagger/Models/CurrencyCreateBody.cs b/src/IO.Swagger/Models/CurrencyCreateBody.cs new file mode 100644 index 0000000..0b506bf --- /dev/null +++ b/src/IO.Swagger/Models/CurrencyCreateBody.cs @@ -0,0 +1,137 @@ +/* + * T&J Central Bank API + * + * API documentation for T&J Central Bank's digital wallets + * + * OpenAPI spec version: 1.0.0 + * + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ +using System; +using System.Linq; +using System.IO; +using System.Text; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel.DataAnnotations; +using System.Runtime.Serialization; +using Newtonsoft.Json; + +namespace IO.Swagger.Models +{ + /// + /// + /// + [DataContract] + public partial class CurrencyCreateBody : IEquatable + { + /// + /// Gets or Sets Name + /// + + [StringLength(32, MinimumLength=1)] + [DataMember(Name="name")] + public string Name { get; set; } + + /// + /// Gets or Sets Symbol + /// + + [StringLength(4, MinimumLength=1)] + [DataMember(Name="symbol")] + public string Symbol { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append("class CurrencyCreateBody {\n"); + sb.Append(" Name: ").Append(Name).Append("\n"); + sb.Append(" Symbol: ").Append(Symbol).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public string ToJson() + { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj.GetType() == GetType() && Equals((CurrencyCreateBody)obj); + } + + /// + /// Returns true if CurrencyCreateBody instances are equal + /// + /// Instance of CurrencyCreateBody to be compared + /// Boolean + public bool Equals(CurrencyCreateBody other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + + return + ( + Name == other.Name || + Name != null && + Name.Equals(other.Name) + ) && + ( + Symbol == other.Symbol || + Symbol != null && + Symbol.Equals(other.Symbol) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + var hashCode = 41; + // Suitable nullity checks etc, of course :) + if (Name != null) + hashCode = hashCode * 59 + Name.GetHashCode(); + if (Symbol != null) + hashCode = hashCode * 59 + Symbol.GetHashCode(); + return hashCode; + } + } + + #region Operators + #pragma warning disable 1591 + + public static bool operator ==(CurrencyCreateBody left, CurrencyCreateBody right) + { + return Equals(left, right); + } + + public static bool operator !=(CurrencyCreateBody left, CurrencyCreateBody right) + { + return !Equals(left, right); + } + + #pragma warning restore 1591 + #endregion Operators + } +} diff --git a/src/IO.Swagger/Models/CurrencyCreateCollectionBody.cs b/src/IO.Swagger/Models/CurrencyCreateCollectionBody.cs new file mode 100644 index 0000000..9d7f8b0 --- /dev/null +++ b/src/IO.Swagger/Models/CurrencyCreateCollectionBody.cs @@ -0,0 +1,120 @@ +/* + * T&J Central Bank API + * + * API documentation for T&J Central Bank's digital wallets + * + * OpenAPI spec version: 1.0.0 + * + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ +using System; +using System.Linq; +using System.IO; +using System.Text; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel.DataAnnotations; +using System.Runtime.Serialization; +using Newtonsoft.Json; + +namespace IO.Swagger.Models +{ + /// + /// + /// + [DataContract] + public partial class CurrencyCreateCollectionBody : IEquatable + { + /// + /// Gets or Sets CollectionName + /// + + [DataMember(Name="collectionName")] + public string CollectionName { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append("class CurrencyCreateCollectionBody {\n"); + sb.Append(" CollectionName: ").Append(CollectionName).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public string ToJson() + { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj.GetType() == GetType() && Equals((CurrencyCreateCollectionBody)obj); + } + + /// + /// Returns true if CurrencyCreateCollectionBody instances are equal + /// + /// Instance of CurrencyCreateCollectionBody to be compared + /// Boolean + public bool Equals(CurrencyCreateCollectionBody other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + + return + ( + CollectionName == other.CollectionName || + CollectionName != null && + CollectionName.Equals(other.CollectionName) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + var hashCode = 41; + // Suitable nullity checks etc, of course :) + if (CollectionName != null) + hashCode = hashCode * 59 + CollectionName.GetHashCode(); + return hashCode; + } + } + + #region Operators + #pragma warning disable 1591 + + public static bool operator ==(CurrencyCreateCollectionBody left, CurrencyCreateCollectionBody right) + { + return Equals(left, right); + } + + public static bool operator !=(CurrencyCreateCollectionBody left, CurrencyCreateCollectionBody right) + { + return !Equals(left, right); + } + + #pragma warning restore 1591 + #endregion Operators + } +} diff --git a/src/IO.Swagger/Models/CurrencyMintBody.cs b/src/IO.Swagger/Models/CurrencyMintBody.cs new file mode 100644 index 0000000..8ff6244 --- /dev/null +++ b/src/IO.Swagger/Models/CurrencyMintBody.cs @@ -0,0 +1,135 @@ +/* + * T&J Central Bank API + * + * API documentation for T&J Central Bank's digital wallets + * + * OpenAPI spec version: 1.0.0 + * + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ +using System; +using System.Linq; +using System.IO; +using System.Text; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel.DataAnnotations; +using System.Runtime.Serialization; +using Newtonsoft.Json; + +namespace IO.Swagger.Models +{ + /// + /// + /// + [DataContract] + public partial class CurrencyMintBody : IEquatable + { + /// + /// Gets or Sets CurrencyId + /// + + [DataMember(Name="currencyId")] + public int? CurrencyId { get; set; } + + /// + /// Gets or Sets Amount + /// + + [DataMember(Name="amount")] + public decimal? Amount { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append("class CurrencyMintBody {\n"); + sb.Append(" CurrencyId: ").Append(CurrencyId).Append("\n"); + sb.Append(" Amount: ").Append(Amount).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public string ToJson() + { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj.GetType() == GetType() && Equals((CurrencyMintBody)obj); + } + + /// + /// Returns true if CurrencyMintBody instances are equal + /// + /// Instance of CurrencyMintBody to be compared + /// Boolean + public bool Equals(CurrencyMintBody other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + + return + ( + CurrencyId == other.CurrencyId || + CurrencyId != null && + CurrencyId.Equals(other.CurrencyId) + ) && + ( + Amount == other.Amount || + Amount != null && + Amount.Equals(other.Amount) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + var hashCode = 41; + // Suitable nullity checks etc, of course :) + if (CurrencyId != null) + hashCode = hashCode * 59 + CurrencyId.GetHashCode(); + if (Amount != null) + hashCode = hashCode * 59 + Amount.GetHashCode(); + return hashCode; + } + } + + #region Operators + #pragma warning disable 1591 + + public static bool operator ==(CurrencyMintBody left, CurrencyMintBody right) + { + return Equals(left, right); + } + + public static bool operator !=(CurrencyMintBody left, CurrencyMintBody right) + { + return !Equals(left, right); + } + + #pragma warning restore 1591 + #endregion Operators + } +} diff --git a/src/IO.Swagger/Models/WalletTransferDigitalBody.cs b/src/IO.Swagger/Models/WalletTransferDigitalBody.cs new file mode 100644 index 0000000..358c7d2 --- /dev/null +++ b/src/IO.Swagger/Models/WalletTransferDigitalBody.cs @@ -0,0 +1,135 @@ +/* + * T&J Central Bank API + * + * API documentation for T&J Central Bank's digital wallets + * + * OpenAPI spec version: 1.0.0 + * + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ +using System; +using System.Linq; +using System.IO; +using System.Text; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel.DataAnnotations; +using System.Runtime.Serialization; +using Newtonsoft.Json; + +namespace IO.Swagger.Models +{ + /// + /// + /// + [DataContract] + public partial class WalletTransferDigitalBody : IEquatable + { + /// + /// Gets or Sets Email + /// + + [DataMember(Name="email")] + public string Email { get; set; } + + /// + /// Gets or Sets AssetId + /// + + [DataMember(Name="assetId")] + public int? AssetId { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append("class WalletTransferDigitalBody {\n"); + sb.Append(" Email: ").Append(Email).Append("\n"); + sb.Append(" AssetId: ").Append(AssetId).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public string ToJson() + { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj.GetType() == GetType() && Equals((WalletTransferDigitalBody)obj); + } + + /// + /// Returns true if WalletTransferDigitalBody instances are equal + /// + /// Instance of WalletTransferDigitalBody to be compared + /// Boolean + public bool Equals(WalletTransferDigitalBody other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + + return + ( + Email == other.Email || + Email != null && + Email.Equals(other.Email) + ) && + ( + AssetId == other.AssetId || + AssetId != null && + AssetId.Equals(other.AssetId) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + var hashCode = 41; + // Suitable nullity checks etc, of course :) + if (Email != null) + hashCode = hashCode * 59 + Email.GetHashCode(); + if (AssetId != null) + hashCode = hashCode * 59 + AssetId.GetHashCode(); + return hashCode; + } + } + + #region Operators + #pragma warning disable 1591 + + public static bool operator ==(WalletTransferDigitalBody left, WalletTransferDigitalBody right) + { + return Equals(left, right); + } + + public static bool operator !=(WalletTransferDigitalBody left, WalletTransferDigitalBody right) + { + return !Equals(left, right); + } + + #pragma warning restore 1591 + #endregion Operators + } +} diff --git a/src/IO.Swagger/Models/WalletTransferPhysicalBody.cs b/src/IO.Swagger/Models/WalletTransferPhysicalBody.cs new file mode 100644 index 0000000..2233bcc --- /dev/null +++ b/src/IO.Swagger/Models/WalletTransferPhysicalBody.cs @@ -0,0 +1,150 @@ +/* + * T&J Central Bank API + * + * API documentation for T&J Central Bank's digital wallets + * + * OpenAPI spec version: 1.0.0 + * + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ +using System; +using System.Linq; +using System.IO; +using System.Text; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel.DataAnnotations; +using System.Runtime.Serialization; +using Newtonsoft.Json; + +namespace IO.Swagger.Models +{ + /// + /// + /// + [DataContract] + public partial class WalletTransferPhysicalBody : IEquatable + { + /// + /// Gets or Sets Email + /// + + [DataMember(Name="email")] + public string Email { get; set; } + + /// + /// Gets or Sets Amount + /// + + [DataMember(Name="amount")] + public decimal? Amount { get; set; } + + /// + /// Gets or Sets CurrencyId + /// + + [DataMember(Name="currencyId")] + public int? CurrencyId { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append("class WalletTransferPhysicalBody {\n"); + sb.Append(" Email: ").Append(Email).Append("\n"); + sb.Append(" Amount: ").Append(Amount).Append("\n"); + sb.Append(" CurrencyId: ").Append(CurrencyId).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public string ToJson() + { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj.GetType() == GetType() && Equals((WalletTransferPhysicalBody)obj); + } + + /// + /// Returns true if WalletTransferPhysicalBody instances are equal + /// + /// Instance of WalletTransferPhysicalBody to be compared + /// Boolean + public bool Equals(WalletTransferPhysicalBody other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + + return + ( + Email == other.Email || + Email != null && + Email.Equals(other.Email) + ) && + ( + Amount == other.Amount || + Amount != null && + Amount.Equals(other.Amount) + ) && + ( + CurrencyId == other.CurrencyId || + CurrencyId != null && + CurrencyId.Equals(other.CurrencyId) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + var hashCode = 41; + // Suitable nullity checks etc, of course :) + if (Email != null) + hashCode = hashCode * 59 + Email.GetHashCode(); + if (Amount != null) + hashCode = hashCode * 59 + Amount.GetHashCode(); + if (CurrencyId != null) + hashCode = hashCode * 59 + CurrencyId.GetHashCode(); + return hashCode; + } + } + + #region Operators + #pragma warning disable 1591 + + public static bool operator ==(WalletTransferPhysicalBody left, WalletTransferPhysicalBody right) + { + return Equals(left, right); + } + + public static bool operator !=(WalletTransferPhysicalBody left, WalletTransferPhysicalBody right) + { + return !Equals(left, right); + } + + #pragma warning restore 1591 + #endregion Operators + } +} diff --git a/src/IO.Swagger/Program.cs b/src/IO.Swagger/Program.cs new file mode 100644 index 0000000..ae409c1 --- /dev/null +++ b/src/IO.Swagger/Program.cs @@ -0,0 +1,29 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore; + +namespace IO.Swagger +{ + /// + /// Program + /// + public class Program + { + /// + /// Main + /// + /// + public static void Main(string[] args) + { + CreateWebHostBuilder(args).Build().Run(); + } + + /// + /// Create the web host builder. + /// + /// + /// IWebHostBuilder + public static IWebHostBuilder CreateWebHostBuilder(string[] args) => + WebHost.CreateDefaultBuilder(args) + .UseStartup(); + } +} diff --git a/src/IO.Swagger/Properties/launchSettings.json b/src/IO.Swagger/Properties/launchSettings.json new file mode 100644 index 0000000..5bb6f82 --- /dev/null +++ b/src/IO.Swagger/Properties/launchSettings.json @@ -0,0 +1,36 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:50352/", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger/", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "web": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:5001;http://localhost:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Docker": { + "commandName": "Docker", + "launchBrowser": true, + "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger", + "publishAllPorts": true, + "useSSL": true + } + } +} \ No newline at end of file diff --git a/src/IO.Swagger/Security/BearerAuthenticationHandler.cs b/src/IO.Swagger/Security/BearerAuthenticationHandler.cs new file mode 100644 index 0000000..15c7ab0 --- /dev/null +++ b/src/IO.Swagger/Security/BearerAuthenticationHandler.cs @@ -0,0 +1,58 @@ +using System; +using System.Net.Http.Headers; +using System.Security.Claims; +using System.Text; +using System.Text.Encodings.Web; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authentication; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace IO.Swagger.Security +{ + /// + /// class to handle bearer authentication. + /// + public class BearerAuthenticationHandler : AuthenticationHandler + { + /// + /// scheme name for authentication handler. + /// + public const string SchemeName = "Bearer"; + + public BearerAuthenticationHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) + { + } + + /// + /// verify that require authorization header exists. + /// + protected override async Task HandleAuthenticateAsync() + { + if (!Request.Headers.ContainsKey("Authorization")) + { + return AuthenticateResult.Fail("Missing Authorization Header"); + } + try + { + var authHeader = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]); + + /// TODO handle token. + } + catch + { + return AuthenticateResult.Fail("Invalid Authorization Header"); + } + + var claims = new[] { + new Claim(ClaimTypes.NameIdentifier, "changeme"), + new Claim(ClaimTypes.Name, "changeme"), + }; + var identity = new ClaimsIdentity(claims, Scheme.Name); + var principal = new ClaimsPrincipal(identity); + var ticket = new AuthenticationTicket(principal, Scheme.Name); + + return AuthenticateResult.Success(ticket); + } + } +} diff --git a/src/IO.Swagger/Startup.cs b/src/IO.Swagger/Startup.cs new file mode 100644 index 0000000..9a497e9 --- /dev/null +++ b/src/IO.Swagger/Startup.cs @@ -0,0 +1,146 @@ +/* + * T&J Central Bank API + * + * API documentation for T&J Central Bank's digital wallets + * + * OpenAPI spec version: 1.0.0 + * + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ +using System; +using System.IO; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.OpenApi.Models; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Serialization; +using Swashbuckle.AspNetCore.Swagger; +using Swashbuckle.AspNetCore.SwaggerGen; +using IO.Swagger.Filters; +using IO.Swagger.Security; + +namespace IO.Swagger +{ + /// + /// Startup + /// + public class Startup + { + private readonly IWebHostEnvironment _hostingEnv; + + private IConfiguration Configuration { get; } + + /// + /// Constructor + /// + /// + /// + public Startup(IWebHostEnvironment env, IConfiguration configuration) + { + _hostingEnv = env; + Configuration = configuration; + } + + /// + /// This method gets called by the runtime. Use this method to add services to the container. + /// + /// + public void ConfigureServices(IServiceCollection services) + { + // Add framework services. + services + .AddMvc(options => + { + options.InputFormatters.RemoveType(); + options.OutputFormatters.RemoveType(); + }) + .AddNewtonsoftJson(opts => + { + opts.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); + opts.SerializerSettings.Converters.Add(new StringEnumConverter(new CamelCaseNamingStrategy())); + }) + .AddXmlSerializerFormatters(); + + services.AddAuthentication(BearerAuthenticationHandler.SchemeName) + .AddScheme(BearerAuthenticationHandler.SchemeName, null); + + + services + .AddSwaggerGen(c => + { + c.SwaggerDoc("1.0.0", new OpenApiInfo + { + Version = "1.0.0", + Title = "T&J Central Bank API", + Description = "T&J Central Bank API (ASP.NET 7.0)", + Contact = new OpenApiContact() + { + Name = "Swagger Codegen Contributors", + Url = new Uri("https://github.com/swagger-api/swagger-codegen"), + Email = "" + }, + // TermsOfService = new Uri("") + }); + c.CustomSchemaIds(type => type.FullName); + c.IncludeXmlComments($"{AppContext.BaseDirectory}{Path.DirectorySeparatorChar}{_hostingEnv.ApplicationName}.xml"); + // Sets the basePath property in the Swagger document generated + c.DocumentFilter("/v1"); + + // Include DataAnnotation attributes on Controller Action parameters as Swagger validation rules (e.g required, pattern, ..) + // Use [ValidateModelState] on Actions to actually validate it in C# as well! + c.OperationFilter(); + }); + } + + /// + /// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + /// + /// + /// + /// + public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) + { + app.UseRouting(); + + //TODO: Uncomment this if you need wwwroot folder + // app.UseStaticFiles(); + + app.UseAuthorization(); + + app.UseSwagger(); + app.UseSwaggerUI(c => + { + //TODO: Either use the SwaggerGen generated Swagger contract (generated from C# classes) + c.SwaggerEndpoint("/swagger/1.0.0/swagger.json", "T&J Central Bank API"); + + //TODO: Or alternatively use the original Swagger contract that's included in the static files + // c.SwaggerEndpoint("/swagger-original.json", "T&J Central Bank API Original"); + }); + + //TODO: Use Https Redirection + // app.UseHttpsRedirection(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + else + { + //TODO: Enable production exception handling (https://docs.microsoft.com/en-us/aspnet/core/fundamentals/error-handling) + app.UseExceptionHandler("/Error"); + + app.UseHsts(); + } + } + } +} diff --git a/src/IO.Swagger/appsettings.json b/src/IO.Swagger/appsettings.json new file mode 100644 index 0000000..c6af7d9 --- /dev/null +++ b/src/IO.Swagger/appsettings.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "IncludeScopes": false, + "LogLevel": { + "Default": "Information", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/src/IO.Swagger/web.config b/src/IO.Swagger/web.config new file mode 100644 index 0000000..2c68e3c --- /dev/null +++ b/src/IO.Swagger/web.config @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/IO.Swagger/wwwroot/README.md b/src/IO.Swagger/wwwroot/README.md new file mode 100644 index 0000000..6a0b784 --- /dev/null +++ b/src/IO.Swagger/wwwroot/README.md @@ -0,0 +1,42 @@ +# Welcome to ASP.NET 5 Preview + +We've made some big updates in this release, so it’s **important** that you spend a few minutes to learn what’s new. + +ASP.NET 5 has been rearchitected to make it **lean** and **composable**. It's fully **open source** and available on [GitHub](http://go.microsoft.com/fwlink/?LinkID=517854). +Your new project automatically takes advantage of modern client-side utilities like [Bower](http://go.microsoft.com/fwlink/?LinkId=518004) and [npm](http://go.microsoft.com/fwlink/?LinkId=518005) (to add client-side libraries) and [Gulp](http://go.microsoft.com/fwlink/?LinkId=518007) (for client-side build and automation tasks). + +We hope you enjoy the new capabilities in ASP.NET 5 and Visual Studio 2015. +The ASP.NET Team + +### You've created a new ASP.NET 5 project. [Learn what's new](http://go.microsoft.com/fwlink/?LinkId=518016) + +### This application consists of: +* Sample pages using ASP.NET MVC 6 +* [Gulp](http://go.microsoft.com/fwlink/?LinkId=518007) and [Bower](http://go.microsoft.com/fwlink/?LinkId=518004) for managing client-side resources +* Theming using [Bootstrap](http://go.microsoft.com/fwlink/?LinkID=398939) + +#### NEW CONCEPTS +* [The 'wwwroot' explained](http://go.microsoft.com/fwlink/?LinkId=518008) +* [Configuration in ASP.NET 5](http://go.microsoft.com/fwlink/?LinkId=518012) +* [Dependency Injection](http://go.microsoft.com/fwlink/?LinkId=518013) +* [Razor TagHelpers](http://go.microsoft.com/fwlink/?LinkId=518014) +* [Manage client packages using Gulp](http://go.microsoft.com/fwlink/?LinkID=517849) +* [Develop on different platforms](http://go.microsoft.com/fwlink/?LinkID=517850) + +#### CUSTOMIZE APP +* [Add Controllers and Views](http://go.microsoft.com/fwlink/?LinkID=398600) +* [Add Data using EntityFramework](http://go.microsoft.com/fwlink/?LinkID=398602) +* [Add Authentication using Identity](http://go.microsoft.com/fwlink/?LinkID=398603) +* [Add real time support using SignalR](http://go.microsoft.com/fwlink/?LinkID=398606) +* [Add Class library](http://go.microsoft.com/fwlink/?LinkID=398604) +* [Add Web APIs with MVC 6](http://go.microsoft.com/fwlink/?LinkId=518009) +* [Add client packages using Bower](http://go.microsoft.com/fwlink/?LinkID=517848) + +#### DEPLOY +* [Run your app locally](http://go.microsoft.com/fwlink/?LinkID=517851) +* [Run your app on ASP.NET Core 5](http://go.microsoft.com/fwlink/?LinkID=517852) +* [Run commands in your 'project.json'](http://go.microsoft.com/fwlink/?LinkID=517853) +* [Publish to Microsoft Azure Web Sites](http://go.microsoft.com/fwlink/?LinkID=398609) +* [Publish to the file system](http://go.microsoft.com/fwlink/?LinkId=518019) + +We would love to hear your [feedback](http://go.microsoft.com/fwlink/?LinkId=518015) diff --git a/src/IO.Swagger/wwwroot/index.html b/src/IO.Swagger/wwwroot/index.html new file mode 100644 index 0000000..cde1f2f --- /dev/null +++ b/src/IO.Swagger/wwwroot/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/IO.Swagger/wwwroot/swagger-original.json b/src/IO.Swagger/wwwroot/swagger-original.json new file mode 100644 index 0000000..9ec6b5c --- /dev/null +++ b/src/IO.Swagger/wwwroot/swagger-original.json @@ -0,0 +1,471 @@ +{ + "openapi" : "3.0.0", + "info" : { + "title" : "T&J Central Bank API", + "description" : "API documentation for T&J Central Bank's digital wallets", + "version" : "1.0.0" + }, + "servers" : [ { + "url" : "https://tjbank.shrukanslab.xyz/v1" + } ], + "tags" : [ { + "name" : "auth", + "description" : "User authentication operations" + }, { + "name" : "wallet", + "description" : "User wallet operations" + }, { + "name" : "currency", + "description" : "Currency and asset operations" + } ], + "paths" : { + "/api/auth/register" : { + "post" : { + "tags" : [ "auth" ], + "summary" : "Register a new user", + "operationId" : "registerUser", + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/auth_register_body" + } + } + }, + "required" : true + }, + "responses" : { + "201" : { + "description" : "User registered successfully", + "content" : { + "application/json" : { + "example" : { + "token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" + } + } + } + }, + "400" : { + "description" : "Bad Request" + }, + "409" : { + "description" : "Conflict (user with provided email already exists)" + } + } + } + }, + "/api/auth/login" : { + "post" : { + "tags" : [ "auth" ], + "summary" : "Log in with email and password", + "operationId" : "loginUser", + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/auth_login_body" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "description" : "Logged in successfully", + "content" : { + "application/json" : { + "example" : { + "token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" + } + } + } + }, + "401" : { + "description" : "Unauthorized" + } + } + } + }, + "/api/auth/details" : { + "get" : { + "tags" : [ "auth" ], + "summary" : "Get user details", + "operationId" : "getUserDetails", + "responses" : { + "200" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "example" : { + "firstName" : "John", + "lastName" : "Doe", + "email" : "user@example.com" + } + } + } + }, + "401" : { + "description" : "Unauthorized" + } + }, + "security" : [ { + "BearerAuth" : [ ] + } ] + } + }, + "/api/wallet" : { + "get" : { + "tags" : [ "wallet" ], + "summary" : "Get user's wallet", + "operationId" : "getUserWallet", + "responses" : { + "200" : { + "description" : "Successful response", + "content" : { + "application/json" : { + "example" : { + "currencies" : [ { + "id" : 1, + "name" : "US Dollar", + "symbol" : "USD", + "amount" : 1500 + } ], + "digitalAssets" : [ { + "id" : 101, + "name" : "Bitcoin", + "link" : "https://example.com/bitcoin" + } ] + } + } + } + }, + "401" : { + "description" : "Unauthorized" + } + }, + "security" : [ { + "BearerAuth" : [ ] + } ] + } + }, + "/api/wallet/transferPhysical" : { + "post" : { + "tags" : [ "wallet" ], + "summary" : "Transfer physical currency to another user", + "operationId" : "transferPhysicalCurrency", + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/wallet_transferPhysical_body" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "description" : "Successful transfer" + }, + "400" : { + "description" : "Bad Request" + }, + "401" : { + "description" : "Unauthorized" + } + }, + "security" : [ { + "BearerAuth" : [ ] + } ] + } + }, + "/api/wallet/transferDigital" : { + "post" : { + "tags" : [ "wallet" ], + "summary" : "Transfer digital asset to another user", + "operationId" : "transferDigitalAsset", + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/wallet_transferDigital_body" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "description" : "Successful transfer" + }, + "400" : { + "description" : "Bad Request" + }, + "401" : { + "description" : "Unauthorized" + } + }, + "security" : [ { + "BearerAuth" : [ ] + } ] + } + }, + "/api/currency/mint" : { + "post" : { + "tags" : [ "currency" ], + "summary" : "Mint additional units of a currency", + "operationId" : "mintCurrency", + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/currency_mint_body" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "description" : "Successful minting" + }, + "400" : { + "description" : "Bad Request" + }, + "401" : { + "description" : "Unauthorized" + } + }, + "security" : [ { + "BearerAuth" : [ ] + } ] + } + }, + "/api/currency/create" : { + "post" : { + "tags" : [ "currency" ], + "summary" : "Create a new currency type", + "operationId" : "createCurrency", + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/currency_create_body" + } + } + }, + "required" : true + }, + "responses" : { + "201" : { + "description" : "Currency type created successfully" + }, + "400" : { + "description" : "Bad Request" + }, + "401" : { + "description" : "Unauthorized" + } + }, + "security" : [ { + "BearerAuth" : [ ] + } ] + } + }, + "/api/currency/createCollection" : { + "post" : { + "tags" : [ "currency" ], + "summary" : "Create a new collection of digital assets owned by the user", + "operationId" : "createAssetCollection", + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/currency_createCollection_body" + } + } + }, + "required" : true + }, + "responses" : { + "201" : { + "description" : "Successful collection creation", + "content" : { + "application/json" : { + "example" : { + "message" : "Digital asset collection created successfully", + "collectionId" : 123 + } + } + } + }, + "400" : { + "description" : "Bad Request" + }, + "401" : { + "description" : "Unauthorized" + } + }, + "security" : [ { + "BearerAuth" : [ ] + } ] + } + }, + "/api/currency/addAsset" : { + "post" : { + "tags" : [ "currency" ], + "summary" : "Add a digital asset to the user's collection", + "operationId" : "addDigitalAssetToCollection", + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/currency_addAsset_body" + } + } + }, + "required" : true + }, + "responses" : { + "201" : { + "description" : "Successful asset addition" + }, + "400" : { + "description" : "Bad Request" + }, + "401" : { + "description" : "Unauthorized" + } + }, + "security" : [ { + "BearerAuth" : [ ] + } ] + } + } + }, + "components" : { + "schemas" : { + "auth_register_body" : { + "type" : "object", + "properties" : { + "firstName" : { + "maxLength" : 32, + "minLength" : 3, + "type" : "string" + }, + "lastName" : { + "maxLength" : 32, + "minLength" : 3, + "type" : "string" + }, + "email" : { + "pattern" : "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", + "type" : "string", + "format" : "email" + }, + "password" : { + "type" : "string" + } + } + }, + "currency_addAsset_body" : { + "type" : "object", + "properties" : { + "collectionId" : { + "type" : "integer" + }, + "assetName" : { + "maxLength" : 32, + "minLength" : 1, + "type" : "string" + }, + "assetLink" : { + "pattern" : "^(https?|ftp):\\/\\/[^\\s/$.?#].[^\\s]*$", + "type" : "string" + } + } + }, + "currency_create_body" : { + "type" : "object", + "properties" : { + "name" : { + "maxLength" : 32, + "minLength" : 1, + "type" : "string" + }, + "symbol" : { + "maxLength" : 4, + "minLength" : 1, + "type" : "string" + } + } + }, + "auth_login_body" : { + "type" : "object", + "properties" : { + "email" : { + "pattern" : "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", + "type" : "string", + "format" : "email" + }, + "password" : { + "type" : "string" + } + } + }, + "currency_mint_body" : { + "type" : "object", + "properties" : { + "currencyId" : { + "type" : "integer" + }, + "amount" : { + "type" : "number" + } + } + }, + "currency_createCollection_body" : { + "type" : "object", + "properties" : { + "collectionName" : { + "type" : "string" + } + } + }, + "wallet_transferPhysical_body" : { + "type" : "object", + "properties" : { + "email" : { + "type" : "string", + "format" : "email" + }, + "amount" : { + "type" : "number" + }, + "currencyId" : { + "type" : "integer" + } + } + }, + "wallet_transferDigital_body" : { + "type" : "object", + "properties" : { + "email" : { + "type" : "string", + "format" : "email" + }, + "assetId" : { + "type" : "integer" + } + } + } + }, + "securitySchemes" : { + "BearerAuth" : { + "type" : "http", + "scheme" : "bearer", + "bearerFormat" : "JWT" + } + } + } +} diff --git a/src/IO.Swagger/wwwroot/web.config b/src/IO.Swagger/wwwroot/web.config new file mode 100644 index 0000000..e70a777 --- /dev/null +++ b/src/IO.Swagger/wwwroot/web.config @@ -0,0 +1,9 @@ + + + + + + + + +