-
Notifications
You must be signed in to change notification settings - Fork 890
Description
One thing I often deal with is… attributes of a resource that are protected; consideration must be made whether or not to include the attribute of the resource for a given user. The use case below is super simple but illustrates the options of whom to show a protected attribute to.
Resource: A Comment with attributes: body:string & approved:boolean (default: false)
- Visitor: only sees Comments that are approved but never sees the 'approved' attribute in the resource
- Commenter: only sees the 'approved' attribute for Comments owned by the Commenter (never sees the 'approved' attribute for Comments owned by other Commenters
- Moderator: Sees the approved attribute for any Comment in the system
Now that the JSON representation of a resource has the optional "attributes" node (which includes the attrs of the resource) I started thinking about an (optional) "protected-attributes" node (sibling to "attributes") This "protected-attributes" object may contain any attributes that are not guaranteed to be included in the resource; however if the scenario is fitting for the response to include any protected attribute(s), then the resource may include those attribute(s) in the "protected-attributes" object.
In the following resource example the "approved" attribute may or may not be presented, depending on the scenario of the request…
{
"data": {
"id": "1",
"type": "comments",
"attributes": {
"body": "Ah this is sweet"
"protected": {
"approved": false
}
}
}
}
{
"data": {
"id": "1",
"type": "comments",
"attributes": {
"body": "Ah this is sweet"
}
}
}
{
"data": {
"id": "1",
"type": "comments",
"attributes": {
"body": "Ah this is sweet"
"approved": false
}
}
}
However this seems like a better (more standard) representation for "Protected" attributes:
{
"data": {
"id": "1",
"type": "comments",
"attributes": {
"body": "Ah this is sweet"
},
"protected-attributes": {
"approved": false
}
}
}
For example, consider a blog comment that needs moderation:
A Commenter may see a JSON response which includes a comment the Commenter owns. A Moderator would see the same response:
{
"data": {
"id": "1",
"type": "comments",
"attributes": {
"body": "Ah this is sweet"
},
"protected-attributes": {
"approved": false
},
"links": {
"self": "http://localhost:3000/api/v1/comments/1",
"commenter": {
"self": "http://localhost:3000/api/v1/comments/1/links/commenter",
"related": "http://localhost:3000/api/v1/comments/1/commenter",
"linkage": {
"type": "commenters",
"id": "1"
}
},
"post": {
"self": "http://localhost:3000/api/v1/comments/1/links/post",
"related": "http://localhost:3000/api/v1/comments/1/post",
"linkage": {
"type": "posts",
"id": "1"
}
}
}
},
"included": [
{
"id": "1",
"type": "commenters",
"attributes": {
"name": "Bill Heaton"
},
"links": {
"self": "http://localhost:3000/api/v1/commenters/1",
"comments": {
"self": "http://localhost:3000/api/v1/commenters/1/links/comments",
"related": "http://localhost:3000/api/v1/commenters/1/comments"
}
}
}
]
}
Another Commenter viewing a Comment owned by someone else:
{
"data": {
"id": "2",
"type": "comments",
"attributes": {
"body": "Well now, how about that!",
},
"protected-attributes": {},
"links": {
"self": "http://localhost:3000/api/v1/comments/2",
"commenter": {
"self": "http://localhost:3000/api/v1/comments/2/links/commenter",
"related": "http://localhost:3000/api/v1/comments/2/commenter",
"linkage": {
"type": "commenters",
"id": "2"
}
},
"post": {
"self": "http://localhost:3000/api/v1/comments/1/links/post",
"related": "http://localhost:3000/api/v1/comments/1/post",
"linkage": {
"type": "posts",
"id": "1"
}
}
}
},
"included": [
{
"id": "2",
"type": "commenters",
"attributes": {
"name": "Nobody Special"
},
"links": {
"self": "http://localhost:3000/api/v1/commenters/2",
"comments": {
"self": "http://localhost:3000/api/v1/commenters/2/links/comments",
"related": "http://localhost:3000/api/v1/commenters/2/comments"
}
}
}
]
}
And a Visitor may not even be aware of any protected attributes
{
"data": {
"id": "5",
"type": "comments",
"attributes": {
"body": "yeah another one, I know"
},
"links": {
"self": "http://localhost:3000/api/v1/comments/5",
"commenter": {
"self": "http://localhost:3000/api/v1/comments/5/links/commenter",
"related": "http://localhost:3000/api/v1/comments/5/commenter",
"linkage": {
"type": "commenters",
"id": "2"
}
},
"post": {
"self": "http://localhost:3000/api/v1/comments/5/links/post",
"related": "http://localhost:3000/api/v1/comments/5/post",
"linkage": {
"type": "posts",
"id": "2"
}
}
}
}
}