This commit is contained in:
Steven Hildreth 2018-11-10 17:26:04 -06:00
parent 97483dee11
commit 0344d1e604
15 changed files with 163 additions and 134 deletions

View file

@ -54,7 +54,8 @@ namespace Roadie.Api.Controllers
}
// If successful login return OK with generated token
var user = await userManager.FindByNameAsync(model.Username);
return Ok(this.tokenService.GenerateToken(user));
var t = await this.tokenService.GenerateToken(user, this.userManager);
return Ok(t);
}
catch (Exception ex)
{
@ -76,7 +77,7 @@ namespace Roadie.Api.Controllers
if (!String.IsNullOrWhiteSpace(username))
{
var user = await userManager.FindByNameAsync(username);
return Ok(this.tokenService.GenerateToken(user));
return Ok(await this.tokenService.GenerateToken(user, this.userManager));
}
else
{
@ -103,7 +104,7 @@ namespace Roadie.Api.Controllers
if (identityResult.Succeeded)
{
await signInManager.SignInAsync(user, isPersistent: false);
return Ok(this.tokenService.GenerateToken(user));
return Ok(this.tokenService.GenerateToken(user, this.userManager));
}
else
{
@ -129,7 +130,7 @@ namespace Roadie.Api.Controllers
if (identityResult.Succeeded)
{
await signInManager.SignInAsync(user, isPersistent: false);
return Ok(this.tokenService.GenerateToken(user));
return Ok(this.tokenService.GenerateToken(user, this.userManager));
}
else
{

View file

@ -1,9 +1,11 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Roadie.Api.Services;
using Roadie.Library.Caching;
using Roadie.Library.Identity;
using Roadie.Library.Models;
using System;
using System.Net;
@ -19,11 +21,14 @@ namespace Roadie.Api.Controllers
{
private IArtistService ArtistService { get; }
public ArtistController(IArtistService artistService, ILoggerFactory logger, ICacheManager cacheManager, IConfiguration configuration)
private UserManager<ApplicationUser> UserManager { get; }
public ArtistController(IArtistService artistService, ILoggerFactory logger, ICacheManager cacheManager, IConfiguration configuration, UserManager<ApplicationUser> userManager)
: base(cacheManager, configuration)
{
this._logger = logger.CreateLogger("RoadieApi.Controllers.ArtistController");
this.ArtistService = artistService;
this.UserManager = userManager;
}
//[EnableQuery]

View file

@ -1,4 +1,5 @@
using Roadie.Library.Data;
using Microsoft.AspNetCore.Identity;
using Roadie.Library.Data;
using Roadie.Library.Identity;
using System;
using System.Collections.Generic;
@ -9,6 +10,6 @@ namespace Roadie.Api.Services
{
public interface ITokenService
{
string GenerateToken(ApplicationUser user);
Task<string> GenerateToken(ApplicationUser user, UserManager<ApplicationUser> userManager);
}
}

View file

@ -1,9 +1,12 @@
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Configuration;
using Roadie.Library.Data;
using Roadie.Library.Identity;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
namespace Roadie.Api.Services
{
@ -16,10 +19,13 @@ namespace Roadie.Api.Services
this._configuration = configuration;
}
public string GenerateToken(ApplicationUser user)
public async Task<string> GenerateToken(ApplicationUser user, UserManager<ApplicationUser> userManager)
{
var utcNow = DateTime.UtcNow;
var roles = await userManager.GetRolesAsync(user);
var userRoles = roles.Select(r => new Claim(ClaimTypes.Role, r)).ToArray();
var tokenHandler = new JwtSecurityTokenHandler();
var claims = new Claim[]
@ -28,7 +34,7 @@ namespace Roadie.Api.Services
new Claim(JwtRegisteredClaimNames.UniqueName, user.UserName),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Iat, utcNow.ToString())
};
}.Union(userRoles);
var now = DateTime.UtcNow;
var securityKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(this._configuration.GetValue<String>("Tokens:PrivateKey")));

View file

@ -33,16 +33,16 @@ namespace Roadie.Api
private readonly IConfiguration _configuration;
private readonly ILoggerFactory _loggerFactory;
public static string AssemblyDirectory
{
get
{
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
var uri = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uri.Path);
return Path.GetDirectoryName(path);
}
}
//public static string AssemblyDirectory
//{
// get
// {
// string codeBase = Assembly.GetExecutingAssembly().CodeBase;
// var uri = new UriBuilder(codeBase);
// string path = Uri.UnescapeDataString(uri.Path);
// return Path.GetDirectoryName(path);
// }
//}
public Startup(IConfiguration configuration, ILoggerFactory loggerFactory)
{
@ -55,22 +55,8 @@ namespace Roadie.Api
src => src.Artist.RoadieId)
.Compile();
//TypeAdapterConfig<Roadie.Library.Data.ReleaseMedia, Roadie.Library.Models.Releases.ReleaseMediaList>
// .NewConfig()
// .Map(rml => rml.Id,
// src => src.RoadieId)
// .Compile();
//TypeAdapterConfig<Roadie.Library.Data.Track, Roadie.Library.Models.TrackList>
// .NewConfig()
// .Map(rml => rml.ReleaseArtistId,
// src => src.Artist.RoadieId)
// .Compile();
TypeAdapterConfig.GlobalSettings.Default.PreserveReference(true);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
@ -113,22 +99,6 @@ namespace Roadie.Api
services.AddSingleton<IHttpEncoder, HttpEncoder>();
//services.AddSingleton<IRoadieSettings, RoadieSettings>(options =>
//{
// var settingsPath = Path.Combine(AssemblyDirectory, "settings.json");
// var settings = new RoadieSettings();
// if (File.Exists(settingsPath))
// {
// var settingsFileContents = File.ReadAllText(settingsPath);
// var fromSettingsFile = Newtonsoft.Json.JsonConvert.DeserializeObject<RoadieSettings>(settingsFileContents);
// if (fromSettingsFile != null)
// {
// settings.MergeWith(fromSettingsFile);
// }
// }
// return settings;
//});
var cacheManager = new MemoryCacheManager(this._loggerFactory.CreateLogger<MemoryCacheManager>(), new CachePolicy(TimeSpan.FromHours(4)));
services.AddSingleton<ICacheManager>(cacheManager);
@ -141,13 +111,13 @@ namespace Roadie.Api
));
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<ApplicationUserDbContext>()
.AddClaimsPrincipalFactory<ApplicationClaimsFactory>();
.AddRoles<ApplicationRole>()
.AddEntityFrameworkStores<ApplicationUserDbContext>();
services.AddAuthorization(options =>
{
options.AddPolicy("Admin", policy => policy.RequireClaim("Admin"));
options.AddPolicy("Editor", policy => policy.RequireClaim("Editor"));
options.AddPolicy("Admin", policy => policy.RequireRole("Admin"));
options.AddPolicy("Editor", policy => policy.RequireRole("Editor"));
});
services.Configure<IConfiguration>(this._configuration);
@ -210,7 +180,7 @@ namespace Roadie.Api
services.AddScoped<IHttpContext>(factory =>
{
var actionContext = factory.GetService<IActionContextAccessor>()
.ActionContext;
.ActionContext;
return new HttpContext(new UrlHelper(actionContext));
});
}

View file

@ -37,6 +37,8 @@ namespace Roadie.Library.Data
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder
.Entity<Release>()
.Property(e => e.ReleaseType)

View file

@ -1,39 +0,0 @@
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
namespace Roadie.Library.Identity
{
public class ApplicationClaimsFactory : UserClaimsPrincipalFactory<ApplicationUser, ApplicationRole>
{
public const string SecurityClaimRoleType = "req-security-claim";
private readonly ApplicationUserDbContext _applicationUserDbContext = null;
public ApplicationClaimsFactory(
ApplicationUserDbContext applicationUserDbContext,
UserManager<ApplicationUser> userManager,
RoleManager<ApplicationRole> roleManager,
IOptions<IdentityOptions> optionsAccessor) : base(userManager, roleManager, optionsAccessor)
{
_applicationUserDbContext = applicationUserDbContext;
}
#pragma warning disable 1998
public override async Task<ClaimsPrincipal> CreateAsync(ApplicationUser user)
{
var usersRoles = (from ur in _applicationUserDbContext.UsersInRoles.Where(x => x.UserId == user.Id)
join r in _applicationUserDbContext.Roles on ur.UserRoleId equals r.Id
select r);
IEnumerable<Claim> userClaims = null;
if (usersRoles.Any())
{
userClaims = usersRoles.Select(x => new Claim(SecurityClaimRoleType, x.Name));
}
return new ClaimsPrincipal(new ClaimsIdentity(userClaims, "Password"));
}
}
}

View file

@ -16,9 +16,9 @@ namespace Roadie.Library.Identity
[StringLength(200)]
public string Description { get; set; }
[Column("id")]
[Key]
public override int Id { get; set; }
//[Column("id")]
//[Key]
//public override int Id { get; set; }
[Column("isLocked")]
public bool? IsLocked { get; set; }
@ -35,9 +35,11 @@ namespace Roadie.Library.Identity
[StringLength(36)]
public string RoadieId { get; set; }
public virtual ICollection<ApplicationRoleClaim> RoleClaims { get; set; }
[Column("status")]
public short? Status { get; set; }
public ICollection<UsersInRoles> Users { get; set; }
public virtual ICollection<ApplicationUserRole> UserRoles { get; set; }
}
}

View file

@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Identity;
using System.ComponentModel.DataAnnotations.Schema;
namespace Roadie.Library.Identity
{
[Table("userRoleClaims")]
public class ApplicationRoleClaim : IdentityRoleClaim<int>
{
public virtual ApplicationRole Role { get; set; }
[Column("userRoleId")]
public override int RoleId { get; set; }
}
}

View file

@ -14,13 +14,15 @@ namespace Roadie.Library.Identity
[StringLength(100)]
public string ApiToken { get; set; }
public ICollection<UserArtist> ArtistRatings { get; set; }
public virtual ICollection<UserArtist> ArtistRatings { get; set; }
[Column("avatar", TypeName = "blob")]
public byte[] Avatar { get; set; }
public ICollection<Bookmark> Bookmarks { get; set; }
public virtual ICollection<ApplicationUserClaim> Claims { get; set; }
[Column("createdDate")]
public DateTime? CreatedDate { get; set; }
@ -101,7 +103,7 @@ namespace Roadie.Library.Identity
[StringLength(36)]
public Guid RoadieId { get; set; }
public ICollection<UsersInRoles> Roles { get; set; }
// public virtual ICollection<UsersInRoles> Roles { get; set; }
[Column("status")]
public short? Status { get; set; }
@ -122,5 +124,7 @@ namespace Roadie.Library.Identity
[Required]
[StringLength(20)]
public string Username { get; set; }
public virtual ICollection<ApplicationUserRole> UserRoles { get; set; }
}
}

View file

@ -0,0 +1,11 @@
using Microsoft.AspNetCore.Identity;
using System.ComponentModel.DataAnnotations.Schema;
namespace Roadie.Library.Identity
{
[Table("userClaims")]
public class ApplicationUserClaim : IdentityUserClaim<int>
{
public virtual ApplicationUser User { get; set; }
}
}

View file

@ -1,22 +1,72 @@
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace Roadie.Library.Identity
{
public class ApplicationUserDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, int>
public class ApplicationUserDbContext : IdentityDbContext<
ApplicationUser, ApplicationRole, int,
ApplicationUserClaim, ApplicationUserRole, IdentityUserLogin<int>,
ApplicationRoleClaim, IdentityUserToken<int>>
{
public DbSet<UsersInRoles> UsersInRoles { get; set; }
public ApplicationUserDbContext(DbContextOptions<ApplicationUserDbContext> options) : base(options)
public ApplicationUserDbContext(DbContextOptions<ApplicationUserDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(modelBuilder);
base.OnModelCreating(builder);
modelBuilder.Entity<ApplicationUser>().ToTable("user");
modelBuilder.Entity<ApplicationRole>().ToTable("userrole");
builder.Entity<ApplicationUser>(b =>
{
b.ToTable("user");
// Each User can have many UserClaims
b.HasMany(e => e.Claims)
.WithOne(e => e.User)
.HasForeignKey(uc => uc.UserId)
.IsRequired();
// Each User can have many entries in the UserRole join table
b.HasMany(e => e.UserRoles)
.WithOne(e => e.User)
.HasForeignKey(ur => ur.UserId)
.IsRequired();
});
builder.Entity<ApplicationRole>(b =>
{
b.ToTable("userrole");
b.HasKey(ar => ar.Id);
// Each Role can have many entries in the UserRole join table
b.HasMany(e => e.UserRoles)
.WithOne(e => e.Role)
.HasForeignKey(ur => ur.RoleId)
.IsRequired();
// Each Role can have many associated RoleClaims
b.HasMany(e => e.RoleClaims)
.WithOne(e => e.Role)
.HasForeignKey(rc => rc.RoleId)
.IsRequired();
});
builder.Entity<ApplicationUserClaim>(b =>
{
b.ToTable("userClaims");
});
builder.Entity<ApplicationUserRole>(b =>
{
b.ToTable("usersInRoles");
});
builder.Entity<ApplicationRoleClaim>(b =>
{
b.ToTable("userRoleClaims");
});
}
}
}

View file

@ -0,0 +1,17 @@
using Microsoft.AspNetCore.Identity;
using System.ComponentModel.DataAnnotations.Schema;
namespace Roadie.Library.Identity
{
[Table("usersInRoles")]
public class ApplicationUserRole : IdentityUserRole<int>
{
public int Id { get; set; }
public virtual ApplicationRole Role { get; set; }
[Column("userRoleId")]
public override int RoleId { get; set; }
public virtual ApplicationUser User { get; set; }
}
}

View file

@ -1,23 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Roadie.Library.Identity
{
[Table("usersInRoles")]
public class UsersInRoles
{
[Column("id")]
[Key]
public int Id { get; set; }
public ApplicationRole Role { get; set; }
public ApplicationUser User { get; set; }
[Column("userId")]
public int UserId { get; set; }
[Column("userRoleId")]
public int UserRoleId { get; set; }
}
}

View file

@ -12,8 +12,8 @@ namespace Roadie.Library
public const string NotModified = "NotModified";
public const string OkMessage = "OK";
private List<Exception> _errors = new List<Exception>();
private List<string> _messages = new List<string>();
private List<Exception> _errors;
private List<string> _messages;
public Dictionary<string, object> AdditionalData { get; set; }
public T Data { get; set; }
public IEnumerable<Exception> Errors { get; set; }
@ -63,6 +63,10 @@ namespace Roadie.Library
{
if (exception != null)
{
if(this._errors == null)
{
this._errors = new List<Exception>();
}
this._errors.Add(exception);
}
}
@ -71,6 +75,10 @@ namespace Roadie.Library
{
if (!string.IsNullOrEmpty(message))
{
if(this._messages == null)
{
this._messages = new List<string>();
}
this._messages.Add(message);
}
}