using FlexibleAuth.Server.
Models;
using FlexibleAuth.Shared.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using System.Security.Claims;
namespace FlexibleAuth.Server.Authorization;
public class ApplicationUserClaimsPrincipalFactory :
UserClaimsPrincipalFactory<User, Role>
{
public ApplicationUserClaimsPrincipalFactory(
UserManager<User> userManager,
RoleManager<Role> roleManager,
IOptions<IdentityOptions> optionsAccessor)
: base(userManager, roleManager, optionsAccessor)
{ }
protected override async Task<ClaimsIdentity> GenerateClaimsAsync(User user)
{
var identity = await base.GenerateClaimsAsync(user);
var userRoleNames = await UserManager.GetRolesAsync(user) ??
Array.Empty<string>();
var userRoles = await RoleManager.Roles.Where(r =>
userRoleNames.Contains(r.Name!)).ToListAsync();
var userPermissions = Permissions.None;
foreach (var role in userRoles)
userPermissions |= role.Permissions;
var permissionsValue = (int)userPermissions;
identity.AddClaim(
new Claim(CustomClaimTypes.Permissions,
permissionsValue.ToString()));
return identity;
}
}
using FlexibleAuth.Server.Models;
using FlexibleAuth.Shared;
using FlexibleAuth.Shared.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace FlexibleAuth.Server.Controllers.Admin;
[ApiController]
[Route("api/Admin/[controller]")]
public class AccessControlController : ControllerBase
{
private readonly RoleManager<Role> _roleManager;
public AccessControlController(RoleManager<Role> roleManager)
{
_roleManager = roleManager;
}
[HttpGet]
[Authorize(Permissions.ViewAccessControl)]
public async Task<ActionResult<AccessControlVm>> GetConfiguration()
{
var roles = await _roleManager.Roles
.ToListAsync();
var roleDtos = roles
.Select(r => new RoleDto(r.Id, r.Name ?? string.Empty,
r.Permissions))
.OrderBy(r => r.Name)
.ToList();
return new AccessControlVm(roleDtos);
}
[HttpPut]
[Authorize(Permissions.ConfigureAccessControl)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task<IActionResult> UpdateConfiguration(RoleDto updatedRole)
{
var role = await _roleManager.FindByIdAsync(updatedRole.Id);
if (role != null)
{
role.Permissions = updatedRole.Permissions;
await _roleManager.UpdateAsync(role);
}
return NoContent();
}
}
using FlexibleAuth.Server.Models;
using FlexibleAuth.Shared;
using FlexibleAuth.Shared.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace FlexibleAuth.Server.Controllers.Admin;
[ApiController]
[Route("api/Admin/[controller]")]
public class RolesController : ControllerBase
{
private readonly RoleManager<Role> _roleManager;
public RolesController(RoleManager<Role> roleManager)
{
_roleManager = roleManager;
}
// GET: api/Admin/Roles
[HttpGet]
[Authorize(Permissions.ViewRoles)]
public async Task<ActionResult<IEnumerable<RoleDto>>> GetRoles()
{
var roles = await _roleManager.Roles
.OrderBy(r => r.Name)
.ToListAsync();
return roles
.Select(r => new RoleDto(r.Id, r.Name ?? string.Empty,
r.Permissions))
.ToList();
}
// POST: api/Admin/Roles
// To protect from overposting attacks, see
https://go.microsoft.com/fwlink/?linkid=2123754
[HttpPost]
[Authorize(Permissions.ManageRoles)]
public async Task<ActionResult<RoleDto>> PostRole(RoleDto newRole)
{
var role = new Role { Name = newRole.Name };
await _roleManager.CreateAsync(role);
return new RoleDto(role.Id, role.Name, role.Permissions);
}
// PUT: api/Admin/Roles/5
// To protect from overposting attacks, see
https://go.microsoft.com/fwlink/?linkid=2123754
[HttpPut("{id}")]
[Authorize(Permissions.ManageRoles)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> PutRole(string id, RoleDto updatedRole)
{
if (id != updatedRole.Id)
{
return BadRequest();
}
var role = await _roleManager.FindByIdAsync(id);
if (role == null)
{
return NotFound();
}
role.Name = updatedRole.Name;
await _roleManager.UpdateAsync(role);
if (role == null)
{
return NotFound();
}
return NoContent();
}
// DELETE: api/Admin/Roles/5
[HttpDelete("{id}")]
[Authorize(Permissions.ManageRoles)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> DeleteRole(string id)
{
var role = await _roleManager.FindByIdAsync(id);
if (role == null)
{
return NotFound();
}
await _roleManager.DeleteAsync(role);
return NoContent();
}
}
using FlexibleAuth.Server.Models;
using FlexibleAuth.Shared;
using FlexibleAuth.Shared.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace FlexibleAuth.Server.Controllers.Admin
{
[ApiController]
[Route("api/Admin/[controller]")]
public class UsersController : ControllerBase
{
private readonly UserManager<User> _userManager;
public UsersController(UserManager<User> userManager)
{
_userManager = userManager;
}
// GET: api/Admin/Users
[HttpGet]
[Authorize(Permissions.ViewUsers | Permissions.ManageUsers)]
public async Task<ActionResult<IEnumerable<UserDto>>> GetUsers()
{
return await _userManager.Users
.OrderBy(r => r.UserName)
.Select(u => new UserDto(u.Id, u.UserName ?? string.Empty,
u.Email ?? string.Empty))
.ToListAsync();
}
// GET: api/Admin/Users/5
[HttpGet("{id}")]
[Authorize(Permissions.ViewUsers)]
public async Task<ActionResult<UserDto>> GetUser(string id)
{
var user = await _userManager.FindByIdAsync(id);
if (user == null)
{
return NotFound();
}
var dto = new UserDto(user.Id, user.UserName ?? string.Empty,
user.Email ?? string.Empty);
var roles = await _userManager.GetRolesAsync(user);
dto.Roles.AddRange(roles);
return dto;
}
// PUT: api/Admin/Users/5
// To protect from overposting attacks, see
https://go.microsoft.com/fwlink/?linkid=2123754
[HttpPut("{id}")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[Authorize(Permissions.ManageUsers)]
public async Task<IActionResult> PutUser(string id, UserDto updatedUser)
{
if (id != updatedUser.Id)
{
return BadRequest();
}
var user = await _userManager.FindByIdAsync(id);
if (user == null)
{
return NotFound();
}
user.UserName = updatedUser.UserName;
user.Email = updatedUser.Email;
await _userManager.UpdateAsync(user);
var currentRoles = await _userManager.GetRolesAsync(user);
var addedRoles = updatedUser.Roles.Except(currentRoles);
var removedRoles = currentRoles.Except(updatedUser.Roles);
if (addedRoles.Any())
{
await _userManager.AddToRolesAsync(user, addedRoles);
}
if (removedRoles.Any())
{
await _userManager.RemoveFromRolesAsync(user, removedRoles);
}
return NoContent();
}
}
}
using Microsoft.AspNetCore.ApiAuthorization.IdentityServer;
using Microsoft.AspNetCore.Mvc;
namespace FlexibleAuth.Server.Controllers;
[ApiExplorerSettings(IgnoreApi = true)]
public class OidcConfigurationController : Controller
{
private readonly ILogger<OidcConfigurationController> _logger;
public OidcConfigurationController(IClientRequestParametersProvider
clientRequestParametersProvider, ILogger<OidcConfigurationController> logger)
{
ClientRequestParametersProvider = clientRequestParametersProvider;
_logger = logger;
}
public IClientRequestParametersProvider ClientRequestParametersProvider {
get; }
[HttpGet("_configuration/{clientId}")]
public IActionResult GetClientRequestParameters([FromRoute] string clientId)
{
var parameters =
ClientRequestParametersProvider.GetClientParameters(HttpContext, clientId);
return Ok(parameters);
}
}
using FlexibleAuth.Shared;
using FlexibleAuth.Shared.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace FlexibleAuth.Server.Controllers;
[Authorize(Permissions.Forecast)]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot",
"Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
using Duende.IdentityServer.EntityFramework.Entities;
using Duende.IdentityServer.EntityFramework.Extensions;
using Duende.IdentityServer.EntityFramework.Interfaces;
using Duende.IdentityServer.EntityFramework.Options;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
namespace FlexibleAuth.Server.Data;
// Based on
https://github.com/dotnet/aspnetcore/blob/main/src/Identity/ApiAuthorization.Iden
tityServer/src/Data/ApiAuthorizationDbContext.cs
// Customised to add TRole.
public class ApiAuthorizationDbContext<TUser, TRole> : IdentityDbContext<TUser,
TRole, string>, IPersistedGrantDbContext where TUser : IdentityUser where TRole :
IdentityRole
{
private readonly IOptions<OperationalStoreOptions> _operationalStoreOptions;
/// <summary>
/// Initializes a new instance of <see
cref="ApiAuthorizationDbContext{TUser}"/>.
/// </summary>
/// <param name="options">The <see cref="DbContextOptions"/>.</param>
/// <param name="operationalStoreOptions">The <see
cref="IOptions{OperationalStoreOptions}"/>.</param>
public ApiAuthorizationDbContext(
DbContextOptions options,
IOptions<OperationalStoreOptions> operationalStoreOptions)
: base(options)
{
_operationalStoreOptions = operationalStoreOptions;
}
/// <summary>
/// Gets or sets the <see cref="DbSet{PersistedGrant}"/>.
/// </summary>
public DbSet<PersistedGrant> PersistedGrants { get; set; }
/// <summary>
/// Gets or sets the <see cref="DbSet{DeviceFlowCodes}"/>.
/// </summary>
public DbSet<DeviceFlowCodes> DeviceFlowCodes { get; set; }
/// <summary>
/// Gets or sets the <see cref="DbSet{Key}"/>.
/// </summary>
public DbSet<Key> Keys { get; set; }
Task<int> IPersistedGrantDbContext.SaveChangesAsync() =>
base.SaveChangesAsync();
/// <inheritdoc />
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.ConfigurePersistedGrantContext(_operationalStoreOptions.Value);
}
}
using FlexibleAuth.Server.Models;
using Duende.IdentityServer.EntityFramework.Options;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using System.Reflection;
namespace FlexibleAuth.Server.Data
{
public class ApplicationDbContext : ApiAuthorizationDbContext<User, Role>
{
public ApplicationDbContext(
DbContextOptions options,
IOptions<OperationalStoreOptions> operationalStoreOptions) :
base(options, operationalStoreOptions)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
}
}
}
using FlexibleAuth.Server.Models;
using FlexibleAuth.Shared.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
namespace FlexibleAuth.Server.Data;
public class DbInitializer
{
private readonly ApplicationDbContext _context;
private readonly UserManager<User> _userManager;
private readonly RoleManager<Role> _roleManager;
private const string AdministratorsRole = "Administrators";
private const string AccountsRole = "Accounts";
private const string OperationsRole = "Operations";
private const string DefaultPassword = "Password123!";
public DbInitializer(
ApplicationDbContext context,
UserManager<User> userManager,
RoleManager<Role> roleManager)
{
_context = context;
_userManager = userManager;
_roleManager = roleManager;
}
public async Task RunAsync()
{
_context.Database.Migrate();
// Create roles
await _roleManager.CreateAsync(
new Role
{
Name = AdministratorsRole,
NormalizedName = AdministratorsRole.ToUpper(),
Permissions = Permissions.All
});
await _roleManager.CreateAsync(
new Role
{
Name = AccountsRole,
NormalizedName = AccountsRole.ToUpper(),
Permissions =
Permissions.ViewUsers |
Permissions.Counter
});
await _roleManager.CreateAsync(
new Role
{
Name = OperationsRole,
NormalizedName = OperationsRole.ToUpper(),
Permissions =
Permissions.ViewUsers |
Permissions.Forecast
});
// Ensure admin role has all permissions
var adminRole = await _roleManager.FindByNameAsync(AdministratorsRole);
adminRole!.Permissions = Permissions.All;
await _roleManager.UpdateAsync(adminRole);
// Create default admin user
var adminUserName = "admin@localhost";
var adminUser = new User { UserName = adminUserName, Email =
adminUserName };
await _userManager.CreateAsync(adminUser, DefaultPassword);
adminUser = await _userManager.FindByNameAsync(adminUserName);
if (adminUser != null)
{
await _userManager.AddToRoleAsync(adminUser, AdministratorsRole);
}
// Create default auditor user
var auditorUserName = "auditor@localhost";
var auditorUser = new User { UserName = auditorUserName, Email =
auditorUserName };
await _userManager.CreateAsync(auditorUser, DefaultPassword);
await _context.SaveChangesAsync();
}
}
using FlexibleAuth.Shared.Authorization;
using Microsoft.AspNetCore.Identity;
namespace FlexibleAuth.Server.Models;
public class Role : IdentityRole
{
public Permissions Permissions { get; set; }
}
using FlexibleAuth.Shared;
using Microsoft.AspNetCore.Identity;
namespace FlexibleAuth.Server.Models;
public class User : IdentityUser
{
}
@page
@model FlexibleAuth.Server.Pages.ErrorModel
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0,
maximum-scale=1.0, user-scalable=no" />
<title>Error</title>
<link href="~/css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="~/css/app.css" rel="stylesheet" asp-append-version="true" />
</head>
<body>
<div class="main">
<div class="content px-4">
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your
request.</h2>
@if (Model.ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@Model.RequestId</code>
</p>
}
<h3>Development Mode</h3>
<p>
Swapping to the <strong>Development</strong> environment displays
detailed information about the error that occurred.
</p>
<p>
<strong>The Development environment shouldn't be enabled for
deployed applications.</strong>
It can result in displaying sensitive information from exceptions
to end users.
For local debugging, enable the <strong>Development</strong>
environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment
variable to <strong>Development</strong>
and restarting the app.
</p>
</div>
</div>
</body>
</html>
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Diagnostics;
namespace FlexibleAuth.Server.Pages
{
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore =
true)]
[IgnoreAntiforgeryToken]
public class ErrorModel : PageModel
{
public string? RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
private readonly ILogger<ErrorModel> _logger;
public ErrorModel(ILogger<ErrorModel> logger)
{
_logger = logger;
}
public void OnGet()
{
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
}
}
}
using FlexibleAuth.Server.Authorization;
using FlexibleAuth.Server.Data;
using FlexibleAuth.Server.Models;
using FlexibleAuth.Shared.Authorization;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore;
using System.IdentityModel.Tokens.Jwt;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
var connectionString =
builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services
.AddDefaultIdentity<User>(options => options.SignIn.RequireConfirmedAccount =
false)
.AddRoles<Role>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddClaimsPrincipalFactory<ApplicationUserClaimsPrincipalFactory>();
builder.Services.AddIdentityServer()
.AddApiAuthorization<User, ApplicationDbContext>(options =>
{
options.IdentityResources["openid"].UserClaims.Add("role");
options.ApiResources.Single().UserClaims.Add("role");
options.IdentityResources["openid"].UserClaims.Add("permissions");
options.ApiResources.Single().UserClaims.Add("permissions");
});
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("role");
builder.Services.AddAuthentication()
.AddIdentityServerJwt();
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();
builder.Services.AddOpenApiDocument(configure =>
{
configure.Title = "FlexibleAuth";
});
builder.Services.AddScoped<DbInitializer>();
builder.Services.AddSingleton<IAuthorizationHandler,
PermissionAuthorizationHandler>();
builder.Services.AddSingleton<IAuthorizationPolicyProvider,
FlexibleAuthorizationPolicyProvider>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
app.UseWebAssemblyDebugging();
using var scope = app.Services.CreateScope();
var services = scope.ServiceProvider;
var initializer = services.GetRequiredService<DbInitializer>();
await initializer.RunAsync();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for
production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
app.UseRouting();
app.UseOpenApi();
app.UseSwaggerUi3();
app.UseIdentityServer();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
app.MapControllers();
app.MapFallbackToFile("index.html");
app.Run();
namespace FlexibleAuth.Shared.Authorization;
public class AuthorizeAttribute :
Microsoft.AspNetCore.Authorization.AuthorizeAttribute
{
public AuthorizeAttribute() { }
public AuthorizeAttribute(string policy) : base(policy) { }
public AuthorizeAttribute(Permissions permission)
{
Permissions = permission;
}
public Permissions Permissions
{
get
{
return !string.IsNullOrEmpty(Policy)
? PolicyNameHelper.GetPermissionsFrom(Policy)
: Permissions.None;
}
set
{
Policy = value != Permissions.None
? PolicyNameHelper.GeneratePolicyNameFor(value)
: string.Empty;
}
}
}
namespace System.Security.Claims;
public static class CustomClaimTypes
{
public const string Permissions = "permissions";
}
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Options;
namespace FlexibleAuth.Shared.Authorization;
public class FlexibleAuthorizationPolicyProvider :
DefaultAuthorizationPolicyProvider
{
private readonly AuthorizationOptions _options;
public FlexibleAuthorizationPolicyProvider(IOptions<AuthorizationOptions>
options)
: base(options)
{
_options = options.Value;
}
public override async Task<AuthorizationPolicy?> GetPolicyAsync(string
policyName)
{
var policy = await base.GetPolicyAsync(policyName);
if (policy == null && PolicyNameHelper.IsValidPolicyName(policyName))
{
var permissions = PolicyNameHelper.GetPermissionsFrom(policyName);
policy = new AuthorizationPolicyBuilder()
.AddRequirements(new
PermissionAuthorizationRequirement(permissions))
.Build();
_options.AddPolicy(policyName!, policy);
}
return policy;
}
}
using FlexibleAuth.Shared.Authorization;
using Microsoft.AspNetCore.Authorization;
using System.Security.Claims;
namespace FlexibleAuth.Shared.Authorization;
public static class IAuthorizationServiceExtensions
{
public static Task<AuthorizationResult> AuthorizeAsync(this
IAuthorizationService service, ClaimsPrincipal user, Permissions permissions)
{
return service.AuthorizeAsync(user,
PolicyNameHelper.GeneratePolicyNameFor(permissions));
}
}
using Microsoft.AspNetCore.Authorization;
using System.Security.Claims;
namespace FlexibleAuth.Shared.Authorization;
public class PermissionAuthorizationHandler :
AuthorizationHandler<PermissionAuthorizationRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext
context, PermissionAuthorizationRequirement requirement)
{
var permissionClaim = context.User.FindFirst(
c => c.Type == CustomClaimTypes.Permissions);
if (permissionClaim == null)
{
return Task.CompletedTask;
}
if (!int.TryParse(permissionClaim.Value, out int permissionClaimValue))
{
return Task.CompletedTask;
}
var userPermissions = (Permissions)permissionClaimValue;
if ((userPermissions & requirement.Permissions) != 0)
{
context.Succeed(requirement);
return Task.CompletedTask;
}
return Task.CompletedTask;
}
}
using Microsoft.AspNetCore.Authorization;
namespace FlexibleAuth.Shared.Authorization;
public class PermissionAuthorizationRequirement : IAuthorizationRequirement
{
public PermissionAuthorizationRequirement(Permissions permission)
{
Permissions = permission;
}
public Permissions Permissions { get; }
}
namespace FlexibleAuth.Shared.Authorization;
[Flags]
public enum Permissions
{
None = 0,
ViewRoles = 1,
ManageRoles = 2,
ViewUsers = 4,
ManageUsers = 8,
ConfigureAccessControl = 16,
Counter = 32,
Forecast = 64,
ViewAccessControl = 128,
All = ~None
}
namespace FlexibleAuth.Shared.Authorization;
public static class PermissionsProvider
{
public static List<Permissions> GetAll()
{
return Enum.GetValues(typeof(Permissions))
.OfType<Permissions>()
.ToList();
}
}
namespace FlexibleAuth.Shared.Authorization;
public static class PolicyNameHelper
{
public const string Prefix = "Permissions";
public static bool IsValidPolicyName(string? policyName)
{
return policyName != null && policyName.StartsWith(Prefix,
StringComparison.OrdinalIgnoreCase);
}
public static string GeneratePolicyNameFor(Permissions permissions)
{
return $"{Prefix}{(int)permissions}";
}
public static Permissions GetPermissionsFrom(string policyName)
{
var permissionsValue = int.Parse(policyName[Prefix.Length..]!);
return (Permissions)permissionsValue;
}
}
using FlexibleAuth.Shared.Authorization;
namespace FlexibleAuth.Shared;
public class AccessControlVm
{
internal AccessControlVm() { }
public AccessControlVm(List<RoleDto> roles)
{
Roles = roles;
foreach(var permission in PermissionsProvider.GetAll())
{
if (permission == Permissions.None) continue;
AvailablePermissions.Add(permission);
}
}
public List<RoleDto> Roles { get; set; } = new();
public List<Permissions> AvailablePermissions { get; set; } = new();
}
using FlexibleAuth.Shared.Authorization;
namespace FlexibleAuth.Shared;
public class RoleDto
{
public RoleDto()
{
Id = string.Empty;
Name = string.Empty;
Permissions = Permissions.None;
}
public RoleDto(string id, string name, Permissions permissions)
{
Id = id;
Name = name;
Permissions = permissions;
}
public string Id { get; set; }
public string Name { get; set; }
public Permissions Permissions { get; set; }
public bool Has(Permissions permission)
{
return Permissions.HasFlag(permission);;
}
public void Set(Permissions permission, bool granted)
{
if (granted)
{
Grant(permission);
}
else
{
Revoke(permission);
}
}
public void Grant(Permissions permission)
{
Permissions |= permission;
}
public void Revoke(Permissions permission)
{
Permissions ^= permission;
}
}
namespace FlexibleAuth.Shared;
public class UserDto
{
public UserDto() : this(string.Empty, string.Empty, string.Empty) { }
public UserDto(string id, string userName, string email)
{
Id = id;
UserName = userName;
Email = email;
}
public string Id { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public List<string> Roles { get; set; } = new();
}
namespace FlexibleAuth.Shared;
public class WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public string? Summary { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
@using Microsoft.AspNetCore.Identity
@using FlexibleAuth.Server.Models
@inject SignInManager<User> SignInManager
@inject UserManager<User> UserManager
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
var returnUrl = "/";
if (Context.Request.Query.TryGetValue("returnUrl", out var existingUrl)) {
returnUrl = existingUrl;
}
}
<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-
page="/Account/Manage/Index" title="Manage">Hello @User.Identity?.Name!</a>
</li>
<li class="nav-item">
<form class="form-inline" asp-area="Identity" asp-page="/Account/Logout"
asp-route-returnUrl="/" method="post">
<button type="submit" class="nav-link btn btn-link text-
dark">Logout</button>
</form>
</li>
}
else
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-
page="/Account/Register" asp-route-returnUrl="@returnUrl">Register</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-
page="/Account/Login" asp-route-returnUrl="@returnUrl">Login</a>
</li>
}
</ul>
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication.Internal;
using System.Security.Claims;
using System.Text.Json;
namespace FlexibleAuth.Client.Authorization;
public class CustomAccountClaimsPrincipalFactory :
AccountClaimsPrincipalFactory<RemoteUserAccount>
{
public CustomAccountClaimsPrincipalFactory(IAccessTokenProviderAccessor
accessor)
: base(accessor)
{
}
public async override ValueTask<ClaimsPrincipal> CreateUserAsync(
RemoteUserAccount account,
RemoteAuthenticationUserOptions options)
{
var user = await base.CreateUserAsync(account, options);
var identity = (ClaimsIdentity)user.Identity!;
if (account != null)
{
foreach (var property in account.AdditionalProperties)
{
var key = property.Key;
var value = property.Value;
if (value != null &&
value is JsonElement element && element.ValueKind ==
JsonValueKind.Array)
{
identity.RemoveClaim(identity.FindFirst(property.Key));
var claims = element.EnumerateArray()
.Select(x => new Claim(property.Key, x.ToString()));
identity.AddClaims(claims);
}
}
}
return user;
}
}
@page "/admin/access-control"
@attribute [Authorize(Permissions.ViewAccessControl |
Permissions.ConfigureAccessControl)]
<PageTitle>Access Control</PageTitle>
<h1>Access Control</h1>
<p>This is a description.</p>
@if (_vm == null) return;
<table class="table table-hover">
<thead>
<tr>
<th>Permissions</th>
@foreach(var role in _vm.Roles)
{
<th>@role.Name</th>
}
</tr>
</thead>
<tbody>
@foreach(var permission in _vm.AvailablePermissions)
{
<tr>
<th>@permission.ToString()</th>
@foreach(var role in _vm.Roles)
{
<th>
<FlexibleAuthorizeView
Permissions="@Permissions.ConfigureAccessControl">
<Authorized>
<input
type="checkbox"
class="form-check-input"
checked="@role.Has(permission)"
@onchange="(args) =>
Set(role, permission, (bool)args.Value!)"
/>
</Authorized>
<NotAuthorized>
<input
type="checkbox"
class="form-check-input"
checked="@role.Has(permission)"
disabled="disabled" />
</NotAuthorized>
</FlexibleAuthorizeView>
</th>
}
</tr>
}
</tbody>
</table>
using FlexibleAuth.Client.Services;
using FlexibleAuth.Shared;
using FlexibleAuth.Shared.Authorization;
using Microsoft.AspNetCore.Components;
namespace FlexibleAuth.Client.Pages.Admin.AccessControl;
public partial class Index
{
[Inject]
private IAccessControlClient AccessControlClient { get; set; } = null!;
private AccessControlVm? _vm;
protected override async Task OnInitializedAsync()
{
_vm = await AccessControlClient.GetConfigurationAsync();
}
private async Task Set(RoleDto role, Permissions permission, bool granted)
{
role.Set(permission, granted);
await AccessControlClient.UpdateConfigurationAsync(role);
}
}
@page "/admin/roles"
@attribute [Authorize(Permissions.ViewRoles)]
<PageTitle>Roles</PageTitle>
<h1>Roles</h1>
<p>This is a description.</p>
<table class="table table-striped table-hover w-50">
<thead>
<tr>
<th>Name</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var role in Roles)
{
@if (role != roleToEdit)
{
<tr>
<td>
<input type="text" id="name" class="form-control-
plaintext" style="padding-left: 0.75rem" value="@role.Name" />
</td>
<td>
<FlexibleAuthorizeView
Permissions="@Permissions.ManageRoles">
<button type="button" class="btn btn-secondary"
@onclick="() => EditRole(role)">
<span class="oi oi-pencil"></span>
</button>
<button type="button" class="btn btn-secondary"
@onclick="() => DeleteRole(role)">
<span class="oi oi-x"></span>
</button>
</FlexibleAuthorizeView>
</td>
</tr>
}
else
{
<tr>
<td>
<input type="text" id="name" class="form-control"
@bind="@role.Name" />
</td>
<td>
<FlexibleAuthorizeView
Permissions="@Permissions.ManageRoles">
<button type="button" class="btn btn-secondary"
@onclick="() => UpdateRole()">
<span class="oi oi-check"></span>
</button>
<button type="button" class="btn btn-secondary"
@onclick="() => CancelEditRole()">
<span class="oi oi-action-undo"></span>
</button>
</FlexibleAuthorizeView>
</td>
</tr>
}
}
</tbody>
<FlexibleAuthorizeView Permissions="@Permissions.ManageRoles">
<tfoot>
<tr>
<td>
<input type="text" id="name" class="form-control"
placeholder="New Role..." @bind="newRoleName" />
</td>
<td>
<button type="button" class="btn btn-primary"
@onclick="AddRole">
<span class="oi oi-plus"></span>
</button>
</td>
</tr>
</tfoot>
</FlexibleAuthorizeView>
</table>
using FlexibleAuth.Client.Services;
using FlexibleAuth.Shared;
using FlexibleAuth.Shared.Authorization;
using Microsoft.AspNetCore.Components;
namespace FlexibleAuth.Client.Pages.Admin.Roles;
public partial class Index
{
[Inject]
public IRolesClient RolesClient { get; set; } = null!;
public ICollection<RoleDto> Roles { get; set; } = new List<RoleDto>();
private string newRoleName = string.Empty;
private RoleDto? roleToEdit;
protected override async Task OnInitializedAsync()
{
Roles = await RolesClient.GetRolesAsync();
}
private async Task AddRole()
{
if (!string.IsNullOrWhiteSpace(newRoleName))
{
var role = await RolesClient.PostRoleAsync(
new RoleDto("", newRoleName, Permissions.None));
Roles.Add(role);
}
newRoleName = string.Empty;
}
private void EditRole(RoleDto role)
{
roleToEdit = role;
}
private void CancelEditRole()
{
roleToEdit = null;
}
private async Task UpdateRole()
{
await RolesClient.PutRoleAsync(roleToEdit!.Id, roleToEdit);
roleToEdit = null;
}
private async Task DeleteRole(RoleDto role)
{
await RolesClient.DeleteRoleAsync(role.Id);
Roles.Remove(role);
}
}
@page "/admin/users/{userId}"
@attribute [Authorize(Permissions.ManageUsers)]
<PageTitle>Users - Edit</PageTitle>
<h1>Edit</h1>
<h2>User</h2>
@if (User != null)
{
<div class="row">
<div class="col-md-4">
<EditForm Model="@User" OnValidSubmit="UpdateUser">
<div class="form-group">
<label for="username">Username</label>
<InputText id="username" @bind-Value="User.UserName"
class="form-control-plaintext" />
</div>
<div class="form-group">
<label for="email">Email</label>
<InputText id="email" @bind-Value="User.Email" class="form-
control-plaintext" />
</div>
<div class="form-group">
<label for="roles">Roles</label>
@foreach (var role in Roles)
{
<div class="form-check">
<input type="checkbox" class="form-check-input"
id="@($"role{role.Id}")" checked="@User.Roles.Contains(role.Name)"
@onchange="(args) => ToggleSelectedRole(role.Name)" />
<label class="form-check-label"
for="@($"role{role.Id}")">
@role.Name
</label>
</div>
}
</div>
<button type="submit" class="btn btn-primary">Save</button>
</EditForm>
</div>
</div>
}
<div>
<a href="/admin/users">Back to List</a>
</div>
using FlexibleAuth.Client.Services;
using FlexibleAuth.Shared;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Logging.Abstractions;
namespace FlexibleAuth.Client.Pages.Admin.Users;
public partial class Edit
{
[Parameter]
public string UserId { get; set; } = null!;
[Inject]
public IUsersClient UsersClient { get; set; } = null!;
[Inject]
public IRolesClient RolesClient { get; set; } = null!;
[Inject]
public NavigationManager Navigation { get; set; } = null!;
public UserDto User { get; set; } = new();
public ICollection<RoleDto> Roles { get; set; } = new List<RoleDto>();
protected override async Task OnParametersSetAsync()
{
Roles = await RolesClient.GetRolesAsync();
User = await UsersClient.GetUserAsync(UserId);
}
public void ToggleSelectedRole(string roleName)
{
if (User.Roles.Contains(roleName))
{
User.Roles.Remove(roleName);
}
else
{
User.Roles.Add(roleName);
}
StateHasChanged();
}
public async Task UpdateUser()
{
await UsersClient.PutUserAsync(User.Id, User);
Navigation.NavigateTo("/admin/users");
}
}
@page "/admin/users"
@attribute [Authorize(Permissions.ViewUsers | Permissions.ManageUsers)]
<PageTitle>Users</PageTitle>
<h1>Users</h1>
<p>This is a description.</p>
<table class="table table-striped table-hover w-75">
<thead>
<tr>
<th>Username</th>
<th>Email</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var user in Users)
{
<tr>
<td>@user.UserName</td>
<td>@user.Email</td>
<td>
<FlexibleAuthorizeView
Permissions="@Permissions.ManageUsers">
<a href="/admin/users/@user.Id">Edit</a>
</FlexibleAuthorizeView>
</td>
</tr>
}
</tbody>
</table>
using FlexibleAuth.Client.Services;
using FlexibleAuth.Shared;
using Microsoft.AspNetCore.Components;
namespace FlexibleAuth.Client.Pages.Admin.Users;
public partial class Index
{
[Inject] public IUsersClient UsersClient { get; set; } = null!;
public ICollection<UserDto> Users { get; set; } = new List<UserDto>();
protected override async Task OnInitializedAsync()
{
Users = await UsersClient.GetUsersAsync();
}
}
@page "/authentication/{action}"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
<RemoteAuthenticatorView Action="@Action" />
@code{
[Parameter] public string? Action { get; set; }
}
@page "/claims"
@attribute [Authorize]
<PageTitle>Claims</PageTitle>
<h1>Claims</h1>
<p>This component displays available claims.</p>
<AuthorizeView>
<ul>
@foreach (var claim in context.User.Claims)
{
<li><b>@claim.Type</b>: @claim.Value</li>
}
</ul>
</AuthorizeView>
@page "/counter"
@attribute [Authorize(Permissions.Counter)]
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}
@page "/fetchdata"
@attribute [Authorize(Permissions.Forecast)]
@inject HttpClient Http
<PageTitle>Weather forecast</PageTitle>
<h1>Weather forecast</h1>
<p>This component demonstrates fetching data from the server.</p>
@if (forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (var forecast in forecasts)
{
<tr>
<td>@forecast.Date.ToShortDateString()</td>
<td>@forecast.TemperatureC</td>
<td>@forecast.TemperatureF</td>
<td>@forecast.Summary</td>
</tr>
}
</tbody>
</table>
}
@code {
private WeatherForecast[]? forecasts;
protected override async Task OnInitializedAsync()
{
try
{
forecasts = await
Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast");
}
catch (AccessTokenNotAvailableException exception)
{
exception.Redirect();
}
}
}
@page "/"
<PageTitle>Index</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.
<SurveyPrompt Title="How is Blazor working for you?" />
//----------------------
// <auto-generated>
// Generated using the NSwag toolchain v13.18.2.0 (NJsonSchema v10.8.0.0
(Newtonsoft.Json v13.0.0.0)) (http://NSwag.org)
// </auto-generated>
//----------------------
using FlexibleAuth.Shared;
using Microsoft.AspNetCore.Mvc;
#pragma warning disable 108 // Disable "CS0108 '{derivedDto}.ToJson()' hides inherited
member '{dtoBase}.ToJson()'. Use the new keyword if hiding was intended."
#pragma warning disable 114 // Disable "CS0114
'{derivedDto}.RaisePropertyChanged(String)' hides inherited member
'dtoBase.RaisePropertyChanged(String)'. To make the current member override that
implementation, add the override keyword. Otherwise add the new keyword."
#pragma warning disable 472 // Disable "CS0472 The result of the expression is always
'false' since a value of type 'Int32' is never equal to 'null' of type 'Int32?'
#pragma warning disable 1573 // Disable "CS1573 Parameter '...' has no matching param tag
in the XML comment for ...
#pragma warning disable 1591 // Disable "CS1591 Missing XML comment for publicly visible
type or member ..."
#pragma warning disable 8073 // Disable "CS8073 The result of the expression is always
'false' since a value of type 'T' is never equal to 'null' of type 'T?'"
#pragma warning disable 3016 // Disable "CS3016 Arrays as attribute arguments is not CLS-
compliant"
#pragma warning disable 8603 // Disable "CS8603 Possible null reference return"
namespace FlexibleAuth.Client.Services
{
using System = global::System;
[System.CodeDom.Compiler.GeneratedCode("NSwag", "13.18.2.0 (NJsonSchema
v10.8.0.0 (Newtonsoft.Json v13.0.0.0))")]
public partial interface IWeatherForecastClient
{
/// <exception cref="ApiException">A server side error occurred.</exception>
System.Threading.Tasks.Task<System.Collections.Generic.ICollection<WeatherForecast>>
GetAsync();
/// <param name="cancellationToken">A cancellation token that can be used by other
objects or threads to receive notice of cancellation.</param>
/// <exception cref="ApiException">A server side error occurred.</exception>
System.Threading.Tasks.Task<System.Collections.Generic.ICollection<WeatherForecast>>
GetAsync(System.Threading.CancellationToken cancellationToken);
}
[System.CodeDom.Compiler.GeneratedCode("NSwag", "13.18.2.0 (NJsonSchema
v10.8.0.0 (Newtonsoft.Json v13.0.0.0))")]
public partial class WeatherForecastClient : IWeatherForecastClient
{
private System.Net.Http.HttpClient _httpClient;
private System.Lazy<Newtonsoft.Json.JsonSerializerSettings> _settings;
public WeatherForecastClient(System.Net.Http.HttpClient httpClient)
{
_httpClient = httpClient;
_settings = new
System.Lazy<Newtonsoft.Json.JsonSerializerSettings>(CreateSerializerSettings);
}
private Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings()
{
var settings = new Newtonsoft.Json.JsonSerializerSettings();
UpdateJsonSerializerSettings(settings);
return settings;
}
protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return
_settings.Value; } }
partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings
settings);
partial void PrepareRequest(System.Net.Http.HttpClient client,
System.Net.Http.HttpRequestMessage request, string url);
partial void PrepareRequest(System.Net.Http.HttpClient client,
System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder);
partial void ProcessResponse(System.Net.Http.HttpClient client,
System.Net.Http.HttpResponseMessage response);
/// <exception cref="ApiException">A server side error occurred.</exception>
public virtual
System.Threading.Tasks.Task<System.Collections.Generic.ICollection<WeatherForecast>>
GetAsync()
{
return GetAsync(System.Threading.CancellationToken.None);
}
/// <param name="cancellationToken">A cancellation token that can be used by other
objects or threads to receive notice of cancellation.</param>
/// <exception cref="ApiException">A server side error occurred.</exception>
public virtual async
System.Threading.Tasks.Task<System.Collections.Generic.ICollection<WeatherForecast>>
GetAsync(System.Threading.CancellationToken cancellationToken)
{
var urlBuilder_ = new System.Text.StringBuilder();
urlBuilder_.Append("WeatherForecast");
var client_ = _httpClient;
var disposeClient_ = false;
try
{
using (var request_ = new System.Net.Http.HttpRequestMessage())
{
request_.Method = new System.Net.Http.HttpMethod("GET");
request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValu
e.Parse("application/json"));
PrepareRequest(client_, request_, urlBuilder_);
var url_ = urlBuilder_.ToString();
request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
PrepareRequest(client_, request_, url_);
var response_ = await client_.SendAsync(request_,
System.Net.Http.HttpCompletionOption.ResponseHeadersRead,
cancellationToken).ConfigureAwait(false);
var disposeResponse_ = true;
try
{
var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_
=> h_.Key, h_ => h_.Value);
if (response_.Content != null && response_.Content.Headers != null)
{
foreach (var item_ in response_.Content.Headers)
headers_[item_.Key] = item_.Value;
}
ProcessResponse(client_, response_);
var status_ = (int)response_.StatusCode;
if (status_ == 200)
{
var objectResponse_ = await
ReadObjectResponseAsync<System.Collections.Generic.ICollection<WeatherForecast>>(res
ponse_, headers_, cancellationToken).ConfigureAwait(false);
if (objectResponse_.Object == null)
{
throw new ApiException("Response was null which was not expected.",
status_, objectResponse_.Text, headers_, null);
}
return objectResponse_.Object;
}
else
{
var responseData_ = response_.Content == null ? null : await
response_.Content.ReadAsStringAsync().ConfigureAwait(false);
throw new ApiException("The HTTP status code of the response was not
expected (" + status_ + ").", status_, responseData_, headers_, null);
}
}
finally
{
if (disposeResponse_)
response_.Dispose();
}
}
}
finally
{
if (disposeClient_)
client_.Dispose();
}
}
protected struct ObjectResponseResult<T>
{
public ObjectResponseResult(T responseObject, string responseText)
{
this.Object = responseObject;
this.Text = responseText;
}
public T Object { get; }
public string Text { get; }
}
public bool ReadResponseAsString { get; set; }
protected virtual async System.Threading.Tasks.Task<ObjectResponseResult<T>>
ReadObjectResponseAsync<T>(System.Net.Http.HttpResponseMessage response,
System.Collections.Generic.IReadOnlyDictionary<string,
System.Collections.Generic.IEnumerable<string>> headers,
System.Threading.CancellationToken cancellationToken)
{
if (response == null || response.Content == null)
{
return new ObjectResponseResult<T>(default(T), string.Empty);
}
if (ReadResponseAsString)
{
var responseText = await
response.Content.ReadAsStringAsync().ConfigureAwait(false);
try
{
var typedBody =
Newtonsoft.Json.JsonConvert.DeserializeObject<T>(responseText, JsonSerializerSettings);
return new ObjectResponseResult<T>(typedBody, responseText);
}
catch (Newtonsoft.Json.JsonException exception)
{
var message = "Could not deserialize the response body string as " +
typeof(T).FullName + ".";
throw new ApiException(message, (int)response.StatusCode, responseText,
headers, exception);
}
}
else
{
try
{
using (var responseStream = await
response.Content.ReadAsStreamAsync().ConfigureAwait(false))
using (var streamReader = new System.IO.StreamReader(responseStream))
using (var jsonTextReader = new
Newtonsoft.Json.JsonTextReader(streamReader))
{
var serializer = Newtonsoft.Json.JsonSerializer.Create(JsonSerializerSettings);
var typedBody = serializer.Deserialize<T>(jsonTextReader);
return new ObjectResponseResult<T>(typedBody, string.Empty);
}
}
catch (Newtonsoft.Json.JsonException exception)
{
var message = "Could not deserialize the response body stream as " +
typeof(T).FullName + ".";
throw new ApiException(message, (int)response.StatusCode, string.Empty,
headers, exception);
}
}
}
private string ConvertToString(object value, System.Globalization.CultureInfo
cultureInfo)
{
if (value == null)
{
return "";
}
if (value is System.Enum)
{
var name = System.Enum.GetName(value.GetType(), value);
if (name != null)
{
var field =
System.Reflection.IntrospectionExtensions.GetTypeInfo(value.GetType()).GetDeclaredField(
name);
if (field != null)
{
var attribute =
System.Reflection.CustomAttributeExtensions.GetCustomAttribute(field,
typeof(System.Runtime.Serialization.EnumMemberAttribute))
as System.Runtime.Serialization.EnumMemberAttribute;
if (attribute != null)
{
return attribute.Value != null ? attribute.Value : name;
}
}
var converted = System.Convert.ToString(System.Convert.ChangeType(value,
System.Enum.GetUnderlyingType(value.GetType()), cultureInfo));
return converted == null ? string.Empty : converted;
}
}
else if (value is bool)
{
return System.Convert.ToString((bool)value, cultureInfo).ToLowerInvariant();
}
else if (value is byte[])
{
return System.Convert.ToBase64String((byte[]) value);
}
else if (value.GetType().IsArray)
{
var array = System.Linq.Enumerable.OfType<object>((System.Array) value);
return string.Join(",", System.Linq.Enumerable.Select(array, o =>
ConvertToString(o, cultureInfo)));
}
var result = System.Convert.ToString(value, cultureInfo);
return result == null ? "" : result;
}
}
[System.CodeDom.Compiler.GeneratedCode("NSwag", "13.18.2.0 (NJsonSchema
v10.8.0.0 (Newtonsoft.Json v13.0.0.0))")]
public partial interface IAccessControlClient
{
/// <exception cref="ApiException">A server side error occurred.</exception>
System.Threading.Tasks.Task<AccessControlVm> GetConfigurationAsync();
/// <param name="cancellationToken">A cancellation token that can be used by other
objects or threads to receive notice of cancellation.</param>
/// <exception cref="ApiException">A server side error occurred.</exception>
System.Threading.Tasks.Task<AccessControlVm>
GetConfigurationAsync(System.Threading.CancellationToken cancellationToken);
/// <exception cref="ApiException">A server side error occurred.</exception>
System.Threading.Tasks.Task UpdateConfigurationAsync(RoleDto updatedRole);
/// <param name="cancellationToken">A cancellation token that can be used by other
objects or threads to receive notice of cancellation.</param>
/// <exception cref="ApiException">A server side error occurred.</exception>
System.Threading.Tasks.Task UpdateConfigurationAsync(RoleDto updatedRole,
System.Threading.CancellationToken cancellationToken);
[System.CodeDom.Compiler.GeneratedCode("NSwag", "13.18.2.0 (NJsonSchema
v10.8.0.0 (Newtonsoft.Json v13.0.0.0))")]
public partial class AccessControlClient : IAccessControlClient
{
private System.Net.Http.HttpClient _httpClient;
private System.Lazy<Newtonsoft.Json.JsonSerializerSettings> _settings;
public AccessControlClient(System.Net.Http.HttpClient httpClient)
{
_httpClient = httpClient;
_settings = new
System.Lazy<Newtonsoft.Json.JsonSerializerSettings>(CreateSerializerSettings);
}
private Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings()
{
var settings = new Newtonsoft.Json.JsonSerializerSettings();
UpdateJsonSerializerSettings(settings);
return settings;
}
protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return
_settings.Value; } }
partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings
settings);
partial void PrepareRequest(System.Net.Http.HttpClient client,
System.Net.Http.HttpRequestMessage request, string url);
partial void PrepareRequest(System.Net.Http.HttpClient client,
System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder);
partial void ProcessResponse(System.Net.Http.HttpClient client,
System.Net.Http.HttpResponseMessage response);
/// <exception cref="ApiException">A server side error occurred.</exception>
public virtual System.Threading.Tasks.Task<AccessControlVm> GetConfigurationAsync()
{
return GetConfigurationAsync(System.Threading.CancellationToken.None);
}
/// <param name="cancellationToken">A cancellation token that can be used by other
objects or threads to receive notice of cancellation.</param>
/// <exception cref="ApiException">A server side error occurred.</exception>
public virtual async System.Threading.Tasks.Task<AccessControlVm>
GetConfigurationAsync(System.Threading.CancellationToken cancellationToken)
{
var urlBuilder_ = new System.Text.StringBuilder();
urlBuilder_.Append("api/Admin/AccessControl");
var client_ = _httpClient;
var disposeClient_ = false;
try
{
using (var request_ = new System.Net.Http.HttpRequestMessage())
{
request_.Method = new System.Net.Http.HttpMethod("GET");
request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValu
e.Parse("application/json"));
PrepareRequest(client_, request_, urlBuilder_);
var url_ = urlBuilder_.ToString();
request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
PrepareRequest(client_, request_, url_);
var response_ = await client_.SendAsync(request_,
System.Net.Http.HttpCompletionOption.ResponseHeadersRead,
cancellationToken).ConfigureAwait(false);
var disposeResponse_ = true;
try
{
var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_
=> h_.Key, h_ => h_.Value);
if (response_.Content != null && response_.Content.Headers != null)
{
foreach (var item_ in response_.Content.Headers)
headers_[item_.Key] = item_.Value;
}
ProcessResponse(client_, response_);
var status_ = (int)response_.StatusCode;
if (status_ == 200)
{
var objectResponse_ = await
ReadObjectResponseAsync<AccessControlVm>(response_, headers_,
cancellationToken).ConfigureAwait(false);
if (objectResponse_.Object == null)
{
throw new ApiException("Response was null which was not expected.",
status_, objectResponse_.Text, headers_, null);
}
return objectResponse_.Object;
}
else
{
var responseData_ = response_.Content == null ? null : await
response_.Content.ReadAsStringAsync().ConfigureAwait(false);
throw new ApiException("The HTTP status code of the response was not
expected (" + status_ + ").", status_, responseData_, headers_, null);
}
}
finally
{
if (disposeResponse_)
response_.Dispose();
}
}
}
finally
{
if (disposeClient_)
client_.Dispose();
}
}
/// <exception cref="ApiException">A server side error occurred.</exception>
public virtual System.Threading.Tasks.Task UpdateConfigurationAsync(RoleDto
updatedRole)
{
return UpdateConfigurationAsync(updatedRole,
System.Threading.CancellationToken.None);
}
/// <param name="cancellationToken">A cancellation token that can be used by other
objects or threads to receive notice of cancellation.</param>
/// <exception cref="ApiException">A server side error occurred.</exception>
public virtual async System.Threading.Tasks.Task UpdateConfigurationAsync(RoleDto
updatedRole, System.Threading.CancellationToken cancellationToken)
{
if (updatedRole == null)
throw new System.ArgumentNullException("updatedRole");
var urlBuilder_ = new System.Text.StringBuilder();
urlBuilder_.Append("api/Admin/AccessControl");
var client_ = _httpClient;
var disposeClient_ = false;
try
{
using (var request_ = new System.Net.Http.HttpRequestMessage())
{
var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(updatedRole,
_settings.Value);
var content_ = new System.Net.Http.StringContent(json_);
content_.Headers.ContentType =
System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json");
request_.Content = content_;
request_.Method = new System.Net.Http.HttpMethod("PUT");
PrepareRequest(client_, request_, urlBuilder_);
var url_ = urlBuilder_.ToString();
request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
PrepareRequest(client_, request_, url_);
var response_ = await client_.SendAsync(request_,
System.Net.Http.HttpCompletionOption.ResponseHeadersRead,
cancellationToken).ConfigureAwait(false);
var disposeResponse_ = true;
try
{
var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_
=> h_.Key, h_ => h_.Value);
if (response_.Content != null && response_.Content.Headers != null)
{
foreach (var item_ in response_.Content.Headers)
headers_[item_.Key] = item_.Value;
}
ProcessResponse(client_, response_);
var status_ = (int)response_.StatusCode;
if (status_ == 204)
{
return;
}
else
{
var responseData_ = response_.Content == null ? null : await
response_.Content.ReadAsStringAsync().ConfigureAwait(false);
throw new ApiException("The HTTP status code of the response was not
expected (" + status_ + ").", status_, responseData_, headers_, null);
}
}
finally
{
if (disposeResponse_)
response_.Dispose();
}
}
}
finally
{
if (disposeClient_)
client_.Dispose();
}
}
protected struct ObjectResponseResult<T>
{
public ObjectResponseResult(T responseObject, string responseText)
{
this.Object = responseObject;
this.Text = responseText;
}
public T Object { get; }
public string Text { get; }
}
public bool ReadResponseAsString { get; set; }
protected virtual async System.Threading.Tasks.Task<ObjectResponseResult<T>>
ReadObjectResponseAsync<T>(System.Net.Http.HttpResponseMessage response,
System.Collections.Generic.IReadOnlyDictionary<string,
System.Collections.Generic.IEnumerable<string>> headers,
System.Threading.CancellationToken cancellationToken)
{
if (response == null || response.Content == null)
{
return new ObjectResponseResult<T>(default(T), string.Empty);
}
if (ReadResponseAsString)
{
var responseText = await
response.Content.ReadAsStringAsync().ConfigureAwait(false);
try
{
var typedBody =
Newtonsoft.Json.JsonConvert.DeserializeObject<T>(responseText, JsonSerializerSettings);
return new ObjectResponseResult<T>(typedBody, responseText);
}
catch (Newtonsoft.Json.JsonException exception)
{
var message = "Could not deserialize the response body string as " +
typeof(T).FullName + ".";
throw new ApiException(message, (int)response.StatusCode, responseText,
headers, exception);
}
}
else
{
try
{
using (var responseStream = await
response.Content.ReadAsStreamAsync().ConfigureAwait(false))
using (var streamReader = new System.IO.StreamReader(responseStream))
using (var jsonTextReader = new
Newtonsoft.Json.JsonTextReader(streamReader))
{
var serializer = Newtonsoft.Json.JsonSerializer.Create(JsonSerializerSettings);
var typedBody = serializer.Deserialize<T>(jsonTextReader);
return new ObjectResponseResult<T>(typedBody, string.Empty);
}
}
catch (Newtonsoft.Json.JsonException exception)
{
var message = "Could not deserialize the response body stream as " +
typeof(T).FullName + ".";
throw new ApiException(message, (int)response.StatusCode, string.Empty,
headers, exception);
}
}
}
private string ConvertToString(object value, System.Globalization.CultureInfo
cultureInfo)
{
if (value == null)
{
return "";
}
if (value is System.Enum)
{
var name = System.Enum.GetName(value.GetType(), value);
if (name != null)
{
var field =
System.Reflection.IntrospectionExtensions.GetTypeInfo(value.GetType()).GetDeclaredField(
name);
if (field != null)
{
var attribute =
System.Reflection.CustomAttributeExtensions.GetCustomAttribute(field,
typeof(System.Runtime.Serialization.EnumMemberAttribute))
as System.Runtime.Serialization.EnumMemberAttribute;
if (attribute != null)
{
return attribute.Value != null ? attribute.Value : name;
}
}
var converted = System.Convert.ToString(System.Convert.ChangeType(value,
System.Enum.GetUnderlyingType(value.GetType()), cultureInfo));
return converted == null ? string.Empty : converted;
}
}
else if (value is bool)
{
return System.Convert.ToString((bool)value, cultureInfo).ToLowerInvariant();
}
else if (value is byte[])
{
return System.Convert.ToBase64String((byte[]) value);
}
else if (value.GetType().IsArray)
{
var array = System.Linq.Enumerable.OfType<object>((System.Array) value);
return string.Join(",", System.Linq.Enumerable.Select(array, o =>
ConvertToString(o, cultureInfo)));
}
var result = System.Convert.ToString(value, cultureInfo);
return result == null ? "" : result;
}
}
[System.CodeDom.Compiler.GeneratedCode("NSwag", "13.18.2.0 (NJsonSchema
v10.8.0.0 (Newtonsoft.Json v13.0.0.0))")]
public partial interface IRolesClient
{
/// <exception cref="ApiException">A server side error occurred.</exception>
System.Threading.Tasks.Task<System.Collections.Generic.ICollection<RoleDto>>
GetRolesAsync();
/// <param name="cancellationToken">A cancellation token that can be used by other
objects or threads to receive notice of cancellation.</param>
/// <exception cref="ApiException">A server side error occurred.</exception>
System.Threading.Tasks.Task<System.Collections.Generic.ICollection<RoleDto>>
GetRolesAsync(System.Threading.CancellationToken cancellationToken);
/// <exception cref="ApiException">A server side error occurred.</exception>
System.Threading.Tasks.Task<RoleDto> PostRoleAsync(RoleDto newRole);
/// <param name="cancellationToken">A cancellation token that can be used by other
objects or threads to receive notice of cancellation.</param>
/// <exception cref="ApiException">A server side error occurred.</exception>
System.Threading.Tasks.Task<RoleDto> PostRoleAsync(RoleDto newRole,
System.Threading.CancellationToken cancellationToken);
/// <exception cref="ApiException">A server side error occurred.</exception>
System.Threading.Tasks.Task PutRoleAsync(string id, RoleDto updatedRole);
/// <param name="cancellationToken">A cancellation token that can be used by other
objects or threads to receive notice of cancellation.</param>
/// <exception cref="ApiException">A server side error occurred.</exception>
System.Threading.Tasks.Task PutRoleAsync(string id, RoleDto updatedRole,
System.Threading.CancellationToken cancellationToken);
/// <exception cref="ApiException">A server side error occurred.</exception>
System.Threading.Tasks.Task DeleteRoleAsync(string id);
/// <param name="cancellationToken">A cancellation token that can be used by other
objects or threads to receive notice of cancellation.</param>
/// <exception cref="ApiException">A server side error occurred.</exception>
System.Threading.Tasks.Task DeleteRoleAsync(string id,
System.Threading.CancellationToken cancellationToken);
[System.CodeDom.Compiler.GeneratedCode("NSwag", "13.18.2.0 (NJsonSchema
v10.8.0.0 (Newtonsoft.Json v13.0.0.0))")]
public partial class RolesClient : IRolesClient
{
private System.Net.Http.HttpClient _httpClient;
private System.Lazy<Newtonsoft.Json.JsonSerializerSettings> _settings;
public RolesClient(System.Net.Http.HttpClient httpClient)
{
_httpClient = httpClient;
_settings = new
System.Lazy<Newtonsoft.Json.JsonSerializerSettings>(CreateSerializerSettings);
}
private Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings()
{
var settings = new Newtonsoft.Json.JsonSerializerSettings();
UpdateJsonSerializerSettings(settings);
return settings;
}
protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return
_settings.Value; } }
partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings
settings);
partial void PrepareRequest(System.Net.Http.HttpClient client,
System.Net.Http.HttpRequestMessage request, string url);
partial void PrepareRequest(System.Net.Http.HttpClient client,
System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder);
partial void ProcessResponse(System.Net.Http.HttpClient client,
System.Net.Http.HttpResponseMessage response);
/// <exception cref="ApiException">A server side error occurred.</exception>
public virtual
System.Threading.Tasks.Task<System.Collections.Generic.ICollection<RoleDto>>
GetRolesAsync()
{
return GetRolesAsync(System.Threading.CancellationToken.None);
}
/// <param name="cancellationToken">A cancellation token that can be used by other
objects or threads to receive notice of cancellation.</param>
/// <exception cref="ApiException">A server side error occurred.</exception>
public virtual async
System.Threading.Tasks.Task<System.Collections.Generic.ICollection<RoleDto>>
GetRolesAsync(System.Threading.CancellationToken cancellationToken)
{
var urlBuilder_ = new System.Text.StringBuilder();
urlBuilder_.Append("api/Admin/Roles");
var client_ = _httpClient;
var disposeClient_ = false;
try
{
using (var request_ = new System.Net.Http.HttpRequestMessage())
{
request_.Method = new System.Net.Http.HttpMethod("GET");
request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValu
e.Parse("application/json"));
PrepareRequest(client_, request_, urlBuilder_);
var url_ = urlBuilder_.ToString();
request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
PrepareRequest(client_, request_, url_);
var response_ = await client_.SendAsync(request_,
System.Net.Http.HttpCompletionOption.ResponseHeadersRead,
cancellationToken).ConfigureAwait(false);
var disposeResponse_ = true;
try
{
var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_
=> h_.Key, h_ => h_.Value);
if (response_.Content != null && response_.Content.Headers != null)
{
foreach (var item_ in response_.Content.Headers)
headers_[item_.Key] = item_.Value;
}
ProcessResponse(client_, response_);
var status_ = (int)response_.StatusCode;
if (status_ == 200)
{
var objectResponse_ = await
ReadObjectResponseAsync<System.Collections.Generic.ICollection<RoleDto>>(response_,
headers_, cancellationToken).ConfigureAwait(false);
if (objectResponse_.Object == null)
{
throw new ApiException("Response was null which was not expected.",
status_, objectResponse_.Text, headers_, null);
}
return objectResponse_.Object;
}
else
{
var responseData_ = response_.Content == null ? null : await
response_.Content.ReadAsStringAsync().ConfigureAwait(false);
throw new ApiException("The HTTP status code of the response was not
expected (" + status_ + ").", status_, responseData_, headers_, null);
}
}
finally
{
if (disposeResponse_)
response_.Dispose();
}
}
}
finally
{
if (disposeClient_)
client_.Dispose();
}
}
/// <exception cref="ApiException">A server side error occurred.</exception>
public virtual System.Threading.Tasks.Task<RoleDto> PostRoleAsync(RoleDto newRole)
{
return PostRoleAsync(newRole, System.Threading.CancellationToken.None);
}
/// <param name="cancellationToken">A cancellation token that can be used by other
objects or threads to receive notice of cancellation.</param>
/// <exception cref="ApiException">A server side error occurred.</exception>
public virtual async System.Threading.Tasks.Task<RoleDto> PostRoleAsync(RoleDto
newRole, System.Threading.CancellationToken cancellationToken)
{
if (newRole == null)
throw new System.ArgumentNullException("newRole");
var urlBuilder_ = new System.Text.StringBuilder();
urlBuilder_.Append("api/Admin/Roles");
var client_ = _httpClient;
var disposeClient_ = false;
try
{
using (var request_ = new System.Net.Http.HttpRequestMessage())
{
var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(newRole,
_settings.Value);
var content_ = new System.Net.Http.StringContent(json_);
content_.Headers.ContentType =
System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json");
request_.Content = content_;
request_.Method = new System.Net.Http.HttpMethod("POST");
request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValu
e.Parse("application/json"));
PrepareRequest(client_, request_, urlBuilder_);
var url_ = urlBuilder_.ToString();
request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
PrepareRequest(client_, request_, url_);
var response_ = await client_.SendAsync(request_,
System.Net.Http.HttpCompletionOption.ResponseHeadersRead,
cancellationToken).ConfigureAwait(false);
var disposeResponse_ = true;
try
{
var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_
=> h_.Key, h_ => h_.Value);
if (response_.Content != null && response_.Content.Headers != null)
{
foreach (var item_ in response_.Content.Headers)
headers_[item_.Key] = item_.Value;
}
ProcessResponse(client_, response_);
var status_ = (int)response_.StatusCode;
if (status_ == 200)
{
var objectResponse_ = await
ReadObjectResponseAsync<RoleDto>(response_, headers_,
cancellationToken).ConfigureAwait(false);
if (objectResponse_.Object == null)
{
throw new ApiException("Response was null which was not expected.",
status_, objectResponse_.Text, headers_, null);
}
return objectResponse_.Object;
}
else
{
var responseData_ = response_.Content == null ? null : await
response_.Content.ReadAsStringAsync().ConfigureAwait(false);
throw new ApiException("The HTTP status code of the response was not
expected (" + status_ + ").", status_, responseData_, headers_, null);
}
}
finally
{
if (disposeResponse_)
response_.Dispose();
}
}
}
finally
{
if (disposeClient_)
client_.Dispose();
}
}
/// <exception cref="ApiException">A server side error occurred.</exception>
public virtual System.Threading.Tasks.Task PutRoleAsync(string id, RoleDto
updatedRole)
{
return PutRoleAsync(id, updatedRole, System.Threading.CancellationToken.None);
}
/// <param name="cancellationToken">A cancellation token that can be used by other
objects or threads to receive notice of cancellation.</param>
/// <exception cref="ApiException">A server side error occurred.</exception>
public virtual async System.Threading.Tasks.Task PutRoleAsync(string id, RoleDto
updatedRole, System.Threading.CancellationToken cancellationToken)
{
if (updatedRole == null)
throw new System.ArgumentNullException("updatedRole");
var urlBuilder_ = new System.Text.StringBuilder();
urlBuilder_.Append("api/Admin/Roles/{id}");
urlBuilder_.Replace("{id}", System.Uri.EscapeDataString(ConvertToString(id,
System.Globalization.CultureInfo.InvariantCulture)));
var client_ = _httpClient;
var disposeClient_ = false;
try
{
using (var request_ = new System.Net.Http.HttpRequestMessage())
{
var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(updatedRole,
_settings.Value);
var content_ = new System.Net.Http.StringContent(json_);
content_.Headers.ContentType =
System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json");
request_.Content = content_;
request_.Method = new System.Net.Http.HttpMethod("PUT");
PrepareRequest(client_, request_, urlBuilder_);
var url_ = urlBuilder_.ToString();
request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
PrepareRequest(client_, request_, url_);
var response_ = await client_.SendAsync(request_,
System.Net.Http.HttpCompletionOption.ResponseHeadersRead,
cancellationToken).ConfigureAwait(false);
var disposeResponse_ = true;
try
{
var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_
=> h_.Key, h_ => h_.Value);
if (response_.Content != null && response_.Content.Headers != null)
{
foreach (var item_ in response_.Content.Headers)
headers_[item_.Key] = item_.Value;
}
ProcessResponse(client_, response_);
var status_ = (int)response_.StatusCode;
if (status_ == 204)
{
return;
}
else
if (status_ == 400)
{
var objectResponse_ = await
ReadObjectResponseAsync<ProblemDetails>(response_, headers_,
cancellationToken).ConfigureAwait(false);
if (objectResponse_.Object == null)
{
throw new ApiException("Response was null which was not expected.",
status_, objectResponse_.Text, headers_, null);
}
throw new ApiException<ProblemDetails>("A server side error occurred.",
status_, objectResponse_.Text, headers_, objectResponse_.Object, null);
}
else
{
var responseData_ = response_.Content == null ? null : await
response_.Content.ReadAsStringAsync().ConfigureAwait(false);
throw new ApiException("The HTTP status code of the response was not
expected (" + status_ + ").", status_, responseData_, headers_, null);
}
}
finally
{
if (disposeResponse_)
response_.Dispose();
}
}
}
finally
{
if (disposeClient_)
client_.Dispose();
}
}
/// <exception cref="ApiException">A server side error occurred.</exception>
public virtual System.Threading.Tasks.Task DeleteRoleAsync(string id)
{
return DeleteRoleAsync(id, System.Threading.CancellationToken.None);
}
/// <param name="cancellationToken">A cancellation token that can be used by other
objects or threads to receive notice of cancellation.</param>
/// <exception cref="ApiException">A server side error occurred.</exception>
public virtual async System.Threading.Tasks.Task DeleteRoleAsync(string id,
System.Threading.CancellationToken cancellationToken)
{
var urlBuilder_ = new System.Text.StringBuilder();
urlBuilder_.Append("api/Admin/Roles/{id}");
urlBuilder_.Replace("{id}", System.Uri.EscapeDataString(ConvertToString(id,
System.Globalization.CultureInfo.InvariantCulture)));
var client_ = _httpClient;
var disposeClient_ = false;
try
{
using (var request_ = new System.Net.Http.HttpRequestMessage())
{
request_.Method = new System.Net.Http.HttpMethod("DELETE");
PrepareRequest(client_, request_, urlBuilder_);
var url_ = urlBuilder_.ToString();
request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
PrepareRequest(client_, request_, url_);
var response_ = await client_.SendAsync(request_,
System.Net.Http.HttpCompletionOption.ResponseHeadersRead,
cancellationToken).ConfigureAwait(false);
var disposeResponse_ = true;
try
{
var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_
=> h_.Key, h_ => h_.Value);
if (response_.Content != null && response_.Content.Headers != null)
{
foreach (var item_ in response_.Content.Headers)
headers_[item_.Key] = item_.Value;
}
ProcessResponse(client_, response_);
var status_ = (int)response_.StatusCode;
if (status_ == 204)
{
return;
}
else
if (status_ == 404)
{
var objectResponse_ = await
ReadObjectResponseAsync<ProblemDetails>(response_, headers_,
cancellationToken).ConfigureAwait(false);
if (objectResponse_.Object == null)
{
throw new ApiException("Response was null which was not expected.",
status_, objectResponse_.Text, headers_, null);
}
throw new ApiException<ProblemDetails>("A server side error occurred.",
status_, objectResponse_.Text, headers_, objectResponse_.Object, null);
}
else
{
var responseData_ = response_.Content == null ? null : await
response_.Content.ReadAsStringAsync().ConfigureAwait(false);
throw new ApiException("The HTTP status code of the response was not
expected (" + status_ + ").", status_, responseData_, headers_, null);
}
}
finally
{
if (disposeResponse_)
response_.Dispose();
}
}
}
finally
{
if (disposeClient_)
client_.Dispose();
}
}
protected struct ObjectResponseResult<T>
{
public ObjectResponseResult(T responseObject, string responseText)
{
this.Object = responseObject;
this.Text = responseText;
}
public T Object { get; }
public string Text { get; }
}
public bool ReadResponseAsString { get; set; }
protected virtual async System.Threading.Tasks.Task<ObjectResponseResult<T>>
ReadObjectResponseAsync<T>(System.Net.Http.HttpResponseMessage response,
System.Collections.Generic.IReadOnlyDictionary<string,
System.Collections.Generic.IEnumerable<string>> headers,
System.Threading.CancellationToken cancellationToken)
{
if (response == null || response.Content == null)
{
return new ObjectResponseResult<T>(default(T), string.Empty);
}
if (ReadResponseAsString)
{
var responseText = await
response.Content.ReadAsStringAsync().ConfigureAwait(false);
try
{
var typedBody =
Newtonsoft.Json.JsonConvert.DeserializeObject<T>(responseText, JsonSerializerSettings);
return new ObjectResponseResult<T>(typedBody, responseText);
}
catch (Newtonsoft.Json.JsonException exception)
{
var message = "Could not deserialize the response body string as " +
typeof(T).FullName + ".";
throw new ApiException(message, (int)response.StatusCode, responseText,
headers, exception);
}
}
else
{
try
{
using (var responseStream = await
response.Content.ReadAsStreamAsync().ConfigureAwait(false))
using (var streamReader = new System.IO.StreamReader(responseStream))
using (var jsonTextReader = new
Newtonsoft.Json.JsonTextReader(streamReader))
{
var serializer = Newtonsoft.Json.JsonSerializer.Create(JsonSerializerSettings);
var typedBody = serializer.Deserialize<T>(jsonTextReader);
return new ObjectResponseResult<T>(typedBody, string.Empty);
}
}
catch (Newtonsoft.Json.JsonException exception)
{
var message = "Could not deserialize the response body stream as " +
typeof(T).FullName + ".";
throw new ApiException(message, (int)response.StatusCode, string.Empty,
headers, exception);
}
}
}
private string ConvertToString(object value, System.Globalization.CultureInfo
cultureInfo)
{
if (value == null)
{
return "";
}
if (value is System.Enum)
{
var name = System.Enum.GetName(value.GetType(), value);
if (name != null)
{
var field =
System.Reflection.IntrospectionExtensions.GetTypeInfo(value.GetType()).GetDeclaredField(
name);
if (field != null)
{
var attribute =
System.Reflection.CustomAttributeExtensions.GetCustomAttribute(field,
typeof(System.Runtime.Serialization.EnumMemberAttribute))
as System.Runtime.Serialization.EnumMemberAttribute;
if (attribute != null)
{
return attribute.Value != null ? attribute.Value : name;
}
}
var converted = System.Convert.ToString(System.Convert.ChangeType(value,
System.Enum.GetUnderlyingType(value.GetType()), cultureInfo));
return converted == null ? string.Empty : converted;
}
}
else if (value is bool)
{
return System.Convert.ToString((bool)value, cultureInfo).ToLowerInvariant();
}
else if (value is byte[])
{
return System.Convert.ToBase64String((byte[]) value);
}
else if (value.GetType().IsArray)
{
var array = System.Linq.Enumerable.OfType<object>((System.Array) value);
return string.Join(",", System.Linq.Enumerable.Select(array, o =>
ConvertToString(o, cultureInfo)));
}
var result = System.Convert.ToString(value, cultureInfo);
return result == null ? "" : result;
}
}
[System.CodeDom.Compiler.GeneratedCode("NSwag", "13.18.2.0 (NJsonSchema
v10.8.0.0 (Newtonsoft.Json v13.0.0.0))")]
public partial interface IUsersClient
{
/// <exception cref="ApiException">A server side error occurred.</exception>
System.Threading.Tasks.Task<System.Collections.Generic.ICollection<UserDto>>
GetUsersAsync();
/// <param name="cancellationToken">A cancellation token that can be used by other
objects or threads to receive notice of cancellation.</param>
/// <exception cref="ApiException">A server side error occurred.</exception>
System.Threading.Tasks.Task<System.Collections.Generic.ICollection<UserDto>>
GetUsersAsync(System.Threading.CancellationToken cancellationToken);
/// <exception cref="ApiException">A server side error occurred.</exception>
System.Threading.Tasks.Task<UserDto> GetUserAsync(string id);
/// <param name="cancellationToken">A cancellation token that can be used by other
objects or threads to receive notice of cancellation.</param>
/// <exception cref="ApiException">A server side error occurred.</exception>
System.Threading.Tasks.Task<UserDto> GetUserAsync(string id,
System.Threading.CancellationToken cancellationToken);
/// <exception cref="ApiException">A server side error occurred.</exception>
System.Threading.Tasks.Task PutUserAsync(string id, UserDto updatedUser);
/// <param name="cancellationToken">A cancellation token that can be used by other
objects or threads to receive notice of cancellation.</param>
/// <exception cref="ApiException">A server side error occurred.</exception>
System.Threading.Tasks.Task PutUserAsync(string id, UserDto updatedUser,
System.Threading.CancellationToken cancellationToken);
[System.CodeDom.Compiler.GeneratedCode("NSwag", "13.18.2.0 (NJsonSchema
v10.8.0.0 (Newtonsoft.Json v13.0.0.0))")]
public partial class UsersClient : IUsersClient
{
private System.Net.Http.HttpClient _httpClient;
private System.Lazy<Newtonsoft.Json.JsonSerializerSettings> _settings;
public UsersClient(System.Net.Http.HttpClient httpClient)
{
_httpClient = httpClient;
_settings = new
System.Lazy<Newtonsoft.Json.JsonSerializerSettings>(CreateSerializerSettings);
}
private Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings()
{
var settings = new Newtonsoft.Json.JsonSerializerSettings();
UpdateJsonSerializerSettings(settings);
return settings;
}
protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return
_settings.Value; } }
partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings
settings);
partial void PrepareRequest(System.Net.Http.HttpClient client,
System.Net.Http.HttpRequestMessage request, string url);
partial void PrepareRequest(System.Net.Http.HttpClient client,
System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder);
partial void ProcessResponse(System.Net.Http.HttpClient client,
System.Net.Http.HttpResponseMessage response);
/// <exception cref="ApiException">A server side error occurred.</exception>
public virtual
System.Threading.Tasks.Task<System.Collections.Generic.ICollection<UserDto>>
GetUsersAsync()
{
return GetUsersAsync(System.Threading.CancellationToken.None);
}
/// <param name="cancellationToken">A cancellation token that can be used by other
objects or threads to receive notice of cancellation.</param>
/// <exception cref="ApiException">A server side error occurred.</exception>
public virtual async
System.Threading.Tasks.Task<System.Collections.Generic.ICollection<UserDto>>
GetUsersAsync(System.Threading.CancellationToken cancellationToken)
{
var urlBuilder_ = new System.Text.StringBuilder();
urlBuilder_.Append("api/Admin/Users");
var client_ = _httpClient;
var disposeClient_ = false;
try
{
using (var request_ = new System.Net.Http.HttpRequestMessage())
{
request_.Method = new System.Net.Http.HttpMethod("GET");
request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValu
e.Parse("application/json"));
PrepareRequest(client_, request_, urlBuilder_);
var url_ = urlBuilder_.ToString();
request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
PrepareRequest(client_, request_, url_);
var response_ = await client_.SendAsync(request_,
System.Net.Http.HttpCompletionOption.ResponseHeadersRead,
cancellationToken).ConfigureAwait(false);
var disposeResponse_ = true;
try
{
var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_
=> h_.Key, h_ => h_.Value);
if (response_.Content != null && response_.Content.Headers != null)
{
foreach (var item_ in response_.Content.Headers)
headers_[item_.Key] = item_.Value;
}
ProcessResponse(client_, response_);
var status_ = (int)response_.StatusCode;
if (status_ == 200)
{
var objectResponse_ = await
ReadObjectResponseAsync<System.Collections.Generic.ICollection<UserDto>>(response_,
headers_, cancellationToken).ConfigureAwait(false);
if (objectResponse_.Object == null)
{
throw new ApiException("Response was null which was not expected.",
status_, objectResponse_.Text, headers_, null);
}
return objectResponse_.Object;
}
else
{
var responseData_ = response_.Content == null ? null : await
response_.Content.ReadAsStringAsync().ConfigureAwait(false);
throw new ApiException("The HTTP status code of the response was not
expected (" + status_ + ").", status_, responseData_, headers_, null);
}
}
finally
{
if (disposeResponse_)
response_.Dispose();
}
}
}
finally
{
if (disposeClient_)
client_.Dispose();
}
}
/// <exception cref="ApiException">A server side error occurred.</exception>
public virtual System.Threading.Tasks.Task<UserDto> GetUserAsync(string id)
{
return GetUserAsync(id, System.Threading.CancellationToken.None);
}
/// <param name="cancellationToken">A cancellation token that can be used by other
objects or threads to receive notice of cancellation.</param>
/// <exception cref="ApiException">A server side error occurred.</exception>
public virtual async System.Threading.Tasks.Task<UserDto> GetUserAsync(string id,
System.Threading.CancellationToken cancellationToken)
{
var urlBuilder_ = new System.Text.StringBuilder();
urlBuilder_.Append("api/Admin/Users/{id}");
urlBuilder_.Replace("{id}", System.Uri.EscapeDataString(ConvertToString(id,
System.Globalization.CultureInfo.InvariantCulture)));
var client_ = _httpClient;
var disposeClient_ = false;
try
{
using (var request_ = new System.Net.Http.HttpRequestMessage())
{
request_.Method = new System.Net.Http.HttpMethod("GET");
request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValu
e.Parse("application/json"));
PrepareRequest(client_, request_, urlBuilder_);
var url_ = urlBuilder_.ToString();
request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
PrepareRequest(client_, request_, url_);
var response_ = await client_.SendAsync(request_,
System.Net.Http.HttpCompletionOption.ResponseHeadersRead,
cancellationToken).ConfigureAwait(false);
var disposeResponse_ = true;
try
{
var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_
=> h_.Key, h_ => h_.Value);
if (response_.Content != null && response_.Content.Headers != null)
{
foreach (var item_ in response_.Content.Headers)
headers_[item_.Key] = item_.Value;
}
ProcessResponse(client_, response_);
var status_ = (int)response_.StatusCode;
if (status_ == 200)
{
var objectResponse_ = await
ReadObjectResponseAsync<UserDto>(response_, headers_,
cancellationToken).ConfigureAwait(false);
if (objectResponse_.Object == null)
{
throw new ApiException("Response was null which was not expected.",
status_, objectResponse_.Text, headers_, null);
}
return objectResponse_.Object;
}
else
{
var responseData_ = response_.Content == null ? null : await
response_.Content.ReadAsStringAsync().ConfigureAwait(false);
throw new ApiException("The HTTP status code of the response was not
expected (" + status_ + ").", status_, responseData_, headers_, null);
}
}
finally
{
if (disposeResponse_)
response_.Dispose();
}
}
}
finally
{
if (disposeClient_)
client_.Dispose();
}
}
/// <exception cref="ApiException">A server side error occurred.</exception>
public virtual System.Threading.Tasks.Task PutUserAsync(string id, UserDto
updatedUser)
{
return PutUserAsync(id, updatedUser, System.Threading.CancellationToken.None);
}
/// <param name="cancellationToken">A cancellation token that can be used by other
objects or threads to receive notice of cancellation.</param>
/// <exception cref="ApiException">A server side error occurred.</exception>
public virtual async System.Threading.Tasks.Task PutUserAsync(string id, UserDto
updatedUser, System.Threading.CancellationToken cancellationToken)
{
if (updatedUser == null)
throw new System.ArgumentNullException("updatedUser");
var urlBuilder_ = new System.Text.StringBuilder();
urlBuilder_.Append("api/Admin/Users/{id}");
urlBuilder_.Replace("{id}", System.Uri.EscapeDataString(ConvertToString(id,
System.Globalization.CultureInfo.InvariantCulture)));
var client_ = _httpClient;
var disposeClient_ = false;
try
{
using (var request_ = new System.Net.Http.HttpRequestMessage())
{
var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(updatedUser,
_settings.Value);
var content_ = new System.Net.Http.StringContent(json_);
content_.Headers.ContentType =
System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json");
request_.Content = content_;
request_.Method = new System.Net.Http.HttpMethod("PUT");
PrepareRequest(client_, request_, urlBuilder_);
var url_ = urlBuilder_.ToString();
request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
PrepareRequest(client_, request_, url_);
var response_ = await client_.SendAsync(request_,
System.Net.Http.HttpCompletionOption.ResponseHeadersRead,
cancellationToken).ConfigureAwait(false);
var disposeResponse_ = true;
try
{
var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_
=> h_.Key, h_ => h_.Value);
if (response_.Content != null && response_.Content.Headers != null)
{
foreach (var item_ in response_.Content.Headers)
headers_[item_.Key] = item_.Value;
}
ProcessResponse(client_, response_);
var status_ = (int)response_.StatusCode;
if (status_ == 204)
{
return;
}
else
if (status_ == 400)
{
var objectResponse_ = await
ReadObjectResponseAsync<ProblemDetails>(response_, headers_,
cancellationToken).ConfigureAwait(false);
if (objectResponse_.Object == null)
{
throw new ApiException("Response was null which was not expected.",
status_, objectResponse_.Text, headers_, null);
}
throw new ApiException<ProblemDetails>("A server side error occurred.",
status_, objectResponse_.Text, headers_, objectResponse_.Object, null);
}
else
{
var responseData_ = response_.Content == null ? null : await
response_.Content.ReadAsStringAsync().ConfigureAwait(false);
throw new ApiException("The HTTP status code of the response was not
expected (" + status_ + ").", status_, responseData_, headers_, null);
}
}
finally
{
if (disposeResponse_)
response_.Dispose();
}
}
}
finally
{
if (disposeClient_)
client_.Dispose();
}
}
protected struct ObjectResponseResult<T>
{
public ObjectResponseResult(T responseObject, string responseText)
{
this.Object = responseObject;
this.Text = responseText;
}
public T Object { get; }
public string Text { get; }
}
public bool ReadResponseAsString { get; set; }
protected virtual async System.Threading.Tasks.Task<ObjectResponseResult<T>>
ReadObjectResponseAsync<T>(System.Net.Http.HttpResponseMessage response,
System.Collections.Generic.IReadOnlyDictionary<string,
System.Collections.Generic.IEnumerable<string>> headers,
System.Threading.CancellationToken cancellationToken)
{
if (response == null || response.Content == null)
{
return new ObjectResponseResult<T>(default(T), string.Empty);
}
if (ReadResponseAsString)
{
var responseText = await
response.Content.ReadAsStringAsync().ConfigureAwait(false);
try
{
var typedBody =
Newtonsoft.Json.JsonConvert.DeserializeObject<T>(responseText, JsonSerializerSettings);
return new ObjectResponseResult<T>(typedBody, responseText);
}
catch (Newtonsoft.Json.JsonException exception)
{
var message = "Could not deserialize the response body string as " +
typeof(T).FullName + ".";
throw new ApiException(message, (int)response.StatusCode, responseText,
headers, exception);
}
}
else
{
try
{
using (var responseStream = await
response.Content.ReadAsStreamAsync().ConfigureAwait(false))
using (var streamReader = new System.IO.StreamReader(responseStream))
using (var jsonTextReader = new
Newtonsoft.Json.JsonTextReader(streamReader))
{
var serializer = Newtonsoft.Json.JsonSerializer.Create(JsonSerializerSettings);
var typedBody = serializer.Deserialize<T>(jsonTextReader);
return new ObjectResponseResult<T>(typedBody, string.Empty);
}
}
catch (Newtonsoft.Json.JsonException exception)
{
var message = "Could not deserialize the response body stream as " +
typeof(T).FullName + ".";
throw new ApiException(message, (int)response.StatusCode, string.Empty,
headers, exception);
}
}
}
private string ConvertToString(object value, System.Globalization.CultureInfo
cultureInfo)
{
if (value == null)
{
return "";
}
if (value is System.Enum)
{
var name = System.Enum.GetName(value.GetType(), value);
if (name != null)
{
var field =
System.Reflection.IntrospectionExtensions.GetTypeInfo(value.GetType()).GetDeclaredField(
name);
if (field != null)
{
var attribute =
System.Reflection.CustomAttributeExtensions.GetCustomAttribute(field,
typeof(System.Runtime.Serialization.EnumMemberAttribute))
as System.Runtime.Serialization.EnumMemberAttribute;
if (attribute != null)
{
return attribute.Value != null ? attribute.Value : name;
}
}
var converted = System.Convert.ToString(System.Convert.ChangeType(value,
System.Enum.GetUnderlyingType(value.GetType()), cultureInfo));
return converted == null ? string.Empty : converted;
}
}
else if (value is bool)
{
return System.Convert.ToString((bool)value, cultureInfo).ToLowerInvariant();
}
else if (value is byte[])
{
return System.Convert.ToBase64String((byte[]) value);
}
else if (value.GetType().IsArray)
{
var array = System.Linq.Enumerable.OfType<object>((System.Array) value);
return string.Join(",", System.Linq.Enumerable.Select(array, o =>
ConvertToString(o, cultureInfo)));
}
var result = System.Convert.ToString(value, cultureInfo);
return result == null ? "" : result;
}
}
[System.CodeDom.Compiler.GeneratedCode("NSwag", "13.18.2.0 (NJsonSchema
v10.8.0.0 (Newtonsoft.Json v13.0.0.0))")]
public partial class ApiException : System.Exception
{
public int StatusCode { get; private set; }
public string Response { get; private set; }
public System.Collections.Generic.IReadOnlyDictionary<string,
System.Collections.Generic.IEnumerable<string>> Headers { get; private set; }
public ApiException(string message, int statusCode, string response,
System.Collections.Generic.IReadOnlyDictionary<string,
System.Collections.Generic.IEnumerable<string>> headers, System.Exception
innerException)
: base(message + "\n\nStatus: " + statusCode + "\nResponse: \n" + ((response == null)
? "(null)" : response.Substring(0, response.Length >= 512 ? 512 : response.Length)),
innerException)
{
StatusCode = statusCode;
Response = response;
Headers = headers;
}
public override string ToString()
{
return string.Format("HTTP Response: \n\n{0}\n\n{1}", Response, base.ToString());
}
}
[System.CodeDom.Compiler.GeneratedCode("NSwag", "13.18.2.0 (NJsonSchema
v10.8.0.0 (Newtonsoft.Json v13.0.0.0))")]
public partial class ApiException<TResult> : ApiException
{
public TResult Result { get; private set; }
public ApiException(string message, int statusCode, string response,
System.Collections.Generic.IReadOnlyDictionary<string,
System.Collections.Generic.IEnumerable<string>> headers, TResult result, System.Exception
innerException)
: base(message, statusCode, response, headers, innerException)
{
Result = result;
}
}
#pragma warning restore 1591
#pragma warning restore 1573
#pragma warning restore 472
#pragma warning restore 114
#pragma warning restore 108
#pragma warning restore 3016
#pragma warning restore 8603using FlexibleAuth.Shared.Authorization;
using Microsoft.AspNetCore.Components;
namespace FlexibleAuth.Client.Shared;
public class FlexibleAuthorizeView :
Microsoft.AspNetCore.Components.Authorization.AuthorizeView
{
[Parameter]
public Permissions Permissions
{
get
{
return string.IsNullOrEmpty(Policy) ? Permissions.None :
PolicyNameHelper.GetPermissionsFrom(Policy);
}
set
{
Policy = PolicyNameHelper.GeneratePolicyNameFor(value);
}
}
}
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@inject NavigationManager Navigation
<AuthorizeView>
<Authorized>
<a href="authentication/profile">Hello, @context.User.Identity?.Name!</a>
<button class="nav-link btn btn-link" @onclick="BeginLogOut">Log
out</button>
</Authorized>
<NotAuthorized>
<a href="authentication/register">Register</a>
<a href="authentication/login">Log in</a>
</NotAuthorized>
</AuthorizeView>
@code{
private void BeginLogOut()
{
Navigation.NavigateToLogout("authentication/logout");
}
}
@inherits LayoutComponentBase
<div class="page">
<div class="sidebar">
<NavMenu />
</div>
<main>
<div class="top-row px-4 auth">
<LoginDisplay />
<a href="https://docs.microsoft.com/aspnet/"
target="_blank">About</a>
</div>
<article class="content px-4">
@Body
</article>
</main>
</div>
.page {
position: relative;
display: flex;
flex-direction: column;
}
main {
flex: 1;
}
.sidebar {
background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
}
.top-row {
background-color: #f7f7f7;
border-bottom: 1px solid #d6d5d5;
justify-content: flex-end;
height: 3.5rem;
display: flex;
align-items: center;
}
.top-row ::deep a, .top-row ::deep .btn-link {
white-space: nowrap;
margin-left: 1.5rem;
text-decoration: none;
}
.top-row ::deep a:hover, .top-row ::deep .btn-link:hover {
text-decoration: underline;
}
.top-row ::deep a:first-child {
overflow: hidden;
text-overflow: ellipsis;
}
@media (max-width: 640.98px) {
.top-row:not(.auth) {
display: none;
}
.top-row.auth {
justify-content: space-between;
}
.top-row ::deep a, .top-row ::deep .btn-link {
margin-left: 0;
}
}
@media (min-width: 641px) {
.page {
flex-direction: row;
}
.sidebar {
width: 250px;
height: 100vh;
position: sticky;
top: 0;
}
.top-row {
position: sticky;
top: 0;
z-index: 1;
}
.top-row.auth ::deep a:first-child {
flex: 1;
text-align: right;
width: 0;
}
.top-row, article {
padding-left: 2rem !important;
padding-right: 1.5rem !important;
}
}
@using FlexibleAuth.Shared.Authorization
<div class="top-row ps-3 navbar navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="">FlexibleAuth</a>
<button title="Navigation menu" class="navbar-toggler"
@onclick="ToggleNavMenu">
<span class="navbar-toggler-icon"></span>
</button>
</div>
</div>
<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
<nav class="flex-column">
<div class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="oi oi-home" aria-hidden="true"></span> Home
</NavLink>
</div>
<FlexibleAuthorizeView Permissions="@Permissions.Counter">
<div class="nav-item px-3">
<NavLink class="nav-link" href="counter">
<span class="oi oi-plus" aria-hidden="true"></span> Counter
</NavLink>
</div>
</FlexibleAuthorizeView>
<FlexibleAuthorizeView Permissions="@Permissions.Forecast">
<div class="nav-item px-3">
<NavLink class="nav-link" href="fetchdata">
<span class="oi oi-list-rich" aria-hidden="true"></span>
Fetch data
</NavLink>
</div>
</FlexibleAuthorizeView>
<FlexibleAuthorizeView Permissions="@(Permissions.ViewUsers |
Permissions.ManageUsers)">
<div class="nav-item px-3">
<NavLink class="nav-link" href="/admin/users">
<span class="oi oi-people" aria-hidden="true"></span> Users
</NavLink>
</div>
</FlexibleAuthorizeView>
<AuthorizeView>
<div class="nav-item px-3">
<NavLink class="nav-link" href="claims">
<span class="oi oi-document" aria-hidden="true"></span>
Claims
</NavLink>
</div>
</AuthorizeView>
<FlexibleAuthorizeView Permissions="@(Permissions.ViewRoles |
Permissions.ManageRoles)">
<div class="nav-item px-3">
<NavLink class="nav-link" href="admin/roles">
<span class="oi oi-badge" aria-hidden="true"></span> Roles
</NavLink>
</div>
</FlexibleAuthorizeView>
<FlexibleAuthorizeView Permissions="@(Permissions.ViewAccessControl |
Permissions.ConfigureAccessControl)">
<div class="nav-item px-3">
<NavLink class="nav-link" href="admin/access-control">
<span class="oi oi-lock-locked" aria-hidden="true"></span>
Access Control
</NavLink>
</div>
</FlexibleAuthorizeView>
</nav>
</div>
@code {
private bool collapseNavMenu = true;
private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null;
private void ToggleNavMenu()
{
collapseNavMenu = !collapseNavMenu;
}
}
.navbar-toggler {
background-color: rgba(255, 255, 255, 0.1);
}
.top-row {
height: 3.5rem;
background-color: rgba(0,0,0,0.4);
}
.navbar-brand {
font-size: 1.1rem;
}
.oi {
width: 2rem;
font-size: 1.1rem;
vertical-align: text-top;
top: -2px;
}
.nav-item {
font-size: 0.9rem;
padding-bottom: 0.5rem;
}
.nav-item:first-of-type {
padding-top: 1rem;
}
.nav-item:last-of-type {
padding-bottom: 1rem;
}
.nav-item ::deep a {
color: #d7d7d7;
border-radius: 4px;
height: 3rem;
display: flex;
align-items: center;
line-height: 3rem;
}
.nav-item ::deep a.active {
background-color: rgba(255,255,255,0.25);
color: white;
}
.nav-item ::deep a:hover {
background-color: rgba(255,255,255,0.1);
color: white;
}
@media (min-width: 641px) {
.navbar-toggler {
display: none;
}
.collapse {
/* Never collapse the sidebar for wide screens */
display: block;
}
}
@inject NavigationManager Navigation
@code {
protected override void OnInitialized()
{
Navigation.NavigateTo($"authentication/login?returnUrl={Uri.EscapeDataString(Navi
gation.Uri)}");
}
}
<div class="alert alert-secondary mt-4">
<span class="oi oi-pencil me-2" aria-hidden="true"></span>
<strong>@Title</strong>
<span class="text-nowrap">
Please take our
<a target="_blank" class="font-weight-bold link-dark"
href="https://go.microsoft.com/fwlink/?linkid=2148851">brief survey</a>
</span>
and tell us what you think.
</div>
@code {
// Demonstrates how a parent component can supply parameters
[Parameter]
public string? Title { get; set; }
}
using FlexibleAuth.Client;
using FlexibleAuth.Client.Authorization;
using FlexibleAuth.Client.Services;
using FlexibleAuth.Shared.Authorization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddHttpClient("FlexibleAuth.ServerAPI", client =>
client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
// Supply HttpClient instances that include access tokens when making requests to
the server project
builder.Services.AddScoped(sp =>
sp.GetRequiredService<IHttpClientFactory>().CreateClient("FlexibleAuth.ServerAPI"
));
builder.Services
.AddApiAuthorization()
.AddAccountClaimsPrincipalFactory<CustomAccountClaimsPrincipalFactory>();
builder.Services.AddSingleton<IAuthorizationHandler,
PermissionAuthorizationHandler>();
builder.Services.AddSingleton<IAuthorizationPolicyProvider,
FlexibleAuthorizationPolicyProvider>();
builder.Services.Scan(scan => scan
.FromAssemblyOf<IAccessControlClient>()
.AddClasses(classes =>
classes.InExactNamespaceOf<IAccessControlClient>())
.AsImplementedInterfaces()
.WithScopedLifetime());
await builder.Build().RunAsync();