Auth endpoints are now functional

This commit is contained in:
2023-08-13 00:54:23 -04:00
parent a636309b5a
commit fdf286e22f
26 changed files with 705 additions and 159 deletions

View File

@ -17,16 +17,30 @@ using System.ComponentModel.DataAnnotations;
using IO.Swagger.Attributes; using IO.Swagger.Attributes;
using IO.Swagger.Security; using IO.Swagger.Security;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using IO.Swagger.Models; using IO.Swagger.Models.dto;
using IO.Swagger.Repositories;
using System.Threading.Tasks;
using System.Linq;
using IO.Swagger.Services;
using System.Security.Claims;
namespace IO.Swagger.Controllers namespace IO.Swagger.Controllers
{ {
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
[ApiController] [ApiController]
public class AuthApiController : ControllerBase public class AuthApiController : ControllerBase
{ {
private readonly IUserRepository repository;
private readonly JwtService jwt;
public AuthApiController(IUserRepository repository, JwtService jwt)
{
this.repository = repository ?? throw new ArgumentNullException(nameof(repository));
this.jwt = jwt ?? throw new ArgumentNullException(nameof(jwt));
}
/// <summary> /// <summary>
/// Get user details /// Get user details
/// </summary> /// </summary>
@ -37,15 +51,13 @@ namespace IO.Swagger.Controllers
[Authorize(AuthenticationSchemes = BearerAuthenticationHandler.SchemeName)] [Authorize(AuthenticationSchemes = BearerAuthenticationHandler.SchemeName)]
[ValidateModelState] [ValidateModelState]
[SwaggerOperation("GetUserDetails")] [SwaggerOperation("GetUserDetails")]
public virtual IActionResult GetUserDetails() public virtual async Task<IActionResult> GetUserDetails()
{ {
//TODO: Uncomment the next line to return response 200 or use other options such as return this.NotFound(), return this.BadRequest(..), ... var userIdString = HttpContext.User.Claims.First(c => c.Type == ClaimTypes.NameIdentifier).Value;
// return StatusCode(200); if (!int.TryParse(userIdString, out int userId))
return Unauthorized();
//TODO: Uncomment the next line to return response 401 or use other options such as return this.NotFound(), return this.BadRequest(..), ... var user = await repository.RetrieveUser(userId);
// return StatusCode(401); return user == null ? NoContent() : Ok(user);
throw new NotImplementedException();
} }
/// <summary> /// <summary>
@ -58,40 +70,39 @@ namespace IO.Swagger.Controllers
[Route("/v1/api/auth/login")] [Route("/v1/api/auth/login")]
[ValidateModelState] [ValidateModelState]
[SwaggerOperation("LoginUser")] [SwaggerOperation("LoginUser")]
public virtual IActionResult LoginUser([FromBody]AuthLoginBody body) public virtual async Task<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(..), ... if (!ModelState.IsValid)
// return StatusCode(200); {
var errors = ModelState.Values.SelectMany(v => v.Errors.Select(e => e.ErrorMessage));
//TODO: Uncomment the next line to return response 401 or use other options such as return this.NotFound(), return this.BadRequest(..), ... return BadRequest(errors);
// return StatusCode(401); }
var user = await repository.LoginUser(body);
throw new NotImplementedException(); return user == null ? Unauthorized() : Ok(new { token = jwt.GenerateJwt(user.Id) });
} }
/// <summary> /// <summary>
/// Register a new user /// Register a new user
/// </summary> /// </summary>
/// <param name="body"></param> /// <param name="body"></param>
/// <response code="201">User registered successfully</response> /// <response code="200">User registered successfully</response>
/// <response code="400">Bad Request</response> /// <response code="400">Bad Request</response>
/// <response code="409">Conflict (user with provided email already exists)</response> /// <response code="409">Conflict (user with provided email already exists)</response>
[HttpPost] [HttpPost]
[Route("/v1/api/auth/register")] [Route("/v1/api/auth/register")]
[ValidateModelState] [ValidateModelState]
[SwaggerOperation("RegisterUser")] [SwaggerOperation("RegisterUser")]
public virtual IActionResult RegisterUser([FromBody]AuthRegisterBody body) public async Task<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(..), ... if (!ModelState.IsValid)
// return StatusCode(201); {
var errors = ModelState.Values.SelectMany(v => v.Errors.Select(e => e.ErrorMessage));
return BadRequest(errors);
}
//TODO: Uncomment the next line to return response 400 or use other options such as return this.NotFound(), return this.BadRequest(..), ... var user = await repository.RegisterUser(body);
// return StatusCode(400); return user == null ? StatusCode(409) : Ok(new { token = jwt.GenerateJwt(user.Id) });
//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();
} }
} }
} }

View File

@ -17,10 +17,10 @@ using System.ComponentModel.DataAnnotations;
using IO.Swagger.Attributes; using IO.Swagger.Attributes;
using IO.Swagger.Security; using IO.Swagger.Security;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using IO.Swagger.Models; using IO.Swagger.Models.dto;
namespace IO.Swagger.Controllers namespace IO.Swagger.Controllers
{ {
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>

View File

@ -17,10 +17,10 @@ using System.ComponentModel.DataAnnotations;
using IO.Swagger.Attributes; using IO.Swagger.Attributes;
using IO.Swagger.Security; using IO.Swagger.Security;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using IO.Swagger.Models; using IO.Swagger.Models.dto;
namespace IO.Swagger.Controllers namespace IO.Swagger.Controllers
{ {
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>

View File

@ -9,6 +9,12 @@
<PackageId>IO.Swagger</PackageId> <PackageId>IO.Swagger</PackageId>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.10">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.5.1" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="5.5.1" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="5.5.1" /> <PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="5.5.1" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="5.5.1" /> <PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="5.5.1" />

View File

@ -0,0 +1,60 @@
// <auto-generated />
using IO.Swagger.Services;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace IO.Swagger.Migrations
{
[DbContext(typeof(BankDbContext))]
[Migration("20230813022042_Initial creation")]
partial class Initialcreation
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.10")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("IO.Swagger.Models.db.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Email")
.HasColumnType("nvarchar(max)");
b.Property<string>("FirstName")
.HasColumnType("nvarchar(max)");
b.Property<string>("LastName")
.HasColumnType("nvarchar(max)");
b.Property<string>("PasswordHash")
.HasColumnType("nvarchar(max)");
b.Property<string>("Salt")
.HasColumnType("nvarchar(max)");
b.Property<string>("Username")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Users");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,39 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace IO.Swagger.Migrations
{
/// <inheritdoc />
public partial class Initialcreation : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Users",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Email = table.Column<string>(type: "nvarchar(max)", nullable: true),
FirstName = table.Column<string>(type: "nvarchar(max)", nullable: true),
LastName = table.Column<string>(type: "nvarchar(max)", nullable: true),
Username = table.Column<string>(type: "nvarchar(max)", nullable: true),
PasswordHash = table.Column<string>(type: "nvarchar(max)", nullable: true),
Salt = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Users", x => x.Id);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Users");
}
}
}

View File

@ -0,0 +1,59 @@
// <auto-generated />
using IO.Swagger.Services;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace IO.Swagger.Migrations
{
[DbContext(typeof(BankDbContext))]
[Migration("20230813022424_Change user table")]
partial class Changeusertable
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.10")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("IO.Swagger.Models.db.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Email")
.HasColumnType("nvarchar(max)");
b.Property<string>("FirstName")
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("LastName")
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("PasswordHash")
.HasColumnType("nvarchar(max)");
b.Property<string>("Salt")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Users");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,68 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace IO.Swagger.Migrations
{
/// <inheritdoc />
public partial class Changeusertable : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Username",
table: "Users");
migrationBuilder.AlterColumn<string>(
name: "LastName",
table: "Users",
type: "nvarchar(32)",
maxLength: 32,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(max)",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "FirstName",
table: "Users",
type: "nvarchar(32)",
maxLength: 32,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(max)",
oldNullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "LastName",
table: "Users",
type: "nvarchar(max)",
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(32)",
oldMaxLength: 32,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "FirstName",
table: "Users",
type: "nvarchar(max)",
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(32)",
oldMaxLength: 32,
oldNullable: true);
migrationBuilder.AddColumn<string>(
name: "Username",
table: "Users",
type: "nvarchar(max)",
nullable: true);
}
}
}

View File

@ -0,0 +1,56 @@
// <auto-generated />
using IO.Swagger.Services;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace IO.Swagger.Migrations
{
[DbContext(typeof(BankDbContext))]
partial class BankDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.10")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("IO.Swagger.Models.db.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Email")
.HasColumnType("nvarchar(max)");
b.Property<string>("FirstName")
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("LastName")
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("PasswordHash")
.HasColumnType("nvarchar(max)");
b.Property<string>("Salt")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Users");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,17 @@
using System.ComponentModel.DataAnnotations;
namespace IO.Swagger.Models.db
{
public class User
{
public int Id { get; set; }
public string Email { get; set; }
[StringLength(32, MinimumLength = 3)]
public string FirstName { get; set; }
[StringLength(32, MinimumLength = 3)]
public string LastName { get; set; }
public string PasswordHash { get; set; }
public string Salt { get; set; }
}
}

View File

@ -18,26 +18,26 @@ using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace IO.Swagger.Models namespace IO.Swagger.Models.dto
{ {
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
[DataContract] [DataContract]
public partial class AuthLoginBody : IEquatable<AuthLoginBody> public partial class AuthLoginBody : IEquatable<AuthLoginBody>
{ {
/// <summary> /// <summary>
/// Gets or Sets Email /// Gets or Sets Email
/// </summary> /// </summary>
[DataMember(Name="email")] [DataMember(Name = "email")]
public string Email { get; set; } public string Email { get; set; }
/// <summary> /// <summary>
/// Gets or Sets Password /// Gets or Sets Password
/// </summary> /// </summary>
[DataMember(Name="password")] [DataMember(Name = "password")]
public string Password { get; set; } public string Password { get; set; }
/// <summary> /// <summary>
@ -85,12 +85,12 @@ namespace IO.Swagger.Models
if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true; if (ReferenceEquals(this, other)) return true;
return return
( (
Email == other.Email || Email == other.Email ||
Email != null && Email != null &&
Email.Equals(other.Email) Email.Equals(other.Email)
) && ) &&
( (
Password == other.Password || Password == other.Password ||
Password != null && Password != null &&
@ -108,16 +108,16 @@ namespace IO.Swagger.Models
{ {
var hashCode = 41; var hashCode = 41;
// Suitable nullity checks etc, of course :) // Suitable nullity checks etc, of course :)
if (Email != null) if (Email != null)
hashCode = hashCode * 59 + Email.GetHashCode(); hashCode = hashCode * 59 + Email.GetHashCode();
if (Password != null) if (Password != null)
hashCode = hashCode * 59 + Password.GetHashCode(); hashCode = hashCode * 59 + Password.GetHashCode();
return hashCode; return hashCode;
} }
} }
#region Operators #region Operators
#pragma warning disable 1591 #pragma warning disable 1591
public static bool operator ==(AuthLoginBody left, AuthLoginBody right) public static bool operator ==(AuthLoginBody left, AuthLoginBody right)
{ {
@ -129,7 +129,7 @@ namespace IO.Swagger.Models
return !Equals(left, right); return !Equals(left, right);
} }
#pragma warning restore 1591 #pragma warning restore 1591
#endregion Operators #endregion Operators
} }
} }

View File

@ -18,42 +18,48 @@ using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace IO.Swagger.Models namespace IO.Swagger.Models.dto
{ {
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
[DataContract] [DataContract]
public partial class AuthRegisterBody : IEquatable<AuthRegisterBody> public partial class AuthRegisterBody : IEquatable<AuthRegisterBody>
{ {
/// <summary> /// <summary>
/// Gets or Sets FirstName /// Gets or Sets FirstName
/// </summary> /// </summary>
[StringLength(32, MinimumLength=3)] [StringLength(32, MinimumLength = 3)]
[DataMember(Name="firstName")] [DataMember(Name = "firstName")]
[Required]
public string FirstName { get; set; } public string FirstName { get; set; }
/// <summary> /// <summary>
/// Gets or Sets LastName /// Gets or Sets LastName
/// </summary> /// </summary>
[StringLength(32, MinimumLength=3)] [StringLength(32, MinimumLength = 3)]
[DataMember(Name="lastName")] [DataMember(Name = "lastName")]
[Required]
public string LastName { get; set; } public string LastName { get; set; }
/// <summary> /// <summary>
/// Gets or Sets Email /// Gets or Sets Email
/// </summary> /// </summary>
[DataMember(Name="email")] [DataMember(Name = "email")]
[EmailAddress(ErrorMessage = "Invalid email format.")]
[Required]
public string Email { get; set; } public string Email { get; set; }
/// <summary> /// <summary>
/// Gets or Sets Password /// Gets or Sets Password
/// </summary> /// </summary>
[DataMember(Name="password")] [DataMember(Name = "password")]
[StringLength(32, MinimumLength = 8)]
[Required]
public string Password { get; set; } public string Password { get; set; }
/// <summary> /// <summary>
@ -103,22 +109,22 @@ namespace IO.Swagger.Models
if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true; if (ReferenceEquals(this, other)) return true;
return return
( (
FirstName == other.FirstName || FirstName == other.FirstName ||
FirstName != null && FirstName != null &&
FirstName.Equals(other.FirstName) FirstName.Equals(other.FirstName)
) && ) &&
( (
LastName == other.LastName || LastName == other.LastName ||
LastName != null && LastName != null &&
LastName.Equals(other.LastName) LastName.Equals(other.LastName)
) && ) &&
( (
Email == other.Email || Email == other.Email ||
Email != null && Email != null &&
Email.Equals(other.Email) Email.Equals(other.Email)
) && ) &&
( (
Password == other.Password || Password == other.Password ||
Password != null && Password != null &&
@ -136,20 +142,20 @@ namespace IO.Swagger.Models
{ {
var hashCode = 41; var hashCode = 41;
// Suitable nullity checks etc, of course :) // Suitable nullity checks etc, of course :)
if (FirstName != null) if (FirstName != null)
hashCode = hashCode * 59 + FirstName.GetHashCode(); hashCode = hashCode * 59 + FirstName.GetHashCode();
if (LastName != null) if (LastName != null)
hashCode = hashCode * 59 + LastName.GetHashCode(); hashCode = hashCode * 59 + LastName.GetHashCode();
if (Email != null) if (Email != null)
hashCode = hashCode * 59 + Email.GetHashCode(); hashCode = hashCode * 59 + Email.GetHashCode();
if (Password != null) if (Password != null)
hashCode = hashCode * 59 + Password.GetHashCode(); hashCode = hashCode * 59 + Password.GetHashCode();
return hashCode; return hashCode;
} }
} }
#region Operators #region Operators
#pragma warning disable 1591 #pragma warning disable 1591
public static bool operator ==(AuthRegisterBody left, AuthRegisterBody right) public static bool operator ==(AuthRegisterBody left, AuthRegisterBody right)
{ {
@ -161,7 +167,7 @@ namespace IO.Swagger.Models
return !Equals(left, right); return !Equals(left, right);
} }
#pragma warning restore 1591 #pragma warning restore 1591
#endregion Operators #endregion Operators
} }
} }

View File

@ -18,34 +18,34 @@ using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace IO.Swagger.Models namespace IO.Swagger.Models.dto
{ {
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
[DataContract] [DataContract]
public partial class CurrencyAddAssetBody : IEquatable<CurrencyAddAssetBody> public partial class CurrencyAddAssetBody : IEquatable<CurrencyAddAssetBody>
{ {
/// <summary> /// <summary>
/// Gets or Sets CollectionId /// Gets or Sets CollectionId
/// </summary> /// </summary>
[DataMember(Name="collectionId")] [DataMember(Name = "collectionId")]
public int? CollectionId { get; set; } public int? CollectionId { get; set; }
/// <summary> /// <summary>
/// Gets or Sets AssetName /// Gets or Sets AssetName
/// </summary> /// </summary>
[StringLength(32, MinimumLength=1)] [StringLength(32, MinimumLength = 1)]
[DataMember(Name="assetName")] [DataMember(Name = "assetName")]
public string AssetName { get; set; } public string AssetName { get; set; }
/// <summary> /// <summary>
/// Gets or Sets AssetLink /// Gets or Sets AssetLink
/// </summary> /// </summary>
[RegularExpression("/^(https?|ftp)://[^\\s/$.?#].[^\\s]*$/")] [RegularExpression("/^(https?|ftp)://[^\\s/$.?#].[^\\s]*$/")]
[DataMember(Name="assetLink")] [DataMember(Name = "assetLink")]
public string AssetLink { get; set; } public string AssetLink { get; set; }
/// <summary> /// <summary>
@ -94,17 +94,17 @@ namespace IO.Swagger.Models
if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true; if (ReferenceEquals(this, other)) return true;
return return
( (
CollectionId == other.CollectionId || CollectionId == other.CollectionId ||
CollectionId != null && CollectionId != null &&
CollectionId.Equals(other.CollectionId) CollectionId.Equals(other.CollectionId)
) && ) &&
( (
AssetName == other.AssetName || AssetName == other.AssetName ||
AssetName != null && AssetName != null &&
AssetName.Equals(other.AssetName) AssetName.Equals(other.AssetName)
) && ) &&
( (
AssetLink == other.AssetLink || AssetLink == other.AssetLink ||
AssetLink != null && AssetLink != null &&
@ -122,18 +122,18 @@ namespace IO.Swagger.Models
{ {
var hashCode = 41; var hashCode = 41;
// Suitable nullity checks etc, of course :) // Suitable nullity checks etc, of course :)
if (CollectionId != null) if (CollectionId != null)
hashCode = hashCode * 59 + CollectionId.GetHashCode(); hashCode = hashCode * 59 + CollectionId.GetHashCode();
if (AssetName != null) if (AssetName != null)
hashCode = hashCode * 59 + AssetName.GetHashCode(); hashCode = hashCode * 59 + AssetName.GetHashCode();
if (AssetLink != null) if (AssetLink != null)
hashCode = hashCode * 59 + AssetLink.GetHashCode(); hashCode = hashCode * 59 + AssetLink.GetHashCode();
return hashCode; return hashCode;
} }
} }
#region Operators #region Operators
#pragma warning disable 1591 #pragma warning disable 1591
public static bool operator ==(CurrencyAddAssetBody left, CurrencyAddAssetBody right) public static bool operator ==(CurrencyAddAssetBody left, CurrencyAddAssetBody right)
{ {
@ -145,7 +145,7 @@ namespace IO.Swagger.Models
return !Equals(left, right); return !Equals(left, right);
} }
#pragma warning restore 1591 #pragma warning restore 1591
#endregion Operators #endregion Operators
} }
} }

View File

@ -18,28 +18,28 @@ using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace IO.Swagger.Models namespace IO.Swagger.Models.dto
{ {
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
[DataContract] [DataContract]
public partial class CurrencyCreateBody : IEquatable<CurrencyCreateBody> public partial class CurrencyCreateBody : IEquatable<CurrencyCreateBody>
{ {
/// <summary> /// <summary>
/// Gets or Sets Name /// Gets or Sets Name
/// </summary> /// </summary>
[StringLength(32, MinimumLength=1)] [StringLength(32, MinimumLength = 1)]
[DataMember(Name="name")] [DataMember(Name = "name")]
public string Name { get; set; } public string Name { get; set; }
/// <summary> /// <summary>
/// Gets or Sets Symbol /// Gets or Sets Symbol
/// </summary> /// </summary>
[StringLength(4, MinimumLength=1)] [StringLength(4, MinimumLength = 1)]
[DataMember(Name="symbol")] [DataMember(Name = "symbol")]
public string Symbol { get; set; } public string Symbol { get; set; }
/// <summary> /// <summary>
@ -87,12 +87,12 @@ namespace IO.Swagger.Models
if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true; if (ReferenceEquals(this, other)) return true;
return return
( (
Name == other.Name || Name == other.Name ||
Name != null && Name != null &&
Name.Equals(other.Name) Name.Equals(other.Name)
) && ) &&
( (
Symbol == other.Symbol || Symbol == other.Symbol ||
Symbol != null && Symbol != null &&
@ -110,16 +110,16 @@ namespace IO.Swagger.Models
{ {
var hashCode = 41; var hashCode = 41;
// Suitable nullity checks etc, of course :) // Suitable nullity checks etc, of course :)
if (Name != null) if (Name != null)
hashCode = hashCode * 59 + Name.GetHashCode(); hashCode = hashCode * 59 + Name.GetHashCode();
if (Symbol != null) if (Symbol != null)
hashCode = hashCode * 59 + Symbol.GetHashCode(); hashCode = hashCode * 59 + Symbol.GetHashCode();
return hashCode; return hashCode;
} }
} }
#region Operators #region Operators
#pragma warning disable 1591 #pragma warning disable 1591
public static bool operator ==(CurrencyCreateBody left, CurrencyCreateBody right) public static bool operator ==(CurrencyCreateBody left, CurrencyCreateBody right)
{ {
@ -131,7 +131,7 @@ namespace IO.Swagger.Models
return !Equals(left, right); return !Equals(left, right);
} }
#pragma warning restore 1591 #pragma warning restore 1591
#endregion Operators #endregion Operators
} }
} }

View File

@ -18,19 +18,19 @@ using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace IO.Swagger.Models namespace IO.Swagger.Models.dto
{ {
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
[DataContract] [DataContract]
public partial class CurrencyCreateCollectionBody : IEquatable<CurrencyCreateCollectionBody> public partial class CurrencyCreateCollectionBody : IEquatable<CurrencyCreateCollectionBody>
{ {
/// <summary> /// <summary>
/// Gets or Sets CollectionName /// Gets or Sets CollectionName
/// </summary> /// </summary>
[DataMember(Name="collectionName")] [DataMember(Name = "collectionName")]
public string CollectionName { get; set; } public string CollectionName { get; set; }
/// <summary> /// <summary>
@ -77,12 +77,12 @@ namespace IO.Swagger.Models
if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true; if (ReferenceEquals(this, other)) return true;
return return
(
CollectionName == other.CollectionName || CollectionName == other.CollectionName ||
CollectionName != null && CollectionName != null &&
CollectionName.Equals(other.CollectionName) CollectionName.Equals(other.CollectionName)
); ;
} }
/// <summary> /// <summary>
@ -95,14 +95,14 @@ namespace IO.Swagger.Models
{ {
var hashCode = 41; var hashCode = 41;
// Suitable nullity checks etc, of course :) // Suitable nullity checks etc, of course :)
if (CollectionName != null) if (CollectionName != null)
hashCode = hashCode * 59 + CollectionName.GetHashCode(); hashCode = hashCode * 59 + CollectionName.GetHashCode();
return hashCode; return hashCode;
} }
} }
#region Operators #region Operators
#pragma warning disable 1591 #pragma warning disable 1591
public static bool operator ==(CurrencyCreateCollectionBody left, CurrencyCreateCollectionBody right) public static bool operator ==(CurrencyCreateCollectionBody left, CurrencyCreateCollectionBody right)
{ {
@ -114,7 +114,7 @@ namespace IO.Swagger.Models
return !Equals(left, right); return !Equals(left, right);
} }
#pragma warning restore 1591 #pragma warning restore 1591
#endregion Operators #endregion Operators
} }
} }

View File

@ -18,26 +18,26 @@ using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace IO.Swagger.Models namespace IO.Swagger.Models.dto
{ {
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
[DataContract] [DataContract]
public partial class CurrencyMintBody : IEquatable<CurrencyMintBody> public partial class CurrencyMintBody : IEquatable<CurrencyMintBody>
{ {
/// <summary> /// <summary>
/// Gets or Sets CurrencyId /// Gets or Sets CurrencyId
/// </summary> /// </summary>
[DataMember(Name="currencyId")] [DataMember(Name = "currencyId")]
public int? CurrencyId { get; set; } public int? CurrencyId { get; set; }
/// <summary> /// <summary>
/// Gets or Sets Amount /// Gets or Sets Amount
/// </summary> /// </summary>
[DataMember(Name="amount")] [DataMember(Name = "amount")]
public decimal? Amount { get; set; } public decimal? Amount { get; set; }
/// <summary> /// <summary>
@ -85,12 +85,12 @@ namespace IO.Swagger.Models
if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true; if (ReferenceEquals(this, other)) return true;
return return
( (
CurrencyId == other.CurrencyId || CurrencyId == other.CurrencyId ||
CurrencyId != null && CurrencyId != null &&
CurrencyId.Equals(other.CurrencyId) CurrencyId.Equals(other.CurrencyId)
) && ) &&
( (
Amount == other.Amount || Amount == other.Amount ||
Amount != null && Amount != null &&
@ -108,16 +108,16 @@ namespace IO.Swagger.Models
{ {
var hashCode = 41; var hashCode = 41;
// Suitable nullity checks etc, of course :) // Suitable nullity checks etc, of course :)
if (CurrencyId != null) if (CurrencyId != null)
hashCode = hashCode * 59 + CurrencyId.GetHashCode(); hashCode = hashCode * 59 + CurrencyId.GetHashCode();
if (Amount != null) if (Amount != null)
hashCode = hashCode * 59 + Amount.GetHashCode(); hashCode = hashCode * 59 + Amount.GetHashCode();
return hashCode; return hashCode;
} }
} }
#region Operators #region Operators
#pragma warning disable 1591 #pragma warning disable 1591
public static bool operator ==(CurrencyMintBody left, CurrencyMintBody right) public static bool operator ==(CurrencyMintBody left, CurrencyMintBody right)
{ {
@ -129,7 +129,7 @@ namespace IO.Swagger.Models
return !Equals(left, right); return !Equals(left, right);
} }
#pragma warning restore 1591 #pragma warning restore 1591
#endregion Operators #endregion Operators
} }
} }

View File

@ -18,26 +18,26 @@ using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace IO.Swagger.Models namespace IO.Swagger.Models.dto
{ {
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
[DataContract] [DataContract]
public partial class WalletTransferDigitalBody : IEquatable<WalletTransferDigitalBody> public partial class WalletTransferDigitalBody : IEquatable<WalletTransferDigitalBody>
{ {
/// <summary> /// <summary>
/// Gets or Sets Email /// Gets or Sets Email
/// </summary> /// </summary>
[DataMember(Name="email")] [DataMember(Name = "email")]
public string Email { get; set; } public string Email { get; set; }
/// <summary> /// <summary>
/// Gets or Sets AssetId /// Gets or Sets AssetId
/// </summary> /// </summary>
[DataMember(Name="assetId")] [DataMember(Name = "assetId")]
public int? AssetId { get; set; } public int? AssetId { get; set; }
/// <summary> /// <summary>
@ -85,12 +85,12 @@ namespace IO.Swagger.Models
if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true; if (ReferenceEquals(this, other)) return true;
return return
( (
Email == other.Email || Email == other.Email ||
Email != null && Email != null &&
Email.Equals(other.Email) Email.Equals(other.Email)
) && ) &&
( (
AssetId == other.AssetId || AssetId == other.AssetId ||
AssetId != null && AssetId != null &&
@ -108,16 +108,16 @@ namespace IO.Swagger.Models
{ {
var hashCode = 41; var hashCode = 41;
// Suitable nullity checks etc, of course :) // Suitable nullity checks etc, of course :)
if (Email != null) if (Email != null)
hashCode = hashCode * 59 + Email.GetHashCode(); hashCode = hashCode * 59 + Email.GetHashCode();
if (AssetId != null) if (AssetId != null)
hashCode = hashCode * 59 + AssetId.GetHashCode(); hashCode = hashCode * 59 + AssetId.GetHashCode();
return hashCode; return hashCode;
} }
} }
#region Operators #region Operators
#pragma warning disable 1591 #pragma warning disable 1591
public static bool operator ==(WalletTransferDigitalBody left, WalletTransferDigitalBody right) public static bool operator ==(WalletTransferDigitalBody left, WalletTransferDigitalBody right)
{ {
@ -129,7 +129,7 @@ namespace IO.Swagger.Models
return !Equals(left, right); return !Equals(left, right);
} }
#pragma warning restore 1591 #pragma warning restore 1591
#endregion Operators #endregion Operators
} }
} }

View File

@ -18,33 +18,33 @@ using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace IO.Swagger.Models namespace IO.Swagger.Models.dto
{ {
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
[DataContract] [DataContract]
public partial class WalletTransferPhysicalBody : IEquatable<WalletTransferPhysicalBody> public partial class WalletTransferPhysicalBody : IEquatable<WalletTransferPhysicalBody>
{ {
/// <summary> /// <summary>
/// Gets or Sets Email /// Gets or Sets Email
/// </summary> /// </summary>
[DataMember(Name="email")] [DataMember(Name = "email")]
public string Email { get; set; } public string Email { get; set; }
/// <summary> /// <summary>
/// Gets or Sets Amount /// Gets or Sets Amount
/// </summary> /// </summary>
[DataMember(Name="amount")] [DataMember(Name = "amount")]
public decimal? Amount { get; set; } public decimal? Amount { get; set; }
/// <summary> /// <summary>
/// Gets or Sets CurrencyId /// Gets or Sets CurrencyId
/// </summary> /// </summary>
[DataMember(Name="currencyId")] [DataMember(Name = "currencyId")]
public int? CurrencyId { get; set; } public int? CurrencyId { get; set; }
/// <summary> /// <summary>
@ -93,17 +93,17 @@ namespace IO.Swagger.Models
if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true; if (ReferenceEquals(this, other)) return true;
return return
( (
Email == other.Email || Email == other.Email ||
Email != null && Email != null &&
Email.Equals(other.Email) Email.Equals(other.Email)
) && ) &&
( (
Amount == other.Amount || Amount == other.Amount ||
Amount != null && Amount != null &&
Amount.Equals(other.Amount) Amount.Equals(other.Amount)
) && ) &&
( (
CurrencyId == other.CurrencyId || CurrencyId == other.CurrencyId ||
CurrencyId != null && CurrencyId != null &&
@ -121,18 +121,18 @@ namespace IO.Swagger.Models
{ {
var hashCode = 41; var hashCode = 41;
// Suitable nullity checks etc, of course :) // Suitable nullity checks etc, of course :)
if (Email != null) if (Email != null)
hashCode = hashCode * 59 + Email.GetHashCode(); hashCode = hashCode * 59 + Email.GetHashCode();
if (Amount != null) if (Amount != null)
hashCode = hashCode * 59 + Amount.GetHashCode(); hashCode = hashCode * 59 + Amount.GetHashCode();
if (CurrencyId != null) if (CurrencyId != null)
hashCode = hashCode * 59 + CurrencyId.GetHashCode(); hashCode = hashCode * 59 + CurrencyId.GetHashCode();
return hashCode; return hashCode;
} }
} }
#region Operators #region Operators
#pragma warning disable 1591 #pragma warning disable 1591
public static bool operator ==(WalletTransferPhysicalBody left, WalletTransferPhysicalBody right) public static bool operator ==(WalletTransferPhysicalBody left, WalletTransferPhysicalBody right)
{ {
@ -144,7 +144,7 @@ namespace IO.Swagger.Models
return !Equals(left, right); return !Equals(left, right);
} }
#pragma warning restore 1591 #pragma warning restore 1591
#endregion Operators #endregion Operators
} }
} }

View File

@ -1,12 +1,4 @@
{ {
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:50352/",
"sslPort": 0
}
},
"profiles": { "profiles": {
"IIS Express": { "IIS Express": {
"commandName": "IISExpress", "commandName": "IISExpress",
@ -20,10 +12,12 @@
"commandName": "Project", "commandName": "Project",
"launchBrowser": true, "launchBrowser": true,
"launchUrl": "swagger", "launchUrl": "swagger",
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development",
} "DATABASE_CONNECTION_STRING": "Server=localhost\\SQLEXPRESS;Database=BankDb;Trusted_Connection=True;Integrated Security=True;TrustServerCertificate=True",
"JWT_SECRET_KEY": "mysuperduperubereepykeepysecretkey"
},
"applicationUrl": "https://localhost:5001;http://localhost:5000"
}, },
"Docker": { "Docker": {
"commandName": "Docker", "commandName": "Docker",
@ -32,5 +26,13 @@
"publishAllPorts": true, "publishAllPorts": true,
"useSSL": true "useSSL": true
} }
},
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:50352/",
"sslPort": 0
}
} }
} }

View File

@ -0,0 +1,13 @@
using IO.Swagger.Models.db;
using IO.Swagger.Models.dto;
using System.Threading.Tasks;
namespace IO.Swagger.Repositories
{
public interface IUserRepository
{
Task<User> LoginUser(AuthLoginBody request);
Task<User> RegisterUser(AuthRegisterBody request);
Task<User> RetrieveUser(int userId);
}
}

View File

@ -0,0 +1,77 @@
using IO.Swagger.Models.db;
using System.Security.Cryptography;
using System;
using IO.Swagger.Services;
using IO.Swagger.Models.dto;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using System.Linq;
namespace IO.Swagger.Repositories
{
public class UserRepository : IUserRepository
{
private readonly BankDbContext bankDbContext;
public UserRepository(BankDbContext bankDbContext)
{
this.bankDbContext = bankDbContext;
}
public async Task<User> RegisterUser(AuthRegisterBody request)
{
request.Email = request.Email.ToLower();
if (await bankDbContext.Users.CountAsync((User u) => u.Email == request.Email) > 0)
return null;
// Generate a random salt
byte[] saltBytes = new byte[16];
new RNGCryptoServiceProvider().GetBytes(saltBytes);
string salt = Convert.ToBase64String(saltBytes);
// Hash the password along with the salt
string password = request.Password;
string saltedPassword = password + salt;
byte[] passwordBytes = System.Text.Encoding.UTF8.GetBytes(saltedPassword);
byte[] hashedBytes = new SHA256Managed().ComputeHash(passwordBytes);
string hashedPassword = Convert.ToBase64String(hashedBytes);
// Create and insert the user
var newUser = new User
{
PasswordHash = hashedPassword,
Salt = salt,
Email = request.Email,
FirstName = request.FirstName,
LastName = request.LastName
};
await bankDbContext.Users.AddAsync(newUser);
await bankDbContext.SaveChangesAsync();
return newUser;
}
public async Task<User> LoginUser(AuthLoginBody request)
{
request.Email = request.Email.ToLower();
var user = await bankDbContext.Users.FirstOrDefaultAsync(u => u.Email.Equals(request.Email));
if (user == null)
return null;
// Hash the supplied password with the retrieved salt
string password = request.Password;
string saltedPassword = password + user.Salt;
byte[] passwordBytes = System.Text.Encoding.UTF8.GetBytes(saltedPassword);
byte[] hashedBytes = new SHA256Managed().ComputeHash(passwordBytes);
string hashedPassword = Convert.ToBase64String(hashedBytes);
if (hashedPassword != user.PasswordHash)
return null;
return user;
}
public async Task<User> RetrieveUser(int userId)
{
return await bankDbContext.Users.FirstOrDefaultAsync(u => u.Id == userId);
}
}
}

View File

@ -1,4 +1,6 @@
using System; using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Security.Claims; using System.Security.Claims;
using System.Text; using System.Text;
@ -7,6 +9,8 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json.Linq;
namespace IO.Swagger.Security namespace IO.Swagger.Security
{ {
@ -15,6 +19,9 @@ namespace IO.Swagger.Security
/// </summary> /// </summary>
public class BearerAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions> public class BearerAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{ {
private readonly string secretKey;
private readonly byte[] secretBytes;
/// <summary> /// <summary>
/// scheme name for authentication handler. /// scheme name for authentication handler.
/// </summary> /// </summary>
@ -22,6 +29,8 @@ namespace IO.Swagger.Security
public BearerAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) public BearerAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
{ {
secretKey = Environment.GetEnvironmentVariable("JWT_SECRET_KEY");
secretBytes = Encoding.UTF8.GetBytes(secretKey);
} }
/// <summary> /// <summary>
@ -37,22 +46,44 @@ namespace IO.Swagger.Security
{ {
var authHeader = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]); var authHeader = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]);
/// TODO handle token. var tokenHandler = new JwtSecurityTokenHandler();
var validationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(secretBytes),
ValidateIssuer = false,
ValidateAudience = false
};
try
{
var claimsPrincipal = tokenHandler.ValidateToken(authHeader.Parameter, validationParameters, out _);
var userIdClaim = claimsPrincipal.FindFirst(ClaimTypes.NameIdentifier);
if (userIdClaim != null && int.TryParse(userIdClaim.Value, out int userId))
{
var claims = new[]{ new Claim(ClaimTypes.NameIdentifier, userId.ToString()) };
var identity = new ClaimsIdentity(claims, SchemeName);
var principal = new ClaimsPrincipal(identity);
var ticket = new AuthenticationTicket(principal, Scheme.Name);
return AuthenticateResult.Success(ticket);
}
}
catch (Exception)
{
return AuthenticateResult.Fail("Invalid Auth Token");
}
} }
catch catch
{ {
return AuthenticateResult.Fail("Invalid Authorization Header"); return AuthenticateResult.Fail("Invalid Authorization Header");
} }
var claims = new[] { return AuthenticateResult.Fail("Missing Authorization Header");
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);
} }
} }
} }

View File

@ -0,0 +1,17 @@
using IO.Swagger.Models.db;
using Microsoft.EntityFrameworkCore;
namespace IO.Swagger.Services
{
public class BankDbContext : DbContext
{
public BankDbContext(DbContextOptions options) : base(options)
{
}
public DbSet<User> Users { get; set; }
}
}

View File

@ -0,0 +1,46 @@
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using System;
namespace IO.Swagger.Services
{
public class JwtService
{
private readonly string secretKey;
private readonly byte[] secretBytes;
public JwtService()
{
secretKey = Environment.GetEnvironmentVariable("JWT_SECRET_KEY");
secretBytes = Encoding.UTF8.GetBytes(secretKey);
}
public string GenerateJwt(int userId)
{
var claims = new[]
{
new Claim(ClaimTypes.NameIdentifier, userId.ToString())
// You can add more claims as needed
};
var tokenHandler = new JwtSecurityTokenHandler();
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims),
Expires = DateTime.UtcNow.AddHours(1), // Token expiration time
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(secretBytes), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
public int GetUserIdFromJwt(string jwtToken)
{
return -1; // Return -1 if user ID extraction fails
}
}
}

View File

@ -23,6 +23,9 @@ using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen; using Swashbuckle.AspNetCore.SwaggerGen;
using IO.Swagger.Filters; using IO.Swagger.Filters;
using IO.Swagger.Security; using IO.Swagger.Security;
using IO.Swagger.Repositories;
using IO.Swagger.Services;
using Microsoft.EntityFrameworkCore;
namespace IO.Swagger namespace IO.Swagger
{ {
@ -80,9 +83,9 @@ namespace IO.Swagger
Description = "T&J Central Bank API (ASP.NET 7.0)", Description = "T&J Central Bank API (ASP.NET 7.0)",
Contact = new OpenApiContact() Contact = new OpenApiContact()
{ {
Name = "Swagger Codegen Contributors", Name = "Swagger Codegen Contributors",
Url = new Uri("https://github.com/swagger-api/swagger-codegen"), Url = new Uri("https://github.com/swagger-api/swagger-codegen"),
Email = "" Email = ""
}, },
// TermsOfService = new Uri("") // TermsOfService = new Uri("")
}); });
@ -94,7 +97,40 @@ namespace IO.Swagger
// Include DataAnnotation attributes on Controller Action parameters as Swagger validation rules (e.g required, pattern, ..) // 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! // Use [ValidateModelState] on Actions to actually validate it in C# as well!
c.OperationFilter<GeneratePathParamsValidationFilter>(); c.OperationFilter<GeneratePathParamsValidationFilter>();
c.AddSecurityDefinition("bearerAuth", new OpenApiSecurityScheme()
{
In = ParameterLocation.Header,
Description = "Please enter a valid token",
Name = "Authorization",
Type = SecuritySchemeType.Http,
BearerFormat = "JWT",
Scheme = "bearer"
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement()
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type=ReferenceType.SecurityScheme,
Id="bearerAuth"
}
},
new string[]{}
}
});
}); });
string connectionString = Environment.GetEnvironmentVariable("DATABASE_CONNECTION_STRING");
if (string.IsNullOrEmpty(connectionString))
{
throw new Exception("Database connection string not found in environment variable.");
}
services.AddScoped<IUserRepository, UserRepository>();
services.AddDbContext<BankDbContext>(x => x.UseSqlServer(connectionString: connectionString));
services.AddSingleton<JwtService>();
} }
/// <summary> /// <summary>
@ -103,8 +139,10 @@ namespace IO.Swagger
/// <param name="app"></param> /// <param name="app"></param>
/// <param name="env"></param> /// <param name="env"></param>
/// <param name="loggerFactory"></param> /// <param name="loggerFactory"></param>
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) /// <param name="context"></param>
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory, BankDbContext context)
{ {
context.Database.Migrate();
app.UseRouting(); app.UseRouting();
//TODO: Uncomment this if you need wwwroot folder //TODO: Uncomment this if you need wwwroot folder

View File

@ -17,7 +17,7 @@
<environmentVariable name="DOTNET_MODIFIABLE_ASSEMBLIES" value="debug" /> <environmentVariable name="DOTNET_MODIFIABLE_ASSEMBLIES" value="debug" />
<environmentVariable name="ASPNETCORE_AUTO_RELOAD_WS_KEY" value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuvpSuAatIokMxzmPdM4egZimjWBPCukyvXO2w3GLeYU+aRSYH/KiZnBvy6785t/Fr2/Y4gF665nvaEMM1uveLOQvwRuICcL/R5mbYwKtKd/VJ4NYamzS5Zd4Fms/9eRf4IHGFu+SjX2Q/MTqVJa7a7w1hLAKoBDGbqJ2V0i7w87qj08XTcBdLRs5gL0je9EJ1QeggFzcY6SVCp+a9MFpybM57WI82h9uysW9rC9H9n0Nelc2D9+2HUbBExHQVTVXKlQ2KWHbxhBKsHzf4k4bBjy6V31e9G/dnWCciXNBQiIPidCp4Nt3AF+bpq080+aRFzIIh5wK1tupyG1BsffFHQIDAQAB" /> <environmentVariable name="ASPNETCORE_AUTO_RELOAD_WS_KEY" value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuvpSuAatIokMxzmPdM4egZimjWBPCukyvXO2w3GLeYU+aRSYH/KiZnBvy6785t/Fr2/Y4gF665nvaEMM1uveLOQvwRuICcL/R5mbYwKtKd/VJ4NYamzS5Zd4Fms/9eRf4IHGFu+SjX2Q/MTqVJa7a7w1hLAKoBDGbqJ2V0i7w87qj08XTcBdLRs5gL0je9EJ1QeggFzcY6SVCp+a9MFpybM57WI82h9uysW9rC9H9n0Nelc2D9+2HUbBExHQVTVXKlQ2KWHbxhBKsHzf4k4bBjy6V31e9G/dnWCciXNBQiIPidCp4Nt3AF+bpq080+aRFzIIh5wK1tupyG1BsffFHQIDAQAB" />
<environmentVariable name="ASPNETCORE_AUTO_RELOAD_VDIR" value="/" /> <environmentVariable name="ASPNETCORE_AUTO_RELOAD_VDIR" value="/" />
<environmentVariable name="DOTNET_HOTRELOAD_NAMEDPIPE_NAME" value="89813085-9fe3-4177-915d-b2a8e67e66aa" /> <environmentVariable name="DOTNET_HOTRELOAD_NAMEDPIPE_NAME" value="43e4d2da-7f6d-4426-a3ad-e156f95d80c9" />
</environmentVariables> </environmentVariables>
</aspNetCore> </aspNetCore>
</system.webServer> </system.webServer>