How to provide translations for field names with Symfony2/Doctrine2 via REST? - rest

We have a backend built on FOSRestBundle (JMSSerializer) based on Symfony2/Doctrine2.
Our API e.g. delivers for some entity something like: 'valid_from': '2015-12-31' in a REST/JSON response.
Our AngularJS frontend consumes this REST API and e.g. presents some form to the user:
Valid from: 31.12.2015
Now I am wondering what's the best way to have a central/or maintainable place for a mapping like:
an English label for field key 'valid_from' is 'Valid from'
To my understanding all Translatable extensions for Doctrine (like Gedmo Kpn etc.) are to translate content (e.g. 'category' = 'Product' in English and = 'Produkt' in German) but not schema.
And of course I cannot change/adapt the field key to the language because it's the identifier for the frontend.
What I thought so far:
Use some mapping file between field_key, language_key and
translation on frontend.
Issue here is that the frontend needs to know a lot and ideally any change in the API can be done thoroughly by the backend developers.
Use some mapping file between field_key, language_key and
translation on frontend.
As we use annotations for our Entity model and JSMSerializer I'd need to open a totally new space for just translation information. Doesn't sound too convincing.
Create custom annotation with properties
Current idea is to use custom annotation (which would be cacheable and could be gathered and provided as one JSON e.g. to the frontend) with my entity properties.
That means any backend developer could immediately check for translation keys at least as soon as the API changes.
Something like:
#ORM\Column(name='product', type='string')
#FieldNameTranslation([
['lng'=> 'de-DE'],['text']=>'Product'],
['lng'=> 'en-En'],['text']=>'Produkt'])
A further idea could be just to provide some translation key like:
#FieldNameTranslation(key='FIELD_PRODUCT')
and use Symfony's translation component and have the content in translation yml files.
What is your opinion? Is there any 'best in class' approach for this?

Related

Generate unpredictable/unforgeable URL from predictable ID

I have a simple API that return Something for a given ID and it must be used without any kind of authentication, the URL should be permanent and yet I want to avoid as much as possible it to be botted.
The Url is something like this:
https://url/{SomeId}/doSomething
The problem is that this is very predicable and a bot could easily try all the ID and get everything associated to it.
I'm looking for a way to make the URL non predictable like for example:
https://url/{SomeId}/doSomething?Key=SomeVeryLongCryptographicKey
In this way except if you run a supercalculator you shouldn't be able to deduce all the URLs
I know that there is probably a lot of ways to do that, like using a DB which I want to avoid.
I guess I'm looking for a kind a JWT associated to the ID without expiration but maybe there is better solution.
Edit: to give a better example i'm looking to do a bit like did Zoom for permanent invitation Links. They had predictable room Ids and they added a password making it unpredictable lie so:
https://us05web.zoom.us/j/132465789?pwd=SUxIU0pLankyhTRtWmlGbFlNZ21Ndz08
What would be the best/light/"secure" way to achieve that ?
Also I'm using .Net if there is a library doing that, it would be great.
I think your idea of using a JWT makes the most sense. Better to use something standard from a cryptographic point of view, and the JSON format allows for encoding whatever you need to provide to the receiving endpoint (user names, entity names, entity IDs, other things).
There are standard Microsoft libraries for building and validating JWTs, but I prefer the library Jwt.Net (https://www.nuget.org/packages/JWT). It lets you do something like this quite easily:
var token = JwtBuilder()
.WithAlgorithm(new RS256Algorithm(publicKey,privateKey))
.AddClaim("uri", String.Format("https://example.com/api/{0}/{1}", entityName, entityId))
.Encode();
Just add whatever claims you like, and the JWT will then contain what you want to transfer (I've used an example of the URI that you want to give to the entity) and a signature with your private key. You could even just give a URL like https://example.com/from_token/eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1cmkiOiJodHRwczovL2V4YW1wbGUuY29tL2FwaS90ZXN0RW50aXR5LzEyMzQifQ.K2P4wSF6g1Kt-IHMzlklWTV09_MIkoiNHQztSIYOohmOWe7aBfFSQLIKSbdTECj9XPjNNG_AjH9fdjFglkPuYfr2G9rtl2eh5vTjwdM-Uc0X6RkBu0Z2j7KyMKjkaI3zfkIwhtL1mH873xEBtNOGOW18fuBpgnm8zhMAj1oD3PlDW8-fYBrfLb6VK97DGh_DyxapbksgUeHst7cAGg3Nz97InDPtYcWDi6lDuVQsj3t4iaJBRL8IM785Q8xjlHHhzdfcX3xU4IhflyNHHXxP56_8ahNNMOZKWdwgbTSIxEEB98b3naY3XknC-ea7Nc1y4_5fszrYdy3LaQWV43jpaA
and have the handler decode the entity name and ID you want to retrieve directly from the URI while verifying the signature. Decoding with the library is just as easy:
var json = JwtBuilder.Create()
.WithAlgorithm(new RS256Algorithm(_key))
.MustVerifySignature()
.Decode(token);

REST - Updating partial data

I am currently programming a REST service and a website that mostly uses this REST service.
Model:
public class User {
private String realname;
private String username;
private String emailAddress;
private String password;
private Role role;
..
}
View:
One form to update
realname
email address
username
Another form to update the role
And a third form to change the password
.
Focussing on the first view, which pattern would be a good practice?
PUT /user/{userId}
imho not because the form contains only partial data (not role, not password). So it cannot send a whole user object.
PATCH /user/{userId}
may be ok. Is a good way to implement it like:
1) read current user entity
2)
if(source.getRealname() != null) // Check if field was set (partial update)
dest.setRealname(source.getRealname());
.. for all available fields
3) save dest
POST /user/{userId}/generalInformation
as summary for realname, email, username
.
Thank you!
One problem with this approach is that user cannot nullify optional fields since code is not applying the value if (input is empty and value) is null.
This might be ok for password or other required entity field but for example if you have an optional Note field then the user cannot "clean" the field.
Also, if you are using a plain FORM you cannot use PATCH method, only GET or POST.
If you are using Ajax you might be interested in JSON Merge Patch (easier) and/or JavaScript Object Notation (JSON) Patch (most complete); for an overview of the problems that one can find in partial updates and in using PATCH see also this page.
A point is that a form can only send empty or filled value, while a JSON object property can have three states: value (update), null (set null) and no-property (ignore).
An implementation I used with success is ZJSONPATCH
Focussing on the first view, which pattern would be a good practice?
My suggestion starts from a simple idea: how would you do this as web pages in HTML?
You probably start from a page that offers a view of the user, with hyperlinks like "Update profile", "Update role", "Change password". Clicking on update profile would load an html form, maybe with a bunch of default values already filled in. The operator would make changes, then submit the form, which would send a message to an endpoint that knows how to decode the message body and update the model.
The first two steps are "safe" -- the operator isn't proposing any changes. In the last step, the operator is proposing a change, so safe methods would not be appropriate.
HTML, as a hypermedia format, is limited to two methods (GET, POST), so we might see the browser do something like
GET /user/:id
GET /forms/updateGeneralInformation?:id
POST /updates/generalInformation/:id
There are lots of different spellings you can use, depending on how to prefer to organize your resources. The browser doesn't care, because it's just following links.
You have that same flexibility in your API. The first trick in the kit should always be "can I solve this with a new resource?".
Ian S Robinson observed: specialization and innovation depend on an open set. If you restrict yourself to a closed vocabulary of HTTP methods, then the open set you need to innovate needs to lie elsewhere: the RESTful approach is to use an open set of resources.
Update of a profile really does sound like an operation that should be idempotent, so you'd like to use PUT if you can. Is there anything wrong with:
GET /user/:id/generalInformation
PUT /user/:id/generalInformation
It's a write, it's idempotent, it's a complete replacement of the generalInformation resource, so the HTTP spec is happy.
Yes, changing the current representation of multiple resources with a single request is valid HTTP. In fact, this is one of the approaches described by RFC 7231
Partial content updates are possible by targeting a separately identified resource with state that overlaps a portion of the larger resource
If you don't like supporting multiple views of a resource and supporting PUT on each, you can apply the same heuristic ("add more resources") by introducing a command queue to handle changes to the underlying model.
GET /user/:id/generalInformation
PUT /changeRequests/:uuid
Up to you whether you want to represent all change requests as entries in the same collection, or having specialized collections of change requests for subsets of operations. Tomato, tomahto.

Restful API for Templating

I am struggling with a design aspect of my restful api for templating collections of resources.
The endpoint calls for a json with the name to a particular template and a collections of tokens. The API will then create entries into numerous tables and use the tokens where appropriate.
A very simple example is:
*{
'template': 'DeviceTemplate'
'tokens': [
'customer': 1234,
'serial_number': '12312RF3242a',
'ip_address': '1.1.1.1'
]
}*
This creates a new device for the customer with that ip address along with several other objects, for instance interfaces, device users etc etc. I use the tokens in various places where needed.
I'm not sure how to make this endpoint restful.
The endpoint for /device is already taken if you want to create this resource individually. The endpoint I need is for creating everything via the template.
I want to reserve the POST /template endpoint for creating the actual template itself and not for implementing it with the tokens to create the various objects.
I want to know how to call the endpoint without using a verbs.
I also want to know if its a good idea to structure a POST with a nested JSON.
I'd suggest that you create an action on the template object itself. So right now if you do /templates/<id> you are given an object. You should include in that object a url endpoint for instantiating an instance of that template. Github follows a scheme that I like a lot [1] where within an object there will be a key pointing to another url with a suffix _url. So for instance, your response could be something like:
{
"template": "DeviceTemplate",
"id": "127",
...
"create_url": "https://yourdomain.com/templates/127/create",
...
}
Then this way you treat a POST to that endpoint the same as if this template (DeviceTemplate) was its own resource.
The way to conceptualize this is you're calling a method on an object instead of calling a function.
[1] - For example https://developer.github.com/v3/#failed-login-limit

How to design complex update actions in REST API

I'm currently working on a REST API, trying to design it with most best practices as possible.
I work with Symfony2 PHP framework but some of my questions are valid for any REST API i guess.
Starting from the base design for a particular resource :
GET /resource - Get all resources
POST /resource - Create resource
GET /resource/{id} - Get resource with id={id}
PUT|PATCH /resource/{id} - Edit the resource with id={id}
DELETE /resource/{id} - Delete the resource with id={id}
Supposing my resource has complex rules while updating.
It has a "status" field, (a float for example), that can be updated only by following a particular scheme
It has a "schedule" field (a datetime), with different choices available that are not always the same
How am I supposed to expose those rules to the API consumer ? For the schedule field, how am I supposed to provide the different choices available at the current time ?
About the Symfony server-side part, I followed most of the recommandations of this walkthrough : http://williamdurand.fr/2012/08/02/rest-apis-with-symfony2-the-right-way/
My POST, PUT & PATCH actions are handled with Symfony Forms, so most of the rules are processed by Symfony constraints/validations features.
But form binding is quite limited, let's supposed I want to trigger a particular event if the user change the status field from 2 to 3? What is the best way to do that ?
Thanks in advance.
HTTP has another verb you aren't using: OPTIONS. You can use this to list the schedule options.
Here's a blog article about it: http://zacstewart.com/2012/04/14/http-options-method.html
As for updating the status, I would reuse POST and include an action in the field. Example:
POST
{
"type": "update",
"status": 3
}
Modified REST:
GET /resource - Get all resources
POST /resource - Create resource
GET /resource/{id} - Get resource with id={id}
PUT|PATCH /resource/{id} - Edit the resource with id={id}
DELETE /resource/{id} - Delete the resource with id={id}
OPTIONS /resource/{id} - Retrieve options of resource with id={id}
Keep in mind that you can pass params along in the body for everything but GET and you can pass any params in the URL for GET.
I have zero knowledge on Symfony2, so I'll just concentrate on your more generic REST how-to qustion about exposing rules.
Give the consumers of your REST API a documentation. It's the first thing they will hit before actually playing with your API. Use tools for that, from auto-generated help pages to 3'rd party providers like Apiary.io or alike.
Create meaningful responses when consumers send "wrong" requests: use correct http response status codes (Bad request, Conflict, etc.) when request parameters are missing or invalid.
If your REST api is relaxed, it can also include information about what went wrong and how to resolve the problem in the response body.
What worked well for me in the past was to have a generic ErrorMessage entity that was returned upon each non-successful request, containing a title, an error description, and a dedicated more technical "dev-description" which can be enabled/disabled for test/production on the server side.
In my case, my consumers all know that they can get either the expected response entity in case of success, or that generic ErrorMessage entity in the response in case of failure.
If you can desribe your rules, why not provide those as meta information for your service? Eg. in my case I know I have a set of parameters, each having a set of available options. Think of the parameters as the key in a query string, and the options as the values for that key. In a complex world, parameter options depend on other parameter options, eg. in my case the available options for parameter B are dependent of what option(s) are "selected" for parameter A. I can expose those dependencies by providing a "metadata" resource in my REST api, eg. a JSON stucture listing all parameters and all options for those parameters, and for each option adding a "requires" section desribing that that option is only "available" if parameter xy has selected option p and q.
This allows my consumers to - with a single request to that meta data resource - create a "state-machine" on the client side. I hope you get the picture.
Here is my understanding of REST-full way to handle updates and advertise update operations to API client.
This is based on this wonderful book and Fowler's article about REST with some additions of File Levels of Media Type and article about Restfull CQRS. Basically you use PUT for update and pass the operation via content type and advertise content type via mediaType in hypermedia controls.
All operations which are available for current state of your resource are listed among hypermedia controls which are passed with representation of resource like this:
<myresource>
<status>ACTIVE</status>
<some-field with-attribute="value"/>
<some-other-field/>
<!-- other fields representing state of resource -->
<link rel = "self"
uri = "/resource/1234"/>
<link rel = "/linkrels/resource/changeStatus"
uri = "/resource/1234"
mediaType = "application/vnd.myapp+xml;domain-model=ChangeStatusCommand"/>
<link rel = "/linkrels/resource/changeSchedule"
uri = "/resource/1234"
mediaType = "application/vnd.myapp+xml;domain-model=ChangeScheduleCommand"/>
<link rel = "/linkrels/help"
uri = "/help/resource"/>
</myresource>
Links together with mediaType gives enough information what command is allowed. In many cases this should be something very specific to current state of resource. For example if you can move it from status ACTIVE to TRASHED than command should be named not StatusChange but TrashCommand and so on.

Symfony2 Form Rest Api only add to Relation

I am using Symfony2 as Rest Api for a JS Frontend App. I came across a scenario where I want users to "invite" (=add) Users to a Group. But I want to only allow them to add Users to the existing Relation and not "overwrite" the whole relation, which is the standard behaviour in combination with a regular Symfony2 Form.
What would be the best practice to achieve this behaviour?
Additional Comment:
I am using Ember-Data in the frontend and my frontend would probably send a put request with the whole Group including additional users (but not all).
My JSON Payload would look something like this:
{
"usergroup": {
"name":"yxcv2",
"stake":"sdfghj",
"imageName":null,
"userCount":5,
"users":[
5,
6,
7
],
"gameGroup":"13",
}
}
In this scenario User 1,2,3 and 4 are already members of the group. And instead of replacing 1,2,3,4 with 5,6,7, I want to ADD 5,6,7 to the already existing members.
A LINK request should be used to add an item to an existing collection instead of overwriting it with a POST request.
Using a symfony form you'd post the User (id) plus a hidden field _method with value LINK to something like /groups/{id}.
routing would be something like this:
group_invite:
path: /groups/{id}
defaults: { _controller: YourBundle:Group:inviteUser }
methods: [LINK]
You could use FOSRestBundle's implicit resource name definition, too.
For the method override to work the config setting framework.http_method_override needs to be set to true ( = default value - available since symfony version 2.3).
More information can be found in the documentation chapter:
How to use HTTP Methods beyond GET and POST in Routes