backup
This commit is contained in:
@@ -3,193 +3,3 @@
|
||||
This document catalogues architecture violations, code smells, and structural issues found during a full project review. Issues are grouped by category and prioritised.
|
||||
|
||||
---
|
||||
|
||||
## 1. Service-to-Service Coupling (Backend)
|
||||
|
||||
The architecture mandates that dependencies flow **routers → services → repositories**, yet **15 service-to-service imports** exist, with 7 using lazy imports to work around circular dependencies.
|
||||
|
||||
| Source Service | Imports From | Line | Mechanism |
|
||||
|---|---|---|---|
|
||||
| `history_service` | `ban_service` | L29 | Direct import of 3 **private** functions: `_get_fail2ban_db_path`, `_parse_data_json`, `_ts_to_iso` |
|
||||
| `auth_service` | `setup_service` | L23 | Top-level import |
|
||||
| `config_service` | `setup_service` | L47 | Top-level import |
|
||||
| `config_service` | `health_service` | L891 | Lazy import inside function |
|
||||
| `config_file_service` | `jail_service` | L57–58 | Top-level import + re-export of `JailNotFoundError` |
|
||||
| `blocklist_service` | `jail_service` | L299 | Lazy import |
|
||||
| `blocklist_service` | `geo_service` | L343 | Lazy import |
|
||||
| `jail_service` | `geo_service` | L860, L1047 | Lazy import (2 sites) |
|
||||
| `ban_service` | `geo_service` | L251, L392 | Lazy import (2 sites) |
|
||||
| `history_service` | `geo_service` | L19 | TYPE_CHECKING import |
|
||||
|
||||
**Impact**: Circular dependency risk; lazy imports hide coupling; private function imports create fragile links between services.
|
||||
|
||||
**Recommendation**:
|
||||
- Extract `_get_fail2ban_db_path()`, `_parse_data_json()`, `_ts_to_iso()` from `ban_service` to `app/utils/fail2ban_db_utils.py` (shared utility).
|
||||
- Pass geo-enrichment as a callback parameter instead of each service importing `geo_service` directly. The router or dependency layer should wire this.
|
||||
- Where services depend on another service's domain exceptions (e.g., `JailNotFoundError`), move exceptions to `app/models/` or a shared `app/exceptions.py`.
|
||||
|
||||
---
|
||||
|
||||
## 2. God Modules (Backend)
|
||||
|
||||
Several service files far exceed a reasonable size for a single-domain module:
|
||||
|
||||
| File | Lines | Functions | Issue |
|
||||
|---|---|---|---|
|
||||
| `config_file_service.py` | **3105** | **73** | Handles jails, filters, and actions — three distinct domains crammed into one file |
|
||||
| `jail_service.py` | **1382** | **34** | Manages jail listing, status, controls, banned-IP queries, and geo enrichment |
|
||||
| `config_service.py` | **921** | ~20 | Socket-based config, log preview, regex testing, and service status |
|
||||
| `file_config_service.py` | **1011** | ~20 | Raw file I/O for jails, filters, and actions |
|
||||
|
||||
**Recommendation**:
|
||||
- Split `config_file_service.py` into `filter_config_service.py`, `action_config_service.py`, and a slimmed-down `jail_config_service.py`.
|
||||
- Extract log-preview / regex-test functionality from `config_service.py` into a dedicated `log_service.py`.
|
||||
|
||||
---
|
||||
|
||||
## 3. Confusing Config Service Naming (Backend)
|
||||
|
||||
Three services with overlapping names handle different aspects of configuration, causing developer confusion:
|
||||
|
||||
| Current Name | Purpose |
|
||||
|---|---|
|
||||
| `config_service` | Read/write via the fail2ban **socket** |
|
||||
| `config_file_service` | Parse/activate/deactivate jails from **files on disk** |
|
||||
| `file_config_service` | **Raw file I/O** for jail/filter/action `.conf` files |
|
||||
|
||||
`config_file_service` vs `file_config_service` differ only by word order, making it easy to import the wrong one.
|
||||
|
||||
**Recommendation**: Rename for clarity:
|
||||
- `config_service` → keep (socket-based)
|
||||
- `config_file_service` → `jail_activation_service` (its main job is activating/deactivating jails)
|
||||
- `file_config_service` → `raw_config_io_service` or merge into `config_file_service`
|
||||
|
||||
---
|
||||
|
||||
## 4. Architecture Doc Drift
|
||||
|
||||
The architecture doc does not fully reflect the current codebase:
|
||||
|
||||
| Category | In Architecture Doc | Actually Exists | Notes |
|
||||
|---|---|---|---|
|
||||
| Repositories | 4 listed | **6 files** | `fail2ban_db_repo.py` and `geo_cache_repo.py` are missing from the doc |
|
||||
| Utils | 4 listed | **8 files** | `conffile_parser.py`, `config_parser.py`, `config_writer.py`, `jail_config.py` are undocumented |
|
||||
| Tasks | 3 listed | **4 files** | `geo_re_resolve.py` is missing from the doc |
|
||||
| Services | `conffile_parser` listed as a service | Actually in `app/utils/` | Doc says "Services" but the file is in `utils/` |
|
||||
| Routers | `file_config.py` not listed | Exists | Missing from router table |
|
||||
|
||||
**Recommendation**: Update the Architecture doc to reflect the actual file inventory.
|
||||
|
||||
---
|
||||
|
||||
## 5. Shared Private Functions Cross Service Boundary (Backend)
|
||||
|
||||
`history_service.py` imports three **underscore-prefixed** ("private") functions from `ban_service.py`:
|
||||
|
||||
```python
|
||||
from app.services.ban_service import _get_fail2ban_db_path, _parse_data_json, _ts_to_iso
|
||||
```
|
||||
|
||||
These are implementation details of `ban_service` that should not be consumed externally. Their `_` prefix signals they are not part of the public API.
|
||||
|
||||
**Recommendation**: Move these to `app/utils/fail2ban_db_utils.py` as public functions and import from there in both services.
|
||||
|
||||
---
|
||||
|
||||
## 6. Missing Error Boundaries (Frontend)
|
||||
|
||||
No React Error Boundary component exists anywhere in the frontend. A single unhandled exception in any component will crash the entire application with a white screen.
|
||||
|
||||
**Recommendation**: Add an `<ErrorBoundary>` wrapper in `MainLayout.tsx` or `App.tsx` with a fallback UI that shows the error and offers a retry/reload.
|
||||
|
||||
---
|
||||
|
||||
## 7. Duplicated Formatting Functions (Frontend)
|
||||
|
||||
Several formatting functions are independently defined in multiple files instead of being shared:
|
||||
|
||||
| Function | Defined In | Also In |
|
||||
|---|---|---|
|
||||
| `formatTimestamp()` | `BanTable.tsx` (L103) | — (but `fmtTime()` in `BannedIpsSection.tsx` does the same thing) |
|
||||
| `fmtSeconds()` | `JailDetailPage.tsx` (L152) | `JailsPage.tsx` (L147) — identical |
|
||||
| `fmtTime()` | `BannedIpsSection.tsx` (L139) | — |
|
||||
|
||||
**Recommendation**: Consolidate into `src/utils/formatDate.ts` and import from there.
|
||||
|
||||
---
|
||||
|
||||
## 8. Duplicated Hook Logic (Frontend)
|
||||
|
||||
Three hooks follow an identical fetch-then-save pattern with near-identical code:
|
||||
|
||||
| Hook | Lines | Pattern |
|
||||
|---|---|---|
|
||||
| `useFilterConfig.ts` | 91 | Load item → expose save → handle abort |
|
||||
| `useActionConfig.ts` | 89 | Load item → expose save → handle abort |
|
||||
| `useJailFileConfig.ts` | 76 | Load item → expose save → handle abort |
|
||||
|
||||
**Recommendation**: Create a generic `useConfigItem<T>()` hook that takes `fetchFn` and `saveFn` parameters and eliminates the triplication.
|
||||
|
||||
---
|
||||
|
||||
## 9. Inconsistent Error Handling in Hooks (Frontend)
|
||||
|
||||
Hooks handle errors differently:
|
||||
|
||||
- Some filter out `AbortError` (e.g., `useHistory`, `useMapData`)
|
||||
- Others catch all errors indiscriminately (e.g., `useBans`, `useBlocklist`)
|
||||
|
||||
This means some hooks surface spurious "request aborted" errors to the UI while others don't.
|
||||
|
||||
**Recommendation**: Standardise a shared error-catching pattern, e.g. a `handleFetchError(err, setError)` utility that always filters `AbortError`.
|
||||
|
||||
---
|
||||
|
||||
## 10. No Global Request State / Caching (Frontend)
|
||||
|
||||
Each hook manages its own loading/error/data state independently. There is:
|
||||
- No request deduplication (two components fetching the same data trigger two requests)
|
||||
- No stale-while-revalidate caching
|
||||
- No automatic background refetching
|
||||
|
||||
**Recommendation**: Consider adopting React Query (TanStack Query) or SWR for data-fetching hooks. This would eliminate boilerplate in every hook (abort handling, loading state, error state, caching) and provide automatic deduplication.
|
||||
|
||||
---
|
||||
|
||||
## 11. Large Frontend Components
|
||||
|
||||
| Component | Lines | Issue |
|
||||
|---|---|---|
|
||||
| `BlocklistsPage.tsx` | 968 | Page does a lot: source list, add/edit dialogs, import log, schedule config |
|
||||
| `JailsTab.tsx` | 939 | Combines jail list, config editing, raw config, validation, activate/deactivate |
|
||||
| `JailsPage.tsx` | 691 | Mixes jail table, detail drawer, ban/unban forms |
|
||||
| `JailDetailPage.tsx` | 663 | Full detail view with multiple sections |
|
||||
|
||||
**Recommendation**: Extract sub-sections into focused child components. For example, `JailsTab.tsx` could delegate to `<JailConfigEditor>`, `<JailValidation>`, and `<JailActivateDialog>`.
|
||||
|
||||
---
|
||||
|
||||
## 12. Duplicated Section Styles (Frontend)
|
||||
|
||||
The same card/section styling pattern (`backgroundColor`, `borderRadius`, `border`, `padding` using Fluent UI tokens) is repeated across 13+ files. Each page recreates it in its own `makeStyles` block.
|
||||
|
||||
**Recommendation**: Define a shared `useCardStyles()` or export a `sectionStyle` in `src/theme/commonStyles.ts` and import it.
|
||||
|
||||
---
|
||||
|
||||
## Summary by Priority
|
||||
|
||||
| Priority | Issue | Section |
|
||||
|---|---|---|
|
||||
| **High** | Service-to-service coupling / circular deps | §1 |
|
||||
| **High** | God module `config_file_service.py` (3105 lines, 73 functions) | §2 |
|
||||
| **High** | Shared private function imports across services | §5 |
|
||||
| **Medium** | Confusing config service naming | §3 |
|
||||
| **Medium** | Architecture doc drift | §4 |
|
||||
| **Medium** | Missing error boundaries (frontend) | §6 |
|
||||
| **Medium** | No global request state / caching (frontend) | §10 |
|
||||
| **Low** | Duplicated formatting functions (frontend) | §7 |
|
||||
| **Low** | Duplicated hook logic (frontend) | §8 |
|
||||
| **Low** | Inconsistent error handling in hooks (frontend) | §9 |
|
||||
| **Low** | Large frontend components | §11 |
|
||||
| **Low** | Duplicated section styles (frontend) | §12 |
|
||||
Reference in New Issue
Block a user