Skip to content

Commit 12d015b

Browse files
committed
feat: can implement faster hasPermission operations
Fixes #1
1 parent 1d58331 commit 12d015b

3 files changed

Lines changed: 50 additions & 6 deletions

File tree

README.md

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,6 @@ For our [Database Store](#database-store) example above, we have the same 3 step
343343
**However it is implemented, the only thing that matters here is returning a list of strings as your final permissions.**
344344

345345
```c#
346-
347346
public class DatabaseUserPolicyHandler : IUserPolicyHandler
348347
{
349348
private readonly RecipesDbContext _dbContext;
@@ -375,6 +374,46 @@ public class DatabaseUserPolicyHandler : IUserPolicyHandler
375374
}
376375
```
377376

377+
#### Enhancing Your `HasPermission` Checks
378+
379+
The method `GetUserPermissions()` method requires all permissions for a user to be returned. When using a database, you might want to enhance the permformance of this call. You can do this by having your db use an `Exists` operation. To do this, you can implement the `HasPermission` method on your `UserPolicyHandler`. For example:
380+
381+
```csharp
382+
383+
public class DatabaseUserPolicyHandler : IUserPolicyHandler
384+
{
385+
private readonly RecipesDbContext _dbContext;
386+
private readonly IHttpContextAccessor _httpContextAccessor;
387+
388+
public UserPolicyHandler(RecipesDbContext dbContext, IHttpContextAccessor httpContextAccessor)
389+
{
390+
_dbContext = dbContext;
391+
_httpContextAccessor = httpContextAccessor;
392+
}
393+
394+
public async Task<IEnumerable<string>> GetUserPermissions()
395+
{
396+
// ...
397+
}
398+
399+
public async Task<bool> HasPermission(string permission)
400+
{
401+
var roles = await GetRoles();
402+
403+
// super admins can do everything
404+
if (roles.Contains(Role.SuperAdmin().Value))
405+
return true;
406+
407+
return await _dbContext.RolePermissions
408+
.Where(rp => roles.Contains(rp.Role.Name))
409+
.Select(rp => rp.Permission.Name)
410+
.AnyAsync(x => x == permission);
411+
}
412+
}
413+
```
414+
415+
416+
378417
### Registering HeimGuard
379418

380419
Once you have your `IUserPolicyHandler` implementation set up, just go to your service builder and register HeimGuard like so:

src/HeimGuard/HeimGuardClient.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,7 @@ public HeimGuardClient(IUserPolicyHandler userPolicyHandler)
4646

4747
/// <inheritdoc />
4848
public async Task<bool> HasPermissionAsync(string permission)
49-
{
50-
var policy = await _userPolicyHandler.GetUserPermissions();
51-
return policy.Contains(permission);
52-
}
49+
=> await _userPolicyHandler.HasPermission(permission);
5350

5451
/// <inheritdoc />
5552
public async Task MustHavePermission<TException>(string permission)

src/HeimGuard/IUserPolicyHandler.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
namespace HeimGuard
22
{
33
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Threading;
46
using System.Threading.Tasks;
57

68
/// <summary>
@@ -11,7 +13,13 @@ public interface IUserPolicyHandler
1113
/// <summary>
1214
/// Returns an IEnumerable of strings that represents a distinct list of a given user's permissions.
1315
/// </summary>
14-
/// <returns><see cref="T:System.Threading.Tasks.Task" /> that represents the asynchronous operation, containing the list of peermissions for the current user..</returns>
16+
/// <returns><see cref="T:System.Threading.Tasks.Task" /> that represents the asynchronous operation, containing the list of permissions for the current user.</returns>
1517
Task<IEnumerable<string>> GetUserPermissions();
18+
19+
/// <summary>
20+
/// Returns a boolean value indicating whether the current user has the specified permission.
21+
/// </summary>
22+
/// <returns><see cref="T:System.Threading.Tasks.Task" /> that represents the asynchronous operation, containing a boolean indicating whether the current user has the specified permission.</returns>
23+
async Task<bool> HasPermission(string permission) => (await GetUserPermissions()).Contains(permission);
1624
}
1725
}

0 commit comments

Comments
 (0)