diff --git a/README.md b/README.md index 2392e8c..d26e460 100644 --- a/README.md +++ b/README.md @@ -5,21 +5,24 @@ A self-hosted ebook management system built with Go, PostgreSQL, HTMX, and Tailw ## ✨ Features - **πŸ”’ Multi-User Authentication**: Complete user system with registration/login, JWT-based sessions, and bcrypt password hashing +- **πŸ‘‘ Admin-Based Control**: Role-based access control with admin privileges for folder and ebook management - **πŸ‘€ User Profile Management**: Update profile information, username, email, password, and account deletion -- **βš™οΈ Scan Settings**: Configure scan frequency and auto-scan options per user +- **βš™οΈ Scan Settings**: Configure scan frequency and auto-scan options per user (admin only) - **βœ… Server-Side Validation**: Comprehensive input validation with detailed error messages - **πŸŒ™ Multiple Themes**: 11 beautiful themes including Tokyo Night, Dracula, Nord, Solarized Dark, Monokai, One Dark Pro, Material Dark, and Catppuccin variants (Mocha, Macchiato, FrappΓ©, Latte) with user preferences saved to database - **🎨 Theme Persistence**: User theme choices sync between browser and server - **πŸ“– Reading Progress**: User-specific reading progress tracking - **⭐ Advanced Rating System**: 5-star rating with half-star precision, dialog-based input, and zero-rating fallback -- **πŸ“ Multiple Folder Support**: Configure multiple ebook folders per user for comprehensive library management -- **πŸ” Enhanced Scanner**: Intelligent ebook discovery with Calibre folder structure support and comprehensive metadata extraction -- **πŸ‘€ Real-Time Monitoring**: File system monitoring for automatic ebook detection and updates +- **πŸ“ Folder Management**: Configure and manage ebook folders (admin only) +- **πŸ” Enhanced Scanner**: Intelligent ebook discovery with Calibre folder structure support and comprehensive metadata extraction (admin only) +- **πŸ‘€ Real-Time Monitoring**: File system monitoring for automatic ebook detection and updates (admin only) - **πŸ“š Rich Metadata**: Automatic extraction of ebook metadata (title, author, description, publisher, series, ISBN, tags) from EPUB files with Calibre-specific support - **πŸ›οΈ Calibre Integration**: Full support for Calibre folder structures and metadata (calibre:series, calibre:series_index) - **πŸ“‚ Smart Folder Detection**: Automatically detects Author/Book, Author/Series/Book, and Calibre naming conventions - **πŸ”„ Subfolder Scanning**: Recursively scans subdirectories with proper folder structure analysis - **πŸ”§ RESTful API**: Clean API endpoints with JWT authentication and proper error handling +- **πŸ›‘οΈ Role-Based Security**: Admin users can manage folders and ebook metadata; regular users can view, rate, and track reading progress +- **πŸ“‹ Shared Library**: All users can view the complete ebook collection, with admin tracking of who added each book - **🐳 Docker Ready**: Single-container deployment with PostgreSQL - **πŸ§ͺ API Testing**: Complete Bruno collection for testing all endpoints - **πŸ“± Responsive Design**: Mobile-first responsive interface using Tailwind CSS @@ -70,18 +73,45 @@ echo "DBPASS=$DBPASS" >> .env ### Running the Application **Option 1: Using .env file** -1. Clone the repository +1. Clone repository 2. Set up environment: - ```bash - cp .env.example .env - # Edit .env with your secure values - ``` + ```bash + cp .env.example .env + # Edit .env with your secure values + ``` 3. Run the application: - ```bash - docker-compose up --build - ``` + ```bash + docker-compose up --build + ``` 4. Access the application at http://localhost:8765 +### Admin Setup + +After creating your first user account, you'll need to set up admin privileges: + +**Option 1: Direct Database Update** +```sql +-- Connect to the database and update user role +UPDATE users SET role = 'admin' WHERE email = 'your-admin-email@example.com'; +``` + +**Option 2: Using psql** +```bash +# Connect to the running database container +docker exec -it bookmann-db-1 psql -U postgres -d ebookdb + +# Update user role +UPDATE users SET role = 'admin' WHERE email = 'your-admin-email@example.com'; + +# Exit psql +\q +``` + +**Role Permissions:** +- **Admin Users**: Can add/edit/delete folders, scan ebooks, modify/delete any ebook metadata +- **Regular Users**: Can view all ebooks, rate books, track reading progress, manage their profile +- **Shared Library**: All users see the same ebook collection, but only admins can modify it + **Option 2: Using docker-compose variables** 1. Clone the repository 2. Set environment variables directly: @@ -140,21 +170,21 @@ The application uses Go HTML templates for server-side rendering with HTMX for d - `PUT /api/user/password` - Update password (requires JWT) - `DELETE /api/user/account` - Delete user account (requires JWT) -### Ebook Folders (Protected) +### Ebook Folders (Admin Only) - `POST /api/auth/ebook-folders` - Add an ebook folder for scanning -- `GET /api/auth/ebook-folders` - List user's configured ebook folders +- `GET /api/auth/ebook-folders` - List configured ebook folders - `DELETE /api/auth/ebook-folders` - Remove an ebook folder -### Library Settings (Protected) +### Library Settings (Admin Only) - `PUT /api/library/scan-settings` - Update scan frequency and auto-scan settings - `GET /api/library/scan-settings` - Get current scan settings -### Ebooks (Protected) -- `GET /api/ebooks` - List ebooks -- `GET /api/ebooks/:id` - Get specific ebook -- `POST /api/ebooks` - Create new ebook -- `PUT /api/ebooks/:id` - Update ebook -- `DELETE /api/ebooks/:id` - Delete ebook +### Ebooks (Mixed Access) +- `GET /api/ebooks` - List ebooks (all authenticated users) +- `GET /api/ebooks/:id` - Get specific ebook (all authenticated users) +- `POST /api/ebooks` - Create new ebook (admin only) +- `PUT /api/ebooks/:id` - Update ebook (admin only) +- `DELETE /api/ebooks/:id` - Delete ebook (admin only) ### Reading Progress (Protected) - `GET /api/ebooks/:id/progress` - Get reading progress @@ -167,8 +197,8 @@ The application uses Go HTML templates for server-side rendering with HTMX for d - `DELETE /api/ebooks/:id/rating` - Delete user's rating - `GET /api/ebooks/:id/ratings` - Get all ratings for ebook -### Scanner (Protected) -- `POST /api/scanner/scan` - Scan user's configured ebook folders (supports optional folder_paths parameter for testing) +### Scanner (Admin Only) +- `POST /api/scanner/scan` - Scan configured ebook folders (supports optional folder_paths parameter for testing) - `POST /api/scanner/start` - Start real-time monitoring of configured folders - `POST /api/scanner/stop` - Stop real-time folder monitoring @@ -211,9 +241,10 @@ Bookmann includes an intelligent ebook scanner with full Calibre integration and ### Setting Up Folders -1. **Add Folders**: Use `POST /api/auth/ebook-folders` to add ebook folders to your account +1. **Add Folders**: Use `POST /api/auth/ebook-folders` to add ebook folders (admin only) 2. **Supported Formats**: EPUB (full metadata), PDF (basic), MOBI, AZW3, FB2, TXT 3. **Calibre Integration**: Automatically recognizes Calibre folder structures and metadata +4. **Admin Privileges**: Only administrators can configure folders and initiate scans ### Folder Structure Support @@ -327,6 +358,16 @@ Use the included Bruno collection in the `bruno/` directory for testing the API: ## 🎨 Recent Enhancements +### πŸ”’ Admin-Based Control System +- **Role-Based Access**: Implemented complete role system with 'admin' and 'user' roles +- **Admin Middleware**: Created authorization middleware for protected operations +- **Folder Management**: Only admins can add/edit/delete ebook folders and configure scanner +- **Ebook CRUD**: Only admins can create, update, or delete ebook metadata +- **Scanner Control**: Only admins can initiate scans and control file system monitoring +- **Shared Library**: All users can view ebooks, but only admins can modify the library +- **Admin Tracking**: Ebooks track which admin added them via `added_by_admin_id` field +- **Frontend Protection**: Admin controls only visible to users with admin role + ### Major Scanner Improvements - **Calibre Integration**: Full support for Calibre folder structures and metadata fields - **Smart Folder Detection**: Automatically recognizes Author/Book, Author/Series/Book patterns diff --git a/bruno/README.md b/bruno/README.md index 888d48b..9d27850 100644 --- a/bruno/README.md +++ b/bruno/README.md @@ -17,18 +17,28 @@ This directory contains Bruno collection for testing the Bookmann API with compr - **Login User**: POST /api/auth/login - Authenticate (email or username) - **Get Profile**: GET /api/auth/profile - Get user info (requires token) -### Ebooks (Protected - JWT Required) -- **List Ebooks**: GET /api/ebooks - Paginated ebook list -- **Get Ebook**: GET /api/ebooks/:id - Single ebook details -- **Create Ebook**: POST /api/ebooks - Add new ebook -- **Update Ebook**: PUT /api/ebooks/:id - Modify ebook metadata -- **Delete Ebook**: DELETE /api/ebooks/:id - Remove ebook +### Folders (Admin Only) +- **Add Ebook Folder**: POST /api/auth/ebook-folders - Add folder for scanning (admin only) +- **Get Ebook Folders**: GET /api/auth/ebook-folders - List configured folders (admin only) +- **Delete Ebook Folder**: DELETE /api/auth/ebook-folders - Remove folder (admin only) -### Reading Progress (Protected - JWT Required) +### Ebooks (Mixed Access) +- **List Ebooks**: GET /api/ebooks - Paginated ebook list (all authenticated users) +- **Get Ebook**: GET /api/ebooks/:id - Single ebook details (all authenticated users) +- **Create Ebook**: POST /api/ebooks - Add new ebook (admin only) +- **Update Ebook**: PUT /api/ebooks/:id - Modify ebook metadata (admin only) +- **Delete Ebook**: DELETE /api/ebooks/:id - Remove ebook (admin only) + +### Scanner (Admin Only) +- **Scan Ebooks**: POST /api/scanner/scan - Scan configured folders (admin only) +- **Start Scanner**: POST /api/scanner/start - Start real-time monitoring (admin only) +- **Stop Scanner**: POST /api/scanner/stop - Stop monitoring (admin only) + +### Reading Progress (All Users) - **Get Reading Progress**: GET /api/ebooks/:id/progress - User's progress - **Update Reading Progress**: PUT /api/ebooks/:id/progress - Update progress -### Ratings (Protected - JWT Required) +### Ratings (All Users) - **Get Ebook Rating**: GET /api/ebooks/:id/rating - User's rating for ebook (returns 0 if unrated) - **Create/Update Rating**: POST /api/ebooks/:id/rating - Rate ebook (1-5 stars) - **Delete Rating**: DELETE /api/ebooks/:id/rating - Remove user's rating @@ -47,8 +57,11 @@ Each request includes: - **Authentication Flow**: Register β†’ Login β†’ Use Bearer token for all other requests - **JWT Tokens**: Valid for 24 hours, include in `Authorization: Bearer ` header -- **User Isolation**: Progress, ratings, and data are user-specific +- **Role System**: Two roles - 'admin' and 'user'. Admins can manage folders and ebooks, users can view/rate/track progress +- **Shared Library**: All users can view the complete ebook collection, but only admins can modify it +- **User Isolation**: Progress, ratings, and profile data are user-specific - **Rating Behavior**: Get rating returns 0 when no rating exists (instead of 404) +- **Admin Setup**: First admin must be created by updating user role in database: `UPDATE users SET role = 'admin' WHERE email = 'admin@example.com';` - **Variables**: Update `ebook_id` for testing specific ebooks -- **Security**: Passwords hashed with bcrypt, unique email/username constraints +- **Security**: Passwords hashed with bcrypt, unique email/username constraints, role-based access control - **JSON**: All requests/responses use JSON format \ No newline at end of file diff --git a/bruno/ebooks/Create Ebook.bru b/bruno/ebooks/Create Ebook.bru index 509a013..379ae3b 100644 --- a/bruno/ebooks/Create Ebook.bru +++ b/bruno/ebooks/Create Ebook.bru @@ -46,9 +46,9 @@ settings { docs { ## Create Ebook - Creates a new ebook entry in the library. + Creates a new ebook entry in the library. **Admin only operation.** - **Authentication:** Required (Bearer token) + **Authentication:** Required (Bearer token + Admin role) **Request Body:** - `title` (string, required): Book title @@ -67,9 +67,12 @@ docs { - `publisher` (string, optional): Publisher name - `contributors` (string, optional): Additional contributors - **Response:** Created ebook object + **Response:** Created ebook object (with added_by_admin_id field) **Error Responses:** - 401: Invalid authentication + - 403: Forbidden (non-admin users) - 400: Invalid request data + + **Note:** Ebook will be automatically associated with the admin user who creates it. } diff --git a/bruno/scanner/Scan Ebooks.bru b/bruno/scanner/Scan Ebooks.bru index 03afcb8..e3c436b 100644 --- a/bruno/scanner/Scan Ebooks.bru +++ b/bruno/scanner/Scan Ebooks.bru @@ -18,16 +18,16 @@ settings { docs { ## Scan Ebooks - Scans the user's configured ebook folders for ebooks and adds them to the database. + Scans configured ebook folders for ebooks and adds them to the database. **Admin only operation.** **Method:** POST **Endpoint:** /api/scanner/scan - **Authentication:** Required + **Authentication:** Required (Admin role required) **Request Body:** - - `folder_paths` (array of strings, optional): Array of folder paths to scan. If not provided, uses user's saved folders from Add Ebook Folder. + - `folder_paths` (array of strings, optional): Array of folder paths to scan. If not provided, uses configured folders from Add Ebook Folder. **Response:** - `message` (string): Success message @@ -36,8 +36,11 @@ docs { - 200: Success - 400: Bad Request - 401: Unauthorized + - 403: Forbidden (non-admin users) **Usage:** - Without body: Scans all folders added via "Add Ebook Folder" - With folder_paths: Scans the specified paths directly (useful for testing) + + **Note:** All discovered ebooks will be associated with the admin user who initiated the scan. } diff --git a/bruno/user/Add Ebook Folder.bru b/bruno/user/Add Ebook Folder.bru index 28b9ef6..c0b3203 100644 --- a/bruno/user/Add Ebook Folder.bru +++ b/bruno/user/Add Ebook Folder.bru @@ -24,20 +24,20 @@ settings { docs { ## Add Ebook Folder - Adds a new ebook folder for the authenticated user. + Adds a new ebook folder for scanning. **Admin only operation.** **Method:** POST **Endpoint:** /api/auth/ebook-folders - **Authentication:** Required + **Authentication:** Required (Admin role required) **Request Body:** - `folder_path` (string, required): Path to the ebook folder **Response:** - `id` (string): Folder ID - - `user_id` (string): User ID + - `user_id` (string): Admin user ID - `folder_path` (string): Folder path - `created_at` (string): Creation timestamp @@ -45,5 +45,6 @@ docs { - 201: Created - 400: Invalid request - 401: Unauthorized + - 403: Forbidden (non-admin users) - 409: Folder already exists }