diff --git a/.gitignore b/.gitignore
index aa226fc..8d7afe7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,5 +15,5 @@ node_modules/
.DS_Store
__pycache__
.cache/
-Cog
.vscode/
+.env
\ No newline at end of file
diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md
index 2f665cd..66d6fdc 100644
--- a/DEVELOPMENT.md
+++ b/DEVELOPMENT.md
@@ -1,27 +1,18 @@
# Development
## Setup
-- Set up a Python2
-[virtualenv](http://python-guide-pt-br.readthedocs.io/en/latest/dev/virtualenvs/)
-to manage Python dependencies
-- Source your virtualenv
-- Run `pip install -r requirements.txt` to install all dependencies
-- Install [PostgreSQL](https://www.postgresql.org/download/) to run a database locally
- - If you're using Mac, install *Postgres.app* from
- [here](https://www.postgresql.org/download/)
-- Set three environment variables:
- - `DATABASE_URL` points to the URL of a development database,
-which has to be set up using Postgres on your system. A sample `DATABASE_URL`
-could look like `postgres://username:password@localhost/cog`.
- - `QUILL` is the URL to your Quill instance for auth.
- - `SECRET` needs to be the same JWT secret used in your Quill instance.
-- Run `python initialize.py`
- - This initializes the database - run it if you make any changes to the models and
- are fine with overwriting data.
+- Install Docker
+- Install Docker Compose
+- Copy `sample.env` to `.env` and enter in the proper values
+- `make migrate` to initialize and set up the db
+
+## Build
+- If you need to rebuild (in case you change the Dockerfile), run `make build`
## Running
-- Run `make run`
-- The site will be visible at `localhost:8000`
+- Run `make start`
+- The site will be visible at `localhost:80`
+- `make logs` for a live stream of logs.
-## Tests
-- Run `make test` to run all tests
+## Destroying
+- Run `make stop` to destroy
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index ff58fb9..dc14f8f 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,6 +1,6 @@
-FROM python:2
+FROM python:3.6.3
-ARG APP_PATH=/hardware-checkout
+ARG APP_PATH=/hardwarecheckout
WORKDIR $APP_PATH
@@ -9,6 +9,6 @@ RUN pip install -r requirements.txt
ADD . $APP_PATH
-EXPOSE 8000
-CMD ["gunicorn", "--bind", ":8000", "-k", "geventwebsocket.gunicorn.workers.GeventWebSocketWorker", "hardwarecheckout:app"]
-
+EXPOSE $FLASK_RUN_PORT
+CMD ["python", "runserver.py"]
+# CMD ["flask", "run"]
diff --git a/HEROKU.md b/HEROKU.md
new file mode 100644
index 0000000..50382ba
--- /dev/null
+++ b/HEROKU.md
@@ -0,0 +1,2 @@
+# Deploying on Heroku
+After deploying on Heroku, you should go into the console and then run `python initialize.py` to properly set up the database. (WARNING: doing this will clear all existing data in the database)
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 9056773..d2c18c6 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,24 @@
-test:
- python -m pytest tests/
+build:
+ docker-compose build
+
+sass:
+ cd hardwarecheckout/static && sass --watch sass/app.scss:css/app.css
+start:
+ docker-compose up -d
+ @echo "hardwarecheckout listening on port 8000, postgres on 5432"
+ @echo "run 'make logs' to watch logs"
+
+stop:
+ docker-compose down
-PORT = 8000
-run:
- gunicorn --bind 0.0.0.0:$(PORT) -k geventwebsocket.gunicorn.workers.GeventWebSocketWorker hardwarecheckout:app
+# watch the logs from hardwarecheckout
+logs:
+ docker-compose logs -f -t hardwarecheckout
+# run all the migrations
+migrate:
+ docker-compose run hardwarecheckout python initialize.py
+ # db/containers still running
+
+test:
+ docker-compose run hardwarecheckout python initialize.py && python -m pytest tests/
\ No newline at end of file
diff --git a/Procfile b/Procfile
index 0de4e17..06a286c 100644
--- a/Procfile
+++ b/Procfile
@@ -1 +1 @@
-web: python runserver.py $PORT
\ No newline at end of file
+web: python runserver.py
\ No newline at end of file
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..cb0f270
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,24 @@
+version: "3"
+services:
+ dev_db:
+ image: postgres
+ ports:
+ - 5432
+ environment:
+ - PG_PASSWORD=password
+ hardwarecheckout:
+ container_name: hardwarecheckout
+ image: hardwarecheckout:latest
+ build:
+ context: .
+ environment:
+ - QUILL=${QUILL}
+ - DATABASE_URL=${DATABASE_URL}
+ - SECRET=${SECRET}
+ - PORT=5000
+ ports:
+ - 127.0.0.1:5000:5000
+ depends_on:
+ - dev_db
+ volumes:
+ - .:/hardwarecheckout
\ No newline at end of file
diff --git a/hardwarecheckout/__init__.py b/hardwarecheckout/__init__.py
index a0d8967..1e43377 100644
--- a/hardwarecheckout/__init__.py
+++ b/hardwarecheckout/__init__.py
@@ -3,7 +3,7 @@
from flask import Flask
from flask_socketio import SocketIO
-from urlparse import urlsplit
+from urllib.parse import urlsplit
from flaskext.markdown import Markdown
from hardwarecheckout.utils import display_date, deltatimeformat
diff --git a/hardwarecheckout/controllers/request.py b/hardwarecheckout/controllers/request.py
index fa96978..3dea1f3 100644
--- a/hardwarecheckout/controllers/request.py
+++ b/hardwarecheckout/controllers/request.py
@@ -1,7 +1,7 @@
from hardwarecheckout import app
from hardwarecheckout import socketio
from hardwarecheckout.models import db
-
+from hardwarecheckout.config import EMAIL_SUBJECT
from hardwarecheckout.models.request import Request, RequestStatus
from hardwarecheckout.models.inventory_entry import InventoryEntry
from hardwarecheckout.models.inventory_entry import ItemType
@@ -10,6 +10,7 @@
from hardwarecheckout.models.request_item import RequestItem
from hardwarecheckout.models.socket import Socket
+
from hardwarecheckout.utils import requires_auth, requires_admin, verify_token
from sqlalchemy import event
@@ -38,10 +39,10 @@ def get_requests():
def request_submit():
"""Submits new request"""
if not (user.location and user.phone):
- return jsonify(
- success=False,
- message="""Please fill out your user info before
- requesting items!"""
+ return jsonify(
+ success=False,
+ message="""Please fill out your user info before
+ requesting items!"""
)
proposal = request.form.get('proposal', '')
requested_quantity = int(request.form.get('quantity', 1))
@@ -91,7 +92,7 @@ def request_submit():
message='Out of stock!'
)
- for _ in xrange(requested_quantity):
+ for _ in range(requested_quantity):
item = RequestItem(
InventoryEntry.query.get(request.form['item_id']),
1)
@@ -148,7 +149,7 @@ def request_approve(id):
quantity = request_item.quantity
# get items of proper type
- for _ in xrange(quantity):
+ for _ in range(quantity):
if entry.quantity < quantity:
return jsonify(
success=False,
@@ -184,7 +185,7 @@ def request_fulfill(id):
quantity = request_item.quantity
# get items of proper type
- for _ in xrange(quantity):
+ for _ in range(quantity):
item = Item.query.filter_by(entry_id = entry.id, user = None).first()
if item == None:
return jsonify(
diff --git a/hardwarecheckout/models/inventory_entry.py b/hardwarecheckout/models/inventory_entry.py
index 2df623b..03112cd 100644
--- a/hardwarecheckout/models/inventory_entry.py
+++ b/hardwarecheckout/models/inventory_entry.py
@@ -42,7 +42,7 @@ def __init__(self, name, description, link, category, tags,
self.image_src = image
self.items = []
- for i in xrange(int(qty)):
+ for i in range(int(qty)):
self.items.append(
Item(self, self.name + " " + str(i+1)))
@@ -61,6 +61,7 @@ def quantity(self):
.filter_by(status=hardwarecheckout.models.request.RequestStatus.APPROVED) \
.with_entities(func.sum(RequestItem.quantity)).scalar()
if not requests: requests = 0
+
return Item.query.filter_by(entry_id = self.id, user = None).count() - requests
@property
diff --git a/hardwarecheckout/utils.py b/hardwarecheckout/utils.py
index 38f13e9..aecb55b 100644
--- a/hardwarecheckout/utils.py
+++ b/hardwarecheckout/utils.py
@@ -11,7 +11,7 @@
from babel import dates
def gen_uuid():
- return str(uuid.uuid4()).replace('-', '')
+ return str(uuid.uuid4()).replace('-', '').decode('utf-8')
def verify_token(token):
try:
diff --git a/requirements.txt b/requirements.txt
index 16fb224..746a602 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -9,11 +9,10 @@ cffi==1.10.0
chardet==3.0.4
click==6.7
configparser==3.5.0
-cryptography==1.7.2
decorator==4.1.2
ecdsa==0.13
enum34==1.1.6
-eventlet
+eventlet==0.25.1
Flask==0.12.2
Flask-Admin==1.5.0
Flask-Markdown==0.3
@@ -37,7 +36,7 @@ Markdown==2.6.9
MarkupSafe==1.0
mccabe==0.6.1
phonenumbers==8.8.1
-psycopg2==2.7.1
+psycopg2==2.7.3.2
py==1.4.34
pyasn1==0.2.3
pycodestyle==2.3.1
@@ -60,4 +59,4 @@ Werkzeug==0.12.2
wrapt==1.10.11
WTForms==2.0
WTForms-Alchemy==0.15.0
-WTForms-Components==0.10.3
+WTForms-Components==0.10.3
\ No newline at end of file
diff --git a/runserver.py b/runserver.py
index 7440841..2e617f6 100644
--- a/runserver.py
+++ b/runserver.py
@@ -1,9 +1,7 @@
from hardwarecheckout import app, socketio
import sys
+import os
if __name__ == '__main__':
- try:
- port = int(sys.argv[1])
- except (IndexError, ValueError):
- port = 5000
- socketio.run(app, host='0.0.0.0', port=port)
+ port = int(os.getenv("PORT", "5000"))
+ socketio.run(app, host='0.0.0.0', port=port)
\ No newline at end of file
diff --git a/runtime.txt b/runtime.txt
deleted file mode 100644
index 5385682..0000000
--- a/runtime.txt
+++ /dev/null
@@ -1 +0,0 @@
-python-2.7.14
diff --git a/sample.env b/sample.env
new file mode 100644
index 0000000..3d55399
--- /dev/null
+++ b/sample.env
@@ -0,0 +1,4 @@
+QUILL=
+DATABASE_URL=postgres://postgres:password@dev_db/postgres
+SECRET=random123456
+FORCE_SSL=False
\ No newline at end of file
diff --git a/tests/test_all.py b/tests/test_all.py
index 96d7d99..b4f499d 100644
--- a/tests/test_all.py
+++ b/tests/test_all.py
@@ -46,7 +46,7 @@ def user(app):
user = User(quill_id, 'alyssap@hacker.org', False)
db.session.add(user)
db.session.commit()
- app.set_cookie('localhost:8000', 'jwt', token)
+ app.set_cookie('localhost:5000', 'jwt', token)
return user
@@ -145,7 +145,7 @@ def test_run_lottery(app, admin, item):
.join(Request).filter_by(status=RequestStatus.APPROVED).count() == 3
def test_run_all_lotteries(app, admin):
- for _ in xrange(3):
+ for _ in range(3):
item = InventoryEntry('Item' + str(_), 'Wow lick my socks',
'http://test.co', 'Item', [], '', 3, item_type=ItemType.LOTTERY)
db.session.add(item)