feat: Koreader plugin#2298
Conversation
|
converted to draft, as the current implementation messes with the progress sync to/from koreader. A fix will be added soon, latest eta is |
rework settings ui rework calculation of historical sessions to use page count provided by koreader to calculate percentages fix percentage being sent to be xx.x instead of 0.x fix sqlite error by using sqlite by koreader add file logging
add warning and confirmation to historical sync update cache to store paths reduce hash calculations by using cache allow user to set decimals for session percentage set minimum session duration reworked network detection
extract settings from main file add options to sync on suspend, connect to wifi on suspend add option to only manually sync add help texts for various actions rework network handling allow session stored messages to be silent
merge koreader plugin changes
|
I think this is ready for review now and has already been tested by some users and myself Feedback is appreciated, and changes can be made |
…derAuthFilter logging
…0 to fix sessions not loading due to max being applied on domain only
|
@acx10 ready here as well. Time to get this merged, it has been open for way too long |
| return book; | ||
| } | ||
|
|
||
| public Book getBookByHash(String md5Hash, boolean withDescription) { |
There was a problem hiding this comment.
This doesn't check for admin access. Every other method in this file does user.getPermissions().isAdmin() before the library-scoped check. An admin who isn't explicitly assigned to the library will get a 404 here.
|
|
||
| @Bean | ||
| @Order(3) | ||
| public SecurityFilterChain readingSessionsSecurityChain(HttpSecurity http, KoreaderAuthFilter koreaderAuthFilter) throws Exception { |
There was a problem hiding this comment.
This new chain at @order(3) matches all /api/v1/reading-sessions/** requests, which means existing web UI reading session calls now go through this chain instead of the general JWT chain at @order(10). The KOReader filter silently skips when headers are missing so it probably works, but those endpoints are now pulled out of the general chain entirely. Any future security changes to the general chain won't apply to reading sessions anymore. Could this be scoped more narrowly, like just the /batch endpoint?
| @NotNull(message = "Book type is required") | ||
| private BookFileType bookType; | ||
|
|
||
| @NotEmpty(message = "Sessions list cannot be empty") |
| BookLoreUser user = authenticationService.getAuthenticatedUser(); | ||
| boolean isAdmin = user.getPermissions().isAdmin(); | ||
|
|
||
| List<BookEntity> allBooks = isAdmin |
There was a problem hiding this comment.
This loads every book with metadata into memory for fuzzy matching. For someone with 10k+ books that's going to be rough. ISBN matching could easily be an exact DB query, only falling back to in-memory for title fuzzy search.
| // Validate all session times | ||
| for (ReadingSessionItemRequest sessionItem : request.getSessions()) { | ||
| if (sessionItem.getEndTime().isBefore(sessionItem.getStartTime())) { | ||
| throw new IllegalArgumentException("End time must be after start time"); |
There was a problem hiding this comment.
Raw IllegalArgumentException here, should be ApiError.GENERIC_BAD_REQUEST.createException(...). Same thing on line 97 with UsernameNotFoundException. These might not get caught by the global error handler properly.
| } | ||
|
|
||
| @Deprecated | ||
| public List<org.booklore.model.dto.response.BookSearchResult> fuzzySearchByTitle(String searchTitle) { |
There was a problem hiding this comment.
This method is brand new and already @deprecated. If nothing calls it, just drop it.
| - Books must exist in your Booklore library (matched by MD5 hash) | ||
| - Network connectivity to your Booklore server | ||
|
|
||
| Further documentation can be found over in the [docs](link to docs here) |
There was a problem hiding this comment.
[docs](link to docs here) is still a placeholder.
|
|
||
| // Only log and process if KOReader headers are present | ||
| if (username != null && key != null) { | ||
| log.info("KoreaderAuthFilter: Processing KOReader auth for user: {}", username); |
There was a problem hiding this comment.
This will be noisy. Better remove it.
| user.isSyncWithBookloreReader(), | ||
| bookLoreUserId, | ||
| List.of(new SimpleGrantedAuthority("ROLE_USER")) | ||
| log.info("KoreaderAuthFilter: Authentication successful for user: {}", username); |
There was a problem hiding this comment.
This will be noisy. Better remove it.
There was a problem hiding this comment.
Completely out of scope for this probably, but would something like this be better behind a debug setting or env variable?
| @@ -0,0 +1,14 @@ | |||
| package org.booklore.model.dto.response; | |||
There was a problem hiding this comment.
This file does not seem to be used anywhere.
|
@acx10 frontend and backend tests pass, docker image builds |
|
Closed due to differences in opinion of open source and how OSS should be handled |
|
That's a shame. I was looking forward to this feature for so long. Any chance this would be reopened in the feature? |
🚀 Pull Request
📝 Description
This PR adds the koreader plugin to record and synchronize reading sessions to booklore
🛠️ Changes Implemented
by-hashto get the bookID based on the calculated hashby-hashmethod🧪 Testing Strategy
I created a docker image and tested the plugin with these conditions:
and monitored the behavior of the plugin, as well as booklore when sessions were being synced
📸 Visual Changes (if applicable)
Please Read - This Checklist is Mandatory
Mandatory Requirements (please check ALL boxes):
developbranch (please resolve any merge conflicts)./gradlew testfor Spring Boot backend, andng testfor Angular frontend - NO EXCEPTIONS)Why This Matters:
Recent production incidents have been traced back to:
Backend changes without tests will not be accepted. By completing this checklist thoroughly, you're helping maintain the quality and stability of Booklore for all users.
Note to Reviewers: Please verify the checklist is complete before beginning your review. If items are unchecked, kindly ask the contributor to complete them first.
💬 Additional Context (optional)