Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
1d6eba3
[Chore #161308201] Add files for build enviroment
Arusey Oct 18, 2018
672ba04
[Chore #161308201] Add files for build enviroment
Arusey Oct 18, 2018
36edfe5
[Feature #161325459] Add test for sign up
Arusey Oct 18, 2018
c9955b2
[Feature #161325459] Add endpoint for signup
Arusey Oct 18, 2018
891d2c7
[Feature #161309671] Add failing test for login endpoint
Arusey Oct 18, 2018
360ef12
[Feature #161309671] Add login endpoint for tests to pass
Arusey Oct 18, 2018
03826a6
[Feature #161320154] Add failing test for posting product
Arusey Oct 18, 2018
c70e340
[Feature #161320154] Add post product endpoint for test to pass
Arusey Oct 18, 2018
20e178f
[Feature #161314817] Add failing tests for posting sale
Arusey Oct 18, 2018
24dae18
[Feature #161314817]Add post sale endpoint for test to pass
Arusey Oct 18, 2018
56dba7f
[Feature #161320158]Add failing test for getting all sales
Arusey Oct 18, 2018
845dcaa
[Feature #161320158]Add get sale endpoint for test to pass
Arusey Oct 18, 2018
c862d95
[Feature #161320143] Add test for getting all products
Arusey Oct 18, 2018
ec04afc
[Feature #161320143]Add get all products endpoint for test to pass
Arusey Oct 18, 2018
5800581
[Feature #161320135]Add test for getting single product
Arusey Oct 18, 2018
69c2d1c
[Feature #161320135]Add endpoint for getting single product
Arusey Oct 18, 2018
d4e28ae
[Feature #161320133]Add failing test for getting single product
Arusey Oct 18, 2018
a2d76b3
[Feature #161320133]Add endpoint for getting a single sale
Arusey Oct 18, 2018
9b3904a
[Feature 161320133]Add coveralls to requirements.txt
Arusey Oct 19, 2018
eb9ee52
[Feature #161320133] Add change to travis.yml
Arusey Oct 19, 2018
e3d5416
[Feature #161320133] Add change to travis.yml
Arusey Oct 19, 2018
1c4917f
add change to travis
Arusey Oct 19, 2018
6388d77
add change to travis
Arusey Oct 19, 2018
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
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
*.pyc
*__pycache__
/env
.coverage
.env
12 changes: 12 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
language: python
python:
- '3.6'
cache: pip
install:
- pip install -r requirements.txt
before_script:
- export SECRET_KEY='secretkey'
script:
- pytest --cov=app -v -W error::UserWarning
after_success:
- coveralls
15 changes: 15 additions & 0 deletions app/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from flask import Flask, Blueprint
from flask_restful import Api
from instance.config import app_config
from .api.v1 import myblue

def create_app(config_name):
app = Flask(__name__, instance_relative_config=True)
app.config.from_object(app_config["development"])
app.config.from_pyfile('config.py')
app.register_blueprint(myblue)

app.config["TESTING"] = True


return app
Empty file added app/api/__init__.py
Empty file.
12 changes: 12 additions & 0 deletions app/api/v1/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from flask import Flask, Blueprint
from flask_restful import Api, Resource
from .views import SignUp, Login, Product, Sale, SingleProduct, SingleSale
myblue = Blueprint("api", __name__, url_prefix="/storemanager/api/v1")

api = Api(myblue)
api.add_resource(SignUp, '/auth/signup')
api.add_resource(Login, '/auth/login')
api.add_resource(Product, '/products')
api.add_resource(Sale, '/sales')
api.add_resource(SingleProduct, '/products/<int:id>')
api.add_resource(SingleSale, '/sales/<int:saleid>')
50 changes: 50 additions & 0 deletions app/api/v1/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
users = []
products = []
sales = []

class UserAuth():
def __init__(self, name, email, password, role):
self.name = username
self.email = email
self.password = password
self.role = role

def save_user(self):
id = len(users) + 1
user = {
'id' : self.id,
'name' : self.name,
'email': self.email,
'password' : self.password,
'role' : self.role
}
users.append(user)

class PostProduct():
def __init__(self, id, name, category, desc, currstock, minstock, price):
self.id = id
self.name = name
self.category = category
self.desc = desc
self.currstock = currstock
self.minstock = minstock
self.price = price

def add_product(self):
payload = {
'id' : self.id,
'name': self.name,
'category' : self.category,
'desc': self.desc,
'currstock' : self.currstock,
'minstock' : self.minstock,
'price': self.price
}

products.append(payload)
print(products)

def collapse():
users = []
products = []
sales = []
Empty file added app/api/v1/utils.py
Empty file.
193 changes: 193 additions & 0 deletions app/api/v1/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
from flask import jsonify, make_response, request
from flask_restful import Resource
from functools import wraps
from instance.config import Config
import datetime
import jwt
import json

from .models import *

def token_required(func):
@wraps(func)
def decorated(*args, **kwargs):
token = None
if 'x-access-token' in request.headers:
token = request.headers['x-access-token']
if not token:
return make_response(jsonify({
"Message": "the access token is missing, Login"}, 401))
try:
data = jwt.decode(token, Config.SECRET_KEY)
for user in users:
if user['email'] == data['email']:
current_user = user

except:

print(Config.SECRET_KEY)
return make_response(jsonify({
"Message": "This token is invalid"
}, 403))

return func(current_user, *args, **kwargs)
return decorated

class Product(Resource):
@token_required
def post(current_user, self):
if current_user["role"] != "admin":
return make_response(jsonify({
"Message": "you have no clearance for this endpoint"}
), 403)
id = len(products) + 1
data = request.get_json()
name = data["name"]
category = data["category"]
desc = data["desc"]
currstock = data["currstock"]
minstock = data["minstock"]
price = data["price"]

prod = PostProduct(id, name, category, desc, currstock, minstock, price)
prod.add_product()
return make_response(jsonify({
"Status": "ok",
"Message": "Product posted successfully",
"Products": products
}
), 201)
def get(self):
return make_response(jsonify({
"Status": "ok",
"Message": "All products fetched successfully",
"products": products
}
), 200)

class SingleProduct(Resource):
def get(self, id):
for product in products:
if product["id"] == id:
return make_response(jsonify({
"Status": "ok",
"Message": "Product ID blah blah",
"Product": product
}
), 200)
class SingleSale(Resource):
@token_required
def get(current_user, self, saleid):
if current_user['role'] != "admin":
return make_response(jsonify({
"Message": "You cannot access this endpoint"
}
), 401)
for sale in sales:
if saleid == sale["saleid"]:
return make_response(jsonify({
"Status": "Sale found",
"Message": "Single sale retrieved",
"Sale": saleid
}
), 200)


class Sale(Resource):
def get(self):
return make_response(jsonify({
"Status": "ok",
"Message": "All products fetched successfully",
"sales": sales
}
))

@token_required
def post(current_user, self):
total = 0
data = request.get_json()
print(data)
if current_user["role"] != "attendant":
return make_response(jsonify({
"Message": "You must be an attendant to access this endpoint"
}
), 401)
id = data['id']
for product in products:
if product["currstock"] > 0:
if product["id"] == id:
sale = {
"saleid": len(sales) + 1,
"product": product
}
product["currstock"] = product["currstock"] - 1
sales.append(sale)
for sale in sales:
if product["id"] in sale.values():
total = total + int(product["price"])
return make_response(jsonify({
"Status": "ok",
"Message": "sale is successfull",
"Sales": sales,
"total cost": total
}), 201)
else:
return make_response(jsonify({
"Status": "non-existent",
"Message": "item not found"
}), 404)
else:
return make_response(jsonify({
"Status": "not found",
"Message": "items have run out"

}), 404)

class SignUp(Resource):
def post(self):
data = request.get_json()
id = len(users) + 1
name = data["name"]
email = data["email"]
password = data["password"]
role = data["role"]

user = {
"id": id,
"name": name,
"email": email,
"password": password,
"role": role
}
users.append(user)
return make_response(jsonify({
"Status": "ok",
"Message": "user successfully created",
"user": users
}
), 201)

class Login(Resource):
def post(self):
data = request.get_json()
if not data:
return make_response(jsonify({
"Message": "Ensure you have inserted your credentials"
}
), 401)
email = data["email"]
password = data["password"]

for user in users:
if email == user["email"] and password == user["password"]:
token = jwt.encode({
"email": email,
"exp": datetime.datetime.utcnow() + datetime.timedelta
(minutes=5)
}, Config.SECRET_KEY)
return make_response(jsonify({
"token": token.decode("UTF-8")}), 200)
return make_response(jsonify({
"Message": "Login failed, wrong entries"
}
), 401)
Empty file added app/tests/__init__.py
Empty file.
Empty file added app/tests/v1/__init__.py
Empty file.
Loading