Skip to content

Commit

Permalink
Few tweaks + comments
Browse files Browse the repository at this point in the history
  • Loading branch information
JonPSmith committed Jun 1, 2021
1 parent 9832460 commit 6410089
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 19 deletions.
7 changes: 4 additions & 3 deletions AuthPermissions.AspNetCore/AuthPermissions.AspNetCore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>

<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="5.0.6" />
</ItemGroup>
Expand All @@ -12,8 +16,5 @@
<ProjectReference Include="..\AuthPermissions\AuthPermissions.csproj" />
</ItemGroup>

<ItemGroup>
<Folder Include="HostedServices\Internal\" />
</ItemGroup>

</Project>
20 changes: 18 additions & 2 deletions AuthPermissions.AspNetCore/SetupExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,44 @@
using AuthPermissions.AspNetCore.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace AuthPermissions.AspNetCore
{
public static class SetupExtensions
{

/// <summary>
/// This will add a single user to ASP.NET Core individual accounts identity system using data in the appsettings.json file.
/// This is here to allow you add a super-admin user when you first start up the application on a new system
/// NOTE: for security reasons this will only add a new user if there isn't a user with the AccessAll permission
/// </summary>
/// <param name="setupData"></param>
/// <returns></returns>
public static AuthSetupData IndividualAccountsAddSuperUser(this AuthSetupData setupData)
{
setupData.Services.AddHostedService<IndividualAccountsAddSuperUser>();

return setupData;
}

/// <summary>
/// This will finalize the setting up of the AuthPermissions parts needed by ASP.NET Core
/// NOTE: It assumes the AuthPermissions database has been created and has the current migration applied
/// </summary>
/// <param name="setupData"></param>
/// <param name="addRolesUsersOnStartup"></param>
public static void SetupAspNetCorePart(this AuthSetupData setupData, bool addRolesUsersOnStartup = false)
{
setupData.RegisterCommonServices();
if (addRolesUsersOnStartup)
setupData.Services.AddHostedService<AddAuthRolesUserOnStartup>();
}

/// <summary>
/// This will ensure that the AuthPermissions database is created and migrated to the current settings.
/// It also finalize the setting up of the AuthPermissions parts needed by ASP.NET Core
/// </summary>
/// <param name="setupData"></param>
public static void SetupAuthDatabaseOnStartup(this AuthSetupData setupData)
{
if (setupData.Options.DatabaseType == AuthPermissionsOptions.DatabaseTypes.NotSet)
Expand Down
4 changes: 4 additions & 0 deletions AuthPermissions/AuthPermissions.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>

<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="GenericServices.StatusGeneric" Version="1.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.6" />
Expand Down
5 changes: 3 additions & 2 deletions AuthPermissions/PermissionsCode/CalcFeaturePermissions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ public CalcAllowedPermissions(AuthPermissionsDbContext context)

/// <summary>
/// This is called if the Permissions that a user needs calculating.
/// It looks at what permissions the user has, and then filters out any permissions
/// they aren't allowed because they haven't get access to the module that permission is linked to.
/// It looks at what permissions the user has based on their roles
/// NOTE: needs upgrading if TenantId is to change the user's roles.
/// </summary>
/// <param name="userId"></param>
/// <returns>a string containing the packed permissions</returns>
Expand All @@ -35,6 +35,7 @@ public async Task<string> CalcPermissionsForUserAsync(string userId)
.Select(x => x.Role.PackedPermissionsInRole)
.ToListAsync());

//thanks to https://stackoverflow.com/questions/5141863/how-to-get-distinct-characters
var packedPermissionsForUser = new string(string.Concat(permissionsForAllRoles).Distinct().ToArray());

return packedPermissionsForUser;
Expand Down
55 changes: 47 additions & 8 deletions AuthPermissions/SetupExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ namespace AuthPermissions
{
public static class SetupExtensions
{
/// <summary>
/// This is the start of registering AuthPermissions library into the available .NET DI provider
/// This takes in the type of your enum holding your permissions and any options you want to set
/// </summary>
/// <typeparam name="TEnumPermissions">Must be an enum, sized as an ushort (16 bit unsigned)</typeparam>
/// <param name="services">The DI register instance</param>
/// <param name="options">optional: You can set certain options to change the way this library works</param>
/// <returns></returns>
public static AuthSetupData RegisterAuthPermissions<TEnumPermissions>(this IServiceCollection services,
AuthPermissionsOptions options = null) where TEnumPermissions : Enum
{
Expand All @@ -32,6 +40,13 @@ public static AuthSetupData RegisterAuthPermissions<TEnumPermissions>(this IServ
return new AuthSetupData(services, options);
}

/// <summary>
/// This will register a SQL Server database to hold the AuthPermissions database.
/// NOTE I have configured the AuthPermissionDbContext such that it can be part of another database (it has its own Migrations history table)
/// </summary>
/// <param name="setupData"></param>
/// <param name="connectionString"></param>
/// <returns></returns>
public static AuthSetupData UsingEfCoreSqlServer(this AuthSetupData setupData, string connectionString)
{
setupData.Services.AddDbContext<AuthPermissionsDbContext>(
Expand All @@ -43,7 +58,7 @@ public static AuthSetupData UsingEfCoreSqlServer(this AuthSetupData setupData, s
}

/// <summary>
/// This registers an in-memory database. The data added to this database will be lost when the app/unit test has been run
/// This registers an in-memory database. The data added to this database will be lost when the app/unit test stops
/// </summary>
/// <param name="setupData"></param>
/// <returns></returns>
Expand All @@ -54,6 +69,10 @@ public static AuthSetupData UsingInMemoryDatabase(this AuthSetupData setupData)
options => options.UseSqlite(inMemoryConnection));
setupData.Options.DatabaseType = AuthPermissionsOptions.DatabaseTypes.InMemory;

using var serviceProvider = setupData.Services.BuildServiceProvider();
using var context = serviceProvider.GetRequiredService<AuthPermissionsDbContext>();
context.Database.EnsureCreated();

return setupData;
}

Expand All @@ -79,11 +98,13 @@ public static AuthSetupData AddRolesPermissionsIfEmpty(this AuthSetupData setupD
}

/// <summary>
/// This allows you to define permission user, but only if the auth database doesn't have any UserToRoles in the database
/// NOTE: The <see cref="userRolesSetup"/> parameter must contain .
/// This allows you to add what roles a user has, but only if the auth database doesn't have any UserToRoles in the database
/// NOTE: The <see cref="userRolesSetup"/> parameter must contain a list of userId+roles.
/// </summary>
/// <param name="setupData"></param>
/// <param name="userRolesSetup">A list of <see cref="DefineUserWithRolesTenant"/> containing the information on users and what auth roles they have</param>
/// <param name="userRolesSetup">A list of <see cref="DefineUserWithRolesTenant"/> containing the information on users and what auth roles they have.
/// In this case the UserId must be filled in with the authorized users' UserId
/// </param>
/// <returns>AuthSetupData</returns>
public static AuthSetupData AddUsersRolesIfEmpty(this AuthSetupData setupData, List<DefineUserWithRolesTenant> userRolesSetup)
{
Expand All @@ -94,25 +115,43 @@ public static AuthSetupData AddUsersRolesIfEmpty(this AuthSetupData setupData, L
Environment.NewLine + string.Join(", ", badUserIds.Select(x => x.UserName))
,nameof(userRolesSetup));

if (setupData.Options.UserRolesSetupData != null)
throw new ArgumentException(
$"The data has already been set. Did you already call this method or the {nameof(AddUsersRolesIfEmptyWithUserIdLookup)} method?",
nameof(userRolesSetup));

setupData.Options.UserRolesSetupData = userRolesSetup;
return setupData;
}

/// <summary>
/// This allows you to define permission user, but only if the auth database doesn't have any UserToRoles in the database
/// It uses the <see cref="TUserLookup"/> service to look up UserIds for user definitions that have a null UserId
/// TThis allows you to add what roles a user has, but only if the auth database doesn't have any UserToRoles in the database
/// It uses the <see cref="TUserLookup"/> service to look up UserIds for user definitions that have a null UserId
/// This allows you add users+roles with a service to link your users to the AuthPermission's UserToRole
/// </summary>
/// <param name="setupData"></param>
/// <param name="userRolesSetup">A list of <see cref="DefineUserWithRolesTenant"/> containing the information on users and what auth roles they have</param>
/// <param name="userRolesSetup">A list of <see cref="DefineUserWithRolesTenant"/> containing the information on users and what auth roles they have.
/// If the UserId in the given data is null, then it will
/// </param>
/// <returns>AuthSetupData</returns>
public static AuthSetupData AddUsersRolesIfEmptyWithUserIdLookup<TUserLookup>(this AuthSetupData setupData,
List<DefineUserWithRolesTenant> userRolesSetup) where TUserLookup : class, IFindUserIdService
{
if (setupData.Options.UserRolesSetupData != null)
throw new ArgumentException(
$"The data has already been set. Did you already call this method or the {nameof(AddUsersRolesIfEmpty)} method?",
nameof(userRolesSetup));

setupData.Options.UserRolesSetupData = userRolesSetup;
setupData.Services.AddScoped<IFindUserIdService, TUserLookup>();
return setupData;
}

/// <summary>
/// This will set up the basic AppPermissions parts and in-memory
/// </summary>
/// <param name="setupData"></param>
/// <returns></returns>
public static async Task<AuthPermissionsDbContext> SetupForUnitTestingAsync(this AuthSetupData setupData)
{
if (setupData.Options.DatabaseType != AuthPermissionsOptions.DatabaseTypes.InMemory)
Expand All @@ -121,7 +160,7 @@ public static async Task<AuthPermissionsDbContext> SetupForUnitTestingAsync(this

var serviceProvider = setupData.Services.BuildServiceProvider();
var context = serviceProvider.GetRequiredService<AuthPermissionsDbContext>();
var findUserIdService = serviceProvider.GetService<IFindUserIdService>();
var findUserIdService = serviceProvider.GetService<IFindUserIdService>(); //Can be null
await context.AddRoleUserToAuthDbAsync(setupData.Options, findUserIdService);

return context;
Expand Down
4 changes: 0 additions & 4 deletions AuthPermissions/SetupParts/AuthDbSetupCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@
// Licensed under MIT license. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AuthPermissions.DataLayer.EfCode;
using AuthPermissions.SetupParts.Internal;
using Microsoft.Extensions.DependencyInjection;
using StatusGeneric;

namespace AuthPermissions.SetupParts
Expand All @@ -28,8 +26,6 @@ public static async Task AddRoleUserToAuthDbAsync(this AuthPermissionsDbContext
private static async Task<IStatusGeneric> SetupRolesAndUsers(this AuthPermissionsDbContext context, IAuthPermissionsOptions options,
IFindUserIdService findUserIdService)
{
await context.Database.EnsureCreatedAsync();

var setupRoles = new SetupRolesService(context);
var status = setupRoles.AddRolesToDatabaseIfEmpty(options.RolesPermissionsSetupText,
options.EnumPermissionsType);
Expand Down

0 comments on commit 6410089

Please sign in to comment.