170 lines
5.4 KiB
Markdown
170 lines
5.4 KiB
Markdown
# HiveOps Portal UI Implementation Plan
|
|
|
|
## Overview
|
|
Add a Thymeleaf portal UI accessible at `mgmt.directlx.dev/portal` for managing:
|
|
- **Customers** (separate from Users/admins)
|
|
- **Product Key Licenses** linked to customers
|
|
- **API Keys** for hiveops-agent (with configurable scopes)
|
|
- **Global Configuration**
|
|
|
|
## Design Decisions
|
|
- **Auth**: Session-based for portal (separate from JWT API)
|
|
- **UI**: Bootstrap 5 (via CDN)
|
|
- **Customer Model**: Separate entity (Users are admins, Customers get licenses)
|
|
- **API Key Scope**: Full agent operations with configurable permissions
|
|
|
|
---
|
|
|
|
## Implementation Phases
|
|
|
|
### Phase 1: Dependencies & Database
|
|
|
|
**1.1 Update pom.xml** - Add dependencies:
|
|
```xml
|
|
<dependency>
|
|
<groupId>org.springframework.boot</groupId>
|
|
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
|
</dependency>
|
|
<dependency>
|
|
<groupId>org.thymeleaf.extras</groupId>
|
|
<artifactId>thymeleaf-extras-springsecurity6</artifactId>
|
|
</dependency>
|
|
```
|
|
|
|
**1.2 Create migration** `V3__add_customer_and_apikey_tables.sql`:
|
|
- `customers` table (name, email, company, phone, status, metadata)
|
|
- `api_keys` table (name, key_prefix, key_hash, scopes, customer_id, status, expires_at)
|
|
- Add `customer_id` FK to `licenses` table
|
|
|
|
### Phase 2: Entities & Repositories
|
|
|
|
**2.1 Create entities:**
|
|
- `Customer.java` - name, email, company, phone, address, notes, status (ACTIVE/SUSPENDED/ARCHIVED)
|
|
- `ApiKey.java` - name, keyPrefix, keyHash, scopes (JSON), status, expiresAt, lastUsedAt
|
|
|
|
**2.2 Update `License.java`** - Add `@ManyToOne Customer customer`
|
|
|
|
**2.3 Create repositories:**
|
|
- `CustomerRepository.java` - findByUuid, findByEmail, search()
|
|
- `ApiKeyRepository.java` - findByKeyPrefix, findActiveByKeyPrefix
|
|
|
|
### Phase 3: Services
|
|
|
|
**3.1 Create services:**
|
|
- `CustomerService.java` - CRUD, search, suspend/activate
|
|
- `ApiKeyService.java` - generate (returns raw key once), validate, revoke
|
|
- `PortalLicenseService.java` - create license for customer, generate key
|
|
- `DashboardService.java` - statistics aggregation
|
|
|
|
**API Key format**: `hiveops_{8-char-prefix}_{32-char-random}`
|
|
- Only SHA-256 hash stored; raw key shown once at creation
|
|
|
|
### Phase 4: Security Configuration
|
|
|
|
**4.1 Create `ApiKeyAuthenticationFilter.java`**
|
|
- Process `X-API-Key` header for agent requests
|
|
- Validate against hashed keys in DB
|
|
|
|
**4.2 Update `SecurityConfig.java`** - Dual filter chains:
|
|
```java
|
|
// Order 1: API chain (JWT, stateless)
|
|
@Bean @Order(1)
|
|
SecurityFilterChain apiFilterChain() { ... }
|
|
|
|
// Order 2: Portal chain (session-based)
|
|
@Bean @Order(2)
|
|
SecurityFilterChain portalFilterChain() {
|
|
// Form login at /portal/login
|
|
// Session management
|
|
// CSRF enabled
|
|
}
|
|
```
|
|
|
|
### Phase 5: Portal Controllers
|
|
|
|
Create in `com.hiveops.mgmt.controller.portal`:
|
|
|
|
| Controller | Routes | Function |
|
|
|------------|--------|----------|
|
|
| `PortalDashboardController` | `/portal/`, `/portal/dashboard`, `/portal/login` | Dashboard, login |
|
|
| `PortalCustomerController` | `/portal/customers/**` | Customer CRUD |
|
|
| `PortalLicenseController` | `/portal/licenses/**` | License management |
|
|
| `PortalApiKeyController` | `/portal/api-keys/**` | API key management |
|
|
| `PortalSettingsController` | `/portal/settings/**` | Global settings (admin only) |
|
|
|
|
### Phase 6: Templates & Static Resources
|
|
|
|
**Directory structure:**
|
|
```
|
|
src/main/resources/
|
|
├── templates/portal/
|
|
│ ├── layout/base.html
|
|
│ ├── fragments/ (header, sidebar, footer, alerts, pagination)
|
|
│ ├── login.html
|
|
│ ├── dashboard.html
|
|
│ ├── customers/ (list, form, view)
|
|
│ ├── licenses/ (list, form, view)
|
|
│ ├── api-keys/ (list, form, created)
|
|
│ ├── settings/list.html
|
|
│ └── error/ (403, 404, 500)
|
|
└── static/portal/
|
|
├── css/styles.css
|
|
├── js/portal.js
|
|
└── images/logo.svg
|
|
```
|
|
|
|
### Phase 7: Configuration Updates
|
|
|
|
**Update `application.yml`:**
|
|
```yaml
|
|
server:
|
|
servlet:
|
|
context-path: / # Changed from /api
|
|
session:
|
|
timeout: 30m
|
|
|
|
spring:
|
|
thymeleaf:
|
|
prefix: classpath:/templates/
|
|
suffix: .html
|
|
cache: false
|
|
```
|
|
|
|
---
|
|
|
|
## Key Files to Modify
|
|
|
|
| File | Changes |
|
|
|------|---------|
|
|
| `pom.xml` | Add Thymeleaf dependencies |
|
|
| `application.yml` | Add Thymeleaf config, change context-path |
|
|
| `SecurityConfig.java` | Dual filter chains for API + Portal |
|
|
| `License.java` | Add customer relationship |
|
|
|
|
## New Files to Create
|
|
|
|
| Category | Count | Files |
|
|
|----------|-------|-------|
|
|
| Migration | 1 | V3__add_customer_and_apikey_tables.sql |
|
|
| Entities | 2 | Customer.java, ApiKey.java |
|
|
| Repositories | 2 | CustomerRepository.java, ApiKeyRepository.java |
|
|
| Services | 4 | CustomerService, ApiKeyService, PortalLicenseService, DashboardService |
|
|
| Security | 2 | ApiKeyAuthenticationFilter, ApiKeyAuthentication |
|
|
| Controllers | 5 | Portal controllers |
|
|
| DTOs | 8 | Request/Response DTOs |
|
|
| Templates | ~20 | Thymeleaf HTML templates |
|
|
| Static | 3 | CSS, JS, images |
|
|
|
|
---
|
|
|
|
## Verification
|
|
|
|
1. **Build**: `./mvnw clean compile` - verify no compilation errors
|
|
2. **Database**: Run migrations, verify tables created
|
|
3. **Login**: Access `/portal/login`, authenticate as admin@hiveops.com
|
|
4. **Customer CRUD**: Create, view, edit, suspend customers
|
|
5. **License Generation**: Create license linked to customer, verify key format
|
|
6. **API Key Generation**: Create API key, verify raw key shown once, test validation
|
|
7. **Settings**: Edit global settings (admin only)
|
|
8. **Existing API**: Verify `/api/v1/auth/login` still works with JWT
|