Skip to content

Generic resource definitions #806

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

Closed
bart-degreed opened this issue Aug 26, 2020 · 1 comment · Fixed by #832
Closed

Generic resource definitions #806

bart-degreed opened this issue Aug 26, 2020 · 1 comment · Fixed by #832
Assignees

Comments

@bart-degreed
Copy link
Contributor

Current situation

The current way how resource definitions work is that JADNC provides a generic base class, which users can derive from for a specific resource type. JADNC contains scanning logic that picks up such non-generic (resource-bound) classes and calls into them from various places.

Example:

public class OrderLineDefinition : ResourceDefinition<OrderLine>
{
    // ...
}

When no resource-bound class is found for a specific resource, then resource callbacks are skipped for that resource type. This is accomplished via a non-generic IResourceDefinition interface, which is a type intended for internal use only to track which callbacks are available. It put me on the wrong track when I started using JADNC: I expected this was something for me to implement (similar to services and repositories), but it is not.

Proposal

I'd like to make resource definitions a first-class pluggable extensibility point, similar to services and repositories, so that resource definitions are always called into. We would provide an interface along with a default generic implementation (that contains no logic). Users can then implement the interface themselves and register their generic type -and- derive from our default generic implementation and register that -and- declare resource-bound definitions, which may derive from their own generic base class.

Example:

namespace JADNC
{
    public interface IResourceDefinition<TResource>
    {
        // ...
    }

    public class JsonApiResourceDefinition<TResource> : IResourceDefinition<TResource>
    {
        // ...
    }
}

namespace ApiDeveloper
{
    public class CustomResourceDefinition<TResource> : JsonApiResourceDefinition<TResource>
    {
        // ...
    }

    public class OrderLineResourceDefinition : CustomResourceDefinition<OrderLine>
    {
        // ...
    }
}

Use case

The use case I have in mind for this is authorization. Assume the system stores whether users have read/write access per resource type. While it is possible to annotate controller methods with attributes, this would not be sufficient. It would only work for primary requests like /articles and /articles/1, but not secondary requests like /articles/1/author. The controller would need to contain custom logic that inspects the relationship parameter and runs the permission check for that too. It is even debatable whether a permission check on articles should be done in that case, because the request is not targeting an article.

But it gets worse: a request like /articles?include=author would not get checked for access to the author resource. The current way to deal with that would be to override ResourceDefinition.OnApplyIncludes for all resource types in the project. A similar override for ResourceDefinition.OnApplyFilter is needed to properly check a request like /articles?filter=any(revisions) to ensure the caller has read permission on the revisions table.

If it were possible to plug in a generic resource definition, it could handle the permission check for all resource types in the project. Resource-bound classes would then call into the base class to ensure authorization is always applied.

@maurei
Copy link
Member

maurei commented Aug 26, 2020

Very much entangled with the challenge of allowing for complex authorization on deeply resource-nested endpoint are ResourceHooks. I'm very happy you have a reason to dive into this! My original reason for introducing these hooks was exactly this: complex authorization. I think it will be fruitful for the design considerations to read through the resource hooks document to get a better idea of how the hooks aimed to solve this problem (and related problems) and to get a better idea how we could perhaps integrate the most recent extensibility points in ResourceDefinition together with the hooks system into a really neat system.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging a pull request may close this issue.

2 participants