Added Authorization
This commit is contained in:
parent
04049f31f6
commit
e47d6488c2
15 changed files with 134 additions and 21 deletions
21
Lieb/Data/Constants.cs
Normal file
21
Lieb/Data/Constants.cs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
namespace Lieb.Data
|
||||||
|
{
|
||||||
|
public static class Constants
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
public const string ClaimType = "Role";
|
||||||
|
public static class Roles
|
||||||
|
{
|
||||||
|
public const string User = "User";
|
||||||
|
public const string RaidLead = "RaidLead";
|
||||||
|
public const string GuildLead = "GuildLead";
|
||||||
|
public const string Admin = "Admin";
|
||||||
|
|
||||||
|
public static List<string> GetAllRoles()
|
||||||
|
{
|
||||||
|
return typeof(Roles).GetFields().Select(f => f.GetValue(f)).Cast<string>().ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,19 +7,27 @@ namespace Lieb.Data
|
||||||
public static void Initialize(LiebContext context)
|
public static void Initialize(LiebContext context)
|
||||||
{
|
{
|
||||||
// Look for any students.
|
// Look for any students.
|
||||||
if (context.Users.Any())
|
if (context.LiebUsers.Any())
|
||||||
{
|
{
|
||||||
return; // DB has been seeded
|
return; // DB has been seeded
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UserRole admin = new UserRole();
|
||||||
|
admin.RoleName = Constants.Roles.Admin;
|
||||||
|
UserRole guildLead = new UserRole();
|
||||||
|
guildLead.RoleName = Constants.Roles.GuildLead;
|
||||||
|
UserRole member = new UserRole();
|
||||||
|
member.RoleName = Constants.Roles.User;
|
||||||
|
|
||||||
|
|
||||||
var users = new LiebUser[]
|
var users = new LiebUser[]
|
||||||
{
|
{
|
||||||
new LiebUser{DiscordUserId=0, Name="Sarah",Birthday=DateTime.Parse("1992-01-15")},
|
new LiebUser{DiscordUserId=0, Name="Sarah",Birthday=DateTime.Parse("1992-01-15"), Roles=new List<UserRole>(){admin}},
|
||||||
new LiebUser{DiscordUserId=0, Name="Lisa",Birthday=DateTime.Parse("1991-02-15")},
|
new LiebUser{DiscordUserId=1, Name="Lisa",Birthday=DateTime.Parse("1991-02-15"), Roles=new List<UserRole>(){guildLead} },
|
||||||
new LiebUser{DiscordUserId=0, Name="Simon",Birthday=DateTime.Parse("2019-09-01")}
|
new LiebUser{DiscordUserId=2, Name="Simon",Birthday=DateTime.Parse("2019-09-01"), Roles=new List<UserRole>(){member}}
|
||||||
};
|
};
|
||||||
|
|
||||||
context.Users.AddRange(users);
|
context.LiebUsers.AddRange(users);
|
||||||
context.SaveChanges();
|
context.SaveChanges();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,8 @@ namespace Lieb.Data
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public DbSet<LiebUser> Users { get; set; }
|
public DbSet<LiebUser> LiebUsers { get; set; }
|
||||||
|
public DbSet<UserRole> UserRoles { get; set; }
|
||||||
public DbSet<GuildWars2Account> GuildWars2Account { get; set; }
|
public DbSet<GuildWars2Account> GuildWars2Account { get; set; }
|
||||||
public DbSet<Equipped> Equipped { get; set; }
|
public DbSet<Equipped> Equipped { get; set; }
|
||||||
public DbSet<GuildWars2Build> RaidRoles { get; set; }
|
public DbSet<GuildWars2Build> RaidRoles { get; set; }
|
||||||
|
@ -27,6 +28,7 @@ namespace Lieb.Data
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
modelBuilder.Entity<LiebUser>().ToTable("LiebUser");
|
modelBuilder.Entity<LiebUser>().ToTable("LiebUser");
|
||||||
|
modelBuilder.Entity<UserRole>().ToTable("UserRole");
|
||||||
modelBuilder.Entity<GuildWars2Account>().ToTable("GuildWars2Account");
|
modelBuilder.Entity<GuildWars2Account>().ToTable("GuildWars2Account");
|
||||||
modelBuilder.Entity<Equipped>().ToTable("Equipped");
|
modelBuilder.Entity<Equipped>().ToTable("Equipped");
|
||||||
modelBuilder.Entity<GuildWars2Build>().ToTable("GuildWars2Build");
|
modelBuilder.Entity<GuildWars2Build>().ToTable("GuildWars2Build");
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
using Microsoft.AspNetCore.Authentication;
|
using Lieb.Data;
|
||||||
|
using Lieb.Models;
|
||||||
|
using Microsoft.AspNetCore.Authentication;
|
||||||
using Microsoft.AspNetCore.Authentication.OAuth;
|
using Microsoft.AspNetCore.Authentication.OAuth;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
|
@ -10,9 +13,12 @@ namespace Discord.OAuth2
|
||||||
{
|
{
|
||||||
internal class DiscordHandler : OAuthHandler<DiscordOptions>
|
internal class DiscordHandler : OAuthHandler<DiscordOptions>
|
||||||
{
|
{
|
||||||
public DiscordHandler(IOptionsMonitor<DiscordOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
|
private readonly Lieb.Data.LiebContext _LiebDbcontext;
|
||||||
|
|
||||||
|
public DiscordHandler(IOptionsMonitor<DiscordOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, Lieb.Data.LiebContext context)
|
||||||
: base(options, logger, encoder, clock)
|
: base(options, logger, encoder, clock)
|
||||||
{
|
{
|
||||||
|
_LiebDbcontext = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task<AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
|
protected override async Task<AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
|
||||||
|
@ -30,6 +36,16 @@ namespace Discord.OAuth2
|
||||||
context.RunClaimActions();
|
context.RunClaimActions();
|
||||||
|
|
||||||
await Events.CreatingTicket(context);
|
await Events.CreatingTicket(context);
|
||||||
|
|
||||||
|
LiebUser? user = await _LiebDbcontext.LiebUsers.Include(u => u.Roles).FirstOrDefaultAsync(m => m.DiscordUserId == 1);
|
||||||
|
if (user != null)
|
||||||
|
{
|
||||||
|
foreach (UserRole role in user.Roles)
|
||||||
|
{
|
||||||
|
context.Identity.AddClaim(new Claim(Constants.ClaimType, role.RoleName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name);
|
return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ namespace Discord.OAuth2
|
||||||
TokenEndpoint = DiscordDefaults.TokenEndpoint;
|
TokenEndpoint = DiscordDefaults.TokenEndpoint;
|
||||||
UserInformationEndpoint = DiscordDefaults.UserInformationEndpoint;
|
UserInformationEndpoint = DiscordDefaults.UserInformationEndpoint;
|
||||||
Scope.Add("identify");
|
Scope.Add("identify");
|
||||||
|
//Scope.Add("guilds.members.read");
|
||||||
|
|
||||||
ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "id", ClaimValueTypes.UInteger64);
|
ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "id", ClaimValueTypes.UInteger64);
|
||||||
ClaimActions.MapJsonKey(ClaimTypes.Name, "username", ClaimValueTypes.String);
|
ClaimActions.MapJsonKey(ClaimTypes.Name, "username", ClaimValueTypes.String);
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
RandomEliteSpecialization = 4,
|
RandomEliteSpecialization = 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class Raid
|
public class Raid
|
||||||
{
|
{
|
||||||
public int RaidId { get; private set; }
|
public int RaidId { get; private set; }
|
||||||
|
|
||||||
|
|
|
@ -10,5 +10,6 @@ namespace Lieb.Models
|
||||||
public string Pronouns { get; set; } = string.Empty;
|
public string Pronouns { get; set; } = string.Empty;
|
||||||
public DateTime? Birthday { get; set; }
|
public DateTime? Birthday { get; set; }
|
||||||
public ICollection<GuildWars2Account> GuildWars2Accounts { get; set; } = new List<GuildWars2Account>();
|
public ICollection<GuildWars2Account> GuildWars2Accounts { get; set; } = new List<GuildWars2Account>();
|
||||||
|
public ICollection<UserRole> Roles { get; set; } = new List<UserRole>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
9
Lieb/Models/UserRole.cs
Normal file
9
Lieb/Models/UserRole.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
namespace Lieb.Models
|
||||||
|
{
|
||||||
|
public class UserRole
|
||||||
|
{
|
||||||
|
public int UserRoleId { get; set; }
|
||||||
|
|
||||||
|
public string RoleName { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,7 +36,7 @@ namespace Lieb.Pages.Users
|
||||||
return Page();
|
return Page();
|
||||||
}
|
}
|
||||||
|
|
||||||
_context.Users.Add(User);
|
_context.LiebUsers.Add(User);
|
||||||
await _context.SaveChangesAsync();
|
await _context.SaveChangesAsync();
|
||||||
|
|
||||||
return RedirectToPage("./Index");
|
return RedirectToPage("./Index");
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace Lieb.Pages.Users
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
User = await _context.Users.FirstOrDefaultAsync(m => m.LiebUserId == id);
|
User = await _context.LiebUsers.FirstOrDefaultAsync(m => m.LiebUserId == id);
|
||||||
|
|
||||||
if (User == null)
|
if (User == null)
|
||||||
{
|
{
|
||||||
|
@ -46,11 +46,11 @@ namespace Lieb.Pages.Users
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
User = await _context.Users.FindAsync(id);
|
User = await _context.LiebUsers.FindAsync(id);
|
||||||
|
|
||||||
if (User != null)
|
if (User != null)
|
||||||
{
|
{
|
||||||
_context.Users.Remove(User);
|
_context.LiebUsers.Remove(User);
|
||||||
await _context.SaveChangesAsync();
|
await _context.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace Lieb.Pages.Users
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
User = await _context.Users.FirstOrDefaultAsync(m => m.LiebUserId == id);
|
User = await _context.LiebUsers.FirstOrDefaultAsync(m => m.LiebUserId == id);
|
||||||
|
|
||||||
if (User == null)
|
if (User == null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace Lieb.Pages.Users
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
User = await _context.Users.FirstOrDefaultAsync(m => m.LiebUserId == id);
|
User = await _context.LiebUsers.FirstOrDefaultAsync(m => m.LiebUserId == id);
|
||||||
|
|
||||||
if (User == null)
|
if (User == null)
|
||||||
{
|
{
|
||||||
|
@ -72,7 +72,7 @@ namespace Lieb.Pages.Users
|
||||||
|
|
||||||
private bool UserExists(int id)
|
private bool UserExists(int id)
|
||||||
{
|
{
|
||||||
return _context.Users.Any(e => e.LiebUserId == id);
|
return _context.LiebUsers.Any(e => e.LiebUserId == id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace Lieb.Pages.Users
|
||||||
|
|
||||||
public async Task OnGetAsync()
|
public async Task OnGetAsync()
|
||||||
{
|
{
|
||||||
User = await _context.Users.ToListAsync();
|
User = await _context.LiebUsers.ToListAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
using Discord.OAuth2;
|
using Discord.OAuth2;
|
||||||
using Lieb.Data;
|
using Lieb.Data;
|
||||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||||
using Microsoft.AspNetCore.Components;
|
|
||||||
using Microsoft.AspNetCore.Components.Web;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
@ -32,6 +29,15 @@ builder.Services.AddAuthentication(opt =>
|
||||||
x.SaveTokens = true;
|
x.SaveTokens = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
builder.Services.AddAuthorization(options =>
|
||||||
|
{
|
||||||
|
foreach(string role in Constants.Roles.GetAllRoles())
|
||||||
|
{
|
||||||
|
options.AddPolicy(role, policy => policy.RequireClaim(Constants.ClaimType, role));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
// Configure the HTTP request pipeline.
|
||||||
|
@ -62,6 +68,7 @@ app.UseStaticFiles();
|
||||||
|
|
||||||
app.UseRouting();
|
app.UseRouting();
|
||||||
app.UseAuthentication();
|
app.UseAuthentication();
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
app.UseEndpoints(endpoints =>
|
app.UseEndpoints(endpoints =>
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
@inherits LayoutComponentBase
|
@using System.Security.Claims
|
||||||
|
@using Microsoft.AspNetCore.Components.Authorization
|
||||||
|
@inject AuthenticationStateProvider AuthenticationStateProvider
|
||||||
|
@inherits LayoutComponentBase
|
||||||
|
|
||||||
<PageTitle>Lieb</PageTitle>
|
<PageTitle>Lieb</PageTitle>
|
||||||
|
|
||||||
|
@ -20,9 +23,54 @@
|
||||||
</NotAuthorized>
|
</NotAuthorized>
|
||||||
</AuthorizeView>
|
</AuthorizeView>
|
||||||
</div>
|
</div>
|
||||||
|
<AuthorizeView>
|
||||||
|
<p>You can only see this if you are loged in</p>
|
||||||
|
</AuthorizeView>
|
||||||
|
<AuthorizeView Policy="Admin">
|
||||||
|
<p>You can only see this if you satisfy the "Admin" policy.</p>
|
||||||
|
</AuthorizeView>
|
||||||
|
|
||||||
|
|
||||||
<article class="content px-4">
|
<article class="content px-4">
|
||||||
@Body
|
@Body
|
||||||
</article>
|
</article>
|
||||||
|
<button @onclick="GetClaimsPrincipalData">Get ClaimsPrincipal Data</button>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
<p>@_authMessage</p>
|
||||||
|
|
||||||
|
@if (_claims.Count() > 0)
|
||||||
|
{
|
||||||
|
<ul>
|
||||||
|
@foreach (var claim in _claims)
|
||||||
|
{
|
||||||
|
<li>@claim.Type: @claim.Value</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
|
|
||||||
|
<p>@_surnameMessage</p>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private string _authMessage;
|
||||||
|
private string _surnameMessage;
|
||||||
|
private IEnumerable<Claim> _claims = Enumerable.Empty<Claim>();
|
||||||
|
|
||||||
|
private async Task GetClaimsPrincipalData()
|
||||||
|
{
|
||||||
|
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
|
||||||
|
var user = authState.User;
|
||||||
|
|
||||||
|
if (user.Identity.IsAuthenticated)
|
||||||
|
{
|
||||||
|
_authMessage = $"{user.Identity.Name} is authenticated.";
|
||||||
|
_claims = user.Claims;
|
||||||
|
_surnameMessage =
|
||||||
|
$"Surname: {user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_authMessage = "The user is NOT authenticated.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue