[Bug 42404] New: Add a batch cover images upload endpoint
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 Bug ID: 42404 Summary: Add a batch cover images upload endpoint Initiative type: --- Sponsorship --- status: Product: Koha Version: Main Hardware: All OS: All Status: NEW Severity: enhancement Priority: P5 - low Component: REST API Assignee: koha-bugs@lists.koha-community.org Reporter: tomascohen@gmail.com QA Contact: testopia@bugs.koha-community.org CC: tomascohen@gmail.com -- You are receiving this mail because: You are watching all bug changes. You are the assignee for the bug.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Assignee|koha-bugs@lists.koha-commun |tomascohen@gmail.com |ity.org | -- You are receiving this mail because: You are the assignee for the bug. You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 Andrew Fuerste-Henry <andrew@bywatersolutions.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Blocks| |42643 Referenced Bugs: https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42643 [Bug 42643] [OMNIBUS] Assorted performance and stability work -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |dcook@prosentient.com.au, | |martin.renvoize@openfifth.c | |o.uk Status|NEW |ASSIGNED -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|ASSIGNED |Needs Signoff Sponsorship status|--- |Sponsored Comma delimited| |ByWater Solutions list of Sponsors| | -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #1 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Created attachment 200145 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200145&action=edit Bug 42404: Add BatchImportCoverImages background job This patch adds a background job that processes a zip file containing cover images and an idlink.txt/datalink.txt mapping file. Each line in the mapping file maps a biblio_id (or item_id) to an image filename. Features: - Supports both biblio_id and item_id targets - Replace mode (deletes existing images before import) - Uses Archive::Zip instead of system unzip - Path traversal protection on extracted files - Reports progress via the background jobs infrastructure Test plan: 1. Apply patch 2. Run: $ ktd --shell k$ prove t/db_dependent/Koha/BackgroundJob/BatchImportCoverImages.t => SUCCESS: Tests pass! 3. Tests cover: - enqueue() sets correct job size, status, and queue - Single and multiple image imports - Replace mode behavior - Bad delimiter handling in mapping files - Cancelled job is skipped - Upload cleanup after processing 4. Sign off :-D Sponsored-by: ByWater Solutions -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #2 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Created attachment 200146 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200146&action=edit Bug 42404: Add REST API endpoint for batch cover image import This patch adds a REST API endpoint for batch importing cover images: POST /api/v1/cover_images/batch It accepts a zip file via multipart/form-data and enqueues a BatchImportCoverImages background job to process it. Query parameters: - replace: boolean, delete existing images before import - target: enum (biblio_id, item_id), specifies what the first column of the mapping file represents Requires tools: upload_local_cover_images permission. Test plan: 1. Apply patch 2. Run: $ ktd --shell k$ prove t/db_dependent/api/v1/cover_images.t => SUCCESS: Tests pass! 3. Tests cover: - Authentication required (401) - Authorization required (403) - Successful upload enqueues job (201) - Replace flag forwarded correctly - Missing file returns 400 4. Sign off :-D Sponsored-by: ByWater Solutions -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Blocks| |42405 Referenced Bugs: https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42405 [Bug 42405] Add single cover image upload path -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |kyle@bywatersolutions.com -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Blocks| |42804 Attachment #200145|0 |1 is obsolete| | Attachment #200146|0 |1 is obsolete| | Referenced Bugs: https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42804 [Bug 42804] Replace svc/cover_images and tools/upload-cover-image.pl with REST API -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #3 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Created attachment 200150 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200150&action=edit Bug 42404: Add BatchImportCoverImages background job This patch adds a background job that processes a zip file containing cover images and an idlink.txt/datalink.txt mapping file. Each line in the mapping file maps a biblio_id (or item_id) to an image filename. Features: - Supports both biblio_id and item_id targets - Replace mode (deletes existing images before import) - Uses Archive::Zip instead of system unzip - Path traversal protection on extracted files - Reports progress via the background jobs infrastructure Test plan: 1. Apply patch 2. Run: $ ktd --shell k$ prove t/db_dependent/Koha/BackgroundJob/BatchImportCoverImages.t => SUCCESS: Tests pass! 3. Tests cover: - enqueue() sets correct job size, status, and queue - Single and multiple image imports - Replace mode behavior - Bad delimiter handling in mapping files - Cancelled job is skipped - Upload cleanup after processing 4. Sign off :-D Sponsored-by: ByWater Solutions -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #4 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Created attachment 200151 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200151&action=edit Bug 42404: Add REST API endpoint for batch cover image import This patch adds a REST API endpoint for batch importing cover images: POST /api/v1/cover_images/batch It accepts a zip file via multipart/form-data and enqueues a BatchImportCoverImages background job to process it. Query parameters: - replace: boolean, delete existing images before import - target: enum (biblio_id, item_id), specifies what the first column of the mapping file represents Requires tools: upload_local_cover_images permission. Test plan: 1. Apply patch 2. Run: $ ktd --shell k$ prove t/db_dependent/api/v1/cover_images.t => SUCCESS: Tests pass! 3. Tests cover: - Authentication required (401) - Authorization required (403) - Successful upload enqueues job (201) - Replace flag forwarded correctly - Missing file returns 400 4. Sign off :-D Sponsored-by: ByWater Solutions -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #5 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Created attachment 200152 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200152&action=edit Bug 42404: (follow-up) Add background job detail template This patch adds the TT include used by the background jobs detail page to display the results of a batch cover image import job. Test plan: 1. Apply patch 2. Upload a zip file with cover images via the upload tool 3. Navigate to Administration > Background jobs 4. Click on the batch_import_cover_images job => SUCCESS: Job detail page shows imported/failed counts and messages 5. Sign off :-D Sponsored-by: ByWater Solutions -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 David Nind <david@davidnind.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |david@davidnind.com --- Comment #6 from David Nind <david@davidnind.com> --- I'm not seeing a background job after these steps: 2. Upload a zip file with cover images via the upload tool 3. Navigate to Administration > Background jobs 4. Click on the batch_import_cover_images job Is there something else I need to do? Steps: 1. All three patches applied 2. yarn build 3. restart_all 4. All the tests mentioned pass 5. Cataloging > Tools > Upload local cover image -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> changed: What |Removed |Added ---------------------------------------------------------------------------- Blocks|42643 | Referenced Bugs: https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42643 [Bug 42643] [OMNIBUS] Assorted performance and stability work -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> changed: What |Removed |Added ---------------------------------------------------------------------------- Blocks|42804 | Referenced Bugs: https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42804 [Bug 42804] Replace svc/cover_images and tools/upload-cover-image.pl with REST API -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 Andrew Fuerste-Henry <andrew@bywatersolutions.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|Needs Signoff |Failed QA CC| |andrew@bywatersolutions.com --- Comment #7 from Andrew Fuerste-Henry <andrew@bywatersolutions.com> --- Agreed, this is not actually enqueueing a background job, it's just processing the uploaded file. -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|Failed QA |Needs Signoff --- Comment #8 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- The only way to test this from the UI is by having bug 42804 applied too. This patchset only adds: * Background job with tests * API for submitting cover images in bulk and enqueueing the job, with tests You should probably just apply the patches and run the tests after doing: ```shell $ yarn api:bundle $ koha-plack --restart kohadev ``` You will have your change to see this in action later. -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #9 from Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> --- I'd be tempted to return a 202 Accepted as apposed to a 201 Created here? The task is transient isn't it.. the final result is the processed covers.. I'd also be tempted to set the Location headers to the job tracking API endpoint? -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #10 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- (In reply to Martin Renvoize (ashimema) from comment #9)
I'd be tempted to return a 202 Accepted as apposed to a 201 Created here?
That's brillant. I went auto-pilot on following the current guidelines for POST, but it makes sense.
The task is transient isn't it.. the final result is the processed covers.. I'd also be tempted to set the Location headers to the job tracking API endpoint?
I think I just forgot it, you're right too! -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #11 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Created attachment 200611 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200611&action=edit Bug 42404: (follow-up) Return 202 Accepted with Location header The batch cover image import endpoint enqueues a background job for processing. A 201 Created is incorrect because no resource is durably created at response time - the work is deferred. This patch changes the response to 202 Accepted, which is the correct HTTP status for async job submission. Additionally, the Location header is set to the job tracking endpoint so clients can poll for completion status without out-of-band knowledge. Changes: - Return 202 instead of 201 from batch_import controller - Set Location header to /api/v1/jobs/{job_id} - Update OpenAPI spec to document 202 response and Location header - Update tests to assert 202 status and Location header Test plan: 1. Apply patch 2. Run: $ ktd --shell k$ prove t/db_dependent/api/v1/cover_images.t => SUCCESS: Tests pass! 3. Verify the OpenAPI spec is valid: k$ cd /kohadevbox/koha && perl t/db_dependent/api/v1/spec.t => SUCCESS: Spec validates! 4. Sign off :-D -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #12 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Hi! (In reply to Martin Renvoize (ashimema) from comment #9)
I'd be tempted to return a 202 Accepted as apposed to a 201 Created here?
The task is transient isn't it.. the final result is the processed covers.. I'd also be tempted to set the Location headers to the job tracking API endpoint?
Implemented these in a follow-up. I also wrote an entry on the wiki about this, with a `DRAFT` status so we vote it next dev meeting: https://wiki.koha-community.org/wiki/Coding_Guidelines_-_API#.5BDRAFT.5D_RES... -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Blocks| |42869 Referenced Bugs: https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42869 [Bug 42869] Adjust async job endpoints to coding guideline (202 Accepted) -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> changed: What |Removed |Added ---------------------------------------------------------------------------- QA Contact|testopia@bugs.koha-communit |martin.renvoize@openfifth.c |y.org |o.uk -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> changed: What |Removed |Added ---------------------------------------------------------------------------- Patch complexity|--- |Medium patch Status|Needs Signoff |Signed Off QA Contact|martin.renvoize@openfifth.c |dcook@prosentient.com.au |o.uk | -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> changed: What |Removed |Added ---------------------------------------------------------------------------- Attachment #200150|0 |1 is obsolete| | Attachment #200151|0 |1 is obsolete| | Attachment #200152|0 |1 is obsolete| | Attachment #200611|0 |1 is obsolete| | -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #13 from Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> --- Created attachment 200832 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200832&action=edit Bug 42404: Add BatchImportCoverImages background job This patch adds a background job that processes a zip file containing cover images and an idlink.txt/datalink.txt mapping file. Each line in the mapping file maps a biblio_id (or item_id) to an image filename. Features: - Supports both biblio_id and item_id targets - Replace mode (deletes existing images before import) - Uses Archive::Zip instead of system unzip - Path traversal protection on extracted files - Reports progress via the background jobs infrastructure Test plan: 1. Apply patch 2. Run: $ ktd --shell k$ prove t/db_dependent/Koha/BackgroundJob/BatchImportCoverImages.t => SUCCESS: Tests pass! 3. Tests cover: - enqueue() sets correct job size, status, and queue - Single and multiple image imports - Replace mode behavior - Bad delimiter handling in mapping files - Cancelled job is skipped - Upload cleanup after processing 4. Sign off :-D Sponsored-by: ByWater Solutions Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #14 from Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> --- Created attachment 200833 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200833&action=edit Bug 42404: Add REST API endpoint for batch cover image import This patch adds a REST API endpoint for batch importing cover images: POST /api/v1/cover_images/batch It accepts a zip file via multipart/form-data and enqueues a BatchImportCoverImages background job to process it. Query parameters: - replace: boolean, delete existing images before import - target: enum (biblio_id, item_id), specifies what the first column of the mapping file represents Requires tools: upload_local_cover_images permission. Test plan: 1. Apply patch 2. Run: $ ktd --shell k$ prove t/db_dependent/api/v1/cover_images.t => SUCCESS: Tests pass! 3. Tests cover: - Authentication required (401) - Authorization required (403) - Successful upload enqueues job (201) - Replace flag forwarded correctly - Missing file returns 400 4. Sign off :-D Sponsored-by: ByWater Solutions Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #15 from Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> --- Created attachment 200834 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200834&action=edit Bug 42404: (follow-up) Add background job detail template This patch adds the TT include used by the background jobs detail page to display the results of a batch cover image import job. Test plan: 1. Apply patch 2. Upload a zip file with cover images via the upload tool 3. Navigate to Administration > Background jobs 4. Click on the batch_import_cover_images job => SUCCESS: Job detail page shows imported/failed counts and messages 5. Sign off :-D Sponsored-by: ByWater Solutions Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #16 from Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> --- Created attachment 200835 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200835&action=edit Bug 42404: (follow-up) Return 202 Accepted with Location header The batch cover image import endpoint enqueues a background job for processing. A 201 Created is incorrect because no resource is durably created at response time - the work is deferred. This patch changes the response to 202 Accepted, which is the correct HTTP status for async job submission. Additionally, the Location header is set to the job tracking endpoint so clients can poll for completion status without out-of-band knowledge. Changes: - Return 202 instead of 201 from batch_import controller - Set Location header to /api/v1/jobs/{job_id} - Update OpenAPI spec to document 202 response and Location header - Update tests to assert 202 status and Location header Test plan: 1. Apply patch 2. Run: $ ktd --shell k$ prove t/db_dependent/api/v1/cover_images.t => SUCCESS: Tests pass! 3. Verify the OpenAPI spec is valid: k$ cd /kohadevbox/koha && perl t/db_dependent/api/v1/spec.t => SUCCESS: Spec validates! 4. Sign off :-D Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #17 from Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> --- Created attachment 200836 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200836&action=edit Bug 42404: (follow-up) Fix GD exception handling, logger, and empty mapping detection - Wrap GD::Image->new() in eval{} so a die from a malformed image is caught per-image rather than aborting the entire job via the outer catch block; images_failed and step() are now always updated correctly on GD errors. - Add Koha::Logger->get->error/warn calls in all catch blocks so operators have server-side detail while users see a sanitized message. - Add _finish_failed() helper that correctly stores messages and the report before setting status to 'failed', fixing the pre-existing issue where early-exit paths called status('failed')->store without calling finish(). - After mapping parsing, fail the job (not silently succeed with 0 imported) when no valid mappings are found, including the case where all lines had unrecognised delimiters. - Update tests accordingly. -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #18 from Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> --- Created attachment 200837 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200837&action=edit Bug 42404: (follow-up) Reject symlinks in image file paths The existing path-traversal check guards against filenames that resolve outside the extraction directory, but did not guard against symlinks that point to arbitrary host filesystem paths (e.g. /etc/passwd). Add an explicit -l check for each resolved image path before passing it to GD::Image->new(); symlinks are treated as path_traversal errors and the image is skipped. The mapping-file symlink checks introduced earlier are therefore consistent across all file reads in the job. -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #19 from Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> --- Created attachment 200838 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200838&action=edit Bug 42404: (follow-up) Wrap per-image replace+store in a transaction Without a transaction, the delete-then-store sequence in replace mode is non-atomic: if ->store() fails the old images are already gone and cannot be recovered. Wrap each image's delete (optional) and store in a txn_do() block so both either succeed together or roll back together. Each image is processed independently so a failure on one does not affect others. -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #20 from Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> --- Created attachment 200839 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200839&action=edit Bug 42404: (follow-up) Reuse item object to avoid redundant fetch in replace mode In item_id target mode, the item was fetched once to obtain the biblionumber, then fetched again inside the replace block via Koha::Items->find(). Store the first result and pass it through to avoid the N+1 pattern. -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #21 from Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> --- Created attachment 200840 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200840&action=edit Bug 42404: (follow-up) Handle move failure and empty filename in _store_upload - Check the return value of move_to(); die if the file could not be written so the caller's catch block returns a 500 rather than silently creating an UploadedFile record pointing to a missing file. - After filename sanitization, fall back to 'upload.zip' if all characters were stripped, preventing an empty path component. -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #22 from Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> --- Created attachment 200841 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200841&action=edit Bug 42404: (follow-up) Validate IDs are numeric before database lookup IDs from the mapping file are used directly in Koha::Items->find() and Koha::Biblios->find(). Add an explicit check that the value is all digits before passing it to the ORM layer so that non-numeric values produce a clear 'invalid_id' message rather than an ORM exception or silent failure. -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #23 from Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> --- Created attachment 200842 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200842&action=edit Bug 42404: (follow-up) Canonicalize extraction directory before path-traversal check The path-traversal guard compares Cwd::abs_path(\$full_path) against \$dirname using a regex anchor. If \$dirname itself contains unresolved symlink components the comparison could be fooled. Resolve \$dirname via Cwd::abs_path() immediately after extraction (once the directory exists on disk) so both sides of the comparison are fully canonicalized. -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #24 from Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> --- Created attachment 200843 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200843&action=edit Bug 42404: (follow-up) Die on upload directory creation failure The mkdir call in _store_upload silently continued if the directory could not be created, leading to a confusing move_to failure later. Die immediately with a descriptive message; the caller's catch block will return a 500 to the client. -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #25 from Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> --- Created attachment 200844 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=200844&action=edit Bug 42404: (follow-up) Ensure upload file is cleaned up on unexpected exception The upload variable was declared inside the outer try block, making it invisible to any cleanup code after the try/catch. Move the declaration outside the try so a guard after the try/catch can delete the upload if an unexpected exception fired before the normal cleanup path ran. -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 Martin Renvoize (ashimema) <martin.renvoize@openfifth.co.uk> changed: What |Removed |Added ---------------------------------------------------------------------------- Blocks| |42891 -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Attachment #200832|0 |1 is obsolete| | Attachment #200833|0 |1 is obsolete| | Attachment #200834|0 |1 is obsolete| | Attachment #200835|0 |1 is obsolete| | Attachment #200836|0 |1 is obsolete| | Attachment #200837|0 |1 is obsolete| | Attachment #200838|0 |1 is obsolete| | Attachment #200839|0 |1 is obsolete| | Attachment #200840|0 |1 is obsolete| | Attachment #200841|0 |1 is obsolete| | Attachment #200842|0 |1 is obsolete| | Attachment #200843|0 |1 is obsolete| | Attachment #200844|0 |1 is obsolete| | -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #26 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Created attachment 201278 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=201278&action=edit Bug 42404: Add BatchImportCoverImages background job This patch adds a background job that processes a zip file containing cover images and an idlink.txt/datalink.txt mapping file. Each line in the mapping file maps a biblio_id (or item_id) to an image filename. Features: - Supports both biblio_id and item_id targets - Replace mode (deletes existing images before import) - Uses Archive::Zip instead of system unzip - Path traversal protection on extracted files - Reports progress via the background jobs infrastructure Test plan: 1. Apply patch 2. Run: $ ktd --shell k$ prove t/db_dependent/Koha/BackgroundJob/BatchImportCoverImages.t => SUCCESS: Tests pass! 3. Tests cover: - enqueue() sets correct job size, status, and queue - Single and multiple image imports - Replace mode behavior - Bad delimiter handling in mapping files - Cancelled job is skipped - Upload cleanup after processing 4. Sign off :-D Sponsored-by: ByWater Solutions Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk> Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #27 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Created attachment 201279 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=201279&action=edit Bug 42404: Add REST API endpoint for batch cover image import This patch adds a REST API endpoint for batch importing cover images: POST /api/v1/cover_images/batch It accepts a zip file via multipart/form-data and enqueues a BatchImportCoverImages background job to process it. Query parameters: - replace: boolean, delete existing images before import - target: enum (biblio_id, item_id), specifies what the first column of the mapping file represents Requires tools: upload_local_cover_images permission. Test plan: 1. Apply patch 2. Run: $ ktd --shell k$ prove t/db_dependent/api/v1/cover_images.t => SUCCESS: Tests pass! 3. Tests cover: - Authentication required (401) - Authorization required (403) - Successful upload enqueues job (201) - Replace flag forwarded correctly - Missing file returns 400 4. Sign off :-D Sponsored-by: ByWater Solutions Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk> Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #28 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Created attachment 201280 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=201280&action=edit Bug 42404: (follow-up) Add background job detail template This patch adds the TT include used by the background jobs detail page to display the results of a batch cover image import job. Test plan: 1. Apply patch 2. Upload a zip file with cover images via the upload tool 3. Navigate to Administration > Background jobs 4. Click on the batch_import_cover_images job => SUCCESS: Job detail page shows imported/failed counts and messages 5. Sign off :-D Sponsored-by: ByWater Solutions Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk> Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #29 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Created attachment 201281 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=201281&action=edit Bug 42404: (follow-up) Return 202 Accepted with Location header The batch cover image import endpoint enqueues a background job for processing. A 201 Created is incorrect because no resource is durably created at response time - the work is deferred. This patch changes the response to 202 Accepted, which is the correct HTTP status for async job submission. Additionally, the Location header is set to the job tracking endpoint so clients can poll for completion status without out-of-band knowledge. Changes: - Return 202 instead of 201 from batch_import controller - Set Location header to /api/v1/jobs/{job_id} - Update OpenAPI spec to document 202 response and Location header - Update tests to assert 202 status and Location header Test plan: 1. Apply patch 2. Run: $ ktd --shell k$ prove t/db_dependent/api/v1/cover_images.t => SUCCESS: Tests pass! 3. Verify the OpenAPI spec is valid: k$ cd /kohadevbox/koha && perl t/db_dependent/api/v1/spec.t => SUCCESS: Spec validates! 4. Sign off :-D Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk> Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #30 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Created attachment 201282 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=201282&action=edit Bug 42404: (follow-up) Fix GD exception handling, logger, and empty mapping detection - Wrap GD::Image->new() in eval{} so a die from a malformed image is caught per-image rather than aborting the entire job via the outer catch block; images_failed and step() are now always updated correctly on GD errors. - Add Koha::Logger->get->error/warn calls in all catch blocks so operators have server-side detail while users see a sanitized message. - Add _finish_failed() helper that correctly stores messages and the report before setting status to 'failed', fixing the pre-existing issue where early-exit paths called status('failed')->store without calling finish(). - After mapping parsing, fail the job (not silently succeed with 0 imported) when no valid mappings are found, including the case where all lines had unrecognised delimiters. - Update tests accordingly. Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #31 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Created attachment 201283 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=201283&action=edit Bug 42404: (follow-up) Reject symlinks in image file paths The existing path-traversal check guards against filenames that resolve outside the extraction directory, but did not guard against symlinks that point to arbitrary host filesystem paths (e.g. /etc/passwd). Add an explicit -l check for each resolved image path before passing it to GD::Image->new(); symlinks are treated as path_traversal errors and the image is skipped. The mapping-file symlink checks introduced earlier are therefore consistent across all file reads in the job. Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #32 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Created attachment 201284 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=201284&action=edit Bug 42404: (follow-up) Wrap per-image replace+store in a transaction Without a transaction, the delete-then-store sequence in replace mode is non-atomic: if ->store() fails the old images are already gone and cannot be recovered. Wrap each image's delete (optional) and store in a txn_do() block so both either succeed together or roll back together. Each image is processed independently so a failure on one does not affect others. Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #33 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Created attachment 201285 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=201285&action=edit Bug 42404: (follow-up) Reuse item object to avoid redundant fetch in replace mode In item_id target mode, the item was fetched once to obtain the biblionumber, then fetched again inside the replace block via Koha::Items->find(). Store the first result and pass it through to avoid the N+1 pattern. Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #34 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Created attachment 201286 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=201286&action=edit Bug 42404: (follow-up) Handle move failure and empty filename in _store_upload - Check the return value of move_to(); die if the file could not be written so the caller's catch block returns a 500 rather than silently creating an UploadedFile record pointing to a missing file. - After filename sanitization, fall back to 'upload.zip' if all characters were stripped, preventing an empty path component. Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #35 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Created attachment 201287 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=201287&action=edit Bug 42404: (follow-up) Validate IDs are numeric before database lookup IDs from the mapping file are used directly in Koha::Items->find() and Koha::Biblios->find(). Add an explicit check that the value is all digits before passing it to the ORM layer so that non-numeric values produce a clear 'invalid_id' message rather than an ORM exception or silent failure. Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #36 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Created attachment 201288 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=201288&action=edit Bug 42404: (follow-up) Canonicalize extraction directory before path-traversal check The path-traversal guard compares Cwd::abs_path(\$full_path) against \$dirname using a regex anchor. If \$dirname itself contains unresolved symlink components the comparison could be fooled. Resolve \$dirname via Cwd::abs_path() immediately after extraction (once the directory exists on disk) so both sides of the comparison are fully canonicalized. Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #37 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Created attachment 201289 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=201289&action=edit Bug 42404: (follow-up) Die on upload directory creation failure The mkdir call in _store_upload silently continued if the directory could not be created, leading to a confusing move_to failure later. Die immediately with a descriptive message; the caller's catch block will return a 500 to the client. Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #38 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Created attachment 201290 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=201290&action=edit Bug 42404: (follow-up) Ensure upload file is cleaned up on unexpected exception The upload variable was declared inside the outer try block, making it invisible to any cleanup code after the try/catch. Move the declaration outside the try so a guard after the try/catch can delete the upload if an unexpected exception fired before the normal cleanup path ran. Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #39 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Hi reviewed Martin's follow-ups, they look ok and make sense. I also squashed some QA check failures in the follow-ups. Thanks! -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 Andrew Fuerste-Henry <andrew@bywatersolutions.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Blocks| |43016 Referenced Bugs: https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=43016 [Bug 43016] [OMNIBUS] Server resource protection -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #40 from David Cook <dcook@prosentient.com.au> --- A consolidated testing plan should be provided... especially including rebuilding the API and restarting Plack... -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #41 from David Cook <dcook@prosentient.com.au> --- (In reply to Tomás Cohen Arazi (tcohen) from comment #8)
The only way to test this from the UI is by having bug 42804 applied too.
This patchset only adds:
* Background job with tests * API for submitting cover images in bulk and enqueueing the job, with tests
The dependency tree is a bit of a mess... can't make bug 42804 a dependency of this one because bug 42804 depends on bug 42405 but bug 42404 blocks bug 42405... It's not at all clear what the order of testing these bugs should be... -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 David Cook <dcook@prosentient.com.au> changed: What |Removed |Added ---------------------------------------------------------------------------- QA Contact|dcook@prosentient.com.au |testopia@bugs.koha-communit | |y.org --- Comment #42 from David Cook <dcook@prosentient.com.au> --- Going to reset QA for now... -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #43 from David Cook <dcook@prosentient.com.au> --- (In reply to David Cook from comment #41)
(In reply to Tomás Cohen Arazi (tcohen) from comment #8)
The only way to test this from the UI is by having bug 42804 applied too.
This patchset only adds:
* Background job with tests * API for submitting cover images in bulk and enqueueing the job, with tests
The dependency tree is a bit of a mess... can't make bug 42804 a dependency of this one because bug 42804 depends on bug 42405 but bug 42404 blocks bug 42405...
It's not at all clear what the order of testing these bugs should be...
After reviewing all the bugs and the dependency tree... I think I understand what you're trying to do here. Trying to build up the components in separate bug reports before tying them all together. Yeah that makes sense conceptually. Makes things a bit tougher to test, but I get it now... I don't love the idea of signing off on a bug report just because it's passing tests though... I've used up most of my testing time trying to figure out how to test it, so I think I'll have to come back another time... -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #44 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- (In reply to David Cook from comment #43)
I don't love the idea of signing off on a bug report just because it's passing tests though...
What I expect testers is: - You apply 42404, 42405 and 42804. - Tests from all bugs pass. - All cover image-related features in the UI work as expected. I know splitting like this might have not been the best. On the other hand, the endpoints are features by themselves third parties couldrely on, appart from the internal use in Koha itself! It can be tested using Postman, but I haven't really played with it for this use case myself. When you choose `raw` for the request body format, it lets you choose a file to upload. But you are still able to test from the tools section! -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 Lisette Scheer <lisette@bywatersolutions.com> changed: What |Removed |Added ---------------------------------------------------------------------------- QA Contact|testopia@bugs.koha-communit |lucas@bywatersolutions.com |y.org | CC| |lisette@bywatersolutions.co | |m -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Text to go in the| |This work adds an endpoint release notes| |for handling batch cover | |images uploads on the REST | |API. It accepts uploaded | |files and schedules a | |background job for | |processing them. it | |conveniently returns a 202 | |with the effective job | |endpoint in the Location | |header so consumers can | |query progress afterwards. -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 Lisette Scheer <lisette@bywatersolutions.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |zoho.roboto@bywatersolution | |s.com -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 Lucas Gass (lukeg) <lucas@bywatersolutions.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|Signed Off |Failed QA --- Comment #45 from Lucas Gass (lukeg) <lucas@bywatersolutions.com> --- I found what I think is a problem: To recreate: 1. Enable LocalCoverImages 2. Enable AllowMultipleCovers 3. Go to a record -> Uplaod image ( upload any image ) 4. In the holdings table click Edit -> Upload image ( any image ) 5. Do a POST to `/api/v1/cover_images/batch?replace=true` with the zip file. The biblio level image is replaced. The item level image is just gone. Questions, not necessarily blockers: -Should this ever replace item level images? Or are we waiting on Bug 42405 to do that? -When I put two images in a ZIP only the first one is ever used to replace at `/api/v1/cover_images/batch?replace=true`, even when AllowMultipleCovers is on. It should honor AllowMultipleCovers, right? -Maybe I missed this, or there is a separate bug report, will the staff image upload tool use the API? -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|Failed QA |Signed Off --- Comment #46 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Thanks Lucas! You were right on both counts. - Replacing a record's covers no longer removes its item level covers. - With AllowMultipleCovers enabled, existing covers are removed once per record, so all the images in the zip are kept. With it disabled, covers are always replaced, even without ?replace=true. Bug 42405 had the same item cover problem in POST /biblios/{biblio_id}/cover_images, fixed there too. And yes: the staff upload tool uses the API in bug 42804. The follow-ups also tighten the path checks, finish the job exactly once, and add tests. The commit messages have the details and test plans. -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #47 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Created attachment 209366 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=209366&action=edit Bug 42404: (follow-up) Finish BatchImportCoverImages jobs exactly once The early returns in process() (upload not found, unreadable zip, no valid mappings) only returned from the Try::Tiny block, so the job was finished by _finish_failed() and then a second time after the block. Unexpected exceptions, on the other hand, ended up with the 'finished' status. This patch makes the try block return whether the job failed, and the job is finished once, after the block. The uploaded zip is deleted in a single place, and unexpected exceptions now mark the job as 'failed'. The extraction directory is now a File::Temp->newdir object, so it is removed when process() is done instead of when the process exits. File::Temp is now explicitly loaded, it was only available because another module loaded it. Test plan: 1. Apply patch 2. Run: $ ktd --shell k$ prove t/db_dependent/Koha/BackgroundJob/BatchImportCoverImages.t => SUCCESS: Tests pass! 3. Sign off :-D Assisted-by: Opus 5.5 (Anthropic) -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #48 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Created attachment 209367 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=209367&action=edit Bug 42404: (follow-up) Tighten path checks in BatchImportCoverImages The checks on the image paths read from the mapping file were weaker than they looked: - The symlink check ran on the path returned by Cwd::abs_path, which has already resolved symlinks, so it could never match. - The containment check was a plain prefix match on the extraction directory, so a sibling directory sharing the prefix (e.g. /tmp/abc and /tmp/abcx) was accepted. This patch checks for symlinks before resolving the path, and requires the resolved path to start with the extraction directory followed by a '/'. It also validates the id (and finds the item, when targeting items) before opening the image, so bad lines do not load images for nothing, and trims whitespace around the id like it was already done for the filename. Note: Archive::Zip extracts symlink entries as regular files, so the symlink check is defense in depth. The tests add the symlink after extraction. Test plan: 1. Apply patch 2. Run: $ ktd --shell k$ prove t/db_dependent/Koha/BackgroundJob/BatchImportCoverImages.t => SUCCESS: Tests pass! 3. Revert the changes to Koha/BackgroundJob/BatchImportCoverImages.pm and repeat 2 => FAIL: The sibling directory and the symlink are accepted 4. Sign off :-D Assisted-by: Opus 5.5 (Anthropic) -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #49 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Created attachment 209368 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=209368&action=edit Bug 42404: (follow-up) Fix replace behaviour in BatchImportCoverImages The way BatchImportCoverImages replaced existing covers had three problems. The first two were reported by Lucas on comment #45: 1. Replacing a biblio's covers used $biblio->cover_images, which also includes the covers of its items, so the item level covers were deleted too. tools/upload-cover-image.pl only deleted the biblio level ones when uploading a single image. 2. The existing covers were deleted for every line of the mapping file, so when several images were mapped to the same record, each one deleted the previous one and only one image was kept, even with AllowMultipleCovers enabled. 3. tools/upload-cover-image.pl always replaced existing covers when the AllowMultipleCovers system preference was disabled. The job only looked at the 'replace' parameter, so API consumers could attach several covers to a record when the library does not allow it. This patch: - Only deletes the biblio level covers (itemnumber IS NULL) when replacing a biblio's covers. Item covers are only replaced when importing with target=item_id. - Removes the existing covers of a record only once per job when AllowMultipleCovers is enabled, so all the images in the file are kept. When it is disabled each image replaces the previous one, so the record ends up with the last one. - Replaces existing covers when AllowMultipleCovers is disabled, whatever the 'replace' parameter says. The check lives in the job so every caller gets it. The API spec documents the behaviour. Test plan: 1. Apply patch 2. Run: $ ktd --shell k$ prove t/db_dependent/Koha/BackgroundJob/BatchImportCoverImages.t \ xt/api.t => SUCCESS: Tests pass! 3. Revert the changes to Koha/BackgroundJob/BatchImportCoverImages.pm and repeat 2 => FAIL: Item level covers are deleted, only one image is kept when several are mapped to the same record, and two covers are attached to a record with AllowMultipleCovers disabled 4. Restore the changes and restart services: k$ restart_all 5. Enable LocalCoverImages, AllowMultipleCovers and RESTBasicAuth 6. Go to record 1 and upload a cover image (Images tab -> Upload) 7. In the holdings table, pick an item: Edit -> Upload image, upload another image 8. Create a zip with two images and an idlink.txt mapping both to record 1: k$ mkdir /tmp/covers && cd /tmp/covers k$ cp /kohadevbox/koha/koha-tmpl/intranet-tmpl/prog/img/koha-logo.png a.png k$ cp a.png b.png k$ printf "1\ta.png\n1\tb.png\n" > idlink.txt k$ python3 -m zipfile -c covers.zip idlink.txt a.png b.png 9. Upload it, replacing existing covers: k$ curl -u koha:koha -F file=@covers.zip \ "http://localhost:8081/api/v1/cover_images/batch?replace=true" => SUCCESS: A job id is returned 10. Check the job in Administration -> Manage jobs => SUCCESS: 2 images imported 11. Go to record 1 => SUCCESS: The record cover uploaded in 6 is gone, the two new images are there => SUCCESS: The item cover uploaded in 7 is still there 12. Disable AllowMultipleCovers and repeat 9 => SUCCESS: Record 1 has a single record level cover 13. Sign off :-D Assisted-by: Opus 5.5 (Anthropic) -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #50 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Created attachment 209369 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=209369&action=edit Bug 42404: (follow-up) Log item cover imports as item covers When importing with target=item_id, the action log entry said "biblio cover image" like for biblio level covers. This patch logs "item <itemnumber> cover image" in that case. The log object is still the biblionumber. It also adds tests for the item_id target, which was not covered: item lookup, missing items, replacing item covers without touching the biblio level ones, and the log entry. Test plan: 1. Apply patch 2. Run: $ ktd --shell k$ prove t/db_dependent/Koha/BackgroundJob/BatchImportCoverImages.t => SUCCESS: Tests pass! 3. Sign off :-D Assisted-by: Opus 5.5 (Anthropic) -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #51 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Created attachment 209370 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=209370&action=edit Bug 42404: (follow-up) Remove the upload if the batch import job cannot be enqueued If enqueueing the BatchImportCoverImages job failed, the zip stored by _store_upload was left behind until cleanup_database.pl purged it. This patch deletes it before rethrowing the exception. The API tests are also improved: - 'replace' and 'target' were sent as form fields while the spec declares them as query parameters, and the mocked enqueue ignored its arguments, so nothing checked they reached the job. The tests now use query parameters and check the job arguments, including the defaults. - The stored upload is checked (temporary, file on disk). - An invalid 'target' is rejected with a 400. - An enqueue failure returns a 500 and leaves no upload behind. Test plan: 1. Apply patch 2. Run: $ ktd --shell k$ prove t/db_dependent/api/v1/cover_images.t => SUCCESS: Tests pass! 3. Revert the changes to Koha/REST/V1/CoverImages.pm and repeat 2 => FAIL: The upload is left behind when the job cannot be enqueued 4. Sign off :-D Assisted-by: Opus 5.5 (Anthropic) -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 --- Comment #52 from Tomás Cohen Arazi (tcohen) <tomascohen@gmail.com> --- Created attachment 209371 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=209371&action=edit Bug 42404: (follow-up) Add more BatchImportCoverImages tests This patch adds tests for parts of the mapping file handling that were not covered: - idlink.txt takes precedence over datalink.txt in the same directory - quoted, comma delimited lines with CRLF line endings - mapping files in subdirectories - directories starting with '_' or '.' (e.g. __MACOSX) are skipped It also tests that a failure storing one image is reported and logged without failing the whole job. Test plan: 1. Apply patch 2. Run: $ ktd --shell k$ prove t/db_dependent/Koha/BackgroundJob/BatchImportCoverImages.t => SUCCESS: Tests pass! 3. Sign off :-D Assisted-by: Opus 5.5 (Anthropic) -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=42404 Lucas Gass (lukeg) <lucas@bywatersolutions.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|Signed Off |Failed QA --- Comment #53 from Lucas Gass (lukeg) <lucas@bywatersolutions.com> --- 1. AllowMultipleCovers = off 2. Create a zip with two images and an idlink.txt mapping both to record 1 3. Do a POST to /api/v1/cover_images/batch ( I used cURL ) 4. Go to Administration -> Manage jobs 5. Find you job ID and click on it 6. Only 1 of the 2 images is on the record; the other was replaced. Nothing on the job page says so. -- You are receiving this mail because: You are watching all bug changes.
participants (1)
-
bugzilla-daemon@bugs.koha-community.org