EntityFrameworkCore.PolicyEnforcement 1.0.0

dotnet add package EntityFrameworkCore.PolicyEnforcement --version 1.0.0
                    
NuGet\Install-Package EntityFrameworkCore.PolicyEnforcement -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="EntityFrameworkCore.PolicyEnforcement" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="EntityFrameworkCore.PolicyEnforcement" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="EntityFrameworkCore.PolicyEnforcement" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add EntityFrameworkCore.PolicyEnforcement --version 1.0.0
                    
#r "nuget: EntityFrameworkCore.PolicyEnforcement, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#addin nuget:?package=EntityFrameworkCore.PolicyEnforcement&version=1.0.0
                    
Install EntityFrameworkCore.PolicyEnforcement as a Cake Addin
#tool nuget:?package=EntityFrameworkCore.PolicyEnforcement&version=1.0.0
                    
Install EntityFrameworkCore.PolicyEnforcement as a Cake Tool

publish to nuget EntityFrameworkCore.PolicyEnforcement on NuGet NuGet License Sponsor

EntityFrameworkCore.PolicyEnforcement

๐Ÿ“Œ Introduction

A .NET library for enforcing access control policies in Entity Framework Core applications with dependency injection support.

๐Ÿ“Œ Key Features:

  • ๐Ÿ”’ Declarative Access Control: Define policies at the entity level using a fluent API
  • ๐Ÿงฉ Multiple Policy Types: Support for role-based, permission-based, ownership-based, and property-based policies
  • โšก Automatic Enforcement: Policies applied automatically to both queries and commands
  • ๐Ÿ”Œ Extensible: Build custom policy types for specific business requirements
  • ๐Ÿ—๏ธ Clean Architecture Friendly: Designed to work well with domain-driven and clean architecture approaches
  • ๐Ÿงช Testable: Easy to mock and test in isolation
  • ๐Ÿ”„ Chainable Policies: Combine multiple policies with AND/OR operators
  • ๐Ÿง  Smart Caching: Performance optimized with compiled expression caching

๐Ÿ“ฅ Installation

dotnet add package EntityFrameworkCore.PolicyEnforcement

๐Ÿš€ Quick Start:

1. Configure in your DbContext

public class ApplicationDbContext : DbContext
{
    public DbSet<Document> Documents { get; set; }
    
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(connectionString)
                     .UsePolicyEnforcement();
    }
    
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Document>()
            .HasAccessPolicy(policy => 
                policy.RequireOwnership(d => d.OwnerId)
                    .Or(policy.RequireRole("Admin"))
            );
    }
}

2. Set up the User Context

Create a class implementing IUserContext:

public class CurrentUserContext : IUserContext
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    
    public CurrentUserContext(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }
    
    public string? GetCurrentUserId() => 
        _httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier);
    
    public bool IsInRole(string role) => 
        _httpContextAccessor.HttpContext?.User?.IsInRole(role) ?? false;
    
    public bool HasPermission(string permission) => 
        _httpContextAccessor.HttpContext?.User?.HasClaim(c => 
            c.Type == "Permission" && c.Value == permission) ?? false;
}

3. Configure in Startup

public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<IUserContext, CurrentUserContext>();
    
    services.AddDbContext<ApplicationDbContext>(options => 
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))
               .UsePolicyEnforcement(opt => 
               {
                   opt.EnableForQueries = true;
                   opt.EnableForCommands = true;
                   opt.ThrowOnViolation = true;
               }));
}

4. Set User Context Before Operations

public class DocumentService
{
    private readonly ApplicationDbContext _dbContext;
    private readonly IUserContext _userContext;
    
    public DocumentService(ApplicationDbContext dbContext, IUserContext userContext)
    {
        _dbContext = dbContext;
        _userContext = userContext;
    }
    
    public async Task<List<Document>> GetUserDocumentsAsync()
    {
        // Set the user context before querying
        _dbContext.SetUserContext(_userContext);
        
        // Policy is automatically applied
        return await _dbContext.Documents.ToListAsync();
    }
}

Policy Types

Role-Based Policies

modelBuilder.Entity<Payroll>()
    .HasAccessPolicy(policy => policy.RequireRole("HR"));

Permission-Based Policies

modelBuilder.Entity<Customer>()
    .HasAccessPolicy(policy => policy.RequirePermission("customers.read"));

Ownership-Based Policies

modelBuilder.Entity<UserProfile>()
    .HasAccessPolicy(policy => policy.RequireOwnership(p => p.UserId));

Property-Based Policies

modelBuilder.Entity<Document>()
    .HasAccessPolicy(policy => policy.RequireProperty(d => d.IsPublic));

Combined Policies

modelBuilder.Entity<Project>()
    .HasAccessPolicy(policy => 
        policy.RequireOwnership(p => p.OwnerId)
            .Or(policy.RequireRole("Manager"))
            .Or(policy.RequireProperty(p => p.IsPublic))
    );

Operation-Specific Policies

modelBuilder.Entity<Ticket>()
    .HasAccessPolicy(policy => policy.RequireRole("Support"), "Default")
    .HasAccessPolicy(policy => policy.RequireRole("SupportLead"), "Update")
    .HasAccessPolicy(policy => policy.RequireRole("Manager"), "Delete");

Advanced Usage

Custom Policies

modelBuilder.Entity<FinancialRecord>()
    .HasAccessPolicy(policy => policy.Custom(userContext => 
        fr => fr.Amount < 1000 || userContext.IsInRole("FinancialApprover")
    ));

Self-Checking Entities

public class Team : IDefineOwnAccessPolicy
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<TeamMember> Members { get; set; }
    
    public bool CanAccess(IUserContext userContext, string operation)
    {
        var userId = userContext.GetCurrentUserId();
        if (string.IsNullOrEmpty(userId)) return false;
        
        // Allow members to read, but only admins to modify
        if (operation == "Read")
            return Members.Any(m => m.UserId == userId);
            
        return Members.Any(m => m.UserId == userId && m.IsAdmin);
    }
}

๐Ÿ”— License

This project is licensed under the MIT License. See the LICENSE file for details.


๐Ÿ™Œ Contributing

๐ŸŽฏ Found a bug or have an idea for improvement?
Feel free to open an issue or submit a pull request!
๐Ÿ”— GitHub Issues


โญ Support the Project

If you find this package useful, give it a star โญ on GitHub and share it with others! ๐Ÿš€

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.0 139 a month ago

- Initial release of EntityFrameworkCore.PolicyEnforcement.