Source code for my fourth project for the Full Stack Web Developer Nanodegree (FSWDN) program from Udacity.
This project is a web application that provides a list of items within a variety of categories and integrate third party user registration and authentication via OAuth 1.0 and 2.0 The web app also provides rate limited API endpoints to access/edit the same information as displayed in the HTML endpoints for an arbitrary item in the catalog.
Clone or download the repository on your computer. Create a file in the catalog folder called for example catalog/local_config.py. Copy and paste in it the following and update with your own settings:
# App secret key
SECRET_KEY='your_app_secret_key'
# OAuth credentials
OAUTH_CREDENTIALS = {
'google': {
'client_id': 'your_google_client_id',
'client_secret': 'your_google_client_secret'
},
'facebook': {
'client_id': 'your_facebook_client_id',
'client_secret': 'your_facebook_client_secret'
},
'github': {
'client_id': 'your_github_client_id',
'client_secret': 'your_github_client_secret'
},
'linkedin': {
'client_id': 'your_linkedin_client_id',
'client_secret': 'your_linkedin_client_secret'
},
'twitter': {
'consumer_key': 'your_twitter_consumer_key',
'consumer_secret': 'your_twitter_consumer_secret'
}
}
If you need to override any settings from default_settings.py do so in local_config.py.
You must then set the environment variable APPLICATION_SETTINGS to:
export APPLICATION_SETTINGS=local_config.py
Run python run.py to create the database and start the webserver. Access the app in your web browser at http://localhost:5000/.
Optionally you can run python db_seed.py to populate the database with random placeholder items. Edit the db_seed.py file with your own email address if you want to be able to edit or delete those items.
Go to your (or create a new) developer account with each of the OAuth provider and create a new web app. Update local_config.py with the client ID and client secret (or consumer key and consumer secret) of the new app.
Set the callback uri to http://localhost:5000/oauth2callback/:provider. Twitter uses OAuth 1.0, the callback uri in this case should be: http://localhost:5000/oauth1callback/twitter.
SQLite, Redis, and Python as well as the following Python libraries:
The catalog API provides methods for accessing a resource such as an item or a category. POST, PUT and DELETE requests require an authorization token (valid for 1 hour) that can be obtained at http://localhost:5000/token once you are signed in. (The following is inspired from this template)
-
URL catalog/api/v1.0/items
-
Method:
GET -
Success Response:
- Code: 200
Content:{ "catalog": { "categories": [ { "id": 14, "items": [ { "category_id": 14, "description": "Lorem ipsum do...", "id": 40, "image_url": "/static/img/uploads/image1.jpg", "name": "Sociosqu", "user_id": 1 }, { "category_id": 14, "description": "Lorem ipsum do...", "id": 80, "image_url": "/static/img/uploads/image2.jpg", "name": "Integer", "user_id": 3 } ], "name": "Aenean" }, ..., { "id": 3, "items": [ { "category_id": 3, "description": "Lorem ipsum do...", "id": 20, "image_url": "/static/img/uploads/image8.jpg", "name": "Blandit", "user_id": 1 }, ..., { "category_id": 3, "description": "Lorem ipsum do...", "id": 39, "image_url": "/static/img/uploads/image9.jpg", "name": "Vestibulum", "user_id": 10 } ], "name": "Aliquam" }, ] } }
- Code: 200
-
Sample Call:
curl -X GET http://localhost:5000/catalog/api/v1.0/items
-
URL catalog/api/v1.0/:category
-
Method:
GET -
URL Params
Required:
category=[string] -
Success Response:
- Code: 200
Content:{ "Category": { "id": 14, "items": [ { "category_id": 14, "description": "Lorem ipsum do...", "id": 40, "image_url": "/static/img/uploads/image1.jpg", "name": "Sociosqu", "user_id": 10 }, ..., { "category_id": 14, "description": "Lorem ipsum do...", "id": 80, "image_url": "/static/img/uploads/image2.jpg", "name": "Integer", "user_id": 1 } ], "name": "Aenean" } }
- Code: 200
-
Error Response:
- Code: 404 NOT FOUND
Content:{ "Error": "no category 'category_name' found" }
- Code: 404 NOT FOUND
-
Sample Call:
curl -X GET http://localhost:5000/catalog/api/v1.0/category_name
-
URL catalog/api/v1.0/:category/:item
-
Method:
GET -
URL Params
Required:
category=[string]
item=[string]
-
Success Response:
- Code: 200
Content:{ "Item": { "category_id": 14, "description": "Lorem ipsum do...", "id": 40, "image_url": "/static/img/uploads/image.jpg", "name": "Sociosqu", "user_id": 10 } }
- Code: 200
-
Error Response:
- Code: 404 NOT FOUND
Content:{ "Error": "no item 'item_name' found" }or{ "Error": "no category 'category_name' found" }
- Code: 404 NOT FOUND
-
Sample Call:
curl -X GET http://localhost:5000/catalog/api/v1.0/category_name/item_name
-
URL catalog/api/v1.0/items
-
Method:
POST -
Data Params
Required:
name=[string] category_id=[integer]Optional:
description=[string] image=[file] -
Success Response:
- Code: 200
Content:{ "Item": { "category_id": 14, "description": "Lorem ipsum do..", "id": 64, "image_url": "/static/img/uploads/image.jpg", "name": "Sociosqu", "user_id": 1 } }
- Code: 200
-
Error Response:
-
Code: 401 UNAUTHORIZED
Content:{ "Error" : "Missing authorization credentials" }or{ "Error" : "Wrong authorization type" }or{ "Error" : "Wrong authorization token" } -
Code: 404 NOT FOUND
Content:{ "Error" : "User id not found" } -
Code: 422 UNPROCESSABLE ENTRY
Content:{ "Error": "(sqlite3.IntegrityError) UNIQUE constraint failed: item.name, item.category_id" }or{ "Error": "(sqlite3.IntegrityError) CHECK constraint failed: item" }or{ "Error": "(sqlite3.IntegrityError) NOT NULL constraint failed: item.category_id" }or{ "Error": "(sqlite3.IntegrityError) NOT NULL constraint failed: item.name" }or{ "Error": "Item not created" }
-
-
Sample Call:
curl -X POST http://localhost:5000/catalog/api/v1.0/items \ -H 'authorization: Bearer api_token \ -H 'content-type: application/json' \ -d '{ "name": "Item name", "description": "Lorem ipsum do...", "category_id": 1 }'Alternatively, x-www-form-urlencoded can be used:
curl -X POST http://localhost:5000/catalog/api/v1.0/items \ -H 'authorization: Bearer api_token' \ -H 'content-type: application/x-www-form-urlencoded' \ -d 'name=Item%20name&description=Lorem%20ipsum%20do...&category_id=1'If an image needs to be uploaded, use multipart/form-data:
curl -X POST http://localhost:5000/catalog/api/v1.0/items \ -H 'authorization: Bearer api_token' \ -H 'content-type: multipart/form-data; boundary=----Boundary' \ -F 'name=Item name' \ -F 'description=Lorem ipsum do...' \ -F category_id=1 \ -F 'image=@Path_to_image_file'
-
URL catalog/api/v1.0/:category/:item
-
Method:
PUT -
Data Params
Optional:
name=[string] description=[string] category_id=[integer] image=[file] -
Success Response:
- Code: 200
Content:{ "Item": { "category_id": 14, "description": "Lorem ipsum do..", "id": 64, "image_url": "/static/img/uploads/image.jpg", "name": "Sociosqu", "user_id": 1 } }
- Code: 200
-
Error Response:
-
Code: 401 UNAUTHORIZED
Content:{ "Error" : "Missing authorization credentials" }or{ "Error" : "Wrong authorization type" }or{ "Error" : "Wrong authorization token" }or{ "Error" : "You are not authorized to edit this item"} -
Code: 404 NOT FOUND
Content:{ "Error" : "User id not found" }or{ "Error": "no category 'category_name' found" }or{ "Error": "no item 'item_name' found" } -
Code: 422 UNPROCESSABLE ENTRY
Content:{ "Error": "(sqlite3.IntegrityError) UNIQUE constraint failed: item.name, item.category_id" }or{ "Error": "(sqlite3.IntegrityError) CHECK constraint failed: item" }
-
-
Sample Call:
curl -X PUT http://localhost:5000/catalog/api/v1.0/category_name/item_name \ -H 'authorization: Bearer api_token \ -H 'content-type: application/json' \ -d '{ "name": "Item name", "description": "Lorem ipsum do...'", "category_id": 1 }'Alternatively, x-www-form-urlencoded can be used:
curl -X PUT http://localhost:5000/catalog/api/v1.0/category_name/item_name \ -H 'authorization: Bearer api_token' \ -H 'content-type: application/x-www-form-urlencoded' \ -d 'name=Item%20name&description=Lorem%20ipsum%20do...&category_id=1'If an image needs to be uploaded, use multipart/form-data:
curl -X PUT http://localhost:5000/catalog/api/v1.0/category_name/item_name \ -H 'authorization: Bearer api_token' \ -H 'content-type: multipart/form-data; boundary=----Boundary' \ -F 'name=Item name' \ -F 'description=Lorem ipsum do...' \ -F category_id=1 \ -F 'image=@Path_to_image_file'
-
URL catalog/api/v1.0/:category/:item
-
Method:
DELETE -
Success Response:
- Code: 200
Content:{ "Success": "item deleted" }
- Code: 200
-
Error Response:
-
Code: 401 UNAUTHORIZED
Content:{ "Error" : "Missing authorization credentials" }or{ "Error" : "Wrong authorization type" }or{ "Error" : "Wrong authorization token" }or{ "Error" : "You are not authorized to delete this item"} -
Code: 404 NOT FOUND
Content:{ "Error" : "User id not found" }
-
-
Sample Call:
curl -X DELETE http://localhost:5000/catalog/api/v1.0/category_name/item_name \ -H 'authorization: Bearer api_token' \