## System Overview

The INJECT Exercise Platform (IXP) is architecturally structured into two distinct components: the frontend and the backend.
This separation allows for clear delineation of roles and responsibilities, enhancing modularity and scalability within the system.

The architecture of the IXP can be visualized as follows:

``` mermaid
flowchart LR
    A(INJECT) --> B(BACKEND)
    A --> C(FRONTEND)
    C --> D(TRAINEE PANEL)
    C --> E(INSTRUCTOR PANEL)
    C --> F(ANALYTICS PANEL)
    C --> J(EXERCISE PANEL)
    B --> G(EXERCISES)
    B --> H(EXERCISE DEFINITIONS)
    B --> I(RUNNING EXERCISE)
    B --> K(AUTHENTICATION)
```

This diagram illustrates the high-level architecture of the IXP.
It is composed out of these parts:

* Frontend: The frontend component serves as the user interface of the IXP, allowing users to interact with the system.
  It includes four main parts:
    * Trainee View: This view is designed for trainees participating in tabletop exercises.
      It provides functionalities tailored to their role, such as accessing exercise scenarios, submitting responses, and general interaction with the exercise.
    * Instructor View: This view is tailored for instructors or facilitators overseeing tabletop exercises.
      It offers capabilities for monitoring trainee progress, and providing guidance during the exercise.
    * Analytics: The analytics view provides insights and analytics related to the tabletop exercises conducted on the platform.
      It includes metrics such as participation rates, completion times, and performance trends.
    * Exercise Panel: The exercise panel enables users to view and manage exercises available on the platform, including creating new exercises, editing existing ones, and organizing exercise-related resources.

* Backend: The backend component serves as the backbone of the INJECT platform, handling data management, authentication, and communication with the frontend.
  It includes several parts:
    * Exercises: This module manages the creation, modification, and storage of tabletop exercises on the platform.
    * Exercise Definitions: The exercise definitions module stores templates and definitions for different types of exercises.
      These definitions include details such as injects, emails and tools.
      It also checks and ensures that definitions are correctly configured and set up.
      For a more in-depth explanation of definitions, please refer to [definitions architecture.](definitions.md)
    * Running Exercise: This module manages the execution and runtime aspects of tabletop exercises, including tracking the progress of ongoing exercises and managing the flow of injects.
    * Authentication: Handles user authentication and authorization, ensuring secure access to the platform's functionalities.

## Used Technology

### Backend Technology

The backend component of the IXP is built using Python and Django, a high-level web development framework.
Key components of the backend architecture include:

* Python Backend: The backend of the IXP is implemented using Python.
* Django Framework: Django, the most popular web development framework for Python, is used to build the backend application.
  Django provides robust features for database management, user authentication, and more.
* GraphQL API: The backend exposes a GraphQL API for communication with the frontend.
  GraphQL allows efficient data fetching and enables the client to request only the data it needs.
* Django REST Framework: For file transfers and other functionalities not supported by GraphQL, a REST API is implemented using Django REST Framework.

### Frontend Technology

The frontend component of the IXP utilizes modern web technologies including:

* React Frontend: The frontend application of the IXP is developed using React, library for building user interfaces.
* TypeScript: TypeScript is used instead of JavaScript to ensure type safety and improve code quality.
* React Hooks: React hooks play a crucial role in modern React programming, providing essential features such as state management and performing side effects.
* Libraries and Tools: Various libraries and tools, including Yarn, Vite, Apollo Client, and Generouted, are utilized for package management, building, data management, and routing within the frontend application.

## Security overview

### Authentication

Authentication on the INJECT platform is fundamental to ensuring secure access to its features and resources.
Leveraging Django's built-in session system, the platform utilizes cookies as a means to authenticate client requests.

### Authentication Process Overview

The authentication process involves the following steps:
```mermaid
sequenceDiagram
  Client->>Server: Get backend version
  Server->>Client: Responds with backend version and SET_COOKIE
```

1. Client → Server: Get the backend version from the REST API.
  (No cookies are set yet.)
2. Client ← Server: Responds with backend version and `SET_COOKIE`
  with new `sessionid` and CSRF cookie.

In this state, the server established a session with the client.
The client did not authenticate yet, and thus the session attribute _user_ is set to _AnonymousUser_.
All further requests from the client should now contain the _sessionid_ and _csrf_ cookie together with the _X-csrftoken_ header of requests (most importantly for safe login!).
The client can now make any request to endpoints, which do not enforce authenticated requests.
On every request, the match of _csrf_ cookie and _X-csrftoken_ header is checked.
The next important step in our schema is **login**:

``` mermaid
sequenceDiagram
  Client->>Server: Sends login request on GraphQL login endpoint
  Server->>Client: Server generates new session
```

3. Client → Server: Sends a login request on the GraphQL login endpoint
  containing the username and password (and most importantly,
  the _sesisonid_ and _csrf_ cookie with _X-csrftoken_ header set to the
  value of the _csrf_ cookie to prevent cross-site request forgery).
4. Client ← Server: If the provided credentials were correct,
  the server generated a new session with attribute _user_ set
  to User model of user who successfully authenticated themselves and
  responded with `SET_COOKIE` containing the new _sessionid_ cookie
  and the new _csrf_ cookie.

The client is expected to drop the old _sessionid_ and _csrf_ cookie and replace them with the new ones.
Also, every request from now on should contain _X-csrftoken_ value of the new _csrf_ cookie.

For further information, refer to the official documentation on:

* [Django Sessions](https://docs.djangoproject.com/en/2.0/topics/http/sessions/)
* [CSRF Protection](https://docs.djangoproject.com/en/2.0/ref/csrf/)

### Basic authentication

For the purposes of more convenient development, basic authentication is also supported
according to the [RFC 2617](https://datatracker.ietf.org/doc/html/rfc2617#section-2) standard.

<!--
### Authorization

### Process of Authorization

Every endpoint resolver (in REST API and GraphQL), which allows access to data that should not be visible to everyone, should be decorated by decorators.
The INJECT authorization schema functions on the combinations of these decorators:

#### protected

  - takes as an argument permission needed for accessing the endpoint
  - Role-based access control -> checks whether the requester is assigned to a group with the required permission
  - if request is unauthenticated, it automatically denies access

```python
@protected(required_permission: str)
def resolver_function():
    pass
```
#### extra_protected
  - takes `Enum Check` value
  ```python
  class Check(str, Enum):
    TEAM_ID = "team_id"
    EXERCISE_ID = "exercise_id"
    DEFINITION_ID = "definition_id"
    LOG_ID = "log_id"
    THREAD_ID = "thread_id"
    VISIBLE_ONLY = "visible_only"
  ```
  - based on the value of the argument, checks whether the requester has access to a specific resource
  - utilizes Access-controll list
  - given argument must occur as a key-word argument of the endpoint resolver
  - works by extracting the Check keyword value and executing the relevant check function
  - if request is unauthenticated, it automatically denies access

```python
@extra_protected(check: Check)
def resolver_function(argument):
    pass
```
  - example usage:
```python
@extra_protected(Check.TEAM_ID)
def resolver_function(team_id: str):
    pass
```

#### input_object_protected
  - works on the same principle as **extra_protected** but instead of _Check enum argument, it takes the name of the input object argument.
  - internally uses the same check functions as **extra_protected**, but differs in the extraction of the needed value for the check.
```python
@input_object_protected(object_name: str)
def resolver():
    pass
```
- example usage:
```python
@input_object_protected("create_exercise_input")
def resolver_function(create_exercise_input: CreateExerciseInput):
    pass
```

The best authorization control and functionality are achieved by combining the mentioned decorators. This way, you can set up more granular and specific checks. For example:

```python
# Accessible only to the trainees assigned to the team with an ID equal to the team_id (inheritably for the instructors of the exercise, where the team with "team_id" belongs to)
@protected(Perms.view_trainee_info) # view_trainee_info is permission for the trainee role
@extra_protected(Checks.TEAM_ID)
def resolver(team_id: str):
    pass

# Accessible only to the instructors of the exercise, where the thread with "thread_id" was created
@protected(Perms.analytics_view) # analytics_view is the permission of the instructor role
@extra_protected(Check.THREAD_ID)
def resolver(thread_id):
    pass
```
-->
