Skip to content

Architecture

Danny Jung edited this page May 14, 2024 · 6 revisions

Application Architecture

Front-end

Proposed Technologies

  • TypeScript
  • React using Vite
    • MUI
    • Mantine
  • Redux
    • Single source of truth
    • A place to manage states across the entire application
    • RTX query for fetching
  • Axios
    • Fetching Library
  • React Router
    • Routing Library
  • React-toastify
  • Storybook
    • Component Testing
  • Jest
    • Other testing if required

Back-end

Framework : LoopBack4

Reasoning :

  • Highly flexible and widely used
  • Command Line Interface (CLI) generators (easy and standardised generation of code)
  • Great documentation and explanations
  • Great place to get started and helpful for learning other frameworks
  • Very quick to create REST api with CRUD operationsd

Cons :

  • Does have quite a bit of boilerplate code - minimised by CLI generators
  • Contains some advanced features - E.g. DI. Auto-done by CLI generators, but other features (besides a simple CRUD REST api) such as auth may require more knowledge of how these work

Back-end Project Structure

.
├── public
│   └── index.html
├── src
│   ├── __tests__
│   │   ├── README.md
│   │   └── acceptance
│   │       ├── home-page.acceptance.ts
│   │       ├── ping-controller.acceptance.ts
│   │       └── test-helper.ts
│   ├── controllers
│   │   ├── index.ts
│   │   ├── README.md
│   │   └── ping-controller.ts
│   ├── datasources
│   │   └── README.md
│   ├── models
│   │   └── README.md
│   ├── repositories
│   │   └── README.md
│   ├── application.ts
│   ├── index.ts
│   ├── migrate.ts
│   └── sequence.ts
├── node_modules
│   └── ***
├── LICENSE
├── README.md
├── package.json
├── tsconfig.json
├── .eslintrc.js
├── .prettierrc
└── .mocharc.json

High-level Architecture :

image

Front-end Layers Responsibility
RTK Query HTTP Calls to back-end
Redux Single source of truth (State management)
React Component/Pages Contains the react components (Components, Pages and Styling)
Back-end Layers Responsibility
Controllers Handles HTTP endpoint logic
Repositories Handles CRUD operations as well as other data manipulation to be sent/received from DB
Datasource Represents DB connection source
Services Encapsulates any business logic/operations
Middleware Middleware layer with logics such as logging, authentication, authorisation, etc
DB The database server (In-memory, MongoDB, MySQL, etc)

Authentication / Authorization

For authentication/authorization, I suggest using the technologies mentioned in the LoopBack documentation. This reduces the complexity as the documentation is all provided alongside examples.

Starting point : https://loopback.io/doc/en/lb4/Authentication-overview.html

  • Authentication is a process of verifying user/entity to the system, which enables identified/validated access to the protected routes ("Who are you?")
  • Authorization is the process of deciding if a user can perform an action on a protected resource ("Knowing you, what are your rights/permissions?")

From the documentation, it is highly recommended to understand the JWT todo example. This gives an understanding of how authentication works in LoopBack.

From there, I suggest we use JS Passport for our authentication middleware. This library simplifies our authentication as we do not need to write the authentication strategies ourselves. This middleware supports hundreds of strategies.

Once we have verified the user, we need to focus on authorization. E.g. Students will have different permissions compared to sponsors. We need to define rights/privileges.

Note: There are plenty of other links in the documentation that I also suggest reading. These are only some of them, have a look around >:D

Session Management

The most common session management used in Web API's are token based session management. A common widely used token is JSON Web Tokens (JWT Tokens). If we are using Oauth Service (Google or Microsoft), these services will provide the access token. This can be implemented in the LoopBack4 framework following this tutorial :

JSON Web Tokens :

  • Carries information related to identity and claims of user
  • A claim is a piece of information about a user
  • JWT tokens are signed by the server to detect tampering frontend, preventing modifications of identity/claims
  • JWT Tokens are embedded in headers of HTTP requests
  • JWT Tokens contain three parts
    • Header: Contain JWT algorithm and type
    • Payload: Contain identity/claim information
    • Signature: Signed Hash to detect tampering

Authorization :

Login :

  • Upon successful login, a JWT token is created by the server and returned to the client
  • Using external Oauth services like Google, will return a valid access token after the Oauth process is valid and complete

Logout :

  • In most scenarios, once JWT tokens are issued, they are valid until they expire
  • To logout, we can delete the token from the client localstorage
  • If we wish to be really secure, we can create an endpoint to invalidate/revoke access tokens. External Oauth services like Google contain these endpoints. However this might be unnecessary.

Session timeout :

  • Session timeouts are important to reduce the likelihood of token hijacking where a valid access token is used on behalf of someone else
  • The timeout session will be handled by the external Oauth services

Client JWT token storage :

  • JWT tokens are usually stored in cookies/localstorage
  • The user does not need to login every time they access the webpage

User Role and Access Levels

Page Student Alumni Sponsor Administrator Public
Landing Screen X X X X X
Student Signup - - - X X
Sponsor Signup - - - X X
Alumni Signup - - - X X
Student Profile X X X X -
Sponsor Profile X X X X -
Alumni Profile X X X X -
Student Profile Board - - X X -
Job Board X X X X -
Job Ad Desc X X X X -
Admin Dashboard - - - X -

UML Sequence Diagram

image

Link to the Diagram: https://app.diagrams.net/#G12tjEdDwFJbMe2BvL6ioYJoVsw2O0voGX#%7B%22pageId%22%3A%22qUg-_qivASDQXejja_5J%22%7D

Refering to the diagram above on how the OAuth mechanism works - If email ID is not registered locally, automatically create a new user class and return it.

Problem: A new account will be missing extra information we want (PhoneNo, first/last name, etc)

Solution: The default new account will have a field initialized==false. This way front-end can detect this account has not been initialized and force a setup page.

  • Signing up via an external Social Media app
    1. Click on Login from the header menu, the user will see various buttons under Other login options
      • Facebook
      • Google
      • Twitter
    2. When the user click on any login option, the page is redirected to that social app's login page. On successful login with the social app, the View account page is loaded.
    3. If the email ID registered in the social media app does not match any email IDs registered locally, then a new user is signed up. View account page will display the external profile used to login under the linked accounts section.
    4. Click on Logout to log out of user session.

NOTE: Planned OAuth providers are Google and Microsoft


Design Patterns

A document that details the identified design patterns, their explanations and potential applicantions within the job board application.

Singleton Design Pattern

Purpose and Benefits: The Singleton pattern ensures that only one instance of a class exists and provides a global point of access to it. This is useful when exactly one object is needed to coordinate actions across the system.

Drawbacks: Singleton can hide dependencies in your code and can make unit testing challenging because they introduce a global state into an application.

Real-world Example: A print spooler, a database connection, a file system, or a logging class are examples where only a single instance of a class should exist.

Job Board Application Scenario: could use the Singleton pattern to manage a database connection. This would ensure that all database operations are using the same connection, which can improve performance and consistency.

image

Builder Design Pattern

Purpose and Benefits: The Builder pattern allows the construction of complex objects step by step. It separates the construction of an object from its representation, enabling the same construction process to create different representations of an object. This is useful when the object creation process is complex or when you want to have a more readable and maintainable way to create objects.

Drawbacks: The Builder pattern requires creating a separate Builder class for each different type of Product which increases the overall code complexity.

Real-world Example: The process of assembling a car is a good example of the Builder pattern. The same construction process can create different representations (models) of the car.

Job Board Application Scenario: Use the Builder pattern for creating complex user profiles or job listings. For example, a JobBuilder could allow setting various attributes like job title, required skills, and description progressively, ensuring that the job listing is built step-by-step in a controlled and consistent manner. This approach enhances code readability and maintainability, particularly when dealing with complex objects with numerous attributes.

image

Factory Design Pattern

Purpose and Benefits: The Factory pattern provides an interface for creating objects, but allows subclasses or implementing classes to decide which class to instantiate. It encapsulates the object creation logic within a separate factory class, providing a common interface for creating objects without exposing the instantiation logic to the client.

Drawbacks: The code can become more complicated since you need to introduce a lot of new subclasses which implement the factory method. The factory method in the base class should return some default type of product, but the subclasses are obligated to override the method and return a different type of product.

Real-world Example: A hiring agency is an example of a Factory pattern. The agency is a ‘factory’ that creates employees. The agency interviews the candidates, does all paperwork and returns a ready-to-work employee.

Job Board Application Scenario: Implement the Factory pattern to handle user account creation within the job board. Depending on the user role (Student, Alumni, Sponsor), different types of profiles with specific privileges and features can be generated. For instance, an Alumni account might have access to additional features, whereas a Student account may focus more on job listings and application functionalities.

image

Observer Design Pattern

Purpose and Benefits: The Observer pattern establishes a one-to-many dependency between objects, such that when one object changes its state, all its dependents are notified and updated automatically. This is useful in scenarios where multiple objects need to be notified about changes in another object’s state.

Drawbacks: The Observer pattern can lead to issues like the infinite loop and unexpected updates if not implemented carefully.

Real-world Example: A real-world example is an email subscription model where the Subject is the Email System and the Observers are the subscribers who get notified when a new email arrives.

Job Board Application Scenario: Employ the Observer pattern for real-time notifications within the job board. When a new job is posted by a sponsor, all subscribed members (Observers) can receive immediate updates. This pattern is also applicable in notifying users about changes in application status or updates on job postings they are interested in.

image image

Strategy Design Pattern

Purpose and Benefits: The Strategy pattern enables you to define a family of interchangeable algorithms or strategies, encapsulate each one, and make them interchangeable at runtime. It allows the algorithms to vary independently from the clients that use them.

Drawbacks: Clients must be aware of the differences between strategies to be able to select a proper one. Also, a lot of modern programming languages have functional type support that lets you implement different versions of an algorithm inside a set of anonymous functions. Therefore, you might use a function parameter instead of the whole strategy object.

Real-world Example: A real-world example is a sorting algorithm where the Context is the Sorting System and the Strategies are the different sorting algorithms (like Bubble Sort, Quick Sort, etc.) that can be used interchangeably.

Job Board Application Scenario: Use the Strategy pattern to offer different job recommendation algorithms based on user preferences. For instance, some users might prefer job recommendations based on proximity, while others might prioritise salary or company prestige. By encapsulating these algorithms within different strategy classes, the system can dynamically adjust the job recommendation logic per user preferences, enhancing personalization.

image image image

MVC (Model-View-Controller) Pattern

Purpose and Benefits: The MVC pattern separates the application logic into three interconnected components: the model (data and business logic), the view (user interface), and the controller (handles user input and updates the model and view). This promotes separation of concerns and facilitates modular development.

Drawbacks: Overuse of the MVC pattern can lead to an over-complicated structure as the application grows, since more and more classes are added to each part of the MVC triangle. It can also lead to slower performance as more dependencies are added.

Real-world Example: A real-world example is a music player application where the Model is the music files, the View is the user interface, and the Controller is the logic that handles user input and updates the model and view.

Job Board Application Scenario: Apply the MVC pattern to separate concerns within the job board. For instance, the Model handles data related to job postings and user profiles, the View presents this data through a user-friendly interface, and the Controller manages the flow of data between the server and UI, handling user inputs and system outputs. This separation facilitates easier maintenance and scalability of the application.

image image