Giter VIP home page Giter VIP logo

Comments (7)

JonPSmith avatar JonPSmith commented on May 23, 2024

The exception is from a query of RoleToPermissions which must be within my code, but I can't see anything that matches that. I have also run the Example2 and it works. Make sure you have the latest version of the AuthP.

If it still throws an exception, then you need to find where it happens - if the exception doesn't provide that then you need to debug it to find where it goes wrong.

from authpermissions.aspnetcore.

muliswilliam avatar muliswilliam commented on May 23, 2024

The issue seems to be in CalcPermissionsForUserAsync in ClaimsCalculator. The changes are:

  • Added .Include(x => x.Role) fetching permissions
  • Added
     .Include(x => x.UserTenant)
     .ThenInclude(x => x.TenantRoles)

when fetching tenant Roles.

When I made the changes, the code does not throw the exception.

The whole method is as follows:

private async Task<string> CalcPermissionsForUserAsync(string userId)
{
    var permissionsForAllRoles = (await _context.UserToRoles
        .Include(x => x.Role)
        .Where(x => x.UserId == userId)
        .Select(x => x.Role.PackedPermissionsInRole)
        .ToListAsync());

    if (_options.TenantType != TenantTypes.NotUsingTenants)
    {
      var tenantRoles = await _context.AuthUsers
        .Include(x => x.UserTenant)
        .ThenInclude(x => x.TenantRoles)
        .Where(x => x.UserId == userId && x.TenantId != null)
        .ToListAsync();
        
        
      //We need to add any RoleTypes.TenantAdminAdd for a tenant user
      var autoAddRoles = tenantRoles
        .Select(x => x.UserTenant.TenantRoles.Where(y => y.RoleType == RoleTypes.TenantAutoAdd))
        .SingleOrDefault();

        if (autoAddRoles != null)
            permissionsForAllRoles.AddRange(autoAddRoles.Select(x => x.PackedPermissionsInRole));
    }

    if (!permissionsForAllRoles.Any())
        return null;

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

    return packedPermissionsForUser;
}

from authpermissions.aspnetcore.

JonPSmith avatar JonPSmith commented on May 23, 2024

Hi @muliswilliam,

Good work at tracking that down. I have tests for this type of use of the ClaimsCalculator, but it passes.

Can you provide the configuration of your application and the the list of roles with their RoleType so that I can create a failing test before I change anything.

from authpermissions.aspnetcore.

muliswilliam avatar muliswilliam commented on May 23, 2024

Hi @JonPSmith,

Here's my configuration in Program.cs, I am using .net6:


// Register AuthPermissions
builder.Services.RegisterAuthPermissions<TamAuthPermissions>(options =>
  {
    options.TenantType = TenantTypes.SingleLevel;
    options.AppConnectionString = connectionString;
    // options.PathToFolderToLock = builder.Environment.WebRootPath;
    
    // This tells AuthP that you don't have multiple instances of your app running,
    // so it can run the startup services without a global lock
    options.UseLocksToUpdateGlobalResources = false;

    // This sets up the JWT Token. The config is suitable for using the Refresh Token with your JWT Token
    options.ConfigureAuthPJwtToken = new AuthPJwtConfiguration
    {
      Issuer = jwtBearerTokenSettings.Issuer,
      Audience = jwtBearerTokenSettings.Audience,
      SigningKey = jwtBearerTokenSettings.SigningKey,
      TokenExpires = new TimeSpan(0,5,0), // Quick Token expiration because we use a refresh token
      RefreshTokenExpires = new TimeSpan(1,0,0,0) // Refresh token is valid for one day
    };
  })
  .UsingEfCoreSqlServer(connectionString) //NOTE: This uses the same database as the individual accounts DB
  .IndividualAccountsAuthentication()
  .AddSuperUserToIndividualAccounts()
  .RegisterFindUserInfoService<IndividualAccountUserLookup>()
  .AddTenantsIfEmpty(AppAuthSetupData.TenantDefinition)
  .AddRolesPermissionsIfEmpty(AppAuthSetupData.RolesDefinition)
  .AddAuthUsersIfEmpty(AppAuthSetupData.UsersRolesDefinition)
  .SetupAspNetCoreAndDatabase(options =>
  {
    //Migrate individual account database
    options.RegisterServiceToRunInJob<StartupServiceMigrateAnyDbContext<AppIdentityDbContext>>();
    //Add demo users to the database
    options.RegisterServiceToRunInJob<StartupServicesIndividualAccountsAddDemoUsers>();
  });

The permissions are as below:

public enum TamAuthPermissions : ushort
{
  NotSet = 0, // Error Condition

  // Users Permissions
  [Display(GroupName = "Users", Name = "Read Users", Description = "This allows a user to read user's data")]
  UsersRead = 10,
  [Display(GroupName = "Users", Name = "Create Users", Description = "This allows a user to create users")]
  UsersCreate = 11,
  [Display(GroupName = "Users", Name = "Edit Users", Description = "This allows a user to edit users")]
  UsersEdit = 12,
  [Display(GroupName = "Users", Name = "Delete Users", Description = "This allows a user to delete users")]
  UsersDelete = 13,
  
  [Display(GroupName = "SuperAdmin", Name = "Access All Data", Description = "This allows user to access every feature and data", AutoGenerateFilter = true)]
  AccessAll = ushort.MaxValue,
}

The AppAuthSetupData which contains sample data is as follows:

public static class AppAuthSetupData
{
  public static readonly List<BulkLoadRolesDto> RolesDefinition = new List<BulkLoadRolesDto>()
  {
    new("Admin", null, "UsersCreate, UsersEdit, UsersRead, UsersDelete"),
    new("SuperRole", null, "AccessAll"),
  };
  
  public static readonly List<BulkLoadTenantDto> TenantDefinition = new()
  {
    new("Diageo"),
    new("Pets Ltd."),
    new("Big Rocks Inc.")
  };

  public static readonly List<BulkLoadUserWithRolesTenant> UsersRolesDefinition = new List<BulkLoadUserWithRolesTenant>
  {
    new ("[email protected]", null, "Admin", tenantNameForDataKey: "Diageo"),
    new ("[email protected]", null, "Admin", tenantNameForDataKey: "Diageo"),
    new ("[email protected]", null, "Admin", tenantNameForDataKey: "Diageo"),
    new ("[email protected]", null, "SuperRole"),

  };
}

from authpermissions.aspnetcore.

JonPSmith avatar JonPSmith commented on May 23, 2024

Hi @muliswilliam,

OK, your setup is very standard and you don't use any tenant-specific Roles. My tests include some to check this and I can't see why it doesn't work. So, could you please

  1. Update your clone of the AuthP repo (I found tests that were out of data and updated them) and run all the tests and tell me if they all pass. I think they will pass, but this just that there isn't different on your PC.

  2. Could you update the CalcPermissionsForUserAsync method you updated the the code below. This is a bit quicker than your suggestion as it loads less data. If this works I will release a new version with this change.

private async Task<string> CalcPermissionsForUserAsync(string userId)
{
    //This gets all the permissions, with a distinct to remove duplicates
    var permissionsForAllRoles = await _context.UserToRoles
        .Where(x => x.UserId == userId)
        .Select(x => x.Role.PackedPermissionsInRole)
        .ToListAsync();

    if (_options.TenantType != TenantTypes.NotUsingTenants)
    {
        //We need to add any RoleTypes.TenantAdminAdd for a tenant user

        var autoAddRoles = await _context.AuthUsers
            .Where(x => x.UserId == userId && x.TenantId != null)
            .SelectMany(x => x.UserTenant.TenantRoles.Where(y => y.RoleType == RoleTypes.TenantAutoAdd))
            .ToListAsync();

        if (autoAddRoles.Any())
            permissionsForAllRoles.AddRange(autoAddRoles.Select(x => x.PackedPermissionsInRole));
    }

    if (!permissionsForAllRoles.Any())
        return null;

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

    return packedPermissionsForUser;
}

It's frustrating that I can't create a test that fails, but in the end the changed query is just as fast and a bit easier to understand.

Let me know your result with the changed CalcPermissionsForUserAsync code.

from authpermissions.aspnetcore.

muliswilliam avatar muliswilliam commented on May 23, 2024

@JonPSmith The above code for CalcPermissionsForUserAsync works. You can release a new version with the code. I will run the tests and update this comment.

from authpermissions.aspnetcore.

JonPSmith avatar JonPSmith commented on May 23, 2024

Version 2.3.1 fixes this issue. Thanks for your patience @muliswilliam

from authpermissions.aspnetcore.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.