π’Creating Your Own API
You can use the Petal Pro API for user management (register, sign in and update). It comes with OpenAPI support out of the box.
Last updated
You can use the Petal Pro API for user management (register, sign in and update). It comes with OpenAPI support out of the box.
Last updated
For general information about the Petal Pro API:
You can see OpenAPI in action if you navigate to the Swagger interface:
To make an API call:
Expand a route (e.g. /api/register
)
Click the "Try it out" button
Fill out the appropriate parameter/request fields
Click "Execute"
Check the Server Response for output
Some routes are protected - calling these routes without an authenticated user will result in an :unauthorized
response.
To authenticate a user:
Follow the steps (above) to execute the /api/sign-in
API call (you'll be asked to provide an email
and a password
)
In the response body, copy the value of the token
property
Go to the top of the page and click the "Authorize" button
Paste the bearer token into the "Value" input and click "Authorize" again
While the bearer token is valid, protected routes will provide a response other than :unauthorized
. By default, the bearer token will be valid for the period of thirty days
You can generate an openapi.json
file with the following mix command:
Alternatively, if you navigate to the Swagger UI, you can click the link under the "Petal Pro API" heading. The contents of the .json
file will be displayed in the browser. Use the browsers "Save As..." feature to save the file to local storage.
Say you want to add an API call that returns a list of Organisations for a user. The following is an example of how this might be achieved
First, create the API controller lib/petal_pro_api/controllers/membership_controller.ex
:
Then create the related unit test /test/petal_pro_api/membership_controller_test.exs
:
Finally, for the test to work, you need to add the following line to /lib/petal_pro_api/routes.ex
:
But if you run the test...
...it won't pass:
That's because the route has been placed it in a scope
that pipes through :api_authenticated
:
Adding put_bearer_token
to the "list organisations" test in membership_controllers_test.exs
will address the issue:
put_bearer_token
is a helper function that can be found in /test/support/conn_case.ex
. It will generate a bearer token for user
and inject an authorization
header into the conn
object. The :api_authenticated
pipeline will use this header to check validity of the bearer token.
If you run the test again, this time the user will be authenticated and it will pass!
However, now is a good time to think about access control (authorisation). Let's assume users should only retrieve Organisations for themselves (but admin users can retrieve Organisations for any user). Copying the code that's in profile_controller.ex
, you can add the match_current_user
plug to membership_controller.ex
:
Note that the
list
function has changed - it assumes theuser
assign has been set
The match_current_user
plug checks the current authenticated user. If the user requested is the current user or the current user is an admin, then the user
assigns is set. Otherwise HTTP error 403
(:forbidden
) is returned (preventing further execution).
To double check that your code is working properly, add two tests to membership_controller_test.exs
:
Note that
other_user
andadmin_user
have been added to thesetup
function
If you run mix test
again, then all three unit tests should pass:
Great! Your new API call is fully operational. However, it won't be added to the Open API spec automatically. To do this, you add meta data to the API function using OpenApiSpex
.
In membership_controller.ex
add the following:
The tags
call is used to group API calls together in your Open API definition. In the SwaggerUI page, this will be used as a group heading.
The security
call let's Open API know that all API calls in this file are protected by authentication. In the Swagger UI, routes that have been marked with the security
function will be displayed with a padlock.
NB - The "authorization" string is a reference to a
securitySchemes
setting that's in/lib/petal_pro_api/api_spec.ex
. Open API supports multiple authentication schemes. But for the purposes of this example, "authorization" refers to the bearer/header token mechanism that has been setup with phx.gen.auth.
Next, you need to define an Open API Operation for the :list
function call in membership_controller.ex
:
There's a lot going on here! Let's step through the various parts of the operation
:
:list
refers to the list
method (underneath)
summary
and description
are a short and long descriptions (respectively)
parameters
defines any variable that may be defined in the url
responses
is the list of possible outcomes after the function has been called
An operation
defines the list of expected inputs and outputs. Which is great for generating code/documentation (e.g. for the Swagger UI). In particular, there are three possible outcomes in the above definition:
:ok
- when the call is successful, then the output will be a list of Organisation names. This is defined by the OrganisationNames
schema. There's more on the schema (below)
:unauthorized
- a common response that's defined in the api_spec.ex
file
:forbidden
- also defined in api_spec.ex
To round out the Open API definition, we need to add the following Schema to /lib/petal_pro_api/schemas.ex
:
This defines an array of type "string". The purpose of the schema is to define the output of a valid response - users can discover the format of the response via the Swagger UI.
The new API call should now be available! To view the Swagger UI, run the Phoenix server:
Then navigate to the Swagger interface:
See the Using the Swagger UI section (at the top of this README) to learn more about making API calls