Udacity Fullstack Nanodegree capstone project
https://fsnd-happyhour.herokuapp.com/
The motivation of this project is to practice the skills learned during the Udacity FullStack NanoDegree program. The basis of the app for restaurant managers to be able to post their restraurant and menus for customers to be able to see and make reservations.
- Python 3.8.2
- Flask - Web Framework
- SQLAlechmy ORM
- PostgresSQL 12.2
- Flask - Migrate
- RESTful - API
- Authentication - JSON Web Token (JWT) with Auth0
- User Roles/Permissions
- Python virtual environment - venv
- Python - unittest
- API testing with Postman
- Deployment on Heroku
Requirements
Install the necessary requirmenets by running:
pip install -r requirements.txt
Running on local machine
- Open a terminal and cd to the project directory and install requirements:
cd ~/FSND-Capstone-Project
# Then
pip install -r requirements.txt
- Set up your DATABASE_URL variable depending on OS:
export DATABASE_URL="{DATABASE_URL}"
For Windows use:
$env:DATABASE_URL="{DATABASE_URL}"
- Run ALL three migration commands ONLY on you first set up:
# Run the init command once
python manage.py db init
python manage.py db migrate
python manage.py db upgrade
# Run the last 2 commands if/when you make changes to database structure
- Set up Authentication with Auth0.com. You need two roles with different permissions:
Customer:
permissions:
post:reservation
Restaurant Manager:
permissions:
post:restaurant
patch:restaurant
delete:restaurant
- Set up FLASK_APP variable depending on OS:
export FLASK_APP=app.py
For Windows use:
$env:FLASK_APP="app.py"
- To run the app use:
flask run
- By default, the app will run on http://127.0.0.1:5000/
ENDPONTS
- GET '/restaurants'
- GET '/restaurants/int:id'
- GET '/restaurants/int:id/menu'
- POST '/restaurants/int:id/reservation'
- POST '/restaurants'
- PATCH '/restaurants/int:id'
- DELETE '/restaurants/int:id'
GET '/restaurants'
- No Authorization required
- Gets all the restaurants that are in the database
- Does not take any arguments
- Returns
{
'success': True,
'restaurants': [{
"id": self.id,
"name": self.name,
"address": self.address
}, ...]
}
GET '/restaurants/<int:id>'
- No Authorization required
- Gets all the info from a selected restaurant
- <int:id> relpaces the ID of the restaurant you want
- Returns:
{
'success': True,
'restaurants': [{
"id": self.id,
"name": self.name,
"address": self.address
}]
}
GET '/restaurants/<int:id>/menu'
- No Authorization required
- Gets the menu items that belong to a restaurnt, could be more than one
- <int:id> replaces the ID of restaurant you want to see the menu items
- Returns:
{
'success': True,
"items": [{
"name": self.name,
"description": self.description,
"price": str(self.price),
"restaurant_name": self.restaurnt_menu_item.name
}, ...]
}
POST '/restaurants/<int:id>/reservation'
- Requred Authorization with 'Customer' role
- Posts a reservation for the restaurant with id in <int:id>
- Required input (data type listed inside brackets):
{
"time_of_res": (datetime),
"num_of_people": (int),
"name_for_res": (string)
}
- Returns all upcoming reservation for the customer making the reservation:
{
'success': True,
'upcoming_reservations': [{
"time_of_res": self.time_of_res,
"num_of_people": self.num_of_people,
"restaurant_name": self.restaurant_name,
}, ...]
}
POST '/restaurants'
- Requred Authorization with 'Restaurant Manager' role
- Restaurant Manager can post their restaurant
- Required input (data type listed inside brackets):
{
"name": (string),
"address": (string)
}
- Returns all the restaurants that the user owns:
{
"success": True,
"owned_restaurants": [{
"id": self.id,
"name": self.name,
"address": self.address
}, ...]
}
PATCH '/restaurants/<int:id>'
- Requred Authorization with 'Restaurant Manager' role, and the Restaurant manager can only PATCH his/her own restaurnat
- Restaurant manager can edit their restaurants. They can edit the name, the address, or both
- Required input (data type listed inside brackets):
{
"name": (string),
"address": (string)
}
- Returns the the newly updated restaurant with the new information:
{
"name": 'NEW NAME',
"address": 'NEW ADDRESS'
}
DELETE '/restaurants/<int:id>'
- Requred Authorization with 'Restaurant Manager' role, and the Restaurant manager can only DELETE his/her own restaurnat
- Deletes the restaurant with id replaced by <int:id>
- Returns Response if deletes succesfully:
{
"success": True
}
ERROR HANDLERS
Error 422 (Unprocessable)
Returns:
{
"success": False,
"error": 422,
"message": "unprocessable"
}
Error 404 (Bad Request)
Returns:
{
"success": False,
"error": 404,
"message": "resource not found"
}
Error 401 (Resource Not Found)
Returns:
{
"success": False,
"error": 401,
"message": "Unauthorized Error"
}
Error 400 (Unauthorized Error)
Returns:
{
"success": False,
"error": 400,
"message": "Bad Request"
}
-
This app can be run at https://fsnd-happyhour.herokuapp.com/
-
You can securly Sign Up or Log In through Auth0: https://fsnd-happyhour.auth0.com/authorize?audience=fsndcapstone&response_type=token&client_id=rY3ee6xjoWocXP7PkCUouHS48vX9YAoo&redirect_uri=https://fsnd-happyhour.herokuapp.com/login-results
- Testing instructions
- Create a new database for testing (choose and new name ex. new_testing_db)
createdb new_testing_db
-
In test_app.py set database_name and database_path from your local machine
-
In the command line run
python test_app.py
- The tests will run and should all be completed sucessfully
This app is deployed on Heroku. For deployment, you need to:
-
Install Heroku CLI and login to Heroku on the terminal
-
create a setup.sh file and declare all your variables in the file
-
Install gunicorn
pip install gunicorn
- Create a Procfile and add the line below. The Procfile instructs Heroku on what to do. Make sure that your app is housed in app.py
web: gunicorn app:app
- Install the following requirements
pip install flask_script
pip install flask_migrate
pip install psycopg2-binary
- Freeze your requirements in the requirements.txt file
pip freeze > requirements.txt
- Create Heroku app
heroku create name_of_your_app
- Add git remote for Heroku to local repository
git remote add heroku heroku_git_url
- Add postgresql add on for our database
heroku addons:create heroku-postgresql:hobby-dev --app name_of_your_application
- Add all the Variables in Heroku under settings
# This should already exist from the last step
DATABASE_URL
# Get these from Auth0
AUTH0_DOMAIN
ALGORITHMS
API_AUDIENCE
-
Push any changes to your GitHub Repository
-
Push to Heroku
git push heroku master
- Run Migrations to the Heroku database
heroku run python manage.py db upgrade --app name_of_your_application
Visit your Heroku app on the hosted URL!
- Viktor Dojnov - https://github.com/vdojnov
Special thanks to:
- Kurt Galvin - https://github.com/kurtgalvin
- The Udacity Team!