Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
8779474
[starts #162163623] Add GET order by id endpoint
ipaullly Nov 23, 2018
acd2068
[starts #162530597] add logic to check user role before consuming end…
ipaullly Dec 9, 2018
2ec7f9e
[finishes #162530597] deploy app to heroku
ipaullly Dec 9, 2018
81284a9
remove pkg-resources
ipaullly Dec 9, 2018
f2b3071
modify Procfile
ipaullly Dec 9, 2018
de26056
modify Procfile
ipaullly Dec 9, 2018
a465499
modify Procfile
ipaullly Dec 9, 2018
4d84f4d
modify Procfile
ipaullly Dec 9, 2018
eea7dcb
modify app/__init__.py
ipaullly Dec 9, 2018
ac65c83
modify app/__init__.py
ipaullly Dec 9, 2018
7b5af8f
modify app/__init__.py
ipaullly Dec 9, 2018
4dfa2a0
remove str decode method
ipaullly Dec 9, 2018
a63856a
add decode method
ipaullly Dec 9, 2018
6c10cb2
add convert from byte to string function
ipaullly Dec 9, 2018
dd15414
Add decode to ASCII
ipaullly Dec 9, 2018
c6f4e86
add str() function
ipaullly Dec 9, 2018
7bd3734
move str() function
ipaullly Dec 9, 2018
2dc6a4b
move str() function
ipaullly Dec 9, 2018
d3d0d7b
add decode() function in user model
ipaullly Dec 9, 2018
d4d0843
add decode() function in user model
ipaullly Dec 9, 2018
79e323b
add codecs module
ipaullly Dec 10, 2018
4513271
remove codecs module
ipaullly Dec 10, 2018
894aeaf
add str() function
ipaullly Dec 10, 2018
102d4fd
add arguments to str() function
ipaullly Dec 10, 2018
41a5637
add decode() method
ipaullly Dec 10, 2018
517653f
add encode() method
ipaullly Dec 10, 2018
c1ca181
append decode() to token generation
ipaullly Dec 10, 2018
deae9b5
append decode() to token generation
ipaullly Dec 10, 2018
06bceb4
append decode() to token generation
ipaullly Dec 10, 2018
ecab823
debug decode of token
ipaullly Dec 10, 2018
66c5947
debug decode of token
ipaullly Dec 10, 2018
c8346d3
debug decode of token
ipaullly Dec 10, 2018
cf4fb32
debug decode of token
ipaullly Dec 10, 2018
0221ec8
comment out string operation
ipaullly Dec 10, 2018
aeb6683
comment out string operation
ipaullly Dec 10, 2018
0fd2a54
ignore node modules
ipaullly Jan 11, 2019
191bd00
Add CORS functionality to create_app()
ipaullly Jan 11, 2019
a366bf8
remove pkg-resources from requirements.txt
ipaullly Jan 11, 2019
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
2 changes: 1 addition & 1 deletion .coverage
Original file line number Diff line number Diff line change
@@ -1 +1 @@
!coverage.py: This is a private format, don't read it directly!{"arcs":{"/home/ipaullly/dev/parcels/sendIT/app/utilities/__init__.py":[[-1,1],[1,-1]],"/home/ipaullly/dev/parcels/sendIT/app/utilities/validation_functions.py":[[-1,1],[1,3],[3,10],[10,17],[17,-1],[-3,4],[4,5],[5,6],[6,-3],[5,8],[8,-3],[-10,11],[11,12],[12,13],[13,-10],[-17,18],[18,19],[19,21],[21,22],[22,23],[23,-17],[12,15],[15,-10]],"/home/ipaullly/dev/parcels/sendIT/app/utilities/JWT_token.py":[]}}
!coverage.py: This is a private format, don't read it directly!{"arcs":{"/home/ipaullly/dev/parcels/sendIT/app/__init__.py":[[-1,1],[1,2],[2,3],[3,4],[4,5],[5,6],[6,7],[7,16],[16,-1]],"/home/ipaullly/dev/parcels/sendIT/app/config.py":[[-1,1],[1,3],[-3,3],[3,6],[6,7],[7,8],[8,9],[9,-3],[3,11],[-11,11],[11,14],[14,15],[15,16],[16,-11],[11,18],[-18,18],[18,21],[21,22],[22,23],[23,24],[24,-18],[18,26],[-26,26],[26,29],[29,30],[30,31],[31,-26],[26,34],[34,35],[35,36],[36,-1]],"/home/ipaullly/dev/parcels/sendIT/app/api/__init__.py":[[-1,1],[1,-1]],"/home/ipaullly/dev/parcels/sendIT/app/api/v1/__init__.py":[[-1,1],[1,2],[2,4],[4,6],[6,8],[8,10],[10,11],[11,12],[12,13],[13,-1]],"/home/ipaullly/dev/parcels/sendIT/app/api/v1/views.py":[[-1,1],[1,2],[2,3],[3,4],[4,6],[6,8],[-8,8],[8,11],[11,12],[12,54],[54,-8],[8,64],[-64,64],[64,67],[67,68],[68,-64],[64,85],[-85,85],[85,88],[88,89],[89,-85],[85,102],[-102,102],[102,105],[105,106],[106,-102],[102,-1]],"/home/ipaullly/dev/parcels/sendIT/app/api/v1/models.py":[[-2,2],[2,4],[-4,4],[4,7],[7,8],[8,12],[12,28],[28,34],[34,45],[45,56],[56,-4],[4,-2],[-8,9],[9,10],[10,-8]],"/home/ipaullly/dev/parcels/sendIT/app/utilities/__init__.py":[[-1,1],[1,-1]],"/home/ipaullly/dev/parcels/sendIT/app/utilities/validation_functions.py":[[-1,1],[1,3],[3,7],[7,14],[14,22],[22,-1]],"/home/ipaullly/dev/parcels/sendIT/app/api/v2/__init__.py":[[-1,1],[1,2],[2,4],[4,7],[7,9],[9,11],[11,12],[12,13],[13,14],[14,15],[15,16],[16,17],[17,-1]],"/home/ipaullly/dev/parcels/sendIT/app/api/v2/views.py":[[-1,1],[1,2],[2,6],[6,7],[7,8],[8,10],[10,12],[12,29],[-29,29],[29,32],[32,33],[33,119],[119,-29],[29,133],[-133,133],[133,136],[136,137],[137,-133],[133,156],[-156,156],[156,159],[159,160],[160,-156],[156,199],[-199,199],[199,202],[202,203],[203,-199],[199,249],[-249,249],[249,252],[252,253],[253,-249],[249,292],[-292,292],[292,295],[295,296],[296,-292],[292,328],[-328,328],[328,331],[331,332],[332,-328],[328,-1]],"/home/ipaullly/dev/parcels/sendIT/app/utilities/token_function.py":[[-1,1],[1,2],[2,4],[4,-1]],"/home/ipaullly/dev/parcels/sendIT/app/api/v2/models.py":[[-2,2],[2,4],[-4,4],[4,7],[7,8],[8,29],[29,36],[36,45],[45,61],[61,76],[76,91],[91,103],[103,-4],[4,-2]],"/home/ipaullly/dev/parcels/sendIT/app/api/v2/dbmodel.py":[[-1,1],[1,2],[2,3],[3,5],[-5,5],[5,8],[8,9],[9,17],[17,42],[42,50],[50,59],[59,67],[67,76],[76,84],[84,93],[93,-5],[5,-1]],"/home/ipaullly/dev/parcels/sendIT/app/auth/__init__.py":[[-1,1],[1,-1]],"/home/ipaullly/dev/parcels/sendIT/app/auth/v1/__init__.py":[[-1,1],[1,2],[2,4],[4,6],[6,8],[8,10],[10,11],[11,-1]],"/home/ipaullly/dev/parcels/sendIT/app/auth/v1/views.py":[[-1,1],[1,2],[2,3],[3,4],[4,6],[-6,6],[6,9],[9,10],[10,-6],[6,47],[-47,47],[47,50],[50,51],[51,-47],[47,-1]],"/home/ipaullly/dev/parcels/sendIT/app/auth/v1/models.py":[[-1,1],[1,2],[2,3],[3,4],[4,6],[-6,6],[6,9],[9,10],[10,15],[15,-6],[6,18],[-10,11],[11,12],[12,13],[13,14],[14,-10],[18,20],[-20,20],[20,23],[23,24],[24,-20],[20,31],[-31,31],[31,34],[34,35],[35,42],[42,52],[52,60],[60,67],[67,86],[86,-31],[31,-1]],"/home/ipaullly/dev/parcels/sendIT/app/auth/v2/__init__.py":[[-1,1],[1,2],[2,4],[4,6],[6,8],[8,10],[10,11],[11,-1]],"/home/ipaullly/dev/parcels/sendIT/app/auth/v2/views.py":[[-1,1],[1,2],[2,5],[5,6],[6,8],[8,10],[-10,10],[10,13],[13,14],[14,-10],[10,58],[-58,58],[58,61],[61,62],[62,-58],[58,-1]],"/home/ipaullly/dev/parcels/sendIT/app/auth/v2/models.py":[[-1,1],[1,2],[2,3],[3,4],[4,7],[7,11],[-11,11],[11,14],[14,15],[15,27],[27,34],[34,42],[42,51],[51,-11],[11,-1]],"/home/ipaullly/dev/parcels/sendIT/app/tests/__init__.py":[[-1,1],[1,-1]],"/home/ipaullly/dev/parcels/sendIT/app/tests/test_create_parcel_edgecases.py":[[-1,1],[1,2],[2,5],[5,6],[6,8],[-8,8],[8,11],[11,12],[12,54],[54,57],[57,62],[62,67],[67,72],[72,77],[77,-8],[8,84],[84,-1]],"/home/ipaullly/dev/parcels/sendIT/app/tests/test_edgecases.py":[[-1,1],[1,2],[2,5],[5,6],[6,8],[-8,8],[8,11],[11,12],[12,46],[46,49],[49,58],[58,64],[64,70],[70,77],[77,83],[83,-8],[8,89],[89,-1]],"/home/ipaullly/dev/parcels/sendIT/app/tests/test_login.py":[[-1,1],[1,2],[2,5],[5,6],[6,8],[-8,8],[8,11],[11,12],[12,25],[25,35],[35,42],[42,-8],[8,45],[45,-1]],"/home/ipaullly/dev/parcels/sendIT/app/tests/test_parcels.py":[[-1,1],[1,2],[2,5],[5,6],[6,8],[-8,8],[8,11],[11,12],[12,27],[27,30],[30,39],[39,50],[50,60],[60,70],[70,-8],[8,82],[82,-1]],"/home/ipaullly/dev/parcels/sendIT/app/tests/test_register.py":[[-1,1],[1,2],[2,5],[5,6],[6,8],[-8,8],[8,11],[11,12],[12,25],[25,29],[29,35],[35,-8],[8,43],[43,-1]],"/home/ipaullly/dev/parcels/sendIT/app/tests/v1/__init__.py":[],"/home/ipaullly/dev/parcels/sendIT/app/tests/v2/__init__.py":[]}}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ venv
.vscode
*.pytest_cache
.travis.yml
*.pytest_cache
node_modules
2 changes: 1 addition & 1 deletion Procfile
Original file line number Diff line number Diff line change
@@ -1 +1 @@
web: gunicorn 'app:create_app()'
web: gunicorn 'app:create_app(config_option="ProdConfig")'
5 changes: 4 additions & 1 deletion app/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from flask import Flask, Blueprint
from flask_cors import CORS
from app import config
from app.api.v1 import version1
from app.api.v2 import version2
Expand All @@ -19,12 +20,14 @@ def create_app(config_option="DevConfig"):
"""
app = Flask(__name__)
app.config.from_object(config.config[config_option])
SenditDb.start_db(app.config['DATABASE_URI'])
#SenditDb.start_db(app.config['DATABASE_URI'])
SenditDb.start_db('postgres://vhgobajxbehppp:b05d8b59b7552e74c763d86945c5b29c2fd11c5e000cfc417190eca27f8eb3d5@ec2-54-204-40-248.compute-1.amazonaws.com:5432/d4v7duckviarp9')
SenditDb.build_all()
app.register_blueprint(version1)
app.register_blueprint(version2)
app.register_blueprint(auth)
app.register_blueprint(auth2)
CORS(app)
return app


6 changes: 4 additions & 2 deletions app/api/v2/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from flask import Blueprint
from flask_restful import Api
#from ...api.v2.views import ParcelList, ParcelDestination, ParcelStatus, ParcelCurrentLocation, CancelParcel, UserOrders
from app.api.v2.views import ParcelList, ParcelDestination, ParcelStatus, ParcelCurrentLocation, CancelParcel, UserOrders
from app.api.v2.views import ParcelList, ParcelDestination, ParcelStatus, \
ParcelCurrentLocation, CancelParcel, UserOrders, IndividualParcel

version2 = Blueprint('v2', __name__, url_prefix="/api/v2")

Expand All @@ -12,4 +13,5 @@
api.add_resource(ParcelStatus, '/parcels/<int:id>/status')
api.add_resource(ParcelCurrentLocation, '/parcels/<int:id>/presentLocation')
api.add_resource(CancelParcel, '/parcels/<int:id>/cancel')
api.add_resource(UserOrders, '/users/<int:id>/parcels')
api.add_resource(UserOrders, '/users/<int:id>/parcels')
api.add_resource(IndividualParcel, '/parcels/<int:id>')
7 changes: 4 additions & 3 deletions app/api/v2/dbmodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def build_all(cls):
CREATE TABLE IF NOT EXISTS users (
id serial PRIMARY KEY NOT NULL,
email character varying(50) NOT NULL,
role BIT,
role character varying(50),
password character varying(300) NOT NULL
);"""
)
Expand All @@ -48,7 +48,7 @@ def persist_to_db(cls, query_string, tuple_data):
cls.conn.commit()

@classmethod
def add_to_db(cls, query_string, tuple_data):
def insert_fetch_from_db(cls, query_string, tuple_data):
"""
method that saves queries into the database
"""
Expand All @@ -70,7 +70,8 @@ def retrieve_one(cls, query_string):
method returns data on a particular row from the database
"""
cls.cur.execute(query_string)
return cls.cur.fetchone()
result = cls.cur.fetchone()
return result

@classmethod
def retrieve_all(cls, query_string):
Expand Down
18 changes: 18 additions & 0 deletions app/api/v2/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,31 @@ def order_list(self):
resp = SenditDb.retrieve_all(query)
return resp

def order_identification(self):
"""
retrieves object containing user and order ids
"""
query = """SELECT user_id, order_id FROM orders ORDER BY order_id ASC;"""
resp = SenditDb.retrieve_all(query)
return resp

def retrieve_single_order(self, parcel_id):
"""
retrieves an order by id
"""

query = """SELECT * FROM orders WHERE order_id={}""".format(parcel_id)
resp = SenditDb.retrieve_one(query)
return resp

def update_destination(self, new_dest, parcel_id):
"""
updates the destination of a user's parcels
"""
payload = {
"updated_destination" : new_dest
}

input_query = """SELECT destination FROM orders WHERE order_id={}""".format(parcel_id)
response = SenditDb.retrieve_one(input_query)
if not response:
Expand Down
91 changes: 71 additions & 20 deletions app/api/v2/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
from app.utilities.token_function import decode_token
from app.utilities.validation_functions import check_for_space, check_createparcel_keys
from app.api.v2.models import OrderParcel
from app.auth.v2.models import User

order = OrderParcel()
user = User()

class ParcelList(Resource):
"""
Expand All @@ -17,7 +19,6 @@ def post(self):
"""
post method to add new order to list of orders
"""
"""
auth_header = request.headers.get('Authorization')
if not auth_header:
return make_response(jsonify({
Expand All @@ -35,14 +36,14 @@ def post(self):
return make_response(jsonify({
"message" : "Invalid token type"
}), 400)
"""

try:
data = request.get_json()
item = data['item']
pickup = data['pickup']
dest = data['dest']
pricing = data['pricing']
author = data['user_id']
#author = data['user_id']
status = "pending"
current_location = "sendIT HQ"
except Exception:
Expand All @@ -55,11 +56,6 @@ def post(self):
"message" : "pricing field can only contain numbers"
}), 400)

if not author.isdigit():
return make_response(jsonify({
"message" : "user field can only contain a numeral"
}), 400)

if not check_for_space(item):
return make_response(jsonify({
"message" : "Invalid item name format"
Expand All @@ -80,14 +76,7 @@ def post(self):
"message" : "Invalid price value"
}), 400)


if not check_for_space(author):
return make_response(jsonify({
"message" : "Invalid user id"
}), 400)


res = order.create_order(item, pickup, dest, pricing, author, status, current_location)
res = order.create_order(item, pickup, dest, pricing, user_id, status, current_location)

if res == "User already ordered this item":
return make_response(jsonify({
Expand All @@ -113,6 +102,28 @@ def get(self):
"message" : "No orders in the database"
}), 400)

class IndividualParcel(Resource):
"""
class for API endpoints for retrieving single order and cancelling particular order
"""
def get(self, id):
"""
get method to retrieve order by id
"""

individ_order = order.order_list()

for parcel in individ_order:
if parcel["order_id"] == id:
return make_response(jsonify({
"message" : "Ok",
"order" : parcel
}), 200)
else:
response = {
"message" : "Invalid id"
}
return make_response(jsonify(response), 400)

class ParcelDestination(Resource):
"""
Expand Down Expand Up @@ -140,14 +151,29 @@ def put(self, id):
"message" : "Invalid token type"
}), 400)

new_destination = request.get_json()['new_destination']
individ_order = order.order_identification()

for parcel in individ_order:
if parcel["order_id"] == id:
if not parcel["user_id"] == user_id:
return make_response(jsonify({
"message" : "Sorry you cannot edit the destination of orders you did not place."
}), 400)

try:
new_destination = request.get_json()['new_destination']
except Exception:
return make_response(jsonify({
"message" : "invalid new destination key"
}), 400)


if not check_for_space(new_destination):
return make_response(jsonify({
"message" : "Invalid destination value"
}), 400)


updated_parcel = order.update_destination(new_destination, id)
if updated_parcel:
return make_response(jsonify({
Expand Down Expand Up @@ -184,7 +210,20 @@ def put(self, id):
return make_response(jsonify({
"message" : "Invalid token type"
}), 400)
order_status = request.get_json()['status']

admin = user.check_admin(user_id)

if not admin:
return make_response(jsonify({
"message" : "action only accessible to accounts with admin privileges"
}), 403)

try:
order_status = request.get_json()['status']
except Exception:
return make_response(jsonify({
"message" : "invalid status key"
}), 400)

if order_status == 'In transit' or order_status == 'Arrived':

Expand Down Expand Up @@ -228,8 +267,20 @@ def put(self, id):
return make_response(jsonify({
"message" : "Invalid token type"
}), 400)

admin = user.check_admin(user_id)

order_location = request.get_json()['current_location']
if not admin:
return make_response(jsonify({
"message" : "action only accessible to accounts with admin privileges"
}), 403)

try:
order_location = request.get_json()['current_location']
except Exception:
return make_response(jsonify({
"message" : "invalid current location key"
}), 400)

new_location = order.update_current_location(order_location, id)
if new_location:
Expand Down
55 changes: 41 additions & 14 deletions app/auth/v2/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,55 @@ class User:
"""
class to register user and generate tokens
"""
def add_user(self, email, password):
def add_user(self, email, password, role):
hashed_password = generate_password_hash(password)

user_query = """INSERT INTO users (email, password, role) VALUES (%s, %s, %s) RETURNING email, role, id"""
tup = (email, hashed_password, role)
resp = SenditDb.insert_fetch_from_db(user_query, tup)
payload = resp
return payload

def check_duplicate_email(self, email):

email_query = """SELECT * FROM users WHERE email = '{}'""".format(email)
duplicate_email = SenditDb.retrieve_all(email_query)
if duplicate_email:
return False
user_query = """INSERT INTO users (email, password) VALUES (%s, %s) RETURNING email, id"""
tup = (email, hashed_password)
resp = SenditDb.add_to_db(user_query, tup)
payload = resp
return payload
return True

def check_admin(self, user_id):
"""
method checks whether a user is an admin by id
"""
admin_query = """SELECT role FROM users WHERE id = {}""".format(user_id)
user_role = SenditDb.retrieve_all(admin_query)
if user_role[0]['role'] == 'admin':
return True

def check_role(self):
"""
method returns True if an account with admin privileges already exists in the database
"""
role_query = """SELECT role FROM users ORDER BY id ASC;"""
user_roles = SenditDb.retrieve_all(role_query)
print(user_roles)
for role in user_roles:
if role['role'] == 'admin':
return True

def get_user_by_email(self, email):
email_query = """SELECT * FROM users WHERE email = '{}'""".format(email)
response = SenditDb.retrieve_all(email_query)
if not response:
return False
return response

def get_email_by_id(self, id):
query = """SELECT email FROM users WHERE id = '{}'""".format(id)
response = SenditDb.retrieve_all(query)
if not response:
return False
return response


def validate_password(self, password, user_email):
Expand All @@ -49,13 +80,9 @@ def generate_token(self, userID):
'iat' : datetime.utcnow(),
'id' : userID
}
token = jwt.encode(
payload,
os.environ.get('SECRET_KEY'),
algorithm='HS256'
)
token = jwt.encode(payload, os.environ.get('SECRET_KEY'))
return token
except Exception as err:
return str(err)
except Exception:
return "problem with the token generation"


Loading