# IT Hardware Asset Management System A full-featured web application built with **Python / Flask + MySQL**, containerised with **Docker Compose**. --- ## Features | Module | Capabilities | |---|---| | **Users** | Manual, CSV, and LDAP/AD import · search · GDPR masking | | **Assets** | Track by Serial Number + Service Tag · full history | | **Assignments** | Assign/return assets · complete audit trail | | **Paperwork** | Generate PDF documents (handover, assignment, return, custom) | | **Audit Log** | Immutable log of every create / update / delete / mask action | | **Settings** | Admin user management · LDAP config view | ### User masking (GDPR / off-boarding) When an employee leaves, press **Mask User** to permanently erase PII (name, email, phone). The record is kept — linked by the permanent **Windows ID** — so full asset history is preserved for audits, without exposing personal data. --- ## Quick Start (Docker Compose) ```bash # 1. Copy the example env file and fill in your values cp .env.example .env nano .env # 2. Build and start docker compose up -d --build # 3. Open the app http://localhost:5000 # Default credentials (change immediately in Settings!) Username: admin Password: ChangeMe123! ``` --- ## Running locally (without Docker) ```bash # 1. Create a virtual environment python -m venv venv source venv/bin/activate # Linux/macOS # venv\Scripts\activate # Windows # 2. Install dependencies pip install -r requirements.txt # 3. Configure environment cp .env.example .env # Edit .env — set MYSQL_HOST=localhost and your DB credentials # 4. Initialise the database flask db init flask db migrate -m "initial" flask db upgrade python init_db.py # 5. Run python run.py ``` --- ## Environment Variables (`.env`) | Variable | Description | Default | |---|---|---| | `SECRET_KEY` | Flask secret key | *(must change)* | | `MYSQL_HOST` | MySQL host | `db` (Docker) / `localhost` | | `MYSQL_USER` | MySQL user | `itasset_user` | | `MYSQL_PASSWORD` | MySQL password | `itasset_pass` | | `MYSQL_DB` | Database name | `itasset_db` | | `LDAP_SERVER` | LDAP server URL | *(blank = disabled)* | | `LDAP_BIND_USER` | Service account DN | — | | `LDAP_BIND_PASSWORD` | Service account password | — | | `LDAP_BASE_DN` | Search base | — | | `LDAP_WINDOWS_ID_ATTR` | AD attribute for numeric ID | `employeeID` | | `COMPANY_NAME` | Shown on PDF headers | `Your Company Name` | | `COMPANY_ADDRESS` | Shown on PDF headers | — | | `DEFAULT_ADMIN_USER` | First-run admin username | `admin` | | `DEFAULT_ADMIN_PASS` | First-run admin password | `ChangeMe123!` | --- ## CSV Import Format ```csv windows_id,first_name,last_name,email,department,job_title,location 408525,John,Doe,john.doe@company.com,IT,Engineer,HQ 408526,Jane,Smith,jane.smith@company.com,HR,Manager,HQ ``` Column names are matched case-insensitively. `windows_id` is required; all others are optional. --- ## Project Structure ``` IT_asset_management/ ├── app/ │ ├── __init__.py # App factory │ ├── extensions.py # SQLAlchemy, Flask-Login, Migrate │ ├── models/ # User, Asset, Assignment, Paperwork, AuditLog, AdminUser │ ├── routes/ # auth, dashboard, users, assets, assignments, paperwork, audit, settings │ ├── services/ # csv_service, ldap_service, pdf_service │ └── templates/ # Jinja2 + Bootstrap 5 ├── config.py ├── run.py ├── init_db.py ├── requirements.txt ├── Dockerfile ├── docker-compose.yml └── .env.example ``` --- ## Security Notes - Change `DEFAULT_ADMIN_PASS` immediately after first login. - Set a strong random `SECRET_KEY` in `.env`. - The LDAP bind password is read from the environment — never commit `.env` to source control. - PDF files are stored server-side in the `pdfs/` directory (Docker volume). Restrict access as needed. - Masked user records permanently destroy PII and cannot be reversed.