docs: Fix device authentication implementation plan
- Update section 1.6.3 to pass baseURL as template parameter instead of hardcoding - Add handler update note for passing cfg.BaseURL to template - Fix TypeScript event handling in section 1.6.4: - Add event parameter to regenerateDeviceToken function signature - Update all onclick handlers to explicitly pass event object - Fixes deprecated implicit event in modern browsers - Remove section 1.9 (Device Identifier Verification) as it was never implemented - Clarify device authentication strategy: Kobo uses URL path tokens, KOReader uses Bearer headers
This commit is contained in:
+33
-34
@@ -11,15 +11,12 @@
|
||||
## Table of Contents
|
||||
|
||||
1. [Phase 1: Enhanced Authentication (Week 1)](#phase-1-enhanced-authentication)
|
||||
- Database Query Addition
|
||||
- Middleware Enhancement
|
||||
- Router Updates
|
||||
- Backend Handler Addition
|
||||
- Frontend Template Updates
|
||||
- Bruno API Tests
|
||||
- Database Query Addition
|
||||
- Middleware Enhancement
|
||||
- Router Updates
|
||||
- Backend Handler Addition
|
||||
- Frontend Template Updates
|
||||
2. [Phase 2: Kobo Integration (Week 1-2)](#phase-2-kobo-integration)
|
||||
- Documentation Updates
|
||||
- Test Updates
|
||||
3. [Phase 3: OPDS Security (Week 2-3)](#phase-3-opds-security)
|
||||
- Router Enhancement
|
||||
- Bruno API Tests
|
||||
@@ -337,7 +334,7 @@ koboSync.POST("/sync-from-server", cfg.DeviceAuthMiddleware.Authenticate(koboHan
|
||||
|
||||
**File**: `internal/router/device.go`
|
||||
|
||||
**Location**: After device registration routes (around line 50)
|
||||
**Location**: After device registration routes (around line 25)
|
||||
|
||||
**Current Implementation**: Need to check what device routes exist
|
||||
|
||||
@@ -350,23 +347,16 @@ koboSync.POST("/sync-from-server", cfg.DeviceAuthMiddleware.Authenticate(koboHan
|
||||
devices.PUT("/:id/regenerate-token", jwtMiddleware, h.RegenerateDeviceToken)
|
||||
```
|
||||
|
||||
**Complete Context** (assuming placement after device registration routes):
|
||||
|
||||
**Complete Context** (token regeneration route added to existing device routes):
|
||||
```go
|
||||
// Device registration endpoints
|
||||
devices.POST("/register", h.InitiateRegistration)
|
||||
devices.POST("/approve/:registration_id", jwtMiddleware, h.ApproveDevice)
|
||||
devices.POST("/reject/:registration_id", jwtMiddleware, h.RejectDevice)
|
||||
devices.GET("/pending", jwtMiddleware, h.ListPendingRegistrations)
|
||||
// Existing device management routes (unchanged)
|
||||
devices.GET("", jwtMiddleware, cfg.DeviceHandler.ListDevices)
|
||||
devices.GET("/:id", jwtMiddleware, cfg.DeviceHandler.GetDevice)
|
||||
devices.PUT("/:id", jwtMiddleware, cfg.DeviceHandler.UpdateDevice)
|
||||
devices.DELETE("/:id", jwtMiddleware, cfg.DeviceHandler.DeleteDevice)
|
||||
|
||||
// Device management endpoints
|
||||
devices.GET("", jwtMiddleware, h.ListDevices)
|
||||
devices.GET("/:id", jwtMiddleware, h.GetDevice)
|
||||
devices.PUT("/:id", jwtMiddleware, h.UpdateDevice)
|
||||
devices.DELETE("/:id", jwtMiddleware, h.DeleteDevice)
|
||||
|
||||
// Token regeneration endpoint (JWT authentication required)
|
||||
devices.PUT("/:id/regenerate-token", jwtMiddleware, h.RegenerateDeviceToken)
|
||||
// NEW: Token regeneration endpoint (JWT authentication required)
|
||||
devices.PUT("/:id/regenerate-token", jwtMiddleware, cfg.DeviceHandler.RegenerateDeviceToken)
|
||||
```
|
||||
|
||||
**Verification**: Run `go build ./internal/router`
|
||||
@@ -573,13 +563,16 @@ deviceList[i] = DeviceInfo{
|
||||
|
||||
**File**: `templates/devices.templ`
|
||||
|
||||
**Location**: Lines 46-98 (device card in grid)
|
||||
**Location**: Template function signature (line 5) and device card (lines 46-98)
|
||||
|
||||
**Current Implementation**: Device card shows device info and settings buttons
|
||||
**Required Changes**:
|
||||
|
||||
**Required Addition**: Add buttons for copy sync URL and regenerate token
|
||||
1. **Update template signature** to accept baseURL parameter (line 5):
|
||||
```templ
|
||||
templ Devices(user User, devices []handlers.DeviceInfo, pendingRegistrations []PendingRegistrationData, baseURL string) {
|
||||
```
|
||||
|
||||
**REPLACE DEVICE CARD CONTENT** (lines 46-98) with:
|
||||
2. **REPLACE DEVICE CARD CONTENT** (lines 46-98) with:
|
||||
|
||||
```templ
|
||||
for _, device := range devices {
|
||||
@@ -647,12 +640,12 @@ for _, device := range devices {
|
||||
type="text"
|
||||
id="sync-url-{ device.ID }"
|
||||
readonly
|
||||
value="{ fmt.Sprintf("http://YOUR_IP:8765/api/sync/kobo/%s", device.AuthToken) }"
|
||||
value="{ fmt.Sprintf("%s/api/sync/kobo/%s", baseURL, device.AuthToken) }"
|
||||
class="flex-1 px-3 py-2 text-xs rounded border"
|
||||
style="background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);"
|
||||
/>
|
||||
<button
|
||||
onclick="copyToClipboard('{ fmt.Sprintf("http://YOUR_IP:8765/api/sync/kobo/%s", device.AuthToken) }', 'Kobo sync URL')"
|
||||
onclick="copyToClipboard('{ fmt.Sprintf("%s/api/sync/kobo/%s", baseURL, device.AuthToken) }', 'Kobo sync URL', event)"
|
||||
class="px-3 py-2 text-xs rounded hover:opacity-80"
|
||||
style="background-color: var(--accent); color: white;"
|
||||
>
|
||||
@@ -677,7 +670,7 @@ for _, device := range devices {
|
||||
style="background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border); font-family: monospace;"
|
||||
/>
|
||||
<button
|
||||
onclick="copyToClipboard('{ device.AuthToken }', 'Auth token')"
|
||||
onclick="copyToClipboard('{ device.AuthToken }', 'Auth token', event)"
|
||||
class="px-3 py-2 text-xs rounded hover:opacity-80"
|
||||
style="background-color: var(--accent); color: white;"
|
||||
>
|
||||
@@ -690,7 +683,7 @@ for _, device := range devices {
|
||||
|
||||
<!-- Regenerate Token Button -->
|
||||
<button
|
||||
onclick="regenerateDeviceToken('{ device.ID }')"
|
||||
onclick="regenerateDeviceToken('{ device.ID }', event)"
|
||||
class="w-full px-3 py-2 text-xs rounded border hover:opacity-80"
|
||||
style="border-color: var(--border); color: var(--text-secondary); background-color: var(--bg-primary);"
|
||||
>
|
||||
@@ -709,6 +702,13 @@ for _, device := range devices {
|
||||
- Regenerate button requires confirmation
|
||||
- Clear setup instructions for each device type
|
||||
|
||||
**Handler Update** (`internal/router/frontend.go:171`):
|
||||
```go
|
||||
err = templates.Devices(user, devices, pendingList, cfg.BaseURL).Render(c.Request().Context(), &buf)
|
||||
```
|
||||
|
||||
Pass `cfg.BaseURL` to template instead of hardcoding URLs.
|
||||
|
||||
#### 1.6.4 Add TypeScript Device Management
|
||||
|
||||
**File**: `web/src/device-management.ts` (CREATE NEW FILE)
|
||||
@@ -763,7 +763,7 @@ function copyToClipboard(text: string, label: string): void {
|
||||
}
|
||||
|
||||
// Regenerate device token with confirmation
|
||||
function regenerateDeviceToken(deviceId: string): void {
|
||||
function regenerateDeviceToken(deviceId: string, event: Event): void {
|
||||
const confirmation = '⚠️ This will revoke current token and generate a new one.\n\n' +
|
||||
'The old token will immediately stop working.\n\n' +
|
||||
'You will need to update your device configuration with new token.\n\n' +
|
||||
@@ -1263,7 +1263,6 @@ docs {
|
||||
**KEEP EXISTING REQUESTS** in `bruno/sync-kobo/api.bru` for API clients and testing (Bearer token works for non-Kobo clients)
|
||||
|
||||
**Verification**: Test both authentication methods work (Kobo uses URL path, API clients can use Bearer)
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Kobo Integration
|
||||
|
||||
Reference in New Issue
Block a user