This is a project to showcase learnt backend skills, where I built a Casting Agency API from scratch. This is the project I submitted as a Capstone project in the Udacity Fullstack Nanodegree.
Follow instructions to install the latest version of python for your platform in the python docs
I recommend working within a virtual environment whenever using Python for projects. This keeps your dependencies for each project separate and organaized. Instructions for setting up a virual enviornment for your platform can be found in the python docs
Once you have your virtual environment setup and running, install dependencies by naviging to the /backend
directory and running:
pip install -r requirements.txt
This will install all of the required packages within the requirements.txt
file.
For the project to be able to connect to your local database you will have to:
- open setup.sh and change the DATABASE_URL and TEST_DATABASE_URL to your database URL and test databse URL.
-
Flask is a lightweight backend microservices framework. Flask is required to handle requests and responses.
-
SQLAlchemy and Flask-SQLAlchemy are libraries to handle the postgres database.
-
jose JavaScript Object Signing and Encryption for JWTs. Useful for encoding, decoding, and verifying JWTS.
From within the ./src
directory first ensure you are working using your created virtual environment.
to export the environment variables, run:
. setup.sh
Each time you open a new terminal session, run:
export FLASK_APP=app.py;
To run the server, execute:
flask run --reload
The --reload
flag will detect file changes and restart the server automatically.
https://fsnd-ca.herokuapp.com/
returns the html template for login page
returns the html template for the login-results page (the callback URL after login)
query paginated actors
curl https://fsnd-ca.herokuapp.com/actors
- Fetches a list of dictionaries of actors
- Requires permission:
get:actors
- Request Arguments: integer
page
(defaults to 1 if not provided) - Request Headers: None
- Returns:
- A list of actors objects with the fields:
- integer
id
- string
name
- integer
age
- string
gender
- integer
- An integer
actors_count
(total number of actors) - A boolean
success
- A list of actors objects with the fields:
{
"actors": [
{
"age": 54,
"gender": "female",
"id": 3,
"name": "Salma Hayek"
},
{
"age": 64,
"gender": "male",
"id": 2,
"name": "Tom Hanks"
},
{
"age": 58,
"gender": "male",
"id": 4,
"name": "Tom Cruise"
}
],
"actors_count": 3,
"success": true
}
query paginated movies
curl https://fsnd-ca.herokuapp.com/movies
- Fetches a list of dictionaries of movies
- Requires permission:
get:movies
- Request Arguments: integer
page
(defaults to 1 if not provided) - Request Headers: None
- Returns:
- A list of movies objects with the fields:
- integer
id
- string
title
- date
release_date
- integer
- An integer
movies_count
(total number of movies) - A boolean
success
- A list of movies objects with the fields:
{
"movies": [
{
"id": 2,
"release_date": "Tue, 05 Dec 2017 00:00:00 GMT",
"title": "Jumanji"
},
{
"id": 3,
"release_date": "Thu, 10 Jan 2019 00:00:00 GMT",
"title": "The Upside"
},
{
"id": 1,
"release_date": "Mon, 09 Jun 2025 00:00:00 GMT",
"title": "Whiplash"
}
],
"movies_count": 3,
"success": true
}
add an actor to the database
curl -X POST https://fsnd-ca.herokuapp.com/actors
-
Requires permission:
post:actors
-
Request Arguments: None
-
Request Headers:
Content-Type: application/json
-
Request body (all fields are required):
- string
name
: actor name - integer
age
: actor age - string
gender
: actor gender
{ "name": "Tom Cruise", "age": 58, "gender": "male" }
- string
-
Returns:
- Integer
created
(created actor id) - boolean
success
{ "created": 4, "success": true }
- Integer
add a movie to the database
curl -X POST https://fsnd-ca.herokuapp.com/movies
-
Requires permission:
post:movies
-
Request Arguments: None
-
Request Headers:
Content-Type: application/json
-
Request body (all fields are required):
- string
title
: movie title - date
release_date
: movie release date
{ "title": "Tenet", "release_date": "2020-8-12" }
- string
-
Returns:
- Integer
created
(created movie id) - boolean
success
{ "created": 4, "success": true }
- Integer
update an existing actor
curl -X PATCH https://fsnd-ca.herokuapp.com/actors/1
- Requires permission:
patch:actors
- Request Arguments: integer
actor_id
(the id of the actor you want to modify) - Request Headers:
Content-Type: application/json
- Request body (all fields are optional):
- string
name
- integer
age
- string
gender
{ "name": "Scarlett Johansson", "age": 32, }
- string
- Returns:
- object
actor
(the updated actor) - boolean
success
{ "actor": { "age": 32, "gender": "female", "id": 1, "name": "Scarlett Johansson" }, "success": true }
- object
update an existing movie
curl -X PATCH https://fsnd-ca.herokuapp.com/movies/1
- Requires permission:
patch:movies
- Request Arguments: integer
movie_id
(the id of the movie you want to modify) - Request Headers:
Content-Type: application/json
- Request body (all fields are optional):
- string
title
- date
release_date
{ "title": "Django Unchained" }
- string
- Returns:
- object
movie
(the updated movie) - boolean
success
{ "movie": { "id": 1, "release_date": "Mon, 09 Jun 2025 00:00:00 GMT", "title": "Django Unchained" }, "success": true }
- object
delete an actor from database
curl -X DELETE https://fsnd-ca.herokuapp.com//actors/1
- Requires permission:
delete:actors
- Request Arguments: integer
actor_id
(the id of the actor you want to delete) - Request Headers: None
- Returns:
- integer
deleted
(the deleted actor id) - boolean
success
{ "deleted": 1, "success": true }
- integer
delete a movie from database
curl -X DELETE https://fsnd-ca.herokuapp.com/movies/1
- Requires permission:
delete:movies
- Request Arguments: integer
movie_id
(the id of the movie you want to delete) - Request Headers: None
- Returns:
- integer
deleted
(the deleted movie id) - boolean
success
{ "deleted": 1, "success": true }
- integer
-
Errors are returned as a JSON object with keys:
- boolean
success
- integer
error
- string
message
- boolean
{
'success': False,
'error': 404,
'message': 'resource not found'
}
- 401 :
unauthorized
- 403 :
Forbidden
- 409 :
Conflict
- 400 :
bad request
- 404 :
resource not found
- 422 :
unprocessable
- 405 :
method not allowed
- 500 :
internal server error
Auth0 is setup with RBAC
and the bearer tokens for all roles are in setup.sh,
you can use them with the Authorization
header for your API calls to the running api at the BASE URl.
curl https://fsnd-ca.herokuapp.com/actors -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikt6dEE0ZHY4UVJCT0kyTXkxbTlFNiJ9.eyJpc3MiOiJodHRwczovL2Fwb2xsbzE1MS5ldS5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NjA5NmFlMTM2OWI2MjgwMDY4NjJkMWFkIiwiYXVkIjoiY2FzdGluZ19hZ2VuY3kiLCJpYXQiOjE2MjEyMTEyNDIsImV4cCI6MTYyMTI5NzY0MiwiYXpwIjoiZldUazhMZjZLOGI3T1d0WDJobkYxenZGcU44djVVcDIiLCJzY29wZSI6IiIsInBlcm1pc3Npb25zIjpbImdldDphY3RvcnMiLCJnZXQ6bW92aWVzIl19.Ou3BguKxjU32gfeXnMYPFqEYsOjX1cGEGcrtnVMl3CGtPDn-w7vqrlYfr0Spjaj6eo-UDYFyUiu0ungrY0DdzRGcgAc9d9YZdont6foVCLFWcG356BTq1BZnAqtImnF5AbkYeKd7pC7W-7-Vcf49Ng4V_W4O-oI4FiVDLKlDZgAjqRpZNZ0PWK8e7T4BqvQ2CQUfyO6qNhygEI3y5q4ZfF0h8JrIXqAwYqi4ftcZjTQB71piQW0z6U_Yqcq0zx30KEpWY8EVi7vbCXSJV2RnZ8bdKXaAnJE7heWIAVlwakH-Dl-hKcBCXgZH8EX7bUrqtNeejLciwq9F7q8kO5Ip6w'
if you want to setup Auth0 for local use:
- Create a new Auth0 Account
- Select a unique tenant domain
- Create a new, regular web application
- Create a new API
- in API Settings:
- Enable RBAC
- Enable Add Permissions in the Access Token
- in API Settings:
- change the AUTH0_DOMAIN and API_AUDIENCE environment variables in the setup.sh to yours.
- Create new API permissions:
get:actors
: get actors from the databaseget:movies
: get movies from the databasepost:actors
: add actors to the databasepost:movies
: add movies to the databasepatch:actors
: modify existing actors in the databasepatch:movies
: modify existing movies in the databasedelete:actors
: delete actors form the databasedelete:movies
: delete movies from the database
- Create new roles and assign each it's permissions as following:
- Casting assistant
- can
get:actors
- can
get:movies
- can
- Casting director, has same permissions as casting assistant plus
- can
post:actors
- can
patch:actors
- can
patch:movies
- can
delete:actors
- can
- Executive producer
- can perform all actions Test the endpoints with Postman or using curl
- Register 3 users - assign each user a unique role.
- Sign into each account and make note of the JWT.
- use the JWT tokens for your local api calls
- go to the login.html file in the templates directory and change the herf on the button to your url in the format
https://{{YOUR_DOMAIN}}/authorize?audience={{API_IDENTIFIER}}&response_type=token&client_id={{YOUR_CLIENT_ID}}&redirect_uri={{YOUR_CALLBACK_URI}}
- Casting assistant
before running the tests, run
dropdb CA_test && createdb CA_test
psql CA_test < CA.psql
to run the unittest tests, run
python test_app.py
- if everything went well it should return
........
----------------------------------------------------------------------
Ran 22 tests in 9.989s
OK