diff --git a/src/Gemstone.Web/APIController/AuthorizationInfoControllerBase.cs b/src/Gemstone.Web/APIController/AuthorizationInfoControllerBase.cs
index 49507353..f4fc1892 100644
--- a/src/Gemstone.Web/APIController/AuthorizationInfoControllerBase.cs
+++ b/src/Gemstone.Web/APIController/AuthorizationInfoControllerBase.cs
@@ -190,6 +190,53 @@ bool isSupported(string claimType) => claimsProvider
/// A list of resources within the application.
[HttpGet, Route("resources")]
public virtual async Task GetResources(IAuthorizationPolicyProvider policyProvider, EndpointDataSource endpointDataSource)
+ {
+ Dictionary> resourceAccessLookup = await ResourceAccessLookup(policyProvider, endpointDataSource);
+
+ IEnumerable resources = resourceAccessLookup
+ .OrderBy(kvp => kvp.Key)
+ .Select(kvp => new AuthorizationResource
+ {
+ Type = "Controller",
+ Name = kvp.Key,
+ AccessTypes = kvp.Value.OrderBy(type => type)
+ });
+
+ return Ok(resources);
+
+ }
+
+ ///
+ /// Gets a list of API resources available for which permissions can be granted within the application.
+ ///
+ /// Provides authorization policies defined within the application
+ /// Source for endpoint data used to look up controller and action metadata
+ /// A list of resources within the application.
+ [HttpGet, Route("APIresources")]
+ public virtual async Task GetAPIResources(IAuthorizationPolicyProvider policyProvider, EndpointDataSource endpointDataSource)
+ {
+ Dictionary> resourceAccessLookup = await ResourceAccessLookup(policyProvider, endpointDataSource);
+
+ IEnumerable resources = resourceAccessLookup
+ .OrderBy(kvp => kvp.Key)
+ .Select(kvp => new AuthorizationResource
+ {
+ Type = "API",
+ Name = kvp.Key,
+ AccessTypes = kvp.Value.OrderBy(type => type)
+ });
+
+ return Ok(resources);
+
+ }
+
+ ///
+ /// Gets a list of resources available with the provided .
+ ///
+ /// Provides authorization policies defined within the application
+ /// Source for endpoint data used to look up controller and action metadata
+ /// A list of resources within the application.
+ private async Task>> ResourceAccessLookup(IAuthorizationPolicyProvider policyProvider, EndpointDataSource endpointDataSource) where T : IAuthorizationRequirement
{
Dictionary> resourceAccessLookup = [];
@@ -206,12 +253,12 @@ public virtual async Task GetResources(IAuthorizationPolicyProvid
IReadOnlyList requirementData = endpoint.Metadata.GetOrderedMetadata() ?? [];
AuthorizationPolicy? policy = await AuthorizationPolicy.CombineAsync(policyProvider, authorizeData, policies);
- bool hasControllerAccessRequirement = requirementData
+ bool hasAccessRequirement = requirementData
.SelectMany(datum => datum.GetRequirements())
.Concat(policy?.Requirements ?? [])
- .Any(requirement => requirement is ControllerAccessRequirement);
+ .Any(requirement => requirement is T);
- if (!hasControllerAccessRequirement)
+ if (!hasAccessRequirement)
continue;
IReadOnlyList accessAttributes = endpoint.Metadata
@@ -222,38 +269,7 @@ public virtual async Task GetResources(IAuthorizationPolicyProvid
HashSet access = resourceAccessLookup.GetOrAdd(resourceName, _ => []);
access.UnionWith(accessTypes);
}
-
- IEnumerable resources = resourceAccessLookup
- .OrderBy(kvp => kvp.Key)
- .Select(kvp => new AuthorizationResource
- {
- Type = "Controller",
- Name = kvp.Key,
- AccessTypes = kvp.Value.OrderBy(type => type)
- });
-
- return Ok(resources);
-
- static IEnumerable ToAccessTypes(Endpoint endpoint, IEnumerable accessAttributes)
- {
- ResourceAccessType accessType = accessAttributes.GetAccessType();
-
- if (accessType == ResourceAccessType.None)
- return [];
-
- if (accessType != ResourceAccessType.Default)
- return [accessType];
-
- HttpMethodMetadata? httpMethodMetadata = endpoint.Metadata
- .GetMetadata();
-
- IReadOnlyList httpMethods = httpMethodMetadata?.HttpMethods
- ?? [];
-
- return httpMethods
- .Select(accessAttributes.GetAccessType)
- .Where(type => type != ResourceAccessType.None);
- }
+ return resourceAccessLookup;
}
///
@@ -273,6 +289,27 @@ public virtual IEnumerable CheckAccess([FromBody] ResourceAccessEntry[] ac
// Static Methods
+ private static IEnumerable ToAccessTypes(Endpoint endpoint, IEnumerable accessAttributes)
+ {
+ ResourceAccessType accessType = accessAttributes.GetAccessType();
+
+ if (accessType == ResourceAccessType.None)
+ return [];
+
+ if (accessType != ResourceAccessType.Default)
+ return [accessType];
+
+ HttpMethodMetadata? httpMethodMetadata = endpoint.Metadata
+ .GetMetadata();
+
+ IReadOnlyList httpMethods = httpMethodMetadata?.HttpMethods
+ ?? [];
+
+ return httpMethods
+ .Select(accessAttributes.GetAccessType)
+ .Where(type => type != ResourceAccessType.None);
+ }
+
private static Regex? ToSearchPattern(string? searchText)
{
if (searchText is null)
diff --git a/src/Gemstone.Web/APIController/ReadOnlyModelController.cs b/src/Gemstone.Web/APIController/ReadOnlyModelController.cs
index f681826e..b2d9e113 100644
--- a/src/Gemstone.Web/APIController/ReadOnlyModelController.cs
+++ b/src/Gemstone.Web/APIController/ReadOnlyModelController.cs
@@ -337,12 +337,12 @@ public virtual async Task Search([FromBody] SearchPost postDat
if (ParentKey != string.Empty && parentID is not null)
{
- filters.Append(new RecordFilter()
+ filters = filters.Append(new RecordFilter()
{
FieldName = ParentKey,
Operator = "=",
SearchParameter = parentID
- });
+ }).ToArray();
}
IAsyncEnumerable result = tableOperations.QueryRecordsAsync(HttpContext.User, postData.OrderBy, postData.Ascending, page, PageSize, cancellationToken, filters);
@@ -367,12 +367,12 @@ public virtual async Task GetPageInfo([FromBody] SearchPost po
if (ParentKey != string.Empty && parentID is not null)
{
- filters.Append(new RecordFilter()
+ filters = filters.Append(new RecordFilter()
{
FieldName = ParentKey,
Operator = "=",
SearchParameter = parentID
- });
+ }).ToArray();
}
int recordCount = await tableOperations.QueryRecordCountAsync(HttpContext.User, cancellationToken, filters).ConfigureAwait(false);
@@ -401,12 +401,12 @@ public virtual async Task GetPageInfo(string? parentID, Cancellat
if (ParentKey != string.Empty && parentID is not null)
{
- filters.Append(new RecordFilter()
+ filters = filters.Append(new RecordFilter()
{
FieldName = ParentKey,
Operator = "=",
SearchParameter = parentID
- });
+ }).ToArray();
}
int recordCount = await tableOperations.QueryRecordCountAsync(HttpContext.User, cancellationToken, filters).ConfigureAwait(false);