From f2994f914775d2eba5881833a25930fb8051d209 Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Mon, 26 Jan 2026 21:19:19 -0500 Subject: [PATCH] refactor: Reorganize Bruno requests by role permissions - Create separate admin folder for admin-only operations - Move admin endpoints (Create/Update/Delete Ebook, Scanner, Folder Management) to /bruno/admin/ - Add admin dashboard, profile, and library page requests - Add Register Admin User request with explicit admin role - Update Register User request to include role field - Remove empty scanner folder structure API organization: - Admin requests: /bruno/admin/ (require admin role) - User requests: /bruno/user/ (available to all authenticated users) - Environment: Single {{token}} variable works for both roles --- bruno/admin/Get Admin Dashboard.bru | 10 ++++ bruno/admin/Get Admin Library.bru | 10 ++++ bruno/admin/Get Admin Profile.bru | 10 ++++ bruno/ebooks/Create Ebook.bru | 78 ----------------------------- bruno/ebooks/Delete Ebook.bru | 40 --------------- bruno/ebooks/Update Ebook.bru | 63 ----------------------- bruno/scanner/Scan Ebooks.bru | 46 ----------------- bruno/scanner/Start Scanner.bru | 39 --------------- bruno/scanner/Stop Scanner.bru | 37 -------------- bruno/user/Add Ebook Folder.bru | 50 ------------------ bruno/user/Delete Ebook Folder.bru | 46 ----------------- bruno/user/Get Ebook Folders.bru | 38 -------------- bruno/user/Register Admin User.bru | 68 +++++++++++++++++++++++++ bruno/user/Register User.bru | 11 ++-- 14 files changed, 105 insertions(+), 441 deletions(-) create mode 100644 bruno/admin/Get Admin Dashboard.bru create mode 100644 bruno/admin/Get Admin Library.bru create mode 100644 bruno/admin/Get Admin Profile.bru delete mode 100644 bruno/ebooks/Create Ebook.bru delete mode 100644 bruno/ebooks/Delete Ebook.bru delete mode 100644 bruno/ebooks/Update Ebook.bru delete mode 100644 bruno/scanner/Scan Ebooks.bru delete mode 100644 bruno/scanner/Start Scanner.bru delete mode 100644 bruno/scanner/Stop Scanner.bru delete mode 100644 bruno/user/Add Ebook Folder.bru delete mode 100644 bruno/user/Delete Ebook Folder.bru delete mode 100644 bruno/user/Get Ebook Folders.bru create mode 100644 bruno/user/Register Admin User.bru diff --git a/bruno/admin/Get Admin Dashboard.bru b/bruno/admin/Get Admin Dashboard.bru new file mode 100644 index 0000000..63ecb2c --- /dev/null +++ b/bruno/admin/Get Admin Dashboard.bru @@ -0,0 +1,10 @@ +meta { + name: Get Admin Dashboard + type: http + seq: 10 +} + +get { + url: {{base_url}}/admin + auth: bearer +} \ No newline at end of file diff --git a/bruno/admin/Get Admin Library.bru b/bruno/admin/Get Admin Library.bru new file mode 100644 index 0000000..59857c9 --- /dev/null +++ b/bruno/admin/Get Admin Library.bru @@ -0,0 +1,10 @@ +meta { + name: Get Admin Library + type: http + seq: 12 +} + +get { + url: {{base_url}}/admin/library + auth: bearer +} \ No newline at end of file diff --git a/bruno/admin/Get Admin Profile.bru b/bruno/admin/Get Admin Profile.bru new file mode 100644 index 0000000..0619091 --- /dev/null +++ b/bruno/admin/Get Admin Profile.bru @@ -0,0 +1,10 @@ +meta { + name: Get Admin Profile + type: http + seq: 11 +} + +get { + url: {{base_url}}/admin/profile + auth: bearer +} \ No newline at end of file diff --git a/bruno/ebooks/Create Ebook.bru b/bruno/ebooks/Create Ebook.bru deleted file mode 100644 index 379ae3b..0000000 --- a/bruno/ebooks/Create Ebook.bru +++ /dev/null @@ -1,78 +0,0 @@ -meta { - name: Create Ebook - type: http - seq: 3 -} - -post { - url: http://localhost:8765/api/ebooks - body: json - auth: inherit -} - -body:json { - { - "title": "Sample Book", - "author": "Sample Author", - "isbn": "1234567890", - "description": "A sample ebook", - "file_path": "/uploads/sample.epub", - "file_size": 1024000, - "mime_type": "application/epub+zip", - "cover_image_path": "/uploads/cover.jpg", - "series": "Sample Series", - "series_number": 1, - "tags": "fiction,adventure", - "asin": "B0123456789", - "date_published": "2023-01-15", - "publisher": "Sample Publisher", - "contributors": "Editor Name, Illustrator Name" - } -} - -script:post-response { - function onResponse(res) { - let data = res.getBody(); - let token = bru.setEnvVar("ebookid", data.id, { persist: true }); - } - onResponse(res); -} - -settings { - encodeUrl: true - timeout: 0 -} - -docs { - ## Create Ebook - - Creates a new ebook entry in the library. **Admin only operation.** - - **Authentication:** Required (Bearer token + Admin role) - - **Request Body:** - - `title` (string, required): Book title - - `author` (string, optional): Book author - - `isbn` (string, optional): ISBN number - - `description` (string, optional): Book description - - `file_path` (string, required): Path to ebook file - - `file_size` (number, optional): File size in bytes - - `mime_type` (string, optional): MIME type - - `cover_image_path` (string, optional): Path to cover image - - `series` (string, optional): Book series name - - `series_number` (number, optional): Position in series - - `tags` (string, optional): Comma-separated tags - - `asin` (string, optional): Amazon ASIN - - `date_published` (string, optional): Publication date (YYYY-MM-DD) - - `publisher` (string, optional): Publisher name - - `contributors` (string, optional): Additional contributors - - **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/ebooks/Delete Ebook.bru b/bruno/ebooks/Delete Ebook.bru deleted file mode 100644 index c29a24e..0000000 --- a/bruno/ebooks/Delete Ebook.bru +++ /dev/null @@ -1,40 +0,0 @@ -meta { - name: Delete Ebook - type: http - seq: 5 -} - -delete { - url: http://localhost:8765/api/ebooks/{{ebookid}} - body: none - auth: inherit -} - -script:post-response { - function onResponse(res) { - let token = bru.setEnvVar("ebookid", "", { persist: true }); - } - onResponse(res); -} - -settings { - encodeUrl: true - timeout: 0 -} - -docs { - ## Delete Ebook - - Removes an ebook from the library. - - **Authentication:** Required (Bearer token) - - **Path Parameters:** - - `id` (string): Ebook UUID - - **Response:** 204 No Content - - **Error Responses:** - - 401: Invalid authentication - - 404: Ebook not found -} diff --git a/bruno/ebooks/Update Ebook.bru b/bruno/ebooks/Update Ebook.bru deleted file mode 100644 index a99dda3..0000000 --- a/bruno/ebooks/Update Ebook.bru +++ /dev/null @@ -1,63 +0,0 @@ -meta { - name: Update Ebook - type: http - seq: 4 -} - -put { - url: http://localhost:8765/api/ebooks/{{ebookid}} - body: json - auth: inherit -} - -body:json { - { - "title": "Updated Book Title", - "author": "Updated Author", - "description": "Updated description", - "series": "Updated Series", - "series_number": 2, - "tags": "fiction,drama", - "asin": "B0987654321", - "date_published": "2023-06-15", - "publisher": "Updated Publisher", - "contributors": "Updated Editor" - } -} - -settings { - encodeUrl: true - timeout: 0 -} - -docs { - ## Update Ebook - - Updates an existing ebook's metadata. - - **Authentication:** Required (Bearer token) - - **Path Parameters:** - - `id` (string): Ebook UUID - - **Request Body:** (all fields optional) - - `title` (string): Book title - - `author` (string): Book author - - `isbn` (string): ISBN number - - `description` (string): Book description - - `cover_image_path` (string): Path to cover image - - `series` (string): Book series name - - `series_number` (number): Position in series - - `tags` (string): Comma-separated tags - - `asin` (string): Amazon ASIN - - `date_published` (string): Publication date (YYYY-MM-DD) - - `publisher` (string): Publisher name - - `contributors` (string): Additional contributors - - **Response:** Updated ebook object - - **Error Responses:** - - 401: Invalid authentication - - 404: Ebook not found - - 400: Invalid request data -} diff --git a/bruno/scanner/Scan Ebooks.bru b/bruno/scanner/Scan Ebooks.bru deleted file mode 100644 index e3c436b..0000000 --- a/bruno/scanner/Scan Ebooks.bru +++ /dev/null @@ -1,46 +0,0 @@ -meta { - name: Scan Ebooks - type: http - seq: 1 -} - -post { - url: {{base_url}}/api/scanner/scan - body: json - auth: inherit -} - -settings { - encodeUrl: true - timeout: 0 -} - -docs { - ## Scan Ebooks - - Scans configured ebook folders for ebooks and adds them to the database. **Admin only operation.** - - **Method:** POST - - **Endpoint:** /api/scanner/scan - - **Authentication:** Required (Admin role required) - - **Request Body:** - - `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 - - **Status Codes:** - - 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/scanner/Start Scanner.bru b/bruno/scanner/Start Scanner.bru deleted file mode 100644 index d6143af..0000000 --- a/bruno/scanner/Start Scanner.bru +++ /dev/null @@ -1,39 +0,0 @@ -meta { - name: Start Scanner - type: http - seq: 2 -} - -post { - url: {{base_url}}/api/scanner/start - body: json - auth: inherit -} - -settings { - encodeUrl: true - timeout: 0 -} - -docs { - ## Start Scanner - - Starts monitoring the specified folders for ebook changes. - - **Method:** POST - - **Endpoint:** /api/scanner/start - - **Authentication:** Required - - **Request Body:** - - `folder_paths` (array of strings, required): Array of folder paths to monitor - - **Response:** - - `message` (string): Success message - - **Status Codes:** - - 200: Success - - 400: Bad Request - - 401: Unauthorized -} diff --git a/bruno/scanner/Stop Scanner.bru b/bruno/scanner/Stop Scanner.bru deleted file mode 100644 index d96e161..0000000 --- a/bruno/scanner/Stop Scanner.bru +++ /dev/null @@ -1,37 +0,0 @@ -meta { - name: Stop Scanner - type: http - seq: 3 -} - -post { - url: {{base_url}}/api/scanner/stop - body: none - auth: inherit -} - -settings { - encodeUrl: true - timeout: 0 -} - -docs { - ## Stop Scanner - - Stops monitoring folders for ebook changes. - - **Method:** POST - - **Endpoint:** /api/scanner/stop - - **Authentication:** Required - - **Request Body:** None - - **Response:** - - `message` (string): Success message - - **Status Codes:** - - 200: Success - - 401: Unauthorized -} \ No newline at end of file diff --git a/bruno/user/Add Ebook Folder.bru b/bruno/user/Add Ebook Folder.bru deleted file mode 100644 index c0b3203..0000000 --- a/bruno/user/Add Ebook Folder.bru +++ /dev/null @@ -1,50 +0,0 @@ -meta { - name: Add Ebook Folder - type: http - seq: 8 -} - -post { - url: {{base_url}}/api/auth/ebook-folders - body: json - auth: inherit -} - -body:json { - { - "folder_path": "/app/uploads" - } -} - -settings { - encodeUrl: true - timeout: 0 -} - -docs { - ## Add Ebook Folder - - Adds a new ebook folder for scanning. **Admin only operation.** - - **Method:** POST - - **Endpoint:** /api/auth/ebook-folders - - **Authentication:** Required (Admin role required) - - **Request Body:** - - `folder_path` (string, required): Path to the ebook folder - - **Response:** - - `id` (string): Folder ID - - `user_id` (string): Admin user ID - - `folder_path` (string): Folder path - - `created_at` (string): Creation timestamp - - **Status Codes:** - - 201: Created - - 400: Invalid request - - 401: Unauthorized - - 403: Forbidden (non-admin users) - - 409: Folder already exists -} diff --git a/bruno/user/Delete Ebook Folder.bru b/bruno/user/Delete Ebook Folder.bru deleted file mode 100644 index ee9c1b5..0000000 --- a/bruno/user/Delete Ebook Folder.bru +++ /dev/null @@ -1,46 +0,0 @@ -meta { - name: Delete Ebook Folder - type: http - seq: 10 -} - -delete { - url: {{base_url}}/api/auth/ebook-folders - body: json - auth: inherit -} - -body:json { - { - "folder_path": "/app/uploads" - } -} - -settings { - encodeUrl: true - timeout: 0 -} - -docs { - ## Delete Ebook Folder - - Removes an ebook folder for the authenticated user. - - **Method:** DELETE - - **Endpoint:** /api/auth/ebook-folders - - **Authentication:** Required - - **Request Body:** - - `folder_path` (string, required): Path to the ebook folder to remove - - **Response:** - - `message` (string): Success message - - **Status Codes:** - - 200: Success - - 400: Invalid request - - 401: Unauthorized - - 500: Internal server error -} diff --git a/bruno/user/Get Ebook Folders.bru b/bruno/user/Get Ebook Folders.bru deleted file mode 100644 index a7ad3ff..0000000 --- a/bruno/user/Get Ebook Folders.bru +++ /dev/null @@ -1,38 +0,0 @@ -meta { - name: Get Ebook Folders - type: http - seq: 9 -} - -get { - url: {{base_url}}/api/auth/ebook-folders - body: none - auth: inherit -} - -settings { - encodeUrl: true - timeout: 0 -} - -docs { - ## Get Ebook Folders - - Retrieves the list of ebook folders for the authenticated user. - - **Method:** GET - - **Endpoint:** /api/auth/ebook-folders - - **Authentication:** Required - - **Response:** Array of folder objects - - `id` (string): Folder ID - - `user_id` (string): User ID - - `folder_path` (string): Folder path - - `created_at` (string): Creation timestamp - - **Status Codes:** - - 200: Success - - 401: Unauthorized -} \ No newline at end of file diff --git a/bruno/user/Register Admin User.bru b/bruno/user/Register Admin User.bru new file mode 100644 index 0000000..04ad418 --- /dev/null +++ b/bruno/user/Register Admin User.bru @@ -0,0 +1,68 @@ +meta { + name: Register Admin User + type: http + seq: 4 +} + +post { + url: {{base_url}}/api/auth/register + body: json + auth: inherit +} + +body:json { + { + "email": "admin@example.com", + "username": "admin", + "password": "admin123", + "first_name": "Admin", + "last_name": "User", + "role": "admin" + } +} + +script:post-response { + function onResponse(res) { + let data = res.getBody(); + return bru.setEnvVar("token", data.token, { persist: true }); + } + onResponse(res); +} + +settings { + encodeUrl: true + timeout: 0 +} + +docs { + ## Register Admin User + + Creates a new admin user account. + + **Method:** POST + + **Endpoint:** /api/auth/register + + **Request Body:** + - `email` (string): Email address + - `username` (string): Username + - `password` (string): Password + - `first_name` (string, optional): First name + - `last_name` (string, optional): Last name + - `role` (string): Must be "admin" + + **Response:** + - `token` (string): JWT token with admin role + - `user` (object): User details + - `id` (string): User ID + - `email` (string): Email + - `username` (string): Username + - `theme` (string): User theme preference + - `first_name` (string, optional): First name + - `last_name` (string, optional): Last name + - `role` (string): User role ("admin") + + **Status Codes:** + - 201: Created + - 409: User exists +} \ No newline at end of file diff --git a/bruno/user/Register User.bru b/bruno/user/Register User.bru index 3b47976..571cff6 100644 --- a/bruno/user/Register User.bru +++ b/bruno/user/Register User.bru @@ -16,7 +16,8 @@ body:json { "username": "testuser", "password": "password123", "first_name": "Test", - "last_name": "User" + "last_name": "User", + "role": "user" } } @@ -48,6 +49,7 @@ docs { - `password` (string): Password - `first_name` (string, optional): First name - `last_name` (string, optional): Last name + - `role` (string): User role ("user" or "admin") **Response:** - `token` (string): JWT token @@ -55,9 +57,10 @@ docs { - `id` (string): User ID - `email` (string): Email - `username` (string): Username - - `theme` (string): User theme preference - - `first_name` (string, optional): First name - - `last_name` (string, optional): Last name +- `theme` (string): User theme preference + - `first_name` (string, optional): First name + - `last_name` (string, optional): Last name + - `role` (string): User role ("user" or "admin") **Status Codes:** - 201: Created