Skip to content

Luzkan/FamilyBudget

Repository files navigation

FamilyBudget App

CHANGELOG.md Β· Frontend (React/TypeScript) Β· Backend (Django/Python)

Hey. 🐈

I didn't have any solo-dev full-stack sample app in my portfolio, so now I have. This project was done in 4 days for one of the recruitment process steps.

Full Functionality Overview (.gif)

Table of Contents


πŸš€ Quick Start

Launch bash and type in...

./scripts/one_script_wonder.sh

...website available at localhost:8000!


✨ Features

  • Implementation Technologies:
  • Implementation Design:
    • βš’οΈ Backend:
      • "Screaming" Architecture
    • πŸ–ŒοΈ Frontend:
      • Self-Checkout Hierarchy
      • Tiny Components
      • Separation of Concerns
    • πŸ—’οΈ Docs:
    • πŸ”§ Dev-Style:
      • Deadline Driven Development
        • (a pinch of time compared to how much there should be for such a project)
  • Functionalities
    • Responsiveness
    • Registration / login
    • Token Authorization
    • Users can create budgets
    • Users can manage users assigned to a given budget
    • Tests
    • Pagination
    • Filtering
    • Multi-language Support

πŸ§‘β€πŸ­ Managing Project

You can manage the project via shell scripts (that can be launched on Unix systems or w/ git bash on Windows). These scripts contain some common routines that you might be interested in.

πŸ—οΈ First-time launch:

πŸ‘¨β€πŸ”§ Developing

βš™οΈ Linter Settings

There are lots of files, I know. Tl;dr, these are three rules on frontend:

  • No Semicolons
  • No Spaces between the methods name and parenthesis
  • Double Quotes

πŸ›οΈ Database

Models/Interaction Diagram

It's quite simple to understand, refer to this pseudo-UML diagram below. It contains model, interaction, and implementation perspectives.

./docs/img/database.png


πŸ“ͺ API Communication

All the communication is handled by Services (*.service.ts), which can be found in the /frontend/src/services/ directory. Even though this project is made with React framework, this is the idea that I came across when doing some Angular projects.

These services can be used by anyone, but in this app, everything is exclusively handled by the State Creators - they are placed inside the /frontend/src/store/. More on Action Creators in the react-redux documentation.

Headers

The header of each response contains the user token if the user is logged in.

Endpoints

All endpoints start with /api/rest/.

  • /auth/login/ (post)
    • Data: {email: str, password: str}
    • Logins the user with credentials if registered
  • /auth/register/ (post)
    • Data {email: str, password: str}
    • Registers a new account with given credentials
    • Note: Password string confronts algorithm$salt$iterations$hashed_password
  • /auth/check/ (post)
    • Data {email: str}
    • Safety-check: is the user holding his own valid token?
  • /budget/ (post)
    • Data: {name: str, total_budget: int}
    • Creates a new budget
    • requires auth token
  • /budget/?searchQuery=<str>?page=<int> (get)
    • Parametrized: {searchQuery: str, page: int}
    • Gets all budgets (or budgets whose title match search query) of currently logged in user paged by index page.
    • requires auth token
  • /budget/users (post)
    • Data: {budget_id: str, users: list[{id: int, email: str}]}
    • Updates the given budget with a new user list.
    • requires auth token
  • /budget/expense (post)
    • Data: {budget_id: int, name: str, amount: int, category: str}
    • Creates a new Expense item for given budget.
    • requires auth token
  • /budget/income (post)
    • Data: {budget_id: int, name: str, amount: int, category: str}
    • Creates a new Income item for given budget.
    • requires auth token
  • /users/all/ (get)
    • Queries all users from database.
    • requires auth token

πŸ“‡ Considerations

πŸ—‚οΈ Backend Structure Design

Aka. Views vs ViewSets: inter-app backend structure design.

  • At first, I went with the ViewSets but with only a single one View inside of it - it was just for the ease of switching after making the final decision whether I would like the first or latter option.
  • I'm highly favoring architecture which screams the available use cases - it's just a good design principle.
  • After all, I've created a RequestManagers called Handlers, and those have their own separate directory inside of each Django App, that can inform about the possible use-cases from the perspective of the file hierarchy. This allows me to get the benefits of abstracting Views into ViewSets (commonized base paths or authentification/other stuff that Django gives in its features).
  • It's all debatable though, but that is just my take on that. Here's the structure explanation

File Structure Explained Design

The Django implicit way of working using the benefits of mixins and inheritance by just providing class-level attributes for serializing models and stuff is definitely solid primary solution.

πŸ—‚οΈ Frontend Structure Design

Pages

This is the directory tree hierarchy of pages:

  • landing
    • credentials-form
      • login-form
      • register-form
  • logged
    • budget-container
      • container-tabs
        • tab-searchbar
        • tab-add-budget
        • tab-item-budget
      • container-panes
        • pane-transaction
          • transaction-header
            • header-add-transaction
            • header-manage-users
          • transaction-table
      • container-pagination

As you can read, there are two pages: the landing page and logged page. The landing page contains a credential form that can be either login or register form. The logged page contains a budget-container that consists of tabs and panes. Tabs have budgets items and a search bar functionality, along with add budget functionality. The pane has transactions, which are made out of transaction header (containing add transaction functionality and manage users functionality) along with the table content.

Thus, the DOM Tree and domain implementation perspective is fully preserved.

πŸ•Œ Security

  • I would advocate to never send the password in plaintext via API, even when SSL is used. The best solution would be to generate a unique salt on the client-side, store it in the database, and then perform proper encryption before sending a request with a password. More good practices on REST API Communication here.
  • The very same issue is with the Token authorization that I've implemented - it is not safe, especially because I keep it in localStorage. I would suggest changing the implementation from the Django token (about which I don't know, much and thus I definitely don't trust the mechanism) to something that has a viable reputation like the JWT Tokens. The very best solution would be to handle authentication by 3rd party system in which they know what they are doing.
  • Currently, the passwords are encrypted via random salt and sha-256. This is not safe. Preferably use the AES or RSA. Generally, if this README.md is already "dated" compared to the time you are reading this, refer to OWASP for newest cybersecurity recommendations (password cheatsheet).

πŸ’Ό Querying

  • Lots of stuff is done on the behalves of currently logged-in users. A ready-made solution for such tasks would be great. There is a django-crum library that contains built-in tests, safe-checks, and implementation, but unfortunately is not supported for Django 4.0.

Minor

βž₯ setup.py vs. pyproject.toml

Here's a PEP-0518 with answers.

βž₯ Standardjs?

Standardjs wants single parenthesis. This ' character might be confusing with ` backtick character. For this reason, I gave up the ts-standard library.