Skip to content
This repository has been archived by the owner on Jan 24, 2024. It is now read-only.

Commit

Permalink
feat: Multiple households (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
TomBursch authored Apr 5, 2023
1 parent 932929d commit 8928136
Show file tree
Hide file tree
Showing 56 changed files with 1,247 additions and 562 deletions.
44 changes: 28 additions & 16 deletions app/api/register_controller.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
from flask import Blueprint
from app.config import app
import app.controller as api

# Register Endpoints
app.register_blueprint(
api.health, url_prefix='/api/health/8M4F88S8ooi4sMbLBfkkV7ctWwgibW6V')
app.register_blueprint(api.auth, url_prefix='/api/auth')
app.register_blueprint(api.category, url_prefix='/api/category')
app.register_blueprint(api.expense, url_prefix='/api/expense')
app.register_blueprint(api.export, url_prefix='/api/export')
app.register_blueprint(api.importBP, url_prefix='/api/import')
app.register_blueprint(api.item, url_prefix='/api/item')
app.register_blueprint(api.onboarding, url_prefix='/api/onboarding')
app.register_blueprint(api.planner, url_prefix='/api/planner')
app.register_blueprint(api.recipe, url_prefix='/api/recipe')
app.register_blueprint(api.settings, url_prefix='/api/settings')
app.register_blueprint(api.shoppinglist, url_prefix='/api/shoppinglist')
app.register_blueprint(api.tag, url_prefix='/api/tag')
app.register_blueprint(api.user, url_prefix='/api/user')
app.register_blueprint(api.upload, url_prefix='/api/upload')
apiv1 = Blueprint('api', __name__)

api.household.register_blueprint(api.export, url_prefix='/<int:household_id>/export')
api.household.register_blueprint(api.importBP, url_prefix='/<int:household_id>/import')
api.household.register_blueprint(api.categoryHousehold, url_prefix='/<int:household_id>/category')
api.household.register_blueprint(api.plannerHousehold, url_prefix='/<int:household_id>/planner')
api.household.register_blueprint(api.expenseHousehold, url_prefix='/<int:household_id>/expense')
api.household.register_blueprint(api.itemHousehold, url_prefix='/<int:household_id>/item')
api.household.register_blueprint(api.recipeHousehold, url_prefix='/<int:household_id>/recipe')
api.household.register_blueprint(api.shoppinglistHousehold, url_prefix='/<int:household_id>/shoppinglist')
api.household.register_blueprint(api.tagHousehold, url_prefix='/<int:household_id>/tag')

apiv1.register_blueprint(api.health, url_prefix='/health/8M4F88S8ooi4sMbLBfkkV7ctWwgibW6V')
apiv1.register_blueprint(api.auth, url_prefix='/auth')
apiv1.register_blueprint(api.household, url_prefix='/household')
apiv1.register_blueprint(api.category, url_prefix='/category')
apiv1.register_blueprint(api.expense, url_prefix='/expense')
apiv1.register_blueprint(api.item, url_prefix='/item')
apiv1.register_blueprint(api.onboarding, url_prefix='/onboarding')
apiv1.register_blueprint(api.recipe, url_prefix='/recipe')
apiv1.register_blueprint(api.settings, url_prefix='/settings')
apiv1.register_blueprint(api.shoppinglist, url_prefix='/shoppinglist')
apiv1.register_blueprint(api.tag, url_prefix='/tag')
apiv1.register_blueprint(api.user, url_prefix='/user')
apiv1.register_blueprint(api.upload, url_prefix='/upload')

app.register_blueprint(apiv1, url_prefix='/api')
1 change: 1 addition & 0 deletions app/controller/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@
from .expense import *
from .tag import *
from .upload import *
from .household import *
from .category import *
from .health_controller import health
25 changes: 7 additions & 18 deletions app/controller/auth/auth_controller.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from datetime import datetime
from app.helpers import validate_args
from flask import jsonify, Blueprint, request
from flask_jwt_extended import jwt_required, get_jwt_identity, get_jwt
from flask_jwt_extended import current_user, jwt_required, get_jwt
from app.models import User, Token
from app.errors import UnauthorizedRequest
from .schemas import Login, CreateLongLivedToken
Expand All @@ -26,7 +26,7 @@ def check_if_token_revoked(jwt_header, jwt_payload: dict) -> bool:
# identity when creating JWTs and converts it to a JSON serializable format.
@jwt.user_identity_loader
def user_identity_lookup(user: User):
return user.username
return user.id


# Register a callback function that loads a user from your database whenever
Expand All @@ -36,7 +36,7 @@ def user_identity_lookup(user: User):
@jwt.user_lookup_loader
def user_lookup_callback(_jwt_header, jwt_data) -> User:
identity = jwt_data["sub"]
return User.find_by_username(identity)
return User.find_by_id(identity)


@auth.route('', methods=['POST'])
Expand All @@ -62,22 +62,11 @@ def login(args):
'refresh_token': refreshToken
})

# Not in use as we are using the refresh token pattern
# @auth.route('/fresh-login', methods=['POST'])
# @validate_args(Login)
# def fresh_login(args):
# username = args['username'].lower()
# user = User.find_by_username(username.lower())
# if not user or not user.check_password(args['password']):
# raise UnauthorizedRequest(message='Unauthorized')
# ret = {'access_token': create_access_token(identity=username, fresh=True)}
# return jsonify(ret), 200


@auth.route('/refresh', methods=['GET'])
@jwt_required(refresh=True)
def refresh():
user = User.find_by_username(get_jwt_identity())
user = current_user
if not user:
raise UnauthorizedRequest(
message='Unauthorized: IP {} refresh attemp with wrong username or password'.format(request.remote_addr))
Expand Down Expand Up @@ -117,7 +106,7 @@ def logout():
@jwt_required()
@validate_args(CreateLongLivedToken)
def createLongLivedToken(args):
user = User.find_by_username(get_jwt_identity())
user = current_user
if not user:
raise UnauthorizedRequest(
message='Unauthorized: IP {}'.format(request.remote_addr))
Expand All @@ -129,10 +118,10 @@ def createLongLivedToken(args):
})


@auth.route('llt/<id>', methods=['DELETE'])
@auth.route('llt/<int:id>', methods=['DELETE'])
@jwt_required()
def deleteLongLivedToken(id):
user = User.find_by_username(get_jwt_identity())
user = current_user
if not user:
raise UnauthorizedRequest(
message='Unauthorized: IP {}'.format(request.remote_addr))
Expand Down
2 changes: 1 addition & 1 deletion app/controller/category/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from .category_controller import category
from .category_controller import category, categoryHousehold
38 changes: 25 additions & 13 deletions app/controller/category/category_controller.py
Original file line number Diff line number Diff line change
@@ -1,45 +1,51 @@
from app.helpers import validate_args
from app.helpers import validate_args, authorize_household
from flask import jsonify, Blueprint
from app.errors import NotFoundRequest
from flask_jwt_extended import jwt_required
from app.models import Category
from .schemas import AddCategory, DeleteCategory, UpdateCategory

category = Blueprint('category', __name__)
categoryHousehold = Blueprint('category', __name__)


@category.route('', methods=['GET'])
@categoryHousehold.route('', methods=['GET'])
@jwt_required()
def getAllCategories():
return jsonify([e.obj_to_dict() for e in Category.all_by_ordering()])
@authorize_household()
def getAllCategories(household_id):
return jsonify([e.obj_to_dict() for e in Category.all_by_ordering(household_id)])


@category.route('/<id>', methods=['GET'])
@category.route('/<int:id>', methods=['GET'])
@jwt_required()
def getCategory(id):
category = Category.find_by_id(id)
if not category:
raise NotFoundRequest()
category.checkAuthorized()
return jsonify(category.obj_to_dict())


@category.route('', methods=['POST'])
@categoryHousehold.route('', methods=['POST'])
@jwt_required()
@authorize_household()
@validate_args(AddCategory)
def addCategory(args):
def addCategory(args, household_id):
category = Category()
category.name = args['name']
category.household_id = household_id
category.save()
return jsonify(category.obj_to_dict())


@category.route('/<id>', methods=['POST'])
@category.route('/<int:id>', methods=['POST', 'PATCH'])
@jwt_required()
@validate_args(UpdateCategory)
def updateCategory(args, id):
category = Category.find_by_id(id)
if not category:
raise NotFoundRequest()
category.checkAuthorized()

if 'name' in args:
category.name = args['name']
Expand All @@ -49,19 +55,25 @@ def updateCategory(args, id):
return jsonify(category.obj_to_dict())


@category.route('/<id>', methods=['DELETE'])
@category.route('/<int:id>', methods=['DELETE'])
@jwt_required()
def deleteCategoryById(id):
Category.delete_by_id(id)
category = Category.find_by_id(id)
if not category:
raise NotFoundRequest()
category.checkAuthorized()

category.delete()
return jsonify({'msg': 'DONE'})


@category.route('', methods=['DELETE'])
@categoryHousehold.route('', methods=['DELETE'])
@jwt_required()
@authorize_household()
@validate_args(DeleteCategory)
def deleteExpenseCategoryById(args):
def deleteCategoryByName(args, household_id):
if "name" in args:
category = Category.find_by_name(args['name'])
category = Category.find_by_name(args['name'], household_id)
if category:
category.delete()
return jsonify({'msg': 'DONE'})
Expand Down
2 changes: 1 addition & 1 deletion app/controller/expense/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from .expense_controller import expense
from .expense_controller import expense, expenseHousehold
Loading

0 comments on commit 8928136

Please sign in to comment.