diff --git a/README.md b/README.md index 0ad3c7f..68a0d88 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,152 @@ -# lms-backend +# Learner Management System (LMS) Backend -A learner management system made by WIT students, using Rust Actix \ No newline at end of file +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 + cd # 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`) 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 ` 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 + + + +## License + + \ No newline at end of file