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:
2026-02-13 10:13:26 -05:00
parent fa09850611
commit fdfbec01ef
+33 -34
View File
@@ -11,15 +11,12 @@
## Table of Contents ## Table of Contents
1. [Phase 1: Enhanced Authentication (Week 1)](#phase-1-enhanced-authentication) 1. [Phase 1: Enhanced Authentication (Week 1)](#phase-1-enhanced-authentication)
- Database Query Addition - Database Query Addition
- Middleware Enhancement - Middleware Enhancement
- Router Updates - Router Updates
- Backend Handler Addition - Backend Handler Addition
- Frontend Template Updates - Frontend Template Updates
- Bruno API Tests
2. [Phase 2: Kobo Integration (Week 1-2)](#phase-2-kobo-integration) 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) 3. [Phase 3: OPDS Security (Week 2-3)](#phase-3-opds-security)
- Router Enhancement - Router Enhancement
- Bruno API Tests - Bruno API Tests
@@ -337,7 +334,7 @@ koboSync.POST("/sync-from-server", cfg.DeviceAuthMiddleware.Authenticate(koboHan
**File**: `internal/router/device.go` **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 **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) 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 ```go
// Device registration endpoints // Existing device management routes (unchanged)
devices.POST("/register", h.InitiateRegistration) devices.GET("", jwtMiddleware, cfg.DeviceHandler.ListDevices)
devices.POST("/approve/:registration_id", jwtMiddleware, h.ApproveDevice) devices.GET("/:id", jwtMiddleware, cfg.DeviceHandler.GetDevice)
devices.POST("/reject/:registration_id", jwtMiddleware, h.RejectDevice) devices.PUT("/:id", jwtMiddleware, cfg.DeviceHandler.UpdateDevice)
devices.GET("/pending", jwtMiddleware, h.ListPendingRegistrations) devices.DELETE("/:id", jwtMiddleware, cfg.DeviceHandler.DeleteDevice)
// Device management endpoints // NEW: Token regeneration endpoint (JWT authentication required)
devices.GET("", jwtMiddleware, h.ListDevices) devices.PUT("/:id/regenerate-token", jwtMiddleware, cfg.DeviceHandler.RegenerateDeviceToken)
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)
``` ```
**Verification**: Run `go build ./internal/router` **Verification**: Run `go build ./internal/router`
@@ -573,13 +563,16 @@ deviceList[i] = DeviceInfo{
**File**: `templates/devices.templ` **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 ```templ
for _, device := range devices { for _, device := range devices {
@@ -647,12 +640,12 @@ for _, device := range devices {
type="text" type="text"
id="sync-url-{ device.ID }" id="sync-url-{ device.ID }"
readonly 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" 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);" style="background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);"
/> />
<button <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" class="px-3 py-2 text-xs rounded hover:opacity-80"
style="background-color: var(--accent); color: white;" 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;" style="background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border); font-family: monospace;"
/> />
<button <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" class="px-3 py-2 text-xs rounded hover:opacity-80"
style="background-color: var(--accent); color: white;" style="background-color: var(--accent); color: white;"
> >
@@ -690,7 +683,7 @@ for _, device := range devices {
<!-- Regenerate Token Button --> <!-- Regenerate Token Button -->
<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" 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);" 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 - Regenerate button requires confirmation
- Clear setup instructions for each device type - 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 #### 1.6.4 Add TypeScript Device Management
**File**: `web/src/device-management.ts` (CREATE NEW FILE) **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 // 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' + const confirmation = '⚠️ This will revoke current token and generate a new one.\n\n' +
'The old token will immediately stop working.\n\n' + 'The old token will immediately stop working.\n\n' +
'You will need to update your device configuration with new token.\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) **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) **Verification**: Test both authentication methods work (Kobo uses URL path, API clients can use Bearer)
--- ---
## Phase 2: Kobo Integration ## Phase 2: Kobo Integration