This is an api for a casting-agency. It covers following technical topics in 1 app:-
- Database modeling with
postgres&sqlalchemy(seemodels.py) - API to performance CRUD Operations on database with
Flask(seeapp.py) - Automated testing with
Unittest(seetest_app) - Authorization & Role based Authentification with
Auth0(seeauth.py) - Deployment on
Heroku
Make sure you cd into the correct folder (with all app files) before following the setup steps.
Also, you need the latest version of Python 3
and postgres installed on your machine.
To start and run the local development server,
- Initialize and activate a virtualenv:
$ virtualenv --no-site-packages env_capstone
$ source env_capstone/scripts/activate- Install the dependencies:
$ pip install -r requirements.txtRunning this project locally means that it can´t access Herokus env variables.
To fix this, you need to edit a few informations in config.py, so it can
correctly connect to a local database
- Change database config so it can connect to your local postgres database
- Open
config.pywith your editor of choice. - Here you can see this dict:
database_setup = {
"database_name_production" : "agency",
"user_name" : "postgres", # default postgres user name
"password" : "testpassword123", # if applicable. If no password, just type in None
"port" : "localhost:5432" # default postgres port
}- Just change
user_name,passwordandportto whatever you choose while installing postgres.
tip:
user_nameusually defaults topostgresandportalways defaults tolocalhost:5432while installing postgres, most of the time you just need to change thepassword.
- Setup Auth0
If you only want to test the API (i.e. Project Reviewer), you can
simply take the existing bearer tokens in
config.py.
If you already know your way around Auth0, just insert your data
into config.py => auth0_config.
FYI: Here are the steps I followed to enable authentification.
- Run the development server:
$ python app.py- (optional) To execute tests, run
$ python test_app.pyIf you choose to run all tests, it should give this response if everything went fine:
$ python test_app.py
.........................
----------------------------------------------------------------------
Ran 25 tests in 18.132s
OK
Here you can find all existing endpoints, which methods can be used, how to work with them & example responses you´ll get.
Additionally, common pitfalls & error messages are explained, if applicable.
https://artist-capstone-fsnd-matthew.herokuapp.com
Please see API Authentification
Here is a short table about which ressources exist and which method you can use on them.
Allowed Methods
Endpoints | GET | POST | DELETE | PATCH |
|------|-------|---------|--------|
/actors | [x] | [x] | [x] | [x] |
/movies | [x] | [x] | [x] | [x] |
Click on a link to directly get to the ressource.
- Actors
- Movies
Each ressource documentation is clearly structured:
- Description in a few words
curlexample that can directly be used in terminal- More descriptive explanation of input & outputs.
- Required permission
- Example Response.
- Error Handling (
curlcommand to trigger error + error response)
Query paginated actors.
$ curl -X GET localhost/actors?page1- Fetches a list of dictionaries of examples in which the keys are the ids with all available fields
- Request Arguments:
- integer
page(optional, 10 actors per page, defaults to1if not given)
- integer
- Request Headers: None
- Requires permission:
read:actors - Returns:
- List of dict of actors with following fields:
- integer
id - string
name - string
gender - integer
age
- integer
- boolean
success
- List of dict of actors with following fields:
{
"actors": [
{
"age": 25,
"gender": "Male",
"id": 1,
"name": "Matthew"
}
],
"success": true
}If you try fetch a page which does not have any actors, you will encounter an error which looks like this:
$ curl -X GET localhost/actors?page123124will return
{
"error": 404,
"message": "no actors found in database.",
"success": false
}Insert new actor into database.
$ curl -X POST localhost/actors- Request Arguments: None
- Request Headers: (application/json)
1. string
name(required) 2. integerage(required) 3. stringgender - Requires permission:
create:actors - Returns:
- integer
id from newly created actor - boolean
success
- integer
{
"created": 5,
"success": true
}If you try to create a new actor without a requiered field like name,
it will throw a 422 error:
$ curl -X GET localhost/actors?page123124will return
{
"error": 422,
"message": "no name provided.",
"success": false
}Edit an existing Actor
$ curl -X PATCH localhost/actors/1- Request Arguments: integer
id from actor you want to update - Request Headers: (application/json)
1. string
name2. integerage3. stringgender - Requires permission:
edit:actors - Returns:
- integer
id from updated actor - boolean
success - List of dict of actors with following fields:
- integer
id - string
name - string
gender - integer
age
- integer
- integer
{
"actor": [
{
"age": 30,
"gender": "Other",
"id": 1,
"name": "Test Actor"
}
],
"success": true,
"updated": 1
}If you try to update an actor with an invalid id it will throw an 404error:
$ curl -X PATCH localhost/actors/125will return
{
"error": 404,
"message": "Actor with id 125 not found in database.",
"success": false
}Additionally, trying to update an Actor with already existing field values will result in an 422 error:
{
"error": 422,
"message": "provided field values are already set. No update needed.",
"success": false
}Delete an existing Actor
$ curl -X DELETE localhost/actors/1- Request Arguments: integer
id from actor you want to delete - Request Headers:
None - Requires permission:
delete:actors - Returns:
- integer
id from deleted actor - boolean
success
- integer
{
"deleted": 5,
"success": true
}If you try to delete actor with an invalid id, it will throw an 404error:
$ curl -X DELETE localhost/125will return
{
"error": 404,
"message": "Actor with id 125 not found in database.",
"success": false
}Query paginated movies.
$ curl -X GET https://localhost/movies?page1- Fetches a list of dictionaries of examples in which the keys are the ids with all available fields
- Request Arguments:
- integer
page(optional, 10 movies per page, defaults to1if not given)
- integer
- Request Headers: None
- Requires permission:
read:movies - Returns:
- List of dict of movies with following fields:
- integer
id - string
name - date
release_date
- integer
- boolean
success
- List of dict of movies with following fields:
{
"movies": [
{
"id": 1,
"release_date": "Sun, 16 Feb 2020 00:00:00 GMT",
"title": "Matthew first Movie"
}
],
"success": true
}If you try fetch a page which does not have any movies, you will encounter an error which looks like this:
$ curl -X GET https://localhost/movies?page123124will return
{
"error": 404,
"message": "no movies found in database.",
"success": false
}Insert new Movie into database.
$ curl -X POST https://localhost/movies- Request Arguments: None
- Request Headers: (application/json)
1. string
title(required) 2. daterelease_date(required) - Requires permission:
create:movies - Returns:
- integer
id from newly created movie - boolean
success
- integer
{
"created": 5,
"success": true
}If you try to create a new movie without a requiered field like name,
it will throw a 422 error:
$ curl -X GET https://localhost/movies?page123124will return
{
"error": 422,
"message": "no name provided.",
"success": false
}Edit an existing Movie
$ curl -X PATCH https://localhost/movies/1- Request Arguments: integer
id from movie you want to update - Request Headers: (application/json)
1. string
title2. daterelease_date - Requires permission:
edit:movies - Returns:
- integer
id from updated movie - boolean
success - List of dict of movies with following fields:
- integer
id - string
title - date
release_date
- integer
- integer
{
"created": 1,
"movie": [
{
"id": 1,
"release_date": "Sun, 16 Feb 2020 00:00:00 GMT",
"title": "Test Movie 123"
}
],
"success": true
}If you try to update an movie with an invalid id it will throw an 404error:
$ curl -X PATCH https://localhost/movies/125will return
{
"error": 404,
"message": "Movie with id 125 not found in database.",
"success": false
}Additionally, trying to update an Movie with already existing field values will result in an 422 error:
{
"error": 422,
"message": "provided field values are already set. No update needed.",
"success": false
}Delete an existing movie
$ curl -X DELETE https:/localhost/movies/1- Request Arguments: integer
id from movie you want to delete - Request Headers:
None - Requires permission:
delete:movies - Returns:
- integer
id from deleted movie - boolean
success
- integer
{
"deleted": 5,
"success": true
}If you try to delete movie with an invalid id, it will throw an 404error:
$ curl -X DELETE https://localhost/movies/125will return
{
"error": 404,
"message": "Movie with id 125 not found in database.",
"success": false
}All API Endpoints are decorated with Auth0 permissions. To use the project locally, you need to config Auth0 accordingly
- Login to https://manage.auth0.com/
- Click on Applications Tab
- Create Application
- Give it a name like
Musicand select "Regular Web Application" - Go to Settings and find
domain. Copy & paste it into config.py => auth0_config['AUTH0_DOMAIN'] (i.e. replace"example-matthew.eu.auth0.com") - Click on API Tab
- Create a new API:
- Name:
Music - Identifier
Music - Keep Algorithm as it is
- Name:
- Go to Settings and find
Identifier. Copy & paste it into config.py => auth0_config['API_AUDIENCE'] (i.e. replace"Example")
- Before creating
Roles & Permissions, you need toEnable RBACin your API (API => Click on your API Name => Settings = Enable RBAC => Save) - Also, check the button
Add Permissions in the Access Token. - First, create a new Role under
Users and Roles=>Roles=>Create Roles - Give it a descriptive name like
Casting Assistant. - Go back to the API Tab and find your newly created API. Click on Permissions.
- Create & assign all needed permissions accordingly
- After you created all permissions this app needs, go back to
Users and Roles=>Rolesand select the role you recently created. - Under
Permissions, assign all permissions you want this role to have.
If you want to access the real, temporary API, bearer tokens for all 3 roles are included in the config.py file.
They are 3 Roles with distinct permission sets:
- Casting Assistant:
- GET /actors (view:actors): Can see all actors
- GET /movies (view:movies): Can see all movies
- Casting Director (everything from Casting Assistant plus)
- POST /actors (create:actors): Can create new Actors
- PATCH /actors (edit:actors): Can edit existing Actors
- DELETE /actors (delete:actors): Can remove existing Actors from database
- PATCH /movies (edit:movies): Can edit existing Movies
- Exectutive Dircector (everything from Casting Director plus)
- POST /movies (create:movies): Can create new Movies
- DELETE /movies (delete:movies): Can remove existing Motives from database
In your API Calls, add them as Header, with Authorization as key and the Bearer token as value. Don´t forget to also
prepend Bearer to the token (seperated by space).
For example: (Bearer token for Executive Director)
{
"Authorization": "Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ik16azVRVUk0TXpSR04wSXhOVU13TkRrME16QXdNMFpHTmtFMU1VWXdPRUpCTmpnMFJrVTBSZyJ9.eyJpc3MiOiJodHRwczovL2ZzbmQtbWF0dGhldy5ldS5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NWU0N2VmYzc2N2YxYmEwZWJiNDIwMTYzIiwiYXVkIjoiTXVzaWMiLCJpYXQiOjE1ODE4NjI0NjksImV4cCI6MTU4MTg2OTY2OSwiYXpwIjoiVGh2aG9mdmtkRTQwYlEzTkMzSzdKdFdSSzdSMzFOZDciLCJzY29wZSI6IiIsInBlcm1pc3Npb25zIjpbImNyZWF0ZTphY3RvcnMiLCJjcmVhdGU6bW92aWVzIiwiZGVsZXRlOmFjdG9ycyIsImRlbGV0ZTptb3ZpZXMiLCJlZGl0OmFjdG9ycyIsImVkaXQ6bW92aWVzIiwicmVhZDphY3RvcnMiLCJyZWFkOm1vdmllcyJdfQ.iScamWOFNx9pjiVZhsvPzDoRi6EraZaxWg-WMj80HNW_-dchkOymnKA7OOhPQ8svLc9-wViLlCT-ySnupZ-209cIBVHSA_slncSP-lzEM6NKbBmDEETTQ1oxv2jTH-JL72eLhyAWUsmSIZDmEab1hln1yWEN7mUnn0nZJfxCRCs89h5EGJzXS2v8PbAjq9Mu7wFsrioEMx_PGWzSM0r5WIrKBvpXRy0Jm-vssZl4M1akDHIL5Shcfp_Bfnarc2OLOMvdQVHVDEWhrbFSnfCENLDxkcmB18VnOedJAuY_C88YRUfY2wQAOPux8RVuqIb5KxTg4YP7kiDcBU"
}