Project: Item Catalog
The second project in the Fullstack Web Developer Nanodegree.
Runtime Dependencies
- Python 2.7 - the application runtime.
- Flask - the web application framework.
- sqlalchemy - the ORM library for the underlying database.
- requests-oauthlib - for handling OAuth2 flows.
- flask-login - for handling session management and protecting views.
- psycopg2 - the PostgreSQL DB API for Python.
Dev Dependencies
- pycodestyle - for checking code style practices.
- autopep8 - for automatically fixing issues reported by
pycodestyle
.
Server Configuration
The application is designed to be deployed using nginx as a reverse proxy to a gunicorn wsgi
application server enabled via systemd
.
Software Installed
- Python 2.7 and pip
- Nginx (web server / reverse proxy)
- Gunicorn (
wsgi
application server) - PostgreSQL (database backend)
- Certbot + LetsEncrypt
Configuration Summary
- The
ssh
service is configured to only permit publickey authentication for all users. The service is bound to port2200
instead of22
and theroot
user is not permitted to log in remotely. - PostgreSQL is installed and configured to accept connections from
localhost
only. Peer authentication is used for thecatalog
user.- Because peer authentication is used for connecting to the database, the corresponding system user (
catalog
) is not permitted to log into the server at all. Any attempts will result in a "This account is currently not available" message.
- Because peer authentication is used for connecting to the database, the corresponding system user (
- Gunicorn is the
wsgi
server used to serve the application. It only listens to requests fromlocalhost:8080
. It runs the application as thecatalog
system user.- Gunicorn is configured as a
systemd
service. This enables startup on boot of the server, and status checks/stops/starts can be handled through typicalsystemctl/service
commands. Logs are sent tojournal
automatically bysystemd
.
- Gunicorn is configured as a
- Nginx is configured as the primary web server and reverse proxy.
- Nginx also routes all HTTP requests (on port 80) to HTTPS (443) to ensure encrypted communication for the user, since
requests-oauthlib
requires it.
- Nginx also routes all HTTP requests (on port 80) to HTTPS (443) to ensure encrypted communication for the user, since
- TLS/SSL certificates were obtained using LetsEncrypt and Certbot.
Running the App Locally
- Ensure the fullstack-nanodegree-vm project has been downloaded.
- Ensure VirtualBox and Vagrant have been installed.
- Clone or download this repository and copy the file contents to the
vagrant/catalog/
directory in thefullstack-nanodegree-vm project
mentioned in step 1. - Bring up the vagrant machine and
ssh
into it.$ cd fullstack-nanodegree-vm/vagrant $ vagrant up $ vagrant ssh
- Ensure all of the project dependencies are installed.
$ cd /vagrant/catalog/ $ sudo pip install -r requirements.txt
- Create a file called
client_secrets.json
and paste the provided text into it. This file is required for GitHub (the OAuth2 provider) to verify this application. - Do the database setup and run the application
# setup the database $ python dbhelper.py # run the flask app $ python application.py
- To stop the application, go back to your vagrant session and hit
control + c
.
Interacting With the Application
If you are using the deployed version of the application, please substitute the references to localhost:8000
with
https://tlkamp.com
.
Navigate to http://localhost:8000/
in a browser. To interact with the json endpoints, please use the following:
http://localhost:8000/catalog/json
for a full catalog listinghttp://localhost:8000/catalog/json/item/<item id number>
for informaiton about a specific database item.
An item that does not exist
$ curl -i http://localhost:8000/catalog/json/item/3
HTTP/1.0 404 NOT FOUND
Content-Type: application/json
Content-Length: 29
Server: Werkzeug/0.14.1 Python/3.6.5
Date: Mon, 21 Jan 2019 01:05:02 GMT
{
"message": "Not found"
}
An individual item
$ curl -i http://localhost:8000/catalog/json/item/2
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 209
Server: Werkzeug/0.14.1 Python/3.6.5
Date: Mon, 21 Jan 2019 01:05:00 GMT
{
"item": {
"category": "Default",
"description": "something with a later modified date",
"id": 2,
"last_updated": "2019-01-20 13:31",
"name": "another default",
"user": 1
}
}
The full catalog listing
$ curl -i http://localhost:8000/catalog/json/
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 580
Server: Werkzeug/0.14.1 Python/3.6.5
Date: Mon, 21 Jan 2019 01:05:06 GMT
{
"categories": [
{
"id": 1,
"items": [
{
"category": "Default",
"description": "something to test with",
"id": 1,
"last_updated": "2019-01-20 13:31",
"name": "default item",
"user": 1
},
{
"category": "Default",
"description": "something with a later modified date",
"id": 2,
"last_updated": "2019-01-20 13:31",
"name": "another default",
"user": 1
}
],
"name": "Default"
}
]
}