Commit Graph
765 Commits
Author SHA1 Message Date
john-okeefe e16c277caa docs: remove completed admin library implementation plan
-- Delete ADMIN_LIBRARY_IMPROVEMENTS_PLAN.md
-- All features from the plan have been implemented
-- Plan is no longer needed as reference
2026-02-23 20:24:20 -05:00
john-okeefe e68a53651a refactor(devops): reorganize rebuild targets for clarity
-- Rename 'build' to 'rebuild' for clarity (rebuilds all containers)
-- Rename 'build-force' to 'rebuild-force' for consistency
-- Add 'rebuild-app-force' target for app-only rebuild without cache
-- Add 'rebuild-force-db' target that DELETES database for clean rebuild
-- Improve help text to clarify what each target does
-- Remove circular dependency (rebuild no longer depends on clean)
-- All rebuild targets now preserve database unless explicitly stated
2026-02-23 20:24:16 -05:00
john-okeefe e7f30a00c0 style(templates): fix code formatting with consistent indentation
-- Reformat all generated template Go files with consistent indentation
-- Standardize code style across templates/
-- No functional changes, formatting only
-- Generated by templ tool during development
2026-02-23 20:24:10 -05:00
john-okeefe 85ba3d4060 feat(frontend): add delete confirmation modal for library management
-- Add dedicated delete confirmation modal to admin/library page
-- Refactor deleteLibrary() to use modal instead of inline confirm()
-- Add showDeleteModal(), hideDeleteModal(), confirmDeleteLibrary() functions
-- Modal displays clear warning about what gets deleted
-- Improves UX by making the confirmation dialog more prominent and informative
2026-02-23 20:23:56 -05:00
john-okeefe be49bc13a7 test(bruno): add manual API contract test for folder browsing
- Create bruno/library/browse-folders.yml
- Single manual test case for admin context
- Unit/integration tests cover all scenarios (no auth, user, admin)
- Bruno provides quick manual API contract verification

Fixes: Issue 2 (manual testing)
2026-02-23 17:03:49 -05:00
john-okeefe f91b1bf54b docs(api): document library folder browsing endpoint
- Add docs/developer/api/libraries/browse-folders.md
- Document security features (path traversal protection, admin-only)
- Include usage examples and error responses
- Clarify browses server filesystem, not client's

docs(user): add admin library folder browser documentation

- Add docs/user/admin-library-management.md
- Document how to use the folder browser UI
- Include security notes and manual entry instructions
- Explain server filesystem browsing behavior

Fixes: Issue 2 (documentation)
2026-02-23 17:03:35 -05:00
john-okeefe 22e10fa460 test(backend): add unit and integration tests for folder browsing
- Add unit tests in internal/services/library_service_test.go
  - Test path traversal protection
  - Test non-existent path handling
  - Test file vs directory validation
  - Test successful directory listing
- Add integration tests in cmd/server/tests/library_browse_test.go
  - Use setupTestServer() helper from test_helpers.go
  - Test no authentication returns 401
  - Test regular user returns 403 forbidden
  - Test admin can browse directories
  - Test path traversal blocking
- All tests use table-driven approach with t.Run()

Fixes: Issue 2 (tests)
2026-02-23 17:03:03 -05:00
john-okeefe 2af035d87f feat(backend): add server-side directory browsing API
- Add BrowseDirectories() to library service with path traversal protection
- Add BrowseDirectories handler with proper error handling
- Register GET /api/libraries/browse endpoint (admin-only)
- Returns current path, parent path, and list of subdirectories
- Security: blocks "..", validates path exists, checks is directory

Fixes: Issue 2 (backend)
2026-02-23 17:02:52 -05:00
john-okeefe c333c82c6b fix(frontend): add data parameter support to apiDelete
- Add optional data parameter to apiDelete() with generic type safety
- Enables DELETE requests with request bodies (needed for folder deletion)
- 100% backward compatible (optional parameter)
- Supports type-safe request body passing

Part of: Issue 1
2026-02-23 17:02:35 -05:00
john-okeefe 509423b46e feat(frontend): implement library edit functionality
- Reuse Create Library modal for edit mode
- Add hidden library-id input to track create vs edit
- Update handleCreateLibrarySubmit to detect mode and use PUT vs POST
- Implement editLibrary() to populate modal with existing data
- Pass library data to Edit button via data attributes
- Reset modal title when opening for create mode

Fixes: Issue 3
2026-02-23 17:02:01 -05:00
john-okeefe a137d3ea76 docs: add admin library page improvements implementation plan
- Document 4 improvements to /admin/library page
- Issue 1: Fix folder list display bugs (toggle logic, DELETE request body)
- Issue 2: Add server-side folder browser with full-stack implementation
- Issue 3: Implement edit library functionality
- Issue 4: Clarify delete confirmation message

Key changes:
- Add os import for BrowseDirectories service function
- Use event delegation pattern for folder browser UI
- Add DeleteFolderRequest interface for type safety
- Include comprehensive testing strategy (unit, integration, Bruno)
- Follow PROJECT_GUIDELINES.md throughout
- Procedural/imperative style, no OOP
- Progressive enhancement maintained
2026-02-23 16:12:25 -05:00
john-okeefe ce50312e1b feat(frontend): Add TypeScript for admin library page
Add web/src/library.ts with complete functionality for /admin/library
page interactivity.

Features:
- reloadLibraries() - fetch and render library list after changes
- renderLibraries() - SSR replacement with proper data.data handling
- loadUserVisibility() - load and display user library permissions
- setLibraryVisibility() - toggle library visibility for users
- handleCreateLibrarySubmit() - form submission with fetch API
- deleteLibrary() - delete with confirmation
- showLibraryFolders() - folder management
- addLibraryFolder() / removeLibraryFolder() - folder CRUD
- editLibrary() - placeholder for future implementation
- Modal controls (show/hide)
- Event delegation for dynamic buttons
- XSS protection with escapeHtmlLocal()

TypeScript Features:
- Proper type definitions (Library, User, LibraryFolder)
- Async/await with error handling
- Procedural style (no OOP, per PROJECT_GUIDELINES)
- Exports functions to window for global access

Bug Fixes:
- Fixed data.data API response handling
- Replaced broken HTMX form with fetch()
- Proper error messages with toast notifications

Lines: 394
2026-02-22 21:07:06 -05:00
john-okeefe f39cf3904d fix(frontend): Remove ES6 exports from api.ts
Remove ES6 export statement from api.ts that was causing CommonJS
compilation in browsers, breaking window.api initialization.

Issue: TypeScript compiled 'export { ... }' to CommonJS format
(exports.apiGet = ...), which browsers don't support.

Fix: Remove export statement, rely on existing window.api assignment.
This produces browser-compatible JavaScript.

Before: export { getAuthHeader, apiGet, ... } → CommonJS exports
After: (window as any).api = { ... } → browser global

Resolves: 'Uncaught ReferenceError: exports is not defined'
Resolves: 'Uncaught TypeError: window.api is undefined'
2026-02-22 21:06:47 -05:00
john-okeefe 638f1a901d feat(frontend): Convert admin library to SSR with TypeScript
Complete refactor of /admin/library page to use server-side rendering
and TypeScript, fixing broken Create Library button and improving UX.

Backend Integration:
- Update template signature to accept libraries and users parameters
- Add SSR rendering of library list (no empty state)
- Add SSR rendering of user select dropdown
- Data fetched in router handler and passed to template

TypeScript Conversion:
- Create web/src/library.ts (394 lines) - complete rewrite of inline JS
- Convert all inline JavaScript to TypeScript
- Fix critical data.data API response bug
- Replace broken HTMX form with fetch() API calls
- Implement event delegation for dynamic button clicks
- Add missing editLibrary() function (placeholder)
- Add proper error handling with toast notifications

Template Changes:
- Remove 229 lines of inline JavaScript
- Update Create Library button: onclick → data-action
- Update form: remove HTMX attributes, add onsubmit handler
- Remove duplicate script tags from <head> section
- Keep all script loading at end of <body> for performance

Bug Fixes:
- Fix API response handling: data → data.data
- Replace broken hx-headers (JavaScript not supported in HTMX)
- Fix modal z-index and visibility classes

Progressive Enhancement:
- Page works without JavaScript (SSR content visible)
- JavaScript enhances with interactive features
- Follows PROJECT_GUIDELINES: procedural style, no OOP
2026-02-22 21:06:36 -05:00
john-okeefe f096b86032 feat(router): SSR libraries and users on /admin/library page
Update the /admin/library route handler to fetch and pass data to
template for server-side rendering, improving page load performance.

Changes:
- Fetch all libraries using ListLibrariesData() helper
- Fetch all users for visibility management
- Convert database rows to template types (LibraryData, User)
- Pass data to AdminLibrary template for SSR
- Follows existing pattern from dashboard and custom-section pages

Benefits:
- Faster initial page load (no AJAX fetch)
- Better UX (content visible immediately)
- Progressive enhancement (works without JS)
2026-02-22 21:06:20 -05:00
john-okeefe 3174ec16bc feat(backend): Add SSR data helper for admin library page
Add ListLibrariesData() method to LibraryHandler to support
server-side rendering of all libraries on the /admin/library page.

This follows the existing pattern of GetUserVisibleLibrariesData() and
GetLibraryTypeData() methods, which return data structures instead of
JSON for template rendering.

Changes:
- Add ListLibrariesData() method (3 lines)
- Returns []database.ListLibrariesRow for template consumption
- Called by frontend route handler for SSR
2026-02-22 21:05:57 -05:00
john-okeefe f7e1eab31d refactor(templates): fix admin sidebar navigation link
Update admin dashboard sidebar to point to user administration page
instead of profile settings:
- Change link from /profile to /admin/users
- Update label from 'Profile Settings' to 'User Administration'

This completes the admin navigation refactoring to use dedicated
admin pages instead of the main user profile page.
2026-02-22 19:48:50 -05:00
john-okeefe cb04dbb542 fix(devops): force container recreation on rebuild to ensure template changes appear
Add --force-recreate flag to all build targets that create containers:
- build: Force recreation when building all containers
- rebuild-app: Force recreation of app container only (fixes template update issue)
- build-force: Force recreation even when using --no-cache
- test-env-up: Force recreation in test environment

This fixes a critical issue where 'make rebuild-app' would build a new image
but continue running the old container, causing template changes to not appear.

Root cause: podman-compose up --build doesn't recreate containers if they're
already running, even when a new image is built. The --force-recreate flag
ensures containers are recreated with the new image.

BuildKit caching still works as expected - cache is used during image build,
while --force-recreate ensures the new image is actually deployed.

Changes:
- build: Add --force-recreate flag
- rebuild-app: Add --force-recreate flag, update success message
- build-force: Add --force-recreate flag
- test-env-up: Add --force-recreate flag

Verified: Template changes now appear immediately after rebuild.
2026-02-22 19:48:36 -05:00
john-okeefe 37cb279a15 chore(templates): regenerate Go code after template changes
Run templ generate to update *_templ.go files after admin header
refactoring and template signature changes.
2026-02-22 19:06:32 -05:00
john-okeefe fd08e8c613 fix(router): update AdminUsers call to match new signature
Fix function call to pass currentUser as first parameter instead of
templateUsers, matching the refactored AdminUsers template signature.
2026-02-22 19:06:29 -05:00
john-okeefe 844910a54b refactor(templates): complete admin header extraction
- Add theme.js to admin_users page for proper theme support
- Pass currentUser to Header instead of hardcoded Admin user
- Fix currentUserID reference bug (use currentUser.ID)
- Remove duplicate theme loading script (now in Header)
- Complete header refactoring for admin_users page
2026-02-22 19:06:18 -05:00
john-okeefe d4d93bc0e3 feat(auth): add interactive password requirements validation to registration
- Add password requirements checklist with visual indicators (✓/○)
- Implement real-time validation for length, case, numbers, special chars
- Add confirm password field with matching validation
- Disable submit button until all requirements are met
- Add TypeScript client-side validation with password manager compatibility
2026-02-22 18:40:22 -05:00
john-okeefe d28aa5af4b refactor(templates): extract shared header from admin pages
- Replace inline nav code with @Header component in admin.templ
- Replace inline nav code with @Header component in admin_library.templ
- DRY up navigation, theme switcher, and user menu across admin pages
2026-02-22 18:40:18 -05:00
john-okeefe 55440e0dc8 feat(devops): improve Docker build caching and add dev workflow targets
- Optimize Dockerfile layer caching with --mount=type=cache for Go modules and npm
- Reorganize Dockerfile layers for better cache hit rates
- Improve .dockerignore organization with categorized comments
- Add Makefile targets: up, down, rebuild-app, restart, ps
- Enhance Makefile help output with categorized sections
2026-02-22 18:40:16 -05:00
john-okeefe 48937e9777 feat(auth): improve registration form theming and add name fields
- Add theme.js script for proper theme support
- Update form to use CSS variables (--bg-primary, --text-secondary, etc.)
- Replace hardcoded colors with theming system
- Add optional first_name and last_name fields
- Update button to use .btn-primary class
- All form inputs now properly themed
2026-02-22 16:51:27 -05:00
john-okeefe 807d7b36ef refactor: update sevenzip import to use vendored package
Updated import path from github.com/bodgit/sevenzip to
bookhoard/internal/sevenzip to use the vendored package.
2026-02-22 16:29:28 -05:00
john-okeefe 82efb0d635 chore: remove go4.org dependency and associated telemetry packages
Removed go4.org and its transitive dependencies from go.mod and go.sum:
- go4.org (unused dependency)
- google.golang.org/api/* packages
- google.golang.org/genproto/* packages
- cloud.google.com/go/* packages
- gocloud.dev/* packages

Total reduction: ~4.9 MB of unnecessary telemetry dependencies.
All functionality preserved through vendored sevenzip package.
2026-02-22 16:29:25 -05:00
john-okeefe 46ae45ee92 feat: vendor bodgit/sevenzip package to remove go4.org dependency
Vendored the sevenzip package to eliminate dependency chain:
- sevenzip -> go4.org -> 25+ Google/Cloud/telemetry packages

Changes:
- Added internal/sevenzip/ with full package source
- Inlined go4.org/readerutil into multireaderat.go
- Updated all internal imports to use bookhoard/internal/sevenzip
- Preserved .cb7 comic archive support

This reduces bloat by ~4.9 MB and removes unused telemetry
dependencies while maintaining all functionality.
2026-02-22 16:29:21 -05:00
john-okeefe c6cf038c8e chore(deps): upgrade @tailwindcss/forms to v0.5.11
- Upgrade @tailwindcss/forms from 0.5.7 to 0.5.11 (latest)
- Regenerate minified CSS with new forms plugin
- Build and tests passing
2026-02-22 13:32:51 -05:00
john-okeefe 94e179d9bf removed finished plans
- Carousel has been implemented and tested
- API Consolidation has been implemented and tested
2026-02-22 13:18:03 -05:00
john-okeefe 87e28d18ff chore(deps): upgrade indirect dependencies
Upgrades indirect dependencies:
- davecgh/go-spew: v1.1.1 → v1.1.2
- kr/pretty: v0.3.0 → v0.3.1
- pmezard/go-difflib: v1.0.0 → v1.0.1
- stretchr/objx: v0.5.2 → v0.5.3
- xyproto/randomstring: v1.0.5 → v1.2.0

Also upgrades related cloud, opentelemetry, and grpc
dependencies to their latest compatible versions.

Build and all tests passing.
2026-02-22 13:13:43 -05:00
john-okeefe 9e420b63ad chore(deps): upgrade core dependencies
- pgx/v5: v5.4.3 → v5.8.0
- golang-jwt/jwt/v5: v5.3.0 → v5.3.1
- echo/v4: v4.13.4 → v4.15.1
- google/uuid: v1.4.0 → v1.6.0
- golang.org/x/crypto: v0.46.0 → v0.48.0
- golang.org/x/text: v0.33.0 → v0.34.0

Also updates indirect dependencies including puddle/v2, brotli,
regexp2, and other transitive deps.

Build and tests passing with pgx v5.8.0 (internal/anynil package
removed but not used by our code).
2026-02-22 13:11:06 -05:00
john-okeefe 31e286a14b fix(handlers): check user existence before deletion in DeleteUser
Add explicit check to verify target user exists in database before
attempting deletion. Previously, the handler would return 200 OK when
trying to delete non-existent users.

Changes:
- Add userFound flag to track if target user was found in user list
- Explicitly check pgtype.UUID.Bytes against all users' IDs
- Return 404 Not Found if user doesn't exist (before last admin check)
- Supports both JSON and HTML (HTMX) response formats

This fixes the failing test:
- TestDeleteUserConsolidated/DELETE_/api/auth/profile/:id_-_Delete_non-existent_user

The check uses the existing ListUsers result, so no additional database
query is required. The pgtype.UUID.Bytes comparison ensures exact
16-byte UUID matching.
2026-02-22 12:17:50 -05:00
john-okeefe 19e389f966 test: fix password mismatch test to use valid complex passwords
The test was using simple passwords ('password1', 'password2') that
failed complexity validation before the mismatch check could run.

Changed to use valid complex passwords that don't match:
- new_password: 'NewPassword123!'
- confirm_password: 'DifferentPass123!'

This properly tests the mismatch validation path. All 4 subtests in
TestUpdatePasswordAdminMode now pass.
2026-02-22 11:43:42 -05:00
john-okeefe 4cee9966c3 docs: add testing guide for developers
Add comprehensive testing documentation covering:
- Test email domain usage (@tests.bookhoard.internal)
- Standard test users and their credentials
- Test lifecycle and cleanup process
- How to write tests properly
- Running tests (make targets, specific tests)
- Test organization and helper functions

This helps developers understand the testing infrastructure and
prevents accidental data loss when running tests.
2026-02-22 11:21:25 -05:00
john-okeefe 70dd89ceac test(bruno): update API tests to use @tests.bookhoard.internal
Update test email domain in Bruno API collection files:
- Login User.yml
- Register User.yml
- Update Profile.yml

Ensures API tests use the dedicated test domain and won't conflict
with real user data when developers run tests.
2026-02-22 11:21:15 -05:00
john-okeefe 89732b041b test: update test files to use @tests.bookhoard.internal domain
Update email domain in remaining test files:
- device_cap_test.go
- device_test.go
- queue_test.go
- refresh_token_test.go
- seven_day_session_test.go

All test files now consistently use the dedicated test domain
to prevent conflicts with real user data.
2026-02-22 11:21:00 -05:00
john-okeefe 8ba8601841 test(user): fix TestUpdateProfileAdminMode test failures
- Fix username conflict: use unique name 'updateduser-admin-test'
- Fix 'last admin' test: explicitly delete regular user and verify admin count
- Add missing Content-Type header to PUT request
- Fix assertion: match actual validator error message ('oneof')
- Update email domain references to @tests.bookhoard.internal

All 5 subtests now pass:
- Admin update username ✓
- Admin promote user to admin ✓
- Try to demote last admin ✓
- Non-admin tries update ✓
- Invalid role ✓
2026-02-22 11:20:31 -05:00
john-okeefe cbf80037c4 test(improve): use dedicated test domain and improve cleanup
- Change test email domain from @example.com to @tests.bookhoard.internal
- This prevents accidental deletion of real user data when self-hosters run tests
- Improve test cleanup: delete ALL users with test domains before each test
- Ensures complete test isolation by cleaning up users from previous tests
- Handles edge cases where tests promote users to admin or modify accounts

The @tests.bookhoard.internal domain is clearly for testing only and
won't conflict with real user emails.
2026-02-22 11:20:15 -05:00
john-okeefe 334af53749 chore(templates): remove obsolete admin profile template files
Remove admin_profile.templ and admin_profile_templ.go as they have been
replaced by the new consolidated user management templates.
2026-02-22 02:00:47 -05:00
john-okeefe 2b92d5c6c1 test(bruno): update API collections for consolidated endpoints
Add collections for Delete User, Reset User Password, and Update User
endpoints. Remove obsolete collections for individual profile update
operations. Update Update Profile collection to reflect new consolidated
API structure.
2026-02-22 01:59:58 -05:00
john-okeefe ff25454901 docs: update API documentation for consolidated user management
Add documentation for delete_user and reset_user_password endpoints.
Update update_profile to reflect consolidated endpoint. Remove obsolete
documentation for individual update operations. Add profile guide for
end-users. Update API_CONSOLIDATION_PLAN.md with implementation status.
2026-02-22 01:59:52 -05:00
john-okeefe 9ea0ec5a3e feat(templates): consolidate admin and profile templates
Add admin_users.templ for user management interface with delete, password
reset, and edit capabilities. Add profile.templ and related components for
user profile management. Remove admin_profile.templ. Update all templates
to use new consolidated API endpoints.
2026-02-22 01:58:02 -05:00
john-okeefe 930d020ec1 feat(router): add routes for consolidated user management
Add DELETE /api/auth/users/:id, PUT /api/auth/users/:id/password, and
PUT /api/auth/users/:id routes. Remove individual profile update routes
in favor of consolidated endpoints.
2026-02-22 01:57:56 -05:00
john-okeefe bb0970dfd0 feat(handlers): implement consolidated user profile endpoints
Implement DeleteUser, ResetUserPassword, and UpdateUserAdmin handlers.
Update collections handler to check soft-deleted users. Update dashboard
service to exclude deleted users from statistics.
2026-02-22 01:57:49 -05:00
john-okeefe e3a3aa124f feat(api): consolidate user profile update endpoints
Add delete_user, reset_user_password, and update_user endpoints to replace
individual update operations. Update database schema to include deleted_at
column for soft deletion. Add DeleteUser, ResetUserPassword, and
UpdateUserAdmin queries. Update Querier with new methods for user management.
2026-02-22 01:57:42 -05:00
john-okeefe 86cc9b4e59 test(opds): fix token invalidation by restructuring tests
Restructure TestOPDSEndpoints and TestOPDSConversion to follow the Kobo
test pattern. Create all media items at parent level before any subtests
run, avoiding token invalidation when setupDeviceTest is called. Subtests
now use pre-created media IDs and device.AuthToken for authentication.
2026-02-22 01:57:28 -05:00
john-okeefe f54508e4dd test: improve test isolation and setup management
Add Token and RegularToken fields to TestServerSetup for pre-authenticated
access. Update setupTestServer to create fresh users with valid tokens at
initialization time. Simplify createTestMediaItemID to use setup.Token.
Remove loginTestUser, loginRegularUser, loginAdminUser functions in favor
of setup.Token/setup.RegularToken. Update createTestUserOnce and
getTestUserID/getRegularUserID to be idempotent. Update all test files to
use setup.Token instead of calling login helpers.
2026-02-22 01:57:22 -05:00
john-okeefe 9a09161f24 build: update tailwind config to include TypeScript sources
- Add ./web/src/**/*.ts to tailwind content paths
- Regenerate CSS with updated config
2026-02-21 00:59:51 -05:00
john-okeefe b5899af3c3 refactor(templates): consolidate header.js loading
- Move header.js script from individual templates to header.templ
- Removes duplicate script tags from bookshelf, collections, progress, etc.
- Fixes indentation in docs.templ
2026-02-21 00:59:42 -05:00