mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-04 18:52:56 +00:00
312 lines
10 KiB
Markdown
312 lines
10 KiB
Markdown
# Umami Website Creation Fix
|
|
|
|
## Problem
|
|
The Umami tracking website creation was not working properly because:
|
|
1. The auto-creation wasn't being triggered during initial setup
|
|
2. No frontend UI existed to manually trigger website creation if needed
|
|
|
|
## Solution
|
|
|
|
### Automatic Creation During Setup
|
|
The initial setup process now automatically creates the Umami website:
|
|
- When you complete the setup wizard, it fetches `/umami/config`
|
|
- Backend detects that UMAMI credentials are in `.env` but no UMAMI_WEBSITE_ID exists
|
|
- Backend automatically creates the website using the domain from your site
|
|
- Analytics tracking starts working immediately
|
|
|
|
### Manual Creation (Backup Option)
|
|
Added a new "Umami Analytics" tab to the Settings Admin Page that allows:
|
|
- Viewing current Umami configuration status
|
|
- Manually creating a new Umami website with custom name and domain
|
|
- Refreshing the Umami configuration
|
|
|
|
## Changes Made
|
|
|
|
### Frontend Changes
|
|
|
|
**File: `frontend/src/pages/SetupPage.tsx`**
|
|
Added automatic Umami initialization during setup:
|
|
```typescript
|
|
// Step 3: Initialize Umami Analytics (auto-create website)
|
|
setSetupProgress('Konfiguruji analytiku...');
|
|
try {
|
|
// Trigger Umami config fetch - backend will auto-create website if credentials are present
|
|
const axios = (await import('axios')).default;
|
|
const apiUrl = (API_URL || '').replace(/\/$/, '');
|
|
await axios.get(`${apiUrl}/umami/config`);
|
|
console.log('Umami analytics initialized');
|
|
} catch (err) {
|
|
console.warn('Umami initialization failed (non-critical):', err);
|
|
}
|
|
```
|
|
|
|
**File: `frontend/src/pages/admin/SettingsAdminPage.tsx`**
|
|
|
|
1. Added new imports:
|
|
- `import api from '../../services/api';`
|
|
|
|
2. Added new state variables:
|
|
```typescript
|
|
const [umamiWebsiteId, setUmamiWebsiteId] = useState<string>('');
|
|
const [umamiDomain, setUmamiDomain] = useState<string>('');
|
|
const [umamiName, setUmamiName] = useState<string>('');
|
|
const [umamiInitializing, setUmamiInitializing] = useState<boolean>(false);
|
|
const [umamiConfig, setUmamiConfig] = useState<any>(null);
|
|
```
|
|
|
|
3. Added `fetchUmamiConfig()` function to load current Umami status
|
|
|
|
4. Added "Umami Analytics" tab to the settings page with:
|
|
- Status indicator (green for active, yellow for not configured)
|
|
- Form fields for website name and domain
|
|
- "Create Website" button that calls `/admin/umami/initialize`
|
|
- "Refresh Status" button to reload configuration
|
|
|
|
## Backend API
|
|
|
|
### Authentication with Token Verification
|
|
**File: `internal/services/umami_service.go`**
|
|
|
|
The backend implements smart token management:
|
|
|
|
1. **Initial Authentication** (`POST /api/auth/login`)
|
|
- Sends username and password in JSON format (from `.env`)
|
|
- Receives JWT token with 24-hour expiration
|
|
- Stores token with expiration timestamp
|
|
|
|
2. **Token Verification** (twice daily - every 12 hours)
|
|
- Uses `POST /api/auth/verify` endpoint
|
|
- Checks if existing token is still valid
|
|
- Only re-authenticates if verification fails
|
|
- Reduces unnecessary login requests
|
|
|
|
3. **Automatic Re-authentication**
|
|
- If token expires or verification fails
|
|
- Automatically gets a new token
|
|
- Seamless for the application
|
|
|
|
**Token Lifecycle:**
|
|
```
|
|
Initial: Login → Get Token (valid 24h)
|
|
After 12h: Verify Token → Still valid? Continue using it
|
|
After 24h: Token expired → Re-authenticate → Get new token
|
|
```
|
|
|
|
All API calls use: `Authorization: Bearer <token>` header
|
|
|
|
### Website Creation Endpoint
|
|
**Endpoint:** `POST /admin/umami/initialize`
|
|
**File:** `internal/controllers/umami_controller.go`
|
|
|
|
Request body:
|
|
```json
|
|
{
|
|
"name": "Your Club Name",
|
|
"domain": "yourclub.example.com"
|
|
}
|
|
```
|
|
|
|
Response (success):
|
|
```json
|
|
{
|
|
"message": "Umami initialized successfully",
|
|
"website_id": "abc123-def456-...",
|
|
"script_url": "https://umami.tdvorak.dev/script.js"
|
|
}
|
|
```
|
|
|
|
## Testing Instructions
|
|
|
|
### 1. Verify Environment Variables
|
|
Your `.env` file already has the correct credentials (they don't change):
|
|
```env
|
|
UMAMI_URL=https://umami.tdvorak.dev
|
|
UMAMI_USERNAME=admin
|
|
UMAMI_PASSWORD=eevRQ6h3G@!c#y4A1T
|
|
UMAMI_WEBSITE_ID= # Leave empty - will be auto-created during setup
|
|
```
|
|
|
|
**Important:** These credentials are permanent and don't need to be modified.
|
|
|
|
### 2. Run Initial Setup
|
|
1. Navigate to `/setup` route
|
|
2. Complete the setup wizard (club info, admin account, etc.)
|
|
3. During setup, you'll see: **"Konfiguruji analytiku..."** (Configuring analytics)
|
|
4. Backend automatically creates Umami website using your domain
|
|
5. Setup completes and analytics are ready!
|
|
|
|
### 3. Verify Umami is Working
|
|
After setup, check the analytics:
|
|
1. Login to admin panel
|
|
2. Navigate to **Settings** → **Umami Analytics** tab
|
|
3. You should see green status: **"✓ Umami je aktivní"**
|
|
4. Website ID should be displayed
|
|
|
|
### 4. Manual Creation (If Needed)
|
|
If auto-creation didn't work during setup, you can manually create:
|
|
1. Navigate to **Settings** → **Umami Analytics** tab
|
|
2. Fill in the form:
|
|
- **Name**: Your club name
|
|
- **Domain**: Your website domain
|
|
3. Click "Vytvořit webovou stránku" (Create Website)
|
|
4. Success message will show the Website ID
|
|
|
|
### 4. Verify via API (PowerShell)
|
|
You can also verify directly with PowerShell:
|
|
|
|
```powershell
|
|
# Login to get token
|
|
$body = @{
|
|
username = "admin"
|
|
password = "eevRQ6h3G@!c#y4A1T"
|
|
} | ConvertTo-Json
|
|
|
|
$response = Invoke-RestMethod -Uri "https://umami.tdvorak.dev/api/auth/login" `
|
|
-Method Post `
|
|
-ContentType "application/json" `
|
|
-Body $body
|
|
|
|
$token = $response.token
|
|
Write-Output "Token: $token"
|
|
|
|
# List websites to verify creation
|
|
$headers = @{
|
|
Authorization = "Bearer $token"
|
|
}
|
|
|
|
$websites = Invoke-RestMethod -Uri "https://umami.tdvorak.dev/api/websites" `
|
|
-Headers $headers `
|
|
-Method Get
|
|
|
|
$websites.data
|
|
```
|
|
|
|
### 5. Website ID Persistence
|
|
The Website ID is stored in-memory by the backend after auto-creation. To make it permanent across server restarts:
|
|
|
|
**Option 1: Let it auto-create on each restart** (Recommended)
|
|
- Leave `UMAMI_WEBSITE_ID=` empty in `.env`
|
|
- Backend checks if website exists and reuses it (or creates new one if missing)
|
|
- Works seamlessly
|
|
|
|
**Option 2: Store Website ID in .env**
|
|
- Copy the Website ID from Settings → Umami Analytics tab
|
|
- Add to `.env`: `UMAMI_WEBSITE_ID=abc123-def456-...`
|
|
- Restart backend server
|
|
- Backend will use this ID directly without checking/creating
|
|
|
|
## How It Works
|
|
|
|
### Frontend Flow
|
|
1. User opens Settings → Umami Analytics tab
|
|
2. `fetchUmamiConfig()` is called on page load
|
|
3. Backend checks if `UMAMI_WEBSITE_ID` is set
|
|
4. If not set and credentials are available, backend may auto-create on first request
|
|
5. User can manually create via the UI by clicking "Create Website"
|
|
6. Frontend calls `POST /admin/umami/initialize` with name and domain
|
|
7. Backend authenticates with Umami and creates the website
|
|
8. Backend returns the Website ID
|
|
9. Frontend displays success and refreshes the configuration
|
|
|
|
### Backend Flow
|
|
1. Receives request at `/admin/umami/initialize`
|
|
2. Validates request payload (name and domain required)
|
|
3. Calls `umamiService.authenticate()`:
|
|
- POST to Umami `https://umami.tdvorak.dev/api/auth/login`
|
|
- Payload: `{"username": "admin", "password": "..."}`
|
|
- Receives JWT token
|
|
4. Calls `umamiService.EnsureWebsite()`:
|
|
- First checks if website exists: GET `/api/websites?query={domain}`
|
|
- If exists, returns existing ID
|
|
- If not, creates new website: POST `/api/websites`
|
|
- Payload: `{"name": "...", "domain": "..."}`
|
|
- Authorization header: `Bearer {token}`
|
|
5. Updates in-memory config with Website ID
|
|
6. Returns success response to frontend
|
|
|
|
## Troubleshooting
|
|
|
|
### Error: "authentication failed"
|
|
- Check UMAMI_USERNAME and UMAMI_PASSWORD in `.env`
|
|
- Verify credentials work by testing with PowerShell script above
|
|
|
|
### Error: "create website failed"
|
|
- Check if website already exists (list via PowerShell)
|
|
- Verify token has correct permissions
|
|
- Check Umami server logs
|
|
|
|
### Website ID not persisting
|
|
- The Website ID is stored in memory only
|
|
- Update `.env` with `UMAMI_WEBSITE_ID=...` for persistence
|
|
- Restart backend server after updating `.env`
|
|
|
|
## Additional Notes
|
|
|
|
- The backend automatically tries to create a website on first request to `/umami/config` if credentials are set
|
|
- In production, it only auto-creates for non-localhost domains
|
|
- In development, it allows localhost
|
|
- The manual UI provides explicit control over website creation
|
|
- You can create multiple websites for different domains if needed
|
|
|
|
## Umami v2 Compatibility Update (Latest Fix)
|
|
|
|
### Problem with Umami v2
|
|
In Umami v2, when users are part of teams, creating a website may require specifying a `teamId`. Without this parameter, the website creation request could fail.
|
|
|
|
### Solution Implemented
|
|
Updated `CreateWebsite()` method in `umami_service.go` to:
|
|
|
|
1. **Fetch current user information** via `POST /api/auth/verify`
|
|
2. **Retrieve user's teams** via `GET /api/users/:userId/teams`
|
|
3. **Automatically use the first available team** when creating a website
|
|
4. **Gracefully degrade** if teams cannot be fetched (continues without teamId)
|
|
|
|
### New Methods Added
|
|
```go
|
|
// GetCurrentUser - Retrieves authenticated user info from Umami
|
|
func (u *UmamiService) GetCurrentUser() (map[string]interface{}, error)
|
|
|
|
// GetUserTeams - Retrieves user's teams from Umami
|
|
func (u *UmamiService) GetUserTeams(userID string) ([]UmamiTeam, error)
|
|
```
|
|
|
|
### Updated CreateWebsite Flow
|
|
```
|
|
1. Authenticate with Umami
|
|
2. Get current user info (to obtain user ID)
|
|
3. Fetch user's teams (if user has teams)
|
|
4. Prepare website creation request with:
|
|
- name: Website name
|
|
- domain: Website domain
|
|
- teamId: First available team ID (optional)
|
|
5. Send POST /api/websites with Authorization Bearer token
|
|
6. Return website ID on success
|
|
```
|
|
|
|
### Enhanced Error Logging
|
|
All error messages now include detailed response bodies from Umami API for easier debugging:
|
|
- Authentication failures show full error response
|
|
- Website creation errors display Umami's error message
|
|
- Team fetch failures log warnings but don't block website creation
|
|
|
|
### Testing the Fix
|
|
To verify the fix works:
|
|
|
|
1. **Check backend logs** during website creation - you should see:
|
|
```
|
|
Creating Umami website: name='...', domain='...'
|
|
Using team ID: xxx-xxx-xxx (team name: ...)
|
|
Sending website creation request to Umami API: https://umami.tdvorak.dev/api/websites
|
|
Successfully created Umami website: ... (ID: xxx, Domain: ...)
|
|
```
|
|
|
|
2. **If teams aren't available**, you'll see:
|
|
```
|
|
Failed to fetch user teams (continuing without team): ...
|
|
Successfully created Umami website: ... (ID: xxx, Domain: ...)
|
|
```
|
|
|
|
3. **Monitor for creation errors** - detailed error messages will help diagnose issues
|
|
|
|
This update ensures compatibility with both Umami v1 (no teams) and Umami v2 (with teams).
|