Entity Relations in Services - oop

I have such model relations: User, Task, each user can create his own tasks and can see All tasks. So obviously I'll have TaskService with methods getAllTasks(), getSortedTasks(String value), etc.
I'm confused where should I have createTask(Task task), updateTask(lond id, Task task) methods - in TaskService or in UserService, because I'm told I should have REST API looks like:
rather
post users/{id}/tasks
than
post /tasks
because "a task belongs to a particular user". So I can't choose between separate services,api for each entity and common services,api whre User is relations owner.

You should implement the endpoint for creating tasks in a task resource.
Both is possible:
POST your_root.com/api/{userId}/tasks/ ----> Creates task and takes the value of the creator from the uri.
But you could also go this way:
POST your_root.com/api/tasks/ ---> In this case you have to tell the server by JSON or XML who created the task. The body could look like this i.E.:
{
"author": "user A",
"assingee": null,
"headline": "Login Page for my app",
"text":"Build fancy login page"
}
Last variant and my preferred:
POST your_root.com/api/{userId}/tasks/
and the authorId in the body again:
{
"authorId":"12"
"author": "user A",
"assingee": null,
"headline": "Login Page for my app",
"text":"Build fancy login page"
}
The advantage of the last variant is that you can check whether the userId in the uri equals the authorId of the body. So you can avoid that this request with a certain Id is made by accident.
Hope that helps.

Related

How to use the fields parameter when calling the Gmail API

I am using the Gmail API in Google Apps Script (which is basically Javascript), and I need to make as few calls to the API as possible, for efficiency and speed.
I'm using Users.messages: list to list the messages in a user's mailbox, and the response includes an array called messages, and for each message it includes an id and a threadId, like so:
"messages": [
{
"id": "152b93b1111c33e2",
"threadId": "152b922266c33e2"
},
{
"id": "152b93338c98cb3",
"threadId": "152b922266c33e2"
} ...
But I need the response to include more information about each message, so that I don't have to make a separate Users.messages:get call for each message.
The APIs Explorer on the Users.messages: list page says you can use the fields parameter to "specify which fields to include in a partial response."
When I click "Use fields editor" to select the three items I need, it fills the following in to the field:
messages(id,internalDate,payload)
Then when I execute the command, it shows that the GET command should look like this:
https://www.googleapis.com/gmail/v1/users/test#test.com/messages?fields=messages(id%2CinternalDate%2Cpayload)&key={YOUR_API_KEY}
However, the messages array in the results does not include the internalDate or the payload fields. It just includes the message id only, like so:
"messages": [
{
"id": "152b93b1111c33e2"
},
{
"id": "152b93338c98cb3"
} ...
It also does not include the threadId anymore, but it DOES continue to include the threadId if I select that as one of the fields, like so:
messages(id,threadId)
and the URL looks like this...
https://www.googleapis.com/gmail/v1/users/test#test.com/messages?fields=messages(id%2CthreadId)&key={YOUR_API_KEY}
And the result looks exactly like the first result above, where we weren't using the fields parameter.
So I know the fields parameter is actually doing something.
Thinking this might just be a limitation of the APIs Explorer, I tried making the API call in Google Apps script, but it still does not include the fields I need.
You are almost there.
When listing messages, theid and threadId of each message is all you get. You then have to get each message separately.
If you e.g. just want the internalDate of the message, it is in this request it should be specified in the fields parameter.
Request
GET https://www.googleapis.com/gmail/v1/users/me/messages/152b792a91c9c391?fields=internalDate&key={YOUR_API_KEY}
Response
{
"internalDate": "1454778787000"
}

Are resources state aware or static under hateoas/restful api

My question is about if resources should be aware of the state or statically defined. For example, I have an API that returns account information where the resource uri would be /api/accounts/2.
If I'm authenticated as user henk willemsa the resource would look like this:
{
"id": 2,
"firstname": "henk",
"lastname": "willemsa",
"birthday": "12-31-1980",
"email": "firstname.lastname#email.com",
"other": "other useless info",
"super-secret-info": "some super secret info"
}
Is it good practice to return the resource with stripped out data if you would be authenticated as another user? For instance, making a request to the same endpoint /api/accounts/2, but for a different user, jan smit, the returned response would be:
{
"id": 2,
"firstname": "henk",
"lastname": "willemsa"
"other": "other useless info"
}
The idea is that user jan smit is only allowed to see the public data, where henk willemsma sees the secret as well.
Would it be better for something like this be solved with 2 endpoints, where /api/accounts/2 would return a 403 for user jan smit and 200 for henk willemsa and another api endpoint /api/public-account/2 would return 200 for the both users? The later could give a response like:
{
"id": 2,
"firstname": "henk",
"lastname": "willemsa"
"other": "other useless info"
}
Having one endpoint and stripping out data would in my eyes be inconsistent, because the structure of the data-type/resource would change depending on who requests it and not because extra explicit data is sent, which changes the data-type/resource (like filter options).
But I can also see that splitting this out over multiple endpoints could cause for having lots and lots of different endpoints which basically do the same returning account information.
I also found this question, which somewhat describes what I'm looking for but is about collection calls. In my opinion, these are allowed to return different unique resource, but the data-types should always be the same. In my example, /api/accounts/ would always return a list of accounts, but depending on which user makes the request to the endpoint, while the size of the list could be different, it would always be a list of accounts.
What is the best approach?
The "best" approach can probably not be objectively defined. However, creating multiple resources for the same "thing" is probably not a good idea. Things should be identifiable by URI, so accounts should have a stable URI.
I would probably just omit the fields that the user can not see, if that is possible according to the data definitions/structure. If not, you could serve multiple 'representations', i.e. media-types, and let content-negotation handle the exchange. That means you create 2 media-types, one with the full data and one for the restricted view of the account, and serve both for the same resource URI. The server then can decide which representation you get based on your credentials. The client would also be able to easily see which representation it got, and inform the user if necessary that it has a restricted view of the account.
The client would have to ask with an 'Accept' header similar to this:
Accept: application/vnd.company.account-full; q=1.0, application/vnd.company.account-restricted; q=0.9,

RESTful API Design: PUT or POST for creating many-to-many relationships?

For designing and creating a RESTful API the following question occurs:
The API supports GET (for queries), POST (for creating), PUT (for updates) and DELETE (for deleting).
Lets assume in the database we have an article and a shop both already existing.
Now we need a rest call to link the article instance to the shop instance. Which of the following solutions is the best / most clean REST design:
/shop/id/article/id/ --> with POST
/shop/id/article/id/ --> with PUT
/shoparticlerelation/ --> with POST (object with ids in body)
/shoparticlerelation/ --> with PUT (object with ids in body)
If there is no clear answer or all solutions are equally good this may also be a valid answer if there is a clear argumentation why.
I presume in this situation you already have a collection of shops and a collection of articles, and you just wish to link two together.
One option is to expose a more db like 'resource' that presents this link, and have operations like
POST /shopArticleLinks HTTP/1.1
{ "shop" : xxx,
"article: YYY
}
I would personally look to expose it as a property of the shops and/or articles in a more natural manor, like
PUT /shop/<ID> HTTP/1.1
{ /* existing details */
"articles": [ /* list of articles */ ]
}
I've used JSON there, but of course use what ever format you want to use. I've also stuck with using PUT as you stated, but keep in mind that with PUT you should send a full replacement for the new modified version, PATCH can be used to send partial updates, but then you need to consider how you want do that, may something like
PATCH /shops/<ID>/articleLinks HTTP/1.1
{ "add" : [],
"remove : []
}
Don't forget that server side you can look at what articles are being refereed to and ensure they have a proper back pointer.
Additional thoughts
Regarding the second method, where you expose the link as a property of the shop and/or article resources. Keep in mind that it is perfectly acceptable (and in this case rather appropriate) that when you update the links in a given shop that the links in the corresponding articles are also updated.
/shop/id/article/id/
You cannot use this because at the moment you want to link them, this endpoint doesn't (or at least shouldn't) yet exist. It is the action of linking them together that should define this endpoint.
/shoparticlerelation/
You should not use this because a shoparticlerelation is not a resource / entity. Usually with rest, every named url segment represents a resource that can be CRUD-ed. /shops is a good example and so is /articles but this one isn't.
I suggest the following:
Define the following endpoints
/shops for POSTing new shops
/shops/id for operating on a single shop
/articles for POSTing new articles
/articles/id for operating on a single article
Then to link them together you can do a so called PATCH request, to update a shop's articles, or an article's shops:
PATCH /shops/1 HTTP/1.1
{
"attribute": "articles",
"operation": "add",
"value": "8" // the article id
}
and
PATCH /articles/9 HTTP/1.1
{
"attribute": "shops",
"operation": "add",
"value": "1" // the shop id
}
Based on your comments I made the assumption that an Article model has a list of Shops as attribute, and vice-versa, making this approach valid.
A PATCH request is used to modify an existing resource by specifying how and what to update. This is different from a PUT because a PUT replaces the entire resource with values from the request, however PATCH is only used to modify (not replace) a resource.

Is this a valid REST API?

I am designing an API.
There's the user profile, accessible at
http://example.org/api/v1/users (resp. http://example.org/api/v1/users/:id)
Now, the user's profile will be dynamic.
So we will allow an API function to add a new profile attribute.
Is the following a valid REST API URL for this?
POST http://example.org/api/v1/users/attributes
Indeed, to retrieve a specific user, the user's id would be appended to the .../users/ URL.
Now if I use the "attributes" element after /users/, would that somehow break the user id pattern for the URL?
I'd like to keep the base URL to be api/v1/users though, because logically I am modifying the users profile still...
EDIT: The attributes would be added valid for all profiles, it's independent of a user. Say the profile has "name", "surname", "email", and I want to add "address" to all profiles (Of course I know that users with a missing "address" field would not get the new attribute)
What is a good practice to address such an issue?
I think the id should be kept in the URL because you are adding the attributes to a specific user, right?
It is an acceptable solution to use the /api/v1/users/attributes as long as the :id cannot be the text: "attributes". However I recommend to create your own media type, microformat, or microdata for the attributes, because it is rather a type than a resource.
I think you should check these links:
http://alps.io/spec/index.html
http://www.markus-lanthaler.com/hydra/spec/latest/core/
http://schema.org/
http://microformats.org/wiki/microformats2
http://amundsen.com/media-types/maze/
If the user can set what attributes she can have, only then should you use a resource for attributes. But then each user should have one. But I don't think using resources will be necessary, microdata and microformats both contain more than enough person description attributes...
Some update after 5 months:
Now if I use the "attributes" element after /users/, would that
somehow break the user id pattern for the URL?
From the perspective of the client that "id pattern" does not exist. The client follows links by checking the semantics annotated to them. So REST clients are completely decoupled from the URI structure of the actual REST API (aka. uniform interface constraint). If your pattern breaks, then it is completely a server side, link generation and routing issue, which is not a client side concern.
Say the profile has "name", "surname", "email", and I want to add
"address" to all profiles. What is a good practice to address such an
issue?
Address is an optional field in this case and probably a sub-resource, because it can have further fields, like city, postal code, street, etc... You can add address separately, for example with PUT /users/123/address {city: "", street: "", ...} or you can add those fields to your user form, and add a partial update to the user, like PATCH /users/123 {address: {city: "", street: "", ...}} if only the address changes.
In case you want to update every resource in the entire collection I would send a PATCH request to /users.
While it is a valid URI, I would suggest avoiding POST http://example.org/api/v1/users/attributes. In my opinion, it violates the principle of least surprise when a collection endpoint has a child node which is not a member of the collection. If you want to track user attributes as shared by all users, then that's a separate collection, perhaps /user-attributes.
POST /user-attributes
{
"name": "Email Address",
"type": "String",
...
}
GET /user-attributes would return all the possible attributes, and GET /user-attributes/{id} would return all the metadata around an attribute.
If there's no metadata, then #inf3rno's suggestion to just PUT the attribute up and let the server deal with it is definitely worth considering.
This all presupposes you need to manage attributes through the API. If not, I agree with #inf3rno that media types are the way to go. Of course, in that case you may want a media type for the user-attributes resource ..

Use a single POST request to update to create two objects Bad API design?

Consider the scenario, an unknown unauthenticated user is looking at the list of nerddinners and then goes to a particular dinner, enter his name and email and clicks "Attend". This should result in two things. Create the user and create the DinnerAttendRequest for that user.
The user also has a property called FavProgLanguage which is set to the prog language property of the dinner which he wants to attend.
Assuming it is a single page javascript app which talks to an API, there are two approaches which come to mind.
1) On the client, set the users FavProgLanguage and then POST to /user with name, email and favproglanguage to create the user. Use the created UserId and POST to /DinnerAttendRequest with DinnerId and UserId to create DinnerAttendRequest.
2) POST to /somename with Name, email and dinnerId and then use dinnerId at server to populate favproglanguage of user. create user and then use userid to create DinnerAttendRequest
The first approach seems more natural/RESTful, however if the logic of computing the favproglanguage is a bit complex, all the api consumers would have to implement that logic and with the second approach that code is written just once on the server.
Which is a better approach? Is the second approach RESTful?
Your 1st design would place the burden of logic, workflow and the fav lang decision, upon the client, this would make handling the user creation and reservation a single transaction difficult and something that a client app would need to orchestrate. Your fav lang logic sounds like an important business rule that again should ideally sit at the server for re-use...
Why don't you look at having some resources like so:
Dinner e.g. { "name", "date", etc. }
Booking e.g. { "user" { NESTED USER RESOURCE }, "bookingStatus", etc. }
User e.g. { "email", "name", "fav lang", etc.}
Some example urls
/dinners/{uid}
/dinners/{uid}/bookings
/users/{uid}
Basically I would POST a Booking resource containing a nested User resource to the dinner bookings url and run the logic for checking is a user exists, creating if needed and updating their fav lang in a transaction.
So to create a booking I would POST a Booking Resource:
{
"user": {
"email": "john#doe.com",
"name": "name"
},
"bookingStatus": "requested"
}
To /dinners/{uid}/bookings
And expect a 201 created response with a response like this:
{
"uid": "4564654",
"user": {
"uid": "1234564",
"email": "john#doe.com",
"name": "name",
"favLang": "C#"
},
"bookingStatus": "booked"
}
Obviously the properties are largely just for example but hopefully this demonstrates some of the concepts and shows that a single POST can be considered RESTful...