new awesome build

This commit is contained in:
Антон
2026-01-28 22:37:47 +03:00
parent 848646003c
commit fcb8f6bac7
119 changed files with 7291 additions and 5575 deletions

View File

@@ -0,0 +1,85 @@
# Implementation Plan - Authentication & Security
## Goal Description
Add secure authentication to the OpenVPN Monitor application.
This includes:
- **Database Storage**: Store users and credentials in the existing SQLite database.
- **2FA**: Support Google Authenticator (TOTP) for two-factor authentication.
- **Brute-force Protection**: Rate limiting on login attempts.
- **Universal Access Control**: Secure all UI routes and API endpoints.
## User Review Required
> [!IMPORTANT]
> **Default Credentials**: We will create a default admin user (e.g., `admin` / `password`) on first run if no users exist. The user MUST change this immediately.
> [!WARNING]
> **Breaking Change**: Access to the current dashboard will be blocked until the user logs in.
## Proposed Changes
### Backend (Python/Flask)
#### [MODIFY] [requirements.txt](file:///Users/tstark/Documents/ovpmon_simple_gitea/APP_CORE/requirements.txt)
- Add `pyjwt`, `pyotp`, `qrcode`, `bcrypt`, `flask-bcrypt` (or `werkzeug.security`).
#### [MODIFY] [db.py](file:///Users/tstark/Documents/ovpmon_simple_gitea/APP_CORE/db.py)
- Update `init_database` to create:
- `users` table: `id`, `username`, `password_hash`, `totp_secret`, `is_2fa_enabled`.
- `login_attempts` table (for brute-force protection): `ip_address`, `attempts`, `last_attempt`.
#### [MODIFY] [openvpn_api_v3.py](file:///Users/tstark/Documents/ovpmon_simple_gitea/APP_CORE/openvpn_api_v3.py)
- **New Imports**: `jwt`, `pyotp`, `functools.wraps`.
- **Helper Functions**:
- `check_rate_limit(ip)`: Verify login attempts.
- `token_required(f)`: Decorator to check `Authorization` header.
- **New Routes**:
- `POST /api/auth/login`: Validate user/pass. Returns JWT (or 2FA required status).
- `POST /api/auth/verify-2fa`: Validate TOTP. Returns access JWT.
- `POST /api/auth/setup-2fa`: Generate secret & QR code.
- `POST /api/auth/enable-2fa`: Confirm and save secret.
- **Protect Routes**: Apply `@token_required` to all existing API routes (except auth).
### Frontend (Vue.js)
#### [NEW] [Login.vue](file:///Users/tstark/Documents/ovpmon_simple_gitea/APP_UI/src/views/Login.vue)
- Login form (Username/Password).
- 2FA Input (conditional, appears if server responses "2FA required").
#### [NEW] [Setup2FA.vue](file:///Users/tstark/Documents/ovpmon_simple_gitea/APP_UI/src/views/Setup2FA.vue)
- Screen to show QR code and verify OTP to enable 2FA for the first time.
#### [MODIFY] [router/index.js](file:///Users/tstark/Documents/ovpmon_simple_gitea/APP_UI/src/router/index.js)
- Add `/login` route.
- Add global `beforeEach` guard:
- Check if route `requiresAuth`.
- Check if token exists in `localStorage`.
- Redirect to `/login` if unauthorized.
#### [MODIFY] [App.vue](file:///Users/tstark/Documents/ovpmon_simple_gitea/APP_UI/src/App.vue)
- Add `Logout` button to the sidebar.
- Conditionally render Sidebar only if logged in (optional, or just redirect).
#### [MODIFY] [main.js](file:///Users/tstark/Documents/ovpmon_simple_gitea/APP_UI/src/main.js)
- Setup `axios` interceptors:
- **Request**: Add `Authorization: Bearer <token>`.
- **Response**: On `401 Unauthorized`, clear token and redirect to `/login`.
## Verification Plan
### Automated Tests
Since this project does not have a comprehensive test suite, we will verify manually and with targeted scripts.
### Manual Verification
1. **Initial Setup**:
- Start backend and frontend.
- Visit root URL -> Should redirect to `/login`.
2. **Login Flow**:
- Attempt login with wrong password -> Should show error.
- Attempt brute force (5x wrong) -> Should block for X minutes.
- Login with `admin` / `password` -> Should succeed.
3. **2FA Setup**:
- Go to 2FA Setup page (or trigger via API).
- Scan QR code with Google Auth.
- enter code -> Success.
- Logout and Login again -> Should ask for 2FA code.
4. **API Security**:
- Try `curl http://localhost:5000/api/v1/stats` without header -> Should return 401.
- Try with header -> Should return 200.