diff --git a/BlueWest.Api/Context/ApplicationUserDbContext.cs b/BlueWest.Api/Context/ApplicationUserDbContext.cs index 7d4a80c..74f98b9 100644 --- a/BlueWest.Api/Context/ApplicationUserDbContext.cs +++ b/BlueWest.Api/Context/ApplicationUserDbContext.cs @@ -22,21 +22,26 @@ namespace BlueWest.WebApi.Context ApplicationUserToken> { /// - [EfGetMany(typeof(ApplicationUserClaim))] + [EfGetMany(typeof(ApplicationUserClaimUnique))] public sealed override DbSet UserClaims { get; set; } - [EfGetMany(typeof(ApplicationUserRole))] + [EfGetMany(typeof(ApplicationUserRoleUnique))] /// public sealed override DbSet UserRoles { get; set; } - [EfGetMany(typeof(ApplicationRole))] + [EfGetMany(typeof(ApplicationRoleUnique))] /// public sealed override DbSet Roles { get; set; } - [EfGetMany(typeof(ApplicationRoleClaim))] + [EfGetMany(typeof(ApplicationRoleClaimUnique))] /// public sealed override DbSet RoleClaims { get; set; } - + + [EfGetMany(typeof(ApplicationUserUnique))] + [EfUpdateMethods( updateType: typeof(ApplicationUserUnique), returnType: typeof(ApplicationUserUnique), keyPropertyMemberName: nameof(ApplicationUserUnique.Id))] + public sealed override DbSet Users { get; set; } + + #region Initialization /// public ApplicationUserDbContext(DbContextOptions options) : base(options) @@ -76,6 +81,11 @@ namespace BlueWest.WebApi.Context b.HasMany().WithOne().HasForeignKey(rc => rc.RoleId).IsRequired(); }); + builder.Entity().HasOne(x => x.ApplicationRole); + builder.Entity().HasOne(x => x.ApplicationRole); + builder.Entity().HasOne(x => x.ApplicationUser); + + builder.Entity(b => { b.HasKey(rc => rc.Id); @@ -98,5 +108,9 @@ namespace BlueWest.WebApi.Context builder.ConfigureCurrentDbModel(); } + + #endregion + /// + } } \ No newline at end of file diff --git a/BlueWest.Api/Controllers/ApplicationUserController.cs b/BlueWest.Api/Controllers/ApplicationUserController.cs index d3b1d9d..0375d38 100644 --- a/BlueWest.Api/Controllers/ApplicationUserController.cs +++ b/BlueWest.Api/Controllers/ApplicationUserController.cs @@ -1,26 +1,131 @@ +using BlueWest.Data; using BlueWest.WebApi.Context; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; namespace BlueWest.WebApi.Controllers { [ApiController] - [Route("[controller]")] + [Route("application/users")] [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] - [Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)] + [Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)] + [EnableCors(Constants.CorsPolicyName)] + public class ApplicationUserController : ControllerBase { - private readonly ApplicationUserDbContext _context; + private readonly ApplicationUserDbContext _dbContext; public ApplicationUserController(ApplicationUserDbContext context) { - _context = context; + _dbContext = context; } + #region Users + + /// + /// Get Application users + /// + /// + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [HttpGet] + public ActionResult GetApplicationUsers( + int skip = 0, + int take = 50, + int orderDir = 1) + { + + var (success, users) = _dbContext.GetUsers( skip, take, orderDir); + if (!success) return new NotFoundResult(); + return Ok(users); + } + + + /// + /// Updates a User + /// + /// The UserId ISO 3166 code + /// User payload data + /// + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [HttpPut("{UserCode}")] + public ActionResult UpdateApplicationUser(int UserCode, UserUnique UserToUpdate) + { + //var (success, User) = _dbContext.UpdateUser(UserToUpdate, UserCode); + + /* + if (success) + { + return Ok(User); + } + */ + + return new NotFoundResult(); + } + + + #endregion + + + /* + #region GetUserById + + /// + /// Get User by Id + /// + /// ISO 3166-1 UserId numeric code + /// + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [HttpGet("{UserId}", Name = nameof(GetUserById))] + public ActionResult GetUserById(int UserId) + { + var (success, User) = _dbContext.GetOneUserById(UserId); + + if (success) + { + return Ok(User); + } + + return new NotFoundResult(); + } + + #endregion + */ + + #region Roles + + /// + /// Get Application users + /// + /// + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [HttpGet("roles")] + public ActionResult GetApplicationRoles( + int skip = 0, + int take = 50, + int orderDir = 1) + { + + var (success, users) = _dbContext.GetRoles( skip, take, orderDir); + if (!success) return new NotFoundResult(); + return Ok(users); + } + + #endregion + } } +public static class Constants +{ + public const string CorsPolicyName = "_myAllowSpecificOrigins"; +} + diff --git a/BlueWest.Api/Controllers/AuthController.cs b/BlueWest.Api/Controllers/AuthController.cs index 10c5276..14ba787 100644 --- a/BlueWest.Api/Controllers/AuthController.cs +++ b/BlueWest.Api/Controllers/AuthController.cs @@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; @@ -17,7 +18,8 @@ namespace BlueWest.WebApi.Controllers; [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] [Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)] [ApiController] - public class AuthController : Controller +[EnableCors(Constants.CorsPolicyName)] +public class AuthController : Controller { private readonly IAuthManager _authManager; private readonly IUserManager _userManager; @@ -85,11 +87,11 @@ namespace BlueWest.WebApi.Controllers; var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme); identity.AddClaim(new Claim(ClaimTypes.Email, user.Email)); await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity)); - return Json(true); + return Ok(new {authenticated = true}); } } - return Json(false); + return Ok(new {authenticated = false}); } /// diff --git a/BlueWest.Api/Controllers/CountryController.cs b/BlueWest.Api/Controllers/CountryController.cs index 7a61d99..273cdfd 100644 --- a/BlueWest.Api/Controllers/CountryController.cs +++ b/BlueWest.Api/Controllers/CountryController.cs @@ -7,6 +7,7 @@ using BlueWest.WebApi.EF; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -19,7 +20,8 @@ namespace BlueWest.WebApi.Controllers [Route("[controller]")] [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] [Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)] - [Authorize(Roles = "Administrator")] + [EnableCors(Constants.CorsPolicyName)] + // [Authorize(Roles = "Administrator")] public class CountryController : ControllerBase { diff --git a/BlueWest.Api/Controllers/CurrencyController.cs b/BlueWest.Api/Controllers/CurrencyController.cs index 8484ec8..9c5b5e1 100644 --- a/BlueWest.Api/Controllers/CurrencyController.cs +++ b/BlueWest.Api/Controllers/CurrencyController.cs @@ -18,7 +18,7 @@ namespace BlueWest.WebApi.Controllers [Route("[controller]")] [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] [Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)] - [Authorize(Roles = "Administrator")] + // [Authorize(Roles = "Administrator")] public partial class CurrencyController : ControllerBase { diff --git a/BlueWest.Api/Startup.cs b/BlueWest.Api/Startup.cs index 93808cf..d8b118a 100644 --- a/BlueWest.Api/Startup.cs +++ b/BlueWest.Api/Startup.cs @@ -24,7 +24,7 @@ namespace BlueWest.WebApi { private readonly IConfiguration _configuration; private readonly IWebHostEnvironment _environment; - private readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins"; + private readonly string MyAllowSpecificOrigins = Constants.CorsPolicyName; /// /// Startup configuration of the API @@ -47,8 +47,10 @@ namespace BlueWest.WebApi options.AddPolicy(name: MyAllowSpecificOrigins, builder => { - builder.WithOrigins("http://127.0.0.1:5173", "localhost:5173", "127.0.0.1:5173") - .AllowAnyHeader().AllowAnyMethod(); + builder.WithOrigins("http://127.0.0.1:5173", "http://localhost:5173", "http://127.0.0.1:5173") + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials(); }); }); diff --git a/BlueWest.Api/StartupExtensions.cs b/BlueWest.Api/StartupExtensions.cs index 85f9247..c4ad530 100644 --- a/BlueWest.Api/StartupExtensions.cs +++ b/BlueWest.Api/StartupExtensions.cs @@ -170,7 +170,7 @@ namespace BlueWest.WebApi }) .AddCookie(options => { - options.LoginPath = "/api/auth/login"; + options.LoginPath = "/api/auth/logincookie"; options.LogoutPath = "/api/auth/logout"; }) .AddJwtBearer(configureOptions => @@ -198,8 +198,9 @@ namespace BlueWest.WebApi services.AddAuthorization(options => { options.AddPolicy("ApiUser", - policy => policy.RequireClaim(Constants.JwtClaimIdentifiers.Rol, - Constants.JwtClaims.ApiAccess)); + policy => policy.RequireClaim(Context.Users.Constants.JwtClaimIdentifiers.Rol, + Context.Users.Constants.JwtClaims.ApiAccess)); + }); // add identity diff --git a/BlueWest.Data.Capital/Application/ApplicationRole/ApplicationRole.cs b/BlueWest.Data.Capital/Application/ApplicationRole/ApplicationRole.cs index 01a1f29..5fb9d6b 100644 --- a/BlueWest.Data.Capital/Application/ApplicationRole/ApplicationRole.cs +++ b/BlueWest.Data.Capital/Application/ApplicationRole/ApplicationRole.cs @@ -1,9 +1,12 @@ +using MapTo; using Microsoft.AspNetCore.Identity; namespace BlueWest.WebApi.Context.Users { /// - public class ApplicationRole : IdentityRole + [MapFrom(typeof(ApplicationRoleUnique))] + + public partial class ApplicationRole : IdentityRole { /// public sealed override string Id { get; set; } @@ -14,12 +17,6 @@ namespace BlueWest.WebApi.Context.Users /// public sealed override string NormalizedName { get; set; } - public ApplicationRole(ApplicationRole applicationRole) - { - Id = applicationRole.Id; - Name = applicationRole.Name; - NormalizedName = applicationRole.NormalizedName; - } } } diff --git a/BlueWest.Data.Capital/Application/ApplicationRole/ApplicationRoleUnique.cs b/BlueWest.Data.Capital/Application/ApplicationRole/ApplicationRoleUnique.cs new file mode 100644 index 0000000..1a23f0c --- /dev/null +++ b/BlueWest.Data.Capital/Application/ApplicationRole/ApplicationRoleUnique.cs @@ -0,0 +1,13 @@ +using MapTo; + +namespace BlueWest.WebApi.Context.Users +{ + [MapFrom(typeof(ApplicationRole))] + public partial class ApplicationRoleUnique + { + public string Id { get; set; } + public string Name { get; set; } + public string NormalizedName { get; set; } + } +} + diff --git a/BlueWest.Data.Capital/Application/ApplicationRoleClaim/ApplicationRoleClaim.cs b/BlueWest.Data.Capital/Application/ApplicationRoleClaim/ApplicationRoleClaim.cs index 70440b9..be3b387 100644 --- a/BlueWest.Data.Capital/Application/ApplicationRoleClaim/ApplicationRoleClaim.cs +++ b/BlueWest.Data.Capital/Application/ApplicationRoleClaim/ApplicationRoleClaim.cs @@ -1,33 +1,28 @@ using System; using Microsoft.AspNetCore.Identity; +using MapTo; -namespace BlueWest.WebApi.Context.Users; - -/// -public class ApplicationRoleClaim : IdentityRoleClaim +namespace BlueWest.WebApi.Context.Users { - - public sealed override int Id { get; set; } - - #region ApplicationRole - public sealed override string RoleId { get; set; } - public ApplicationRole ApplicationRole { get; set; } - - #endregion - - public sealed override string ClaimType { get; set; } - - public sealed override string ClaimValue { get; set; } - - public ApplicationRoleClaim() { } - - public ApplicationRoleClaim(ApplicationRoleClaim applicationRoleClaim) - { - Id = applicationRoleClaim.Id; - RoleId = applicationRoleClaim.RoleId; - ApplicationRole = applicationRoleClaim.ApplicationRole; - ClaimType = applicationRoleClaim.ClaimType; - ClaimValue = applicationRoleClaim.ClaimValue; - } -} \ No newline at end of file + /// + [MapFrom(typeof(ApplicationRoleClaimUnique))] + + public partial class ApplicationRoleClaim : IdentityRoleClaim + { + + public sealed override int Id { get; set; } + + #region ApplicationRole + public sealed override string RoleId { get; set; } + + public ApplicationRole ApplicationRole { get; set; } + + #endregion + + public sealed override string ClaimType { get; set; } + + public sealed override string ClaimValue { get; set; } + + } +} diff --git a/BlueWest.Data.Capital/Application/ApplicationRoleClaim/ApplicationRoleClaimUnique.cs b/BlueWest.Data.Capital/Application/ApplicationRoleClaim/ApplicationRoleClaimUnique.cs new file mode 100644 index 0000000..079ba9b --- /dev/null +++ b/BlueWest.Data.Capital/Application/ApplicationRoleClaim/ApplicationRoleClaimUnique.cs @@ -0,0 +1,14 @@ +using MapTo; + +namespace BlueWest.WebApi.Context.Users +{ + [MapFrom(typeof(ApplicationRoleClaim))] + public partial class ApplicationRoleClaimUnique + { + public int Id { get; set; } + public string RoleId { get; set; } + public string ClaimType { get; set; } + public string ClaimValue { get; set; } + } +} + diff --git a/BlueWest.Data.Capital/ApplicationUser.cs b/BlueWest.Data.Capital/Application/ApplicationUser/ApplicationUser.cs similarity index 85% rename from BlueWest.Data.Capital/ApplicationUser.cs rename to BlueWest.Data.Capital/Application/ApplicationUser/ApplicationUser.cs index fb791bb..dabd0a9 100644 --- a/BlueWest.Data.Capital/ApplicationUser.cs +++ b/BlueWest.Data.Capital/Application/ApplicationUser/ApplicationUser.cs @@ -3,38 +3,32 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using BlueWest.Data; +using MapTo; using Microsoft.AspNetCore.Identity; -namespace BlueWest.WebApi.Context.Users; - -/// -/// Application User in the Identity System. -/// -public class ApplicationUser : IdentityUser +namespace BlueWest.WebApi.Context.Users { - + /// + /// Application User in the Identity System. + /// + [MapFrom(typeof(ApplicationUserUnique))] + [UseUpdate] + public partial class ApplicationUser : IdentityUser + { /// /// Gets or sets the primary key for this user. /// -[DatabaseGenerated(DatabaseGeneratedOption.Identity)] -[PersonalData] + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + [PersonalData] public new string Id { get; set; } public List Users { get; set; } - /// - /// Gets or sets the user name for this user. - /// + [ProtectedPersonalData] public override string UserName { get; set; } - /// - /// Gets or sets the normalized user name for this user. - /// public override string NormalizedUserName { get; set; } - /// - /// Gets or sets the email address for this user. - /// [ProtectedPersonalData] public override string Email { get; set; } @@ -103,5 +97,5 @@ public class ApplicationUser : IdentityUser /// Gets or sets the number of failed login attempts for the current user. /// public override int AccessFailedCount { get; set; } - + } } \ No newline at end of file diff --git a/BlueWest.Data.Capital/Application/ApplicationUser/ApplicationUserUnique.cs b/BlueWest.Data.Capital/Application/ApplicationUser/ApplicationUserUnique.cs new file mode 100644 index 0000000..02094dc --- /dev/null +++ b/BlueWest.Data.Capital/Application/ApplicationUser/ApplicationUserUnique.cs @@ -0,0 +1,25 @@ +using System; +using MapTo; + +namespace BlueWest.WebApi.Context.Users +{ + [MapFrom(typeof(ApplicationUser))] + public partial class ApplicationUserUnique + { + public string Id { get; set; } + public string UserName { get; set; } + public string NormalizedUserName { get; set; } + public string Email { get; set; } + public string NormalizedEmail { get; set; } + public bool EmailConfirmed { get; set; } + public string PasswordHash { get; set; } + public string SecurityStamp { get; set; } + public string PhoneNumber { get; set; } + public bool PhoneNumberConfirmed { get; set; } + public bool TwoFactorEnabled { get; set; } + public DateTimeOffset? LockoutEnd { get; set; } + public bool LockoutEnabled { get; set; } + public int AccessFailedCount { get; set; } + public string ConcurrencyStamp { get; set; } + } +} \ No newline at end of file diff --git a/BlueWest.Data.Capital/Application/ApplicationUserClaim/ApplicationUserClaim.cs b/BlueWest.Data.Capital/Application/ApplicationUserClaim/ApplicationUserClaim.cs index 556760c..9d2b3c8 100644 --- a/BlueWest.Data.Capital/Application/ApplicationUserClaim/ApplicationUserClaim.cs +++ b/BlueWest.Data.Capital/Application/ApplicationUserClaim/ApplicationUserClaim.cs @@ -1,40 +1,32 @@ using Microsoft.AspNetCore.Identity; +using MapTo; -namespace BlueWest.WebApi.Context.Users; - -/// -public class ApplicationUserClaim : IdentityUserClaim +namespace BlueWest.WebApi.Context.Users { - /// - public sealed override int Id { get; set; } - - #region User - /// - public sealed override string UserId { get; set; } - - /// - /// Application User entity - /// - public ApplicationUser ApplicationUser { get; set; } - - #endregion - - /// - public sealed override string ClaimType { get; set; } + [MapFrom(typeof(ApplicationUserClaimUnique))] /// - public sealed override string ClaimValue { get; set; } - - public ApplicationUserClaim(ApplicationUserClaim applicationUserClaim) + public partial class ApplicationUserClaim : IdentityUserClaim { - Id = applicationUserClaim.Id; - UserId = applicationUserClaim.UserId; - ApplicationUser = applicationUserClaim.ApplicationUser; - ClaimType = applicationUserClaim.ClaimType; - ClaimValue = applicationUserClaim.ClaimValue; - } + /// + public sealed override int Id { get; set; } + + #region User + /// + public sealed override string UserId { get; set; } + + /// + /// Application User entity + /// + public ApplicationUser ApplicationUser { get; set; } + + #endregion + + /// + public sealed override string ClaimType { get; set; } + + /// + public sealed override string ClaimValue { get; set; } - public ApplicationUserClaim() - { } -} \ No newline at end of file +} diff --git a/BlueWest.Data.Capital/Application/ApplicationUserClaim/ApplicationUserClaimUnique.cs b/BlueWest.Data.Capital/Application/ApplicationUserClaim/ApplicationUserClaimUnique.cs new file mode 100644 index 0000000..29d5411 --- /dev/null +++ b/BlueWest.Data.Capital/Application/ApplicationUserClaim/ApplicationUserClaimUnique.cs @@ -0,0 +1,14 @@ +using MapTo; + +namespace BlueWest.WebApi.Context.Users +{ + [MapFrom(typeof(ApplicationUserClaim))] + public partial class ApplicationUserClaimUnique + { + public int Id { get; set; } + public string UserId { get; set; } + public string ClaimType { get; set; } + public string ClaimValue { get; set; } + } +} + diff --git a/BlueWest.Data.Capital/Application/ApplicationUserRole/ApplicationUserRole.cs b/BlueWest.Data.Capital/Application/ApplicationUserRole/ApplicationUserRole.cs index 48dc5c4..c6314aa 100644 --- a/BlueWest.Data.Capital/Application/ApplicationUserRole/ApplicationUserRole.cs +++ b/BlueWest.Data.Capital/Application/ApplicationUserRole/ApplicationUserRole.cs @@ -1,33 +1,28 @@ using System; using System.Collections.Generic; using Microsoft.AspNetCore.Identity; +using MapTo; -namespace BlueWest.WebApi.Context.Users; - -/// -public class ApplicationUserRole : IdentityUserRole +namespace BlueWest.WebApi.Context.Users { - /// - /// User entity of this role - /// - public ApplicationUser User { get; set; } - public ApplicationRole ApplicationRole { get; set; } - /// - public sealed override string UserId { get; set; } + [MapFrom(typeof(ApplicationUserRoleUnique))] - /// - public sealed override string RoleId { get; set; } - - - public ApplicationUserRole() { } - - public ApplicationUserRole(ApplicationUserRole applicationUserRole) + public partial class ApplicationUserRole : IdentityUserRole { - User = applicationUserRole.User; - UserId = applicationUserRole.UserId; - RoleId = applicationUserRole.RoleId; - ApplicationRole = applicationUserRole.ApplicationRole; + /// + /// User entity of this role + /// + public ApplicationUser User { get; set; } + + public ApplicationRole ApplicationRole { get; set; } + + /// + public sealed override string UserId { get; set; } + + /// + public sealed override string RoleId { get; set; } + } -} \ No newline at end of file +} diff --git a/BlueWest.Data.Capital/Application/ApplicationUserRole/ApplicationUserRoleUnique.cs b/BlueWest.Data.Capital/Application/ApplicationUserRole/ApplicationUserRoleUnique.cs new file mode 100644 index 0000000..b7389ee --- /dev/null +++ b/BlueWest.Data.Capital/Application/ApplicationUserRole/ApplicationUserRoleUnique.cs @@ -0,0 +1,13 @@ +using MapTo; + +namespace BlueWest.WebApi.Context.Users +{ + [MapFrom(typeof(ApplicationUserRole))] + public partial class ApplicationUserRoleUnique + { + public string UserId { get; set; } + + public string RoleId { get; set; } + } +} + diff --git a/BlueWest.Data.Capital/BlueWest.Data.Capital.csproj b/BlueWest.Data.Capital/BlueWest.Data.Capital.csproj index d48dde3..e63e3d0 100644 --- a/BlueWest.Data.Capital/BlueWest.Data.Capital.csproj +++ b/BlueWest.Data.Capital/BlueWest.Data.Capital.csproj @@ -22,7 +22,6 @@ -