RE: Modeling permissions with Hydra

On 18 Nov 2015 at 11:08, Asbjørn Ulsberg wrote:
> 2015-11-10 22:42 GMT+01:00 Markus Lanthaler: 
>> This is not "my position". It is how it is currently defined. If you have a
>> class C which supports operation O and a resource of type C, then
>> a client can infer that the resource supports O.
>> 
>>    C hydra:supportedOperation O
>>    R rdf:type C
>>   ==> R operation O
>> I'm open to discuss this. The reason this was designed this way is that
>> in most APIs out there, typically (almost) all instances of a specific type
>> typically support exactly the same operations. You don't see a lot of
>> APIs where each resource behaves completely differently from every
>> other resource exposed by the API.
> 
> I agree; in most situations, the operations will be fairly static. But
> in order to tell the client that an operation is not supported,

I would say that an operation isn't available for all resources of that type, the ApiDocumentation shouldn't say so. It's trivial to introduce an additional (sub)class (BlogPost vs. EditableBlogPost) and attach to operation to that class instead.. or attach the operation to the resource directly.

> I think the current alternatives:
> 
> 1. Force the client to reload the ApiDocumentation
> 2. Make the client try to perform the operation and respond with 403 or 405
> 
> ...are not optimal. How would you do the first one server-side?

Point to a different ApiDocumentation? Similar to how you point to a different, longly-cached CSS/JS file when deploying a new version of a website.


> And the second requires at least one extra request, which is something we
> can avoid if possible, as hypermedia driven API's are chatty enough by
> the nature of HATEOAS.

Right. It is not always avoidable though. There might pass significant time between the client receiving the resource and executing an operation based on it.


>>>> 2. However at least some others think the API documentation should be
>>>> interpreted as a kind of overview of what might be possible; a way to
>>>> document an API using RDF, but always subject to revision by the
>>>> information in an actual representation.
>> 
>> Could you explain how such a "revision" would or could look like in
>> practice?
> 
> I didn't write this, but I agree with the sentiment. A way to do this is
> to say that the operations in ApiDocumentation are just a (complete)
> list of what the client needs to support, but that the inline operations
> are the ones supported in the resource's current state. This incurs
> duplication, but also gives the server more control.

The ApiDocumentation would be of very little value then. Assumptions like having a complete overview etc. are very dangerous in the context of large, distributed systems.


> Another option is to give the inline operations a way to "override",
> possibly through a registered term (either in Hydra or elsewhere)
> saying something like (please excuse my feeble attempt at expressing
> this in what must be invalid Turtle syntax):
> 
> <http://www.w3.org/ns/hydra/core#operation>
>   <http://purl.org/dc/terms/replaces>
>     <http://www.w3.org/ns/hydra/core#supportedOperation>
> I know "dc:replaces" is for resources and not operations and that we
> would need to identify which hydra:supportedOperation our inline
> hydra:operation is replacing, but I hope this gives a general idea on
> how we can model this.
>
>> Apart from adding or removing a class/property from a resource which
>> is how the current design works (e.g., make something a EditableBlogPost
>> instead of just a BlogPost=.
> 
> That is of course one possible solution, but it requires API designers
> to view their resources as being of different classes for every
> mutation of the operation matrix. Given enough combinations of
> operations, this can become unwieldy.

A resource can have multiple classes, so you can combine them. Also, there always the option to simply list the operations inline if listing them upfront becomes impractical.


>>> The ApiDocumentation tells you about every detail you need to cater
>>> to in your client application.
>> 
>> Be careful with the work *every* here. You will have a hard time
>> documenting all details.
> 
> Yes, of course. Which is why the inline operations and other hydra
> metadata is even more important than what's described in the
> ApiDocumentation.
> 
>> The ApiDocumentation is not communicated out of band. So I don't see a
>> problem for the client to consume and interpret it at runtime (apart from
>> additional complexity).
> 
> I think this is a point that is currently too unclear in the
> specification. I also believe that no matter how clear this point is
> communicated, it won't end up working like this in practice. In
> reference Hydra API clients, perhaps, but even there, dynamically
> changing the client will potentially break consumers of the client,
> especially if the client is statically typed.

If that breaks consumers of the client, they won't be able to deal with inline operations either, right?


>> You will similarly find enough people that argue that most of their
>> resources look and behave the same and they see little value in
>> repeating this information everywhere. They want to put it in a
>> central place and just reference it instead (just like the do with
>> CSS for instance).
> 
> Yes, but to continue that analogy, it's not very common that the
> centrally referenced CSS changes dynamically based on the state of the
> resource.

Right, that's the reason why I'm not a big fan of doing that (but mention that is possible). I find using different classes (like in CSS) much better.


> It can and will happen in systems that have dynamic CSS
> bundlers and minifiers that optimize the CSS in runtime, but that
> makes the adapted CSS less cacheable.

Right. You can always change the URL to the ApiDocumentation to force a refresh for (different version for logged-in vs. logged-out users for instance).


> I feel like the mental model of having a centrally referenced
> ApiDocumentation that is supposed to change dynamically given the
> current resource's state is hard to understand.

+1


[...]

>>> especially if the roles themselves are dynamic (one can define and
>>> assign new roles).
>> 
>> Assigning roles could be realized by adding classes to instances
>> which means operations could still be driven by ApiDocumentation.
>> I see no contradiction here.
> 
> This usage of dynamically applying classes to instances in runtime
> might work. I'm not sure how to model it, but if you could make the
> operations general across several different resources, the operations
> themselves could be attached to the "role" as an aspect[1].

How many operations do you typically have to deal with for a resource (type)? In the order of 1-10? 10-20? 20-50? 50-100? More than 100?


>>> Besides, one of the reasons one may not see so many
>>> APIs like this currently is that there hasn't been a great way to
>>> write real hypermedia clients that can handle such dynamic
>>> APIs, but isn't that what you are enabling with Hydra?
>> 
>> Yes, that's why we (currently) allow both inline controls and controls in
>> the ApiDocumentation.
> 
> Yes, but the current model is optimized for extending
> hydra:supportedOperation in hydra:operation, not overriding or
> limiting hydra:supportedOperation. I think we need a way to say in a
> declarative way that a supported operation is not available at the
> current state of the resource.

I need to think a bit more about this.


> [1] https://en.wikipedia.org/wiki/Aspect-oriented_programming


--
Markus Lanthaler
@markuslanthaler

Received on Thursday, 26 November 2015 10:41:18 UTC