Update README.md
This commit is contained in:
parent
fb72f8e86b
commit
452a44d779
153
README.md
153
README.md
@ -1,3 +1,152 @@
|
||||
# lms-backend
|
||||
# Learner Management System (LMS) Backend
|
||||
|
||||
A learner management system made by WIT students, using Rust Actix
|
||||
This is the backend service for the Learner Management System, built with Rust using the Actix Web framework. It provides a RESTful API for the frontend application, handles business logic, interacts with a MariaDB database using SQLx, and implements secure PAKE SRP authentication. The application is designed to be run using Docker and Docker Compose.
|
||||
|
||||
## Features
|
||||
|
||||
* **RESTful API:** Provides endpoints for authentication, user profiles, admin functions, and potentially course/classroom management in the future.
|
||||
* **Secure Authentication:** Implements Password-Authenticated Key Exchange (PAKE) using the Secure Remote Password (SRP-6a) protocol via the `srp` crate.
|
||||
* **High Performance:** Built with Rust and Actix Web for excellent performance, memory safety, and concurrency.
|
||||
* **Database Interaction:** Uses SQLx for asynchronous, compile-time checked SQL queries against MariaDB.
|
||||
* **Database Schema Management:** Automatically creates database tables on initial startup if they don't exist.
|
||||
* **Sample Data Population:** Populates essential data (e.g., courses, sample users without passwords) on first run.
|
||||
* **Dockerized:** Fully containerized using Docker and Docker Compose for easy setup, consistent environments, and deployment.
|
||||
* **Configuration:** Configurable via environment variables (`.env` file support).
|
||||
* **Modular Structure:** Code organized into logical modules (handlers, db, models, errors, config).
|
||||
* **Basic Logging:** Uses `env_logger` for request and application logging.
|
||||
|
||||
## Technologies Used
|
||||
|
||||
* **Rust** (Stable toolchain)
|
||||
* **Actix Web** (v4): High-performance web framework.
|
||||
* **SQLx:** Asynchronous SQL toolkit with compile-time query checking.
|
||||
* **`srp` crate:** For SRP-6a protocol implementation.
|
||||
* **MariaDB:** Relational database (run via Docker).
|
||||
* **Docker & Docker Compose:** For containerization and orchestration.
|
||||
* **`serde`:** For data serialization/deserialization (JSON).
|
||||
* **`dotenv`:** For loading environment variables from `.env` files.
|
||||
* **`env_logger`:** For flexible logging configuration.
|
||||
* **`chrono`:** For date/time handling.
|
||||
* **`hex`:** For encoding/decoding SRP values.
|
||||
* **`uuid`:** For generating session tokens (current implementation).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* **Docker**
|
||||
* **Docker Compose** (v1 or v2 syntax compatible with the `docker-compose.yml`)
|
||||
* **Rust Toolchain** (Stable - only needed if building/running outside the provided Docker setup)
|
||||
|
||||
## Getting Started
|
||||
|
||||
1. **Clone the Repository:** Clone the repository containing *both* the `lms-backend` folder and the main `docker-compose.yml`.
|
||||
```bash
|
||||
git clone <your-main-repository-url>
|
||||
cd <your-main-repository-directory> # Should contain lms-backend/ and docker-compose.yml
|
||||
```
|
||||
|
||||
2. **Create Environment File:** In the **root directory** (the one containing `docker-compose.yml`), create a `.env` file to specify database credentials. You can copy the example below or rely on the defaults defined in `docker-compose.yml`.
|
||||
```dotenv
|
||||
# .env (in the root directory)
|
||||
|
||||
# MariaDB Credentials (used by docker-compose to init the DB)
|
||||
MARIADB_ROOT_PASSWORD=supersecretroot
|
||||
MARIADB_DATABASE=lms_db
|
||||
MARIADB_USER=lms_user
|
||||
MARIADB_PASSWORD=lms_password
|
||||
|
||||
# Backend Configuration (can override defaults)
|
||||
# SERVER_ADDR=0.0.0.0:8080 # Already set in compose file
|
||||
RUST_LOG=info,lms_backend=debug # Example: Set backend log level to debug
|
||||
# SECRET_KEY=your_secret_for_jwt_if_used # Needed if switching to JWT sessions
|
||||
```
|
||||
|
||||
3. **Build and Run using Docker Compose:** From the **root directory**, run:
|
||||
```bash
|
||||
docker-compose up --build -d
|
||||
```
|
||||
* `--build`: Forces rebuilding the backend image if code has changed.
|
||||
* `-d`: Runs the containers in detached mode (in the background).
|
||||
* The first run might take some time to download images and build the Rust application.
|
||||
|
||||
4. **Accessing the API:**
|
||||
* The API should now be running and accessible at `http://localhost:8080`.
|
||||
* Test the health check endpoint: `http://localhost:8080/api/health`. You should receive a JSON response indicating success.
|
||||
|
||||
5. **Stopping the Services:**
|
||||
```bash
|
||||
docker-compose down
|
||||
```
|
||||
|
||||
## Project Structure (`lms-backend/src/`)
|
||||
|
||||
```
|
||||
src/
|
||||
├── main.rs # Entry point, server setup, middleware, routing
|
||||
├── config.rs # Configuration loading (.env)
|
||||
├── db.rs # Database logic (SQLx queries, migrations/setup, data population)
|
||||
├── handlers.rs # Actix route handlers, business logic, API endpoint definitions
|
||||
├── models.rs # Data structures (DB models, API request/response structs)
|
||||
└── errors.rs # Custom error types and `ResponseError` implementation
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Configuration is primarily handled via environment variables, loaded using the `dotenv` crate during startup within the container. Key variables:
|
||||
|
||||
* `DATABASE_URL`: The connection string for MariaDB (automatically constructed in `docker-compose.yml`).
|
||||
* `SERVER_ADDR`: The address and port the Actix server binds to (e.g., `0.0.0.0:8080`).
|
||||
* `RUST_LOG`: Controls logging verbosity (e.g., `info`, `debug`, `actix_web=warn,lms_backend=debug`).
|
||||
* `SECRET_KEY`: **Required** if implementing JWT-based sessions in the future.
|
||||
|
||||
These variables are typically passed from the host's `.env` file (if present) or directly set in the `environment` section of the `backend` service in `docker-compose.yml`.
|
||||
|
||||
## API Endpoints
|
||||
|
||||
The following main API endpoints are implemented in `src/handlers.rs`:
|
||||
|
||||
* `GET /api/health`: Health check.
|
||||
* `POST /api/auth/srp/start`: Initiates SRP login (provides salt, server ephemeral).
|
||||
* `POST /api/auth/srp/verify`: Verifies client SRP proof, generates session token on success.
|
||||
* `POST /api/auth/logout`: (Basic) Invalidates session token.
|
||||
* `GET /api/profile/{user_id}`: Retrieves user profile information.
|
||||
* `PUT /api/profile/settings`: Updates user settings (e.g., profile picture).
|
||||
* `GET /api/admin/dashboard`: Gets admin dashboard counts.
|
||||
* `GET /api/admin/students`: Lists students (basic).
|
||||
* `GET /api/admin/students/{student_id}/financials`: Gets (mocked) financial data for a student.
|
||||
|
||||
Refer to `src/handlers.rs` and `src/models.rs` for detailed request/response structures.
|
||||
|
||||
## Database
|
||||
|
||||
* **Type:** MariaDB (run via `mariadb:10.11` Docker image).
|
||||
* **Interaction:** Asynchronous queries via `sqlx`.
|
||||
* **Schema:** Defined and created in `src/db.rs::init_db`. Tables include `students`, `teachers`, `courses`, `enrollments`. SRP salt and verifier fields replace traditional password hashes.
|
||||
* **Persistence:** Database data is persisted using a Docker named volume (`mariadb_data`) defined in `docker-compose.yml`.
|
||||
* **Initial Data:** `src/db.rs::populate_initial_data` adds sample courses and users (students/teachers) **without any password/SRP data set**. Users cannot log in until a password-setting mechanism is implemented.
|
||||
|
||||
## Authentication (SRP)
|
||||
|
||||
* Uses the PAKE SRP-6a protocol.
|
||||
* **Flow:**
|
||||
1. Client sends `userId` to `/api/auth/srp/start`.
|
||||
2. Server looks up user (student or teacher), finds SRP `salt` and `verifier` (if set), generates server ephemeral `B`, and stores temporary challenge state (**in memory**). Responds with `salt`, `B`, and `userType`.
|
||||
3. Client calculates its ephemeral `A` and proof `M1`, sends `userId`, `userType`, `A`, `M1` to `/api/auth/srp/verify`.
|
||||
4. Server retrieves challenge state, verifies `M1`. If valid, calculates server proof `M2`, generates a session token (UUID), stores session (**in memory**), and responds with `M2` and login data (including token).
|
||||
5. Client verifies `M2`.
|
||||
|
||||
## Important Notes & TODOs
|
||||
|
||||
* 🚨 **Production State Management:** The current use of `AppState` (in-memory `Mutex<HashMap>`) for storing active SRP challenges and user sessions is **NOT suitable for production**. It will lose state on restart and doesn't scale. **Replace this** with a persistent solution like Redis or a dedicated database table for sessions and potentially challenges (with TTL).
|
||||
* 🔐 **Authentication Middleware:** Protected routes (`/profile/*`, `/admin/*`, etc.) currently **lack proper token validation middleware**. Implement Actix middleware to verify the `Authorization: Bearer <token>` header against the active session store before allowing access.
|
||||
* 🔑 **Password Setting/Registration:** There is currently **no mechanism** for users to set their initial password or change it. An endpoint needs to be created that takes a username/password, generates the SRP salt and verifier using `srp::server::generate_verifier`, and stores them in the database for the corresponding user.
|
||||
* 🧪 **Testing:** Implement comprehensive unit and integration tests for handlers, database logic, and authentication flow.
|
||||
* 📈 **Scalability:** Consider connection pool tuning (`max_connections` in `main.rs`) and potential optimizations for high-load scenarios.
|
||||
* 📚 **API Documentation:** Consider generating API documentation (e.g., using OpenAPI specs).
|
||||
|
||||
## Contributing
|
||||
|
||||
<!-- Optional: Link to Contribution Guidelines if applicable -->
|
||||
|
||||
## License
|
||||
|
||||
<!-- Optional: Link to License file if applicable -->
|
||||
Loading…
x
Reference in New Issue
Block a user