Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@ language: python
python:
- "3.6"

services:
- postgresql

install:
- pip install -r requirements.txt
- pip install coveralls

before_script:
- "psql -c 'create database fast_food_app_test;' -U postgres"

script:
- coverage run --source=app -m pytest && coverage report

Expand Down
21 changes: 14 additions & 7 deletions app/__init__.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
"""
the __init__.py file

included to make app a package
Initializes the flask app and mackes it a package
"""
import os

from flask import Flask
from flask_restful import Api
from flask_jwt_extended import JWTManager

from app.api.v1.views import Orders, OrderSpecific
from app.api.v2.views_register import UserRegister, UserLogin

from instance.config import app_config

def create_app(config_name):
"""Application Factory for the app"""
app = Flask(__name__, instance_relative_config=True)
app.config.from_object(app_config[config_name])
app.config.from_pyfile('config.py')
app.secret_key = os.getenv('SECRET_KEY')

#Initialize and use Flask-RESTful
api_endpoint = Api(app)
api_endpoint.add_resource(Orders, '/api/v1/orders')
api_endpoint.add_resource(OrderSpecific, '/api/v1/order/<int:order_id>')
api_endpoint.add_resource(UserRegister, '/api/v2/auth/signup')
api_endpoint.add_resource(UserLogin, '/api/v2/auth/login')

#Initialize and use Flask-JWT-Extended
jwt = JWTManager(app)

return app
return app
1 change: 0 additions & 1 deletion app/api/v1/__init__.py

This file was deleted.

67 changes: 0 additions & 67 deletions app/api/v1/views.py

This file was deleted.

File renamed without changes.
109 changes: 109 additions & 0 deletions app/api/v2/model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
"""
This module is used to interact with the database
"""
import psycopg2
from flask_jwt_extended import create_access_token
from flask import request, jsonify

from app import migration

connection = migration.db_connection()
cursor = connection.cursor()

class Users():
"""Class to handle users"""
def register_user(self, username, password, confirm_password, email, address, telephone, admin):
"""Method to register a user"""
username = request.json.get('username', None)
password = request.json.get('password', None)
confirm_password = request.json.get('confirm_password', None)
email = request.json.get('email', None)
address = request.json.get('address', None)
telephone = request.json.get('telephone', None)
admin = request.json.get('admin', None)
if not isinstance(username, str):
print(type(username))
response = jsonify({'msg':'Username must be a string'})
response.status_code = 400
return response
if not isinstance(password, str) and isinstance(confirm_password, str):
response = jsonify({'msg':'Password must be a string'})
response.status_code = 400
return response
if not isinstance(email, str):
response = jsonify({'msg':'Email must be a string'})
response.status_code = 400
return response
if not isinstance(address, str):
response = jsonify({'msg':'Address must be a string'})
response.status_code = 400
return response
if not isinstance(telephone, str):
response = jsonify({'msg':'Telephone number must be a string'})
response.status_code = 400
return response
if not isinstance(admin, bool):
response = jsonify({'msg':'Admin must be a boolean'})
response.status_code = 400
return response
if password != confirm_password:
response = jsonify({'msg':'Passwords must match'})
response.status_code = 400
return response
try:
if admin is True:
add_user = "INSERT INTO \
users \
(username, password, email, address, telephone, admin) \
VALUES \
('" + username +"', '" + password +"', '" + email + "', \
'" + address + "', '" + telephone + "', true )"
if admin is False:
add_user = "INSERT INTO \
users \
(username, password, email, address, telephone, admin) \
VALUES ('" + username +"', '" + password +"', '" + email + "', \
'" + address + "', '" + telephone + "', false )"
cursor.execute(add_user)
connection.commit()
response = jsonify({'msg':'User successfully added to the databse'})
response.status_code = 201
return response
except (Exception, psycopg2.DatabaseError) as error:
response = jsonify({'msg':'Problem inserting into the databse'})
response.status_code = 400
return response

def login(self, username, password):
"""Method to login a user"""
username = request.json.get('username', None)
password = request.json.get('password', None)
if not isinstance(username, str):
print(type(username))
response = jsonify({'msg' : 'Username must be a string'})
response.status_code = 400
return response
if not isinstance(username, str):
response = jsonify({'msg' : 'Password must be a string'})
response.status_code = 400
return response
try:
get_user = "SELECT username, password \
FROM users \
WHERE username = '" + username + "' AND password = '" + password + "'"
cursor.execute(get_user)
row = cursor.fetchone()
if row is not None:
row = cursor.fetchone()
access_token = create_access_token(identity=username)
print(access_token)
response = jsonify({"msg":"Successfully logged in", "access_token":access_token})
response.status_code = 200
return response
response = jsonify({"msg" : "Error logging in, credentials not found"})
response.status_code = 401
return response
except (Exception, psycopg2.DatabaseError) as error:
print("Error executing", error)
return jsonify({"msg" : "Error, check the database {}".format(error)})

29 changes: 29 additions & 0 deletions app/api/v2/views_register.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""The register and user login endpoints"""
from flask import request
from flask_restful import Resource

from app.api.v2.model import Users

class UserRegister(Resource):
"""This class is used to register a new user"""
def post(self):
"""Method to register a user in the app"""
return Users().register_user(
request.json['username'],
request.json['password'],
request.json['confirm_password'],
request.json['email'],
request.json['address'],
request.json['telephone'],
request.json['admin']
)

class UserLogin(Resource):
"""This class is used to login a user"""
def post(self):
"""Method to log a user into the system."""
return Users().login(
request.json['username'],
request.json['password']
)

90 changes: 90 additions & 0 deletions app/migration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
"""
File to manage the connection to the database, creation and deletion of tables
"""
import os
import psycopg2

def db_connection(config=None):
"""Make a connection to the DB"""
if config == 'testing':
db_name = os.getenv('DB_TEST')
else:
db_name = os.getenv('DB_MAIN')
user = os.getenv('DB_USER')
password = os.getenv('DB_PASSWORD')
host = os.getenv('DB_HOST')
port = os.getenv('DB_PORT')

return psycopg2.connect(user=user, password=password, host=host, port=port, database=db_name)

def create_tables(cursor):
"""Create all tables"""
statements = (
"""
CREATE TABLE IF NOT EXISTS users (
user_id SERIAL PRIMARY KEY,
username VARCHAR(255) NOT NULL UNIQUE,
password VARcHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
address VARCHAR(255) NOT NULL,
telephone VARCHAR(255) NOT NULL,
admin BOOLEAN NOT NULL
)
""",
""" CREATE TABLE IF NOT EXISTS status (
status_id SERIAL PRIMARY KEY,
status_name VARCHAR(255) NOT NULL
)
""",
"""
CREATE TABLE IF NOT EXISTS menus (
menu_id SERIAL PRIMARY KEY,
meal_name VARCHAR(255) NOT NULL UNIQUE,
quantity INTEGER NOT NULL,
description VARCHAR(255) NOT NULL,
cost INTEGER NOT NULL
)
""",
"""
CREATE TABLE IF NOT EXISTS orders (
order_id SERIAL,
total_cost INT NOT NULL,
status_table_id INT REFERENCES status(status_id) ON DELETE CASCADE,
PRIMARY KEY (order_id, status_table_id)
)
""")

for statement in statements:
cursor.execute(statement)

def drop_tables(cursor):
"""Drops all tables"""
drops = ["DROP TABLE users CASCADE",
"DROP TABLE orders CASCADE",
"DROP TABLE menus CASCADE",
"DROP TABLE status CASCADE"]
for drop in drops:
cursor.execute(drop)
cursor.close()
connection.commit()

def main(config=None):
"""
This function is run in the command line to automate the connection to the database
and creation of tables in the database
"""
connection = db_connection(config=config)
cursor = connection.cursor()

create_tables(cursor)

connection.commit()

cursor.close()

connection.close()

print('Done')

if __name__ == '__main__':
main()
Loading