Have Dynamical values for my parameters in the Request payload (POST x-www-form-urlencoded) - apiblueprint

Is there a way (and does it make sense even) to have dynamical values for my request parameters (in my case POST application/x-www-form-urlencoded that has two parameters username and password) which can be altered based on some function or a returned value from the server from a previous request?
The motivation being that i have a register-new-user request which i run from time to time off apiary.io and unless i manually change the example value for the username i get a "use already exists" response instead of 201 i want (since this request was already run with the username in the example).
What i'd like to have instead is a value in the API documentation that will change on each execution of the API call (either using some random number there, or to be able to have it take a value returned from a previous request).
Is there anything you can suggest to solve my "user already exists" response for register-new-user API call?
Here is my current API documentation (the relevant part):
## Registration [/users.json]
The `/users.json` resource handles registration of new user
### Register a New Patient [POST]
Register a new patient action sends email and password and registers
the new user in case it doesn't already exist
+ Request (application/x-www-form-urlencoded)
+ Attributes (Test User)
+ Body
user[email]=username#example.com&user[password]=123456
+ Response 201 (application/json)
{
"id":500
}
# Data Structures
## Test User (object)
+ "user[email]" (string): "username#example.com" - user email
+ "user[password]" (string): "123456" - user password
Thanks in advance

You can partially simulate this in the Apiary mock server by passing a header in your call, for example:
Prefer: status=200
See https://help.apiary.io/tools/mock-server/#multiple-responses
In general the mock server is not yet flexible and programmable enough to fully do what you describe, for example conditionals, dynamic variables or random responses.
We are working on enhancing this. If you'd like you may comment here on your requirements:
https://github.com/apiaryio/api-blueprint/issues/58
Feel free to also ping us in Apiary (in-app chat) or on support#apiary.io.
Thanks

Related

Slack - How to verify interactivity requests

Setting up my first Slack slash command. I built it out originally using the deprecated verification token but, for posterity, have decided to use signed secrets authentication.
Reading through the signed secrets documentation, I've had no issue validating requests that come in from the initial slash command. However, interaction requests have a completely different body structure and the method for calculating a secret hash do not produce a valid result (because the request body is different).
Here is a snippet from the docs on validating signed secrets.
slack_signing_secret = 'MY_SLACK_SIGNING_SECRET' // Set this as an environment variable
>>> 8f742231b10e8888abcd99yyyzzz85a5
request_body = request.body()
>>> token=xyzz0WbapA4vBCDEFasx0q6G&team_id=T1DC2JH3J&team_domain=testteamnow&channel_id=G8PSS9T3V&channel_name=foobar&user_id=U2CERLKJA&user_name=roadrunner&command=%2Fwebhook-collect&text=&response_url=https%3A%2F%2Fhooks.slack.com%2Fcommands%2FT1DC2JH3J%2F397700885554%2F96rGlfmibIGlgcZRskXaIFfN&trigger_id=398738663015.47445629121.803a0bc887a14d10d2c447fce8b6703c
On invocation of the slash command this works as intended - the request body matches the structure in the example above. When the user interacts with the message, the response body uses the blocks api - which is completely different
If I'm not supposed to use the verification token and the request body from the interactive blocks api does not allow me to compute a valid hash, how am I supposed to validate interaction requests? I must be missing something while combing through the docs.

Writing data to model from POST request (Odoo 9.0)

I have the following model:
class LibraryBook(models.Model):
_name = 'library.book'
name = fields.Char('Title', required=True)
date_release = fields.Date("Release Date")
author_ids = fields.Many2many("res.partner", string="Authors")
I'm new to Odoo and trying to understand the basics of how to save data to my model from a POST request like the following
curl -i -X POST --data "name=Odoo%20-%20Much%20Mystery,%20Wow&author_id=Doge" http://0.0.0.0:8069/test
I found a way doing this by setting the csrf parameter in my controller to false like so:
[...]
#http.route('/test', type='http', auth='public',methods=['POST'], website=True, csrf=False)
def test(self, **kwargs):
record = request.env['library.book'].sudo()
record.create(kwargs)
I'm wondering now if there is a way to avoid setting csrf=false since I've read that it's a bad idea to do so in general. Also, what would I need to get rid of that .sudo()? Not setting csrf=false leads to a 400 BAD REQUEST with Invalid CSRF token. Removing sudo() leads to a 500 INTERNAL SERVER ERROR. In Odoo Development Cookbook it says in one example with auth='none'
Lack of a user is also why we have to sudo() all our calls to model methods in the example code
Assuming I would expect a POST request from an API, is it possible to associate it with a user so I don't have to sudo()?
I would very much appreciate any clarification on this.
UPDATE
So I just found this (line 817):
if the form is accessed by an external third party (e.g. REST API endpoint, payment gateway callback) you will need to disable CSRF
protection (and implement your own protection if necessary) by
passing the csrf=False parameter to the route decorator.
which I guess leaves only one question open, regarding sudo.
SUDO()
creates a new environment with the provided user set, uses the administrator if none is provided (to bypass access rights/rules in safe contexts), returns a copy of the recordset it is called on using the new environment:
Odoo does not allow public users to create, update, delete a record.
If we want to create a record from the public users then we need to create a record with the sudo().
Create record object as administrator
request.env['library.book'].sudo().create(vals)
I hope this may help you.
for more information you can navigate to following links :
https://www.odoo.com/documentation/9.0/reference/orm.html
Thanks

Angular $http.delete request with body

So I looked at this post:
is an entity body allowed for an http delete request
Which seems to indicate that while it is 'ok' to do on some conceptual level, in practice it may not be doable because browsers just ignore it.
I have some express.js authentication middleware I need to get through, and I don't want to attach my user details to url params. All my other requests that need to authenticate attach these details to the body of the request.
Is there some way to force this? I saw some other posts where some people seemed to have success in passing a body with their delete request.
I am running a node/sails back-end. It always logs the body as undefined for a delete request. Is there any way to modify
The sails API pulls the id of the object to delete from the params, so we have to append the id to the url.
But if I want to pass some authentication details in a body for server-side verification before processing the delete request, I can't just stick them in an object as the second parameter of the delete request, like you can with $http.post.
Angular's post method automatically assigns whatever we insert as a second parameter to the body of the request, but the delete method does not.
Angular's $http.delete method does allow us to supply a config object as the second parameter, through which we can get access to the 'data' property. This is the same way post does it through it's second parameter.
So if we need to attach a body to a delete request we can use the following:
$http.delete('/api/' + objectToDelete.id, {data: {id: currentUser().id, level: currentUser().level}});
This will pass the object to delete's id in the url parameter, and my user credentials in the body as an object.
Honestly, everytime a trouble sounds like a "restriction of as REST", a rethink of the strategy and the philosophy might be a good idea.
I have some authentication middleware I need to get through
I don't want to attach my user details to url params
I'm not directly answering the question, but you should know that among the commons
URL parameters (or query, but URL anyway)
Body
there is a third option for "passing values to the server" :
request Headers
I'd just suggest to consider that third option to provide your credentials: request header.
Edit : following appendix would just apply to any "external" middleware, like a proxy server or whatever, not a true express middleware inside sails.js
In addition, that would be a good idea that your middleware stripped those headers before redirecting to the real action.

How to specify error codes in Apiary Documentation?

I want to specify the various exceptions/errors that have to be returned while making an API call. How do I achieve this with Apiary.
Kyle's response is indeed correct. I will just add that if you want to add little bit more semantics to this you can write the other possible responses like this:
## POST /users/resendVerification/{userId}
Resends the user's verification code to the email address on record.
+ Response 201
+ Response 403
Returned if the user does not have access to the requested account
+ Body
+ Response 404
Returned if a user was not found for the given userId
+ Body
Note: The + Body is needed (even though it is empty) to distinguish the description from a message-body.
I'm not aware of a specific syntax for error codes. In the past I've simply used bullet points. For example, this is my code for a re-request verification code API.
## POST /users/resendVerification/{userId}
Resends the user's verification code to the email address on record.</br>
• 403 is returned if the user does not have access to the requested account</br>
• 404 is returned if a user was not found for the given userId</br>
+ Response 201
Hope that helps.

RESTful URLs: "Impractical" Requests, and Requiring One of Two Request Parameters

I have a RESTful URL that requires either the offset or the prefix request parameter (but not both).
GET /users?offset=0&count=20
GET /users?prefix=J&count=20
What's the best way to enforce this rule? Spring has the #RequestParam annotation with the 'required' property for optional parameters, but I want to enforce an "either-or" rule on these two parameters. I know I could do it in the code, but is there another way to do it?
Also, what's the proper way to handle "impractical" requests? Say I have 100 million users; the following request, although properly RESTful, is not something I want to support:
GET /users <-- Gets all 100 million users, crashes server and browser!
What should I send back?
You can create two methods and choose one of them with #RequestMapping's params attribute:
#RequestMapping(..., params = {"prefix", "!offset"})
public String usersWithPrefix(#RequestParam("prefix") ...) { ... }
#RequestMapping(..., params = {"offset", "!prefix"})
public String usersWithOffset(#RequestParam("offset") ...) { ... }
what's the proper way to handle "impractical" requests?
The lesser-practiced principles of REST include the requirement that resources be "discoverable". If you are asked for a complete list of 800 million users and you don't want to provide it, you might instead consider serving a page that describes in some way how to filter the collection: for example, an XForms document or HTML containing a FORM element with fields for offset/prefix/count, or a URI template with the appropriate parameters
Or you could just send a "413 Entity too large" error - edit: no you can't. Sorry, I misread the description of whath this code is for
If you decide to go down the route of just sending the first page, I think I would send it as an HTTP redirect to /users?offset=0&count=20 so that the client has a better idea they've not got the full collection (and if your response contains a link to access subsequent pages, even better)

Resources