-
Notifications
You must be signed in to change notification settings - Fork 170
Add OData authorization project #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
119 changes: 119 additions & 0 deletions
119
sample/ODataAuthorizationSample/Controllers/CustomersController.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
using ODataAuthorizationSample.Models; | ||
using Microsoft.AspNet.OData; | ||
using Microsoft.AspNet.OData.Routing; | ||
using Microsoft.AspNetCore.Mvc; | ||
using Microsoft.EntityFrameworkCore; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
|
||
namespace ODataAuthorizationSample.Controllers | ||
{ | ||
public class CustomersController : ODataController | ||
{ | ||
private readonly AppDbContext _context; | ||
|
||
public CustomersController(AppDbContext context) | ||
{ | ||
_context = context; | ||
|
||
if (_context.Customers.Count() == 0) | ||
{ | ||
IList<Customer> customers = new List<Customer> | ||
{ | ||
new Customer | ||
{ | ||
Name = "Jonier", | ||
HomeAddress = new Address { City = "Redmond", Street = "156 AVE NE"}, | ||
FavoriteAddresses = new List<Address> | ||
{ | ||
new Address { City = "Redmond", Street = "256 AVE NE"}, | ||
new Address { City = "Redd", Street = "56 AVE NE"}, | ||
}, | ||
Order = new Order { Title = "104m" }, | ||
Orders = Enumerable.Range(0, 2).Select(e => new Order { Title = "abc" + e }).ToList() | ||
}, | ||
new Customer | ||
{ | ||
Name = "Sam", | ||
HomeAddress = new Address { City = "Bellevue", Street = "Main St NE"}, | ||
FavoriteAddresses = new List<Address> | ||
{ | ||
new Address { City = "Red4ond", Street = "456 AVE NE"}, | ||
new Address { City = "Re4d", Street = "51 NE"}, | ||
}, | ||
Order = new Order { Title = "Zhang" }, | ||
Orders = Enumerable.Range(0, 2).Select(e => new Order { Title = "xyz" + e }).ToList() | ||
}, | ||
new Customer | ||
{ | ||
Name = "Peter", | ||
HomeAddress = new Address { City = "Hollewye", Street = "Main St NE"}, | ||
FavoriteAddresses = new List<Address> | ||
{ | ||
new Address { City = "R4mond", Street = "546 NE"}, | ||
new Address { City = "R4d", Street = "546 AVE"}, | ||
}, | ||
Order = new Order { Title = "Jichan" }, | ||
Orders = Enumerable.Range(0, 2).Select(e => new Order { Title = "ijk" + e }).ToList() | ||
}, | ||
}; | ||
|
||
foreach (var customer in customers) | ||
{ | ||
_context.Customers.Add(customer); | ||
_context.Orders.Add(customer.Order); | ||
_context.Orders.AddRange(customer.Orders); | ||
} | ||
|
||
_context.SaveChanges(); | ||
} | ||
} | ||
|
||
[EnableQuery] | ||
public IActionResult Get() | ||
{ | ||
// Be noted: without the NoTracking setting, the query for $select=HomeAddress with throw exception: | ||
// A tracking query projects owned entity without corresponding owner in result. Owned entities cannot be tracked without their owner... | ||
_context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; | ||
|
||
return Ok(_context.Customers); | ||
} | ||
|
||
[EnableQuery] | ||
public IActionResult Get(int key) | ||
{ | ||
return Ok(_context.Customers.FirstOrDefault(c => c.Id == key)); | ||
} | ||
|
||
/// <summary> | ||
/// If testing in IISExpress with the POST request to: http://localhost:2087/test/my/a/Customers | ||
/// Content-Type : application/json | ||
/// { | ||
/// "Name": "Jonier"," | ||
/// } | ||
/// | ||
/// Check the reponse header, you can see | ||
/// "Location" : "http://localhost:2087/test/my/a/Customers(0)" | ||
/// </summary> | ||
[EnableQuery] | ||
public IActionResult Post([FromBody]Customer customer) | ||
{ | ||
return Created(customer); | ||
} | ||
|
||
public IActionResult Delete(int key) | ||
{ | ||
var customer = _context.Customers.FirstOrDefault(c => c.Id == key); | ||
_context.Customers.Remove(customer); | ||
return Ok(customer); | ||
} | ||
|
||
[ODataRoute("GetTopCustomer")] | ||
public IActionResult GetTopCustomer() | ||
{ | ||
return Ok(_context.Customers.FirstOrDefault()); | ||
} | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
sample/ODataAuthorizationSample/Controllers/WeatherForecastController.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Mvc; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace ODataAuthorizationSample.Controllers | ||
{ | ||
[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() | ||
{ | ||
var rng = new Random(); | ||
return Enumerable.Range(1, 5).Select(index => new WeatherForecast | ||
{ | ||
Date = DateTime.Now.AddDays(index), | ||
TemperatureC = rng.Next(-20, 55), | ||
Summary = Summaries[rng.Next(Summaries.Length)] | ||
}) | ||
.ToArray(); | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using System.ComponentModel.DataAnnotations.Schema; | ||
using Microsoft.EntityFrameworkCore; | ||
|
||
namespace ODataAuthorizationSample.Models | ||
{ | ||
[Owned, ComplexType] | ||
public class Address | ||
{ | ||
public string City { get; set; } | ||
|
||
public string Street { get; set; } | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
using Microsoft.EntityFrameworkCore; | ||
|
||
namespace ODataAuthorizationSample.Models | ||
{ | ||
public class AppDbContext : DbContext | ||
{ | ||
public AppDbContext(DbContextOptions<AppDbContext> options) | ||
: base(options) | ||
{ | ||
} | ||
|
||
public DbSet<Customer> Customers { get; set; } | ||
|
||
public DbSet<Order> Orders { get; set; } | ||
|
||
protected override void OnModelCreating(ModelBuilder modelBuilder) | ||
{ | ||
modelBuilder.Entity<Customer>().OwnsOne(c => c.HomeAddress).WithOwner(); | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
using Microsoft.AspNet.OData.Builder; | ||
using Microsoft.OData.Edm; | ||
using Microsoft.OData.Edm.Vocabularies; | ||
using System.Linq; | ||
|
||
namespace ODataAuthorizationSample.Models | ||
{ | ||
public class AppModel | ||
{ | ||
public static IEdmModel GetEdmModel() | ||
{ | ||
var builder = new ODataConventionModelBuilder(); | ||
builder.EntitySet<Customer>("Customers"); | ||
builder.EntitySet<Order>("Orders"); | ||
builder.Function("GetTopCustomer").ReturnsFromEntitySet<Customer>("Customers"); | ||
|
||
var model = builder.GetEdmModel(); | ||
AddPermissions(model as EdmModel); | ||
|
||
return model; | ||
} | ||
|
||
private static void AddPermissions(EdmModel model) | ||
{ | ||
var readRestrictions = "Org.OData.Capabilities.V1.ReadRestrictions"; | ||
var insertRestrictions = "Org.OData.Capabilities.V1.InsertRestrictions"; | ||
var updateRestrictions = "Org.OData.Capabilities.V1.UpdateRestrictions"; | ||
var deleteRestrictions = "Org.OData.Capabilities.V1.DeleteRestrictions"; | ||
var operationRestrictions = "Org.OData.Capabilities.V1.OperationRestrictions"; | ||
|
||
var customers = model.FindDeclaredEntitySet("Customers"); | ||
var getTopCustomer = model.SchemaElements.OfType<IEdmOperation>().First(o => o.Name == "GetTopCustomer"); | ||
|
||
|
||
model.AddVocabularyAnnotation(new EdmVocabularyAnnotation( | ||
customers, | ||
model.FindTerm(readRestrictions), | ||
new EdmRecordExpression( | ||
CreatePermissionProperty(new string[] { "Customers.Read", "Product.ReadAll" }), | ||
new EdmPropertyConstructor("ReadByKeyRestrictions", CreatePermission(new[] { "Customers.ReadByKey" }))))); | ||
|
||
AddPermissionsTo(model, customers, insertRestrictions, "Customers.Insert"); | ||
AddPermissionsTo(model, customers, updateRestrictions, "Customers.Update"); | ||
AddPermissionsTo(model, customers, deleteRestrictions, "Customers.Delete"); | ||
AddPermissionsTo(model, getTopCustomer, operationRestrictions, "Customers.GetTop"); | ||
} | ||
|
||
public static void AddPermissionsTo(EdmModel model, IEdmVocabularyAnnotatable target, string restrictionName, params string[] scopes) | ||
{ | ||
model.AddVocabularyAnnotation(new EdmVocabularyAnnotation( | ||
target, | ||
model.FindTerm(restrictionName), | ||
CreatePermission(scopes))); | ||
} | ||
|
||
public static IEdmExpression CreatePermission(params string[] scopeNames) | ||
{ | ||
var restriction = new EdmRecordExpression( | ||
CreatePermissionProperty(scopeNames)); | ||
|
||
return restriction; | ||
} | ||
|
||
public static IEdmPropertyConstructor CreatePermissionProperty(params string[] scopeNames) | ||
{ | ||
var scopes = scopeNames.Select(scope => new EdmRecordExpression( | ||
new EdmPropertyConstructor("Scope", new EdmStringConstant(scope)), | ||
new EdmPropertyConstructor("RestrictedProperties", new EdmStringConstant("*")))); | ||
|
||
var permission = new EdmRecordExpression( | ||
new EdmPropertyConstructor("SchemeName", new EdmStringConstant("AuthScheme")), | ||
new EdmPropertyConstructor("Scopes", new EdmCollectionExpression(scopes))); | ||
|
||
var property = new EdmPropertyConstructor("Permissions", new EdmCollectionExpression(permission)); | ||
return property; | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
using System.Collections.Generic; | ||
|
||
namespace ODataAuthorizationSample.Models | ||
{ | ||
public class Customer | ||
{ | ||
public int Id { get; set; } | ||
|
||
public string Name { get; set; } | ||
|
||
public virtual Address HomeAddress { get; set; } | ||
|
||
public virtual IList<Address> FavoriteAddresses { get; set; } | ||
|
||
public virtual Order Order { get; set; } | ||
|
||
public virtual IList<Order> Orders { get; set; } | ||
} | ||
|
||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace ODataAuthorizationSample.Models | ||
{ | ||
public class Order | ||
{ | ||
public int Id { get; set; } | ||
public string Title { get; set; } | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
sample/ODataAuthorizationSample/ODataAuthorizationSample.csproj
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<Project Sdk="Microsoft.NET.Sdk.Web"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>netcoreapp3.1</TargetFramework> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.AspNetCore.OData" Version="7.4.1" /> | ||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.5" /> | ||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="3.1.5" /> | ||
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="3.1.5" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.OData.Authorization\Microsoft.AspNetCore.OData.Authorization.csproj" /> | ||
</ItemGroup> | ||
|
||
|
||
</Project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Hosting; | ||
using Microsoft.Extensions.Configuration; | ||
using Microsoft.Extensions.Hosting; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace ODataAuthorizationSample | ||
{ | ||
public class Program | ||
{ | ||
public static void Main(string[] args) | ||
{ | ||
CreateHostBuilder(args).Build().Run(); | ||
} | ||
|
||
public static IHostBuilder CreateHostBuilder(string[] args) => | ||
Host.CreateDefaultBuilder(args) | ||
.ConfigureWebHostDefaults(webBuilder => | ||
{ | ||
webBuilder.UseStartup<Startup>(); | ||
}); | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's target .net5