from pathlib import Path import sys sys.path.append(str(Path(__file__).parent.parent.parent)) from flask import request from flask_restx import Namespace, Resource, fields from database.finance_database import FinanceDatabase from helpers.helper_functions import ( create_encrypted_string, json_success_response, json_error_response ) namespace = Namespace( 'user', description='API endpoints related to User resource' ) user_payload = namespace.model("Payload", { "name": fields.String(required=True, description="Name of the user"), "email": fields.String(required=True, description="Email of the user"), "password": fields.String( required=True, description="Password of the user" ) }) user_id_payload = namespace.model("Payload", { "password": fields.String(required=True, description='New password') }) user_password_payload = namespace.model("Payload", { "email": fields.String(required=True, description="Email of the user"), "password": fields.String( required=True, description="Password of the user" ) }) @namespace.route('') @namespace.expect(user_payload) class UserAPI(Resource): """ API for the User resource. """ def post(self): """ Insert a User into the database. Returns the user id and name if successful. Expected payload: { name: str, email: str, password: str } Expected return: { user_id: int, name: str } """ payload = request.json name = payload['name'] email = payload['email'] password = payload['password'] password_enc = create_encrypted_string(password) finance_db = FinanceDatabase() user = finance_db.insert_dashboard_user( name=name, email=email, password=password_enc ) if user is None: return json_error_response( f"ERROR: Failed to insert user '{email}' into the database." ) return json_success_response({ 'user_id':user.id, 'name': user.name }) @namespace.route('/<int:id>') class UserByIdAPI(Resource): """ API for the User resource by id. Expected return: { user_id: int, name: str } """ def get(self, id: int): """ Gets the User based on the id given. """ finance_db = FinanceDatabase() user = finance_db.get_dashboard_user(id) if user is None: return json_error_response( 'ERROR: Failed to get user.' ) return json_success_response({ 'user_id': user.id, 'name': user.name }) @namespace.expect(user_id_payload) def put(self, id: int): payload = request.json password = payload['password'] password_enc = create_encrypted_string(password) finance_db = FinanceDatabase() try: is_success = finance_db.update_user_password( user_id=id, password=password_enc ) return json_success_response() if is_success else json_error_response( 'ERROR: Failed to update password.' ) except Exception: return json_error_response( 'ERROR: Failed to update password.' ) @namespace.route('/password') class UserPasswordAPI(Resource): @namespace.expect(user_password_payload) def post(self): """ Checks if the user and password credentials are correct. If correct, return 200. If incorrect password, return 401. If email is not in the database, return 404. """ payload = request.json finance_db = FinanceDatabase() email = payload['email'] password = payload['password'] user = finance_db.get_user_by_email(email) if user is None: return json_error_response( 'ERROR: User not found.', 404 ) password_enc = create_encrypted_string(password) if finance_db.check_user(user.id, password_enc): return json_success_response() return json_error_response( 'ERROR: Invalid login credentials.', 401 )