-
Notifications
You must be signed in to change notification settings - Fork 2
docs: Restructure and update documentation #26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
chore: Release v0.1.5 # Changelog - Security Audit and Fixes ## Backend & UI - Fixed hardcoded Italian notification messages in backend dropdown - Added English translations for all in-app notifications (user registration, reservations, contact messages, overdue loans) - Fixed missing English translations for CSV import interface - Corrected CSV author separator to match export format (semicolon instead of pipe) ## Email & Activation - Restored email functionality with universal domain validation - Removed hardcoded domain whitelist causing email delivery failures - Fixed installer email address configuration - Corrected environment variable handling for canonical URL in activation links ## Installer - Fixed installer deletion form action preventing 404 errors - Corrected installer deletion button path - Updated installer instructions to document both CSV separators (semicolon and pipe) ## Security - Implemented RFC-compliant hostname validation with regex pattern - Replaced brittle whitelist system with universal validation - Added emergency production domain support ## Configuration - Fixed APP_CANONICAL_URL environment variable handling - Corrected .env configuration for email link generation - Improved environment variable parsing and validation --- ## Upgrade Notice If you're upgrading from a previous version and experiencing issues with email activation links or redirects: 1. Navigate to: /admin/maintenance/integrity-report 2. The system will detect the missing APP_CANONICAL_URL configuration 3. Click "Apply Fix" to automatically configure your canonical URL 4. Alternatively, manually add to your .env file: APP_CANONICAL_URL=https://yourdomain.com
Dotenv always populates $_ENV but getenv() may not work depending on PHP's variables_order configuration. This caused false positive warnings on production servers where getenv() returns false even when the variable is properly set in .env. Now checks $_ENV first (where Dotenv always stores values) with fallback to getenv() for compatibility.
Critical fix for email verification links and password reset on production.
getenv() fails on production servers where php.ini variables_order
doesn't include 'E'. Dotenv always populates $_ENV but not getenv().
This caused:
- Email verification links to use wrong URLs (404 errors)
- Password reset links to fail
- Reservation notifications to have broken links
- Integrity check warnings even when properly configured
Fixed in 6 files:
- app/Support/DataIntegrity.php
- app/Support/NotificationService.php
- app/Support/EmailService.php
- app/Support/HtmlHelper.php
- app/Controllers/ReservationManager.php
- app/Controllers/PasswordController.php
Pattern: $_ENV['VAR'] ?? getenv('VAR') ?: false
…ll files" This reverts commit c5deb3a.
Fixed critical issues preventing email verification on production:
1. getenv() fails on production - use $_ENV instead
- Fixed in 5 files: NotificationService, EmailService, HtmlHelper,
ReservationManager, PasswordController
- Pattern: $_ENV['VAR'] ?? getenv('VAR') ?: false
2. Email verification link was hardcoded as '/verify-email' (English)
- On production with it_IT locale, route is '/verifica-email'
- Now uses RouteTranslator::route('verify_email') for locale-aware URLs
3. Missing token_verifica_email in registration email query
- Added token_verifica_email to SELECT query in sendUserRegistrationPending()
- Email verification links now properly included in registration emails
4. Universal route support for all service links
- /verify-email and /verifica-email both work
- /login and /accedi both work
- /reset-password and /reimposta-password both work
- /forgot-password and /password-dimenticata both work
- Email links always work regardless of language
5. All service emails use installation locale
- Ensures emails are sent in correct language (it_IT for Italian)
- Fixed: sendUserRegistrationPending, sendUserAccountApproved,
sendUserActivationWithVerification, sendUserPasswordSetup,
sendAdminInvitation, sendToAdmins
6. Prevent logged-in users from accessing register page
- Redirect to dashboard if already authenticated
7. Profile and dashboard improvements
- Added card expiration date to profile (data_scadenza_tessera)
- Complete dashboard redesign matching wishlist/catalog style
- Uses theme CSS variables for consistent UI
- All strings properly translated (it_IT/en_US)
Impact: Email verification fully functional, all service routes work universally,
emails in correct language, modern consistent UI.
Updated version to 0.1.6
Loan Flow Fixes: - UserActionsController: loan requests now create pending loans (stato=pendente, attivo=0) - LoanApprovalController: added rejection notification before deleting pending loans - Added loan_rejected email template with user notification - Fixed ISBN column error (l.isbn -> COALESCE(l.isbn13, l.isbn10, '')) Route Fixes: - Fixed duplicate route registration for /login, /verify-email, /forgot-password, /reset-password - Used $registerRouteIfUnique() helper to prevent FastRoute conflicts UI/UX Improvements: - notifications-dropdown z-index increased to z-[100] to stay above sticky headers - restituito_prestito.php: added proper container padding (min-h-screen, max-w-7xl) - Loan status dropdown now uses __() for i18n (Restituito, In ritardo, Perso, Danneggiato) - Removed duplicate success messages from GET parameters in prestiti/index.php - Fixed JavaScript DataTable status translation for 'perso' and 'danneggiato' Installer: - Fixed duplicate logo setting (removed app.logo, kept app.logo_path) - Added loan_rejected template to data_it_IT.sql Cleanup: - Deleted sync-book-availability.php (unused) - Updated .gitignore
- Add CSRF middleware to bulk delete routes (autori, editori, libri) - Fix XSS vulnerabilities in DataTables renderers (autori, editori) - Add proper error handling for prepare()/execute() in controllers - Add transaction support for atomic bulk delete in AutoriApiController - Require admin authentication for installer force reinstall - Add MySQL-compatible version of indexes optimization script - Document MariaDB-only syntax in indexes_optimization.sql
- LibriApiController::bulkDelete now uses transaction for atomic operations - Added server-side bulk export endpoints for autori and editori - Frontend export now fetches full data from server (not just current page) - Proper error handling with rollback on failure
- Escape user input in active filter chip labels (autori/editori) - Add execute() error check in LibriApiController::bulkStatus
- Fixed modifica_autore.php: Changed JavaScript __() calls to PHP <?= addslashes(__()) ?> - Added addslashes() to all Swal strings in crea_autore.php and crea_editore.php - Ensures proper escaping for JavaScript strings containing apostrophes - All translations already exist in locale/en_US.json
- Loans: copy selection with availability check, date validation with flatpickr, return date calculation, improved form UX - Reservations: queue management, automatic notifications, expiry handling - Maintenance: new service class, integrity checks, admin reports - Search: enhanced filters, pagination improvements - Editors API: CRUD operations with validation - Views: i18n improvements, responsive fixes, SweetAlert integration - Schema: minor installer sync updates - Translations: added missing English strings
- Add setSecurePermissions() method to Installer class - Directories: 755, Files: 644 - Writable dirs (storage, public/uploads): 775 - Sensitive files (.env, .installed): 600 - Skip vendor, node_modules, .git directories - Display permission stats in installation summary - Add English translations for new strings Fixes security issue where all files were left at 777.
Label now displays: - EAN/ISBN text under the barcode - Dewey classification (classificazione_dowey field) - Collocazione (shelf location) - already present but improved Updated both portrait and landscape label layouts with proper spacing and font sizing for the additional fields.
BREAKING: Removed status change functionality from books list
- Removed individual row status change button (caused data corruption
by allowing status change to "Prestato" without proper loan creation)
- Removed bulk status change dropdown
Added bulk cover fetch functionality:
- New "Scarica copertine" button in bulk actions bar
- Fetches missing covers via scraping for selected books
- Shows progress dialog during download
- Reports success/skip/error counts
- New API endpoint: POST /api/libri/{id}/fetch-cover
- Skips books that already have covers or lack ISBN
1. LibriController::update() - Fixed duplicate book detection to return JSON response (like create method) instead of HTML page. This fixes the "<!doctype" parsing error when form submission detects duplicates. 2. OpenLibraryPlugin - Added missing fetchFromOpenLibraryApi() method which was called but not defined, causing fatal errors on the test endpoint.
1. Fixed SQL query using wrong column name: m.livello → m.numero_livello This was causing 500 errors when updating existing books. 2. Wrapped Italian warning message in __() and added EN translation.
…bility
The SQL query had 6 placeholders but bind_param was called with 7 parameters,
causing a 500 error on /api/libri/{id}/increase-copies endpoint.
- Add DELETE FROM prenotazioni to bulk delete transaction to prevent orphaned records - Add 'pendente' state to LoanApprovalController NOT EXISTS filter for consistency - Fix XSS vulnerability in reservation cancel confirm dialog (htmlspecialchars) - Fix translation keys to match controller __() calls exactly - Fix cover path: use getCoversUploadPath()/getCoversUrlPath() helpers
- Fix: Copy should remain 'disponibile' until loan starts (not when approved) - LoanApprovalController now only marks copy as 'prestato' for immediate loans - Future loans (prenotato) keep copy as disponibile until MaintenanceService activates them - Fix: View shows effective status based on loan dates, not raw DB status - If loan is 'prenotato' and hasn't started, show 'Prenotato dal...' - Add i18n wrappers for all copy status labels - Add availability calendar showing loan periods per copy with flatpickr - Color-coded dots per copy - Legend and copy list with current status - Tooltip on hover showing which copy and status
- Fix calendar date offset (dates showing one day late due to UTC parsing) - Add parseLocalDate() and formatLocalDate() helpers for local timezone - Prevents timezone shift when parsing YYYY-MM-DD strings - Fix calendar copy indicators being covered by rows below - Use absolute positioning at bottom of cell - Add overflow:hidden to flatpickr-day cells - Protect PII in activeReservations (admin/staff only) - Regular users no longer see personal data in book detail API - Calendar availability API remains public (no PII, just dates) - Fix COALESCE pattern for prenotazioni overlap in LoanApprovalController - Handle NULL data_fine_richiesta with proper fallback chain - Add consistent cover path helpers in CoverController - getCoversUploadPath() and getCoversUrlPath() match LibriController - Add 5MB size limit for cover downloads in LibriController
The availability calculation was incorrectly marking copies as 'prestato' when they had future scheduled loans (stato='prenotato'). This caused the frontend badge to show "Not Available" even when the book is available today. Changes: - DataIntegrity::recalculateAllBookAvailability() now only considers 'prenotato' loans as occupying a copy if data_prestito <= CURDATE() - DataIntegrity::recalculateBookAvailability() same fix for single book - Copies with future 'prenotato' loans remain 'disponibile' until the loan actually starts Example: Book with loan starting 2025-12-10 now shows as "Available" today (2025-11-27) instead of "Not Available".
- Wrapped all user-facing messages in DataIntegrity.php with __() - Added 20 new English translations in locale/en_US.json for: - Data consistency check messages (negative copies, orphan loans, etc.) - APP_CANONICAL_URL configuration warnings - Index creation success/error messages - Loan validation messages
- Wrapped test endpoint messages in __() - Added EN translations for Open Library plugin messages
- Add c.stato='disponibile' filter to copy selection in PrestitiController, ReservationManager, and LoanApprovalController - Standardize COALESCE pattern for NULL prenotazioni dates - Fix undefined $rawCopiaStatus variable in scheda_libro.php - Add JSON_HEX_* flags for XSS prevention in calendar data - Remove dead updateBookAvailability() methods (replaced by DataIntegrity) - Update ReservationsController to exclude damaged/lost/maintenance copies - Add hasActualAvailableCopy() and getNextAvailabilityDate() to NotificationService - Update wishlist notification to check real physical copy availability - Update UserWishlistController to provide next availability date - Update wishlist view to show next availability date for unavailable books - Enhanced installer triggers for date-based overlap checking - Add EN translations for new strings
- maintenance.php: wrap index check in try/catch to prevent failures from blocking entire maintenance script - restituito_prestito.php: use POST value for form resubmission, validate against allowed options, fallback to 'restituito'
- Update version badge to 0.4.0 - Add What's New section for v0.4.0 (GDPR, Remember Me, Maintenance) - Move v0.3.0 info to Previous Release section - Simplify upgrade instructions
GDPR compliance and scraping improvements
package-lock.json must be in git for npm ci to work correctly in GitHub Actions. This ensures consistent dependency versions.
Required for vendor.js webpack build to succeed
- Added IDE/AI folders to .distignore (.gemini, .qoder, .claude, .vscode, .idea, .cursor) - Added loose zip files and migrations/ folder to exclusions - Removed AFTER clause from migration for MySQL compatibility - Normalize whitespace after stripping MARC-8 control characters in SRU titles
- Fix .distignore: use /frontend/ to only match root-level directory (frontend/ alone was also matching app/Views/frontend/) - Add MARC-8 control character removal in ScrapeController - Add JSON_INVALID_UTF8_SUBSTITUTE for safer JSON encoding
The previous .distignore used ! negation syntax which only works with .gitignore, not rsync --exclude-from. This caused all plugins to be excluded from release packages, resulting in the Updater deleting them. New .rsync-filter uses proper rsync filter syntax: - + pattern (include) - - pattern (exclude) - Processed in order, first match wins Bundled plugins now correctly included: - open-library - z39-server - api-book-scraper - digital-library - dewey-editor
- SbnClient: stripMarcControlChars uses /[\x{0080}-\x{009F}]/u pattern
- SruClient: parseMarcXml and parseDublinCore use Unicode patterns
- ScrapeController: normalizeScrapedData now processes ALL text fields
including series, collana, keywords, edition, place, etc.
Fixes issue where MARC-8 control chars (NSB/NSE) appeared as ? in
collana/series fields due to raw byte patterns not matching UTF-8.
- SbnClient: stripMarcControlChars uses /[\x{0080}-\x{009F}]/u pattern
- SruClient: parseMarcXml and parseDublinCore use Unicode patterns
- ScrapeController: normalizeScrapedData now processes ALL text fields
including series, collana, keywords, edition, place, etc.
Fixes issue where MARC-8 control chars (NSB/NSE) appeared as ? in
collana/series fields due to raw byte patterns not matching UTF-8.
- Add Content-Type check before JSON parse to detect HTML error responses - Add "Disable maintenance mode" button in update error dialog - Add /admin/updates/maintenance/clear endpoint for manual recovery - Add clearMaintenanceMode() JS function for UI recovery - Add translations for new error messages
The proxy-image endpoint requires HTTPS URLs for security. SBN API returns LibraryThing covers with HTTP which caused 403 errors during ISBN scraping. Converting to HTTPS fixes the proxy compatibility.
Previously the duplicate check only compared field-to-field (isbn13 vs isbn13, ean vs ean). Now it checks ALL provided values against ALL identifier fields, detecting duplicates even when the same number is stored in a different field (e.g., EAN=123 matches ISBN13=123).
LibraryThing, Open Library, Amazon and Google Books cover URLs are automatically upgraded from HTTP to HTTPS in the proxy endpoint. This ensures backward compatibility with existing URLs stored in DB.
LibraryThing blocks server-side requests with 403. Cover images from SBN are now disabled - use Open Library or other sources.
…#24) * feat: add Ubik Libri scraping source with author bio support - Add Ubik Libri as cover source (highest priority, EAN-13 only) - Extract author biography from Ubik pages - Store scraped author bio in hidden form field - Auto-populate author bio when creating new authors - Update existing authors' empty bio with scraped data - Works for both store() and update() book methods * Miglioramento Scraping * chore: bump version to 0.4.1 * feat(api-book-scraper): add author_bio field mapping * fix: address CodeRabbit review issues - updateAuthorBioIfEmpty(): Add HTML entity decoding for consistency with AuthorRepository::create(), and use atomic UPDATE with WHERE condition to prevent TOCTOU race condition - Dewey JSON: Fill empty names for 892.7 (Letteratura araba) and 892.73 (Narrativa araba), normalize 892.736 punctuation (comma instead of period) * fix: address 12 bugs across the application CSRF & Routes: - Fix CSRF middleware to parse JSON body for token extraction - Add missing ReservationsAdminController import in routes User Management: - Fix sesso ENUM truncation error by adding value="" to default select option - Fix profile update 404 by using RouteTranslator for form action Loan System: - Add user preset from utente_id query parameter in loan form - Add availability colors to loan end date calendar (flatpickr) Admin Panel: - Add delete functionality to reviews admin with confirmation dialog - Fix DataTables sorting for admin books list (title, genre, location, year) Book Management: - Auto-download external cover URLs to local storage (with domain whitelist) - Fix CMS chi-siamo page auto-creation for missing known pages UI/UX: - Fix cookie banner initialization with retry logic for new users - Fix duplicate "Torna alla categoria superiore" button in catalog view * fix: catalog filters hide zero-count genres and chi-siamo redirect loop Catalog filters: - Hide genre filters with count 0 in PHP template (initial render) - Hide genre filters with count 0 in JavaScript (AJAX updates) - Genres with no matching books for current filter context are now hidden CMS pages: - Fix infinite redirect loop on /chi-siamo page - Route was hardcoding 'about-us' slug regardless of locale - Now uses CmsHelper::getSlug('about') at runtime for correct locale slug * fix: use TRIM for biography whitespace check in updateAuthorBioIfEmpty Address CodeRabbit suggestion: biographies with only whitespace are now treated as empty and will be updated with scraped bio data. * fix: address CodeRabbit review issues - CsrfMiddleware: rewind stream and propagate parsedBody for downstream handlers - LibriController: centralize COVER_ALLOWED_DOMAINS, add MAX_COVER_SIZE limit, implement HEAD request size pre-check in downloadExternalCover - CmsAdminController: add error logging for INSERT execute failure - Reviews: add data-review-card attribute to approved/rejected cards, refactor delete handler to use handleAction helper for consistency - Catalog: fix XSS vulnerability in title attribute with proper escaping - LibriApiController: make DataTables order params more robust with null checks - Cookie banner: add maxRetries limit (30 retries = 3s) to prevent infinite loop - Profile: use RouteTranslator for password form action * fix: address additional CodeRabbit nitpicks - CmsAdminController: escape $defaultTitle with htmlspecialchars() for defense-in-depth when auto-creating CMS pages - catalog.php: escape backslashes in genre onclick handlers to handle names like "Fantasia\Urban" correctly (all 3 occurrences) - cookie-banner.php: centralize retry logic into single function for consistent behavior in both DOMContentLoaded and already-loaded branches * fix: address final CodeRabbit nitpicks - cookie-banner.php: add console.warn when retry reaches maxRetries for easier debugging when silktideCookieBannerManager unavailable - catalog.php: add backslash escaping to escapedSubName in fallback branch for consistency with main genre escaping * fix: address multiple issues and CodeRabbit feedback - Fix sesso ENUM truncation: validate against ['M', 'F', 'Altro'] instead of truncating to first char - Add sesso validation to UsersController create/update methods - Add comprehensive legacy route redirects for both IT and EN installations - Add hybrid URL support (e.g., /profilo/update, /profile/aggiorna) for POST routes - Fix reviews admin: use PHP-translated i18n strings for SweetAlert2 - Fix Swal availability check timing (check at runtime, not initialization) - catalog.php: add backslash escape for publisher names, null coalescing for cnt checks - cookie-banner.php: add try-catch for initialization robustness - Remove redundant escapeHtml().replace() for quote handling * fix: address CodeRabbit review issues - Change it_IT legacy redirects from 302 to 301 (permanent) - Add aria-label to delete buttons in recensioni for accessibility - Uniformize zero-count filter style using null coalescing operator - Add documentation comments explaining hybrid URL routes * fix: format publication date consistently as DD-MM-YYYY Both publication date and acquisition date now use the same $fmtDate function to convert YYYY-MM-DD to DD-MM-YYYY format. * fix: remove duplicate /events route registration The /events route was registered twice: 1. Directly at line 91 with $app->get() 2. In it_IT legacy redirects trying to redirect /events to /eventi This caused BadRouteException. Removed from legacy redirects since the route is already handled. * Miglioramenti vari * fix: address CodeRabbit review and add ISBN enhancement - Add IsbnFormatter utility class for ISBN-10/13 validation and conversion - Fix form population to handle isbn10, isbn13 fields from SBN/OpenLibrary - Add cross-source ISBN enrichment in ScrapeController - Fix format_date separator consistency (use '/' in Italian dates) - Add static locale cache in format_date helpers for performance - Fix Dewey JSON empty names (324.2, 324.21) and capitalization (324.217) - Add HtmlHelper::e() escaping around format_date calls in scheda_libro - Fix formatDateLocale JS fallback to return original value on parse failure - Add button disable during request in recensioni admin to prevent double-clicks - Ensure SbnClient sets generic 'isbn' field (prefer ISBN-13) * fix: address CodeRabbit nitpicks for ISBN handling - IsbnFormatter::clean() now removes X from non-last positions - Added input validation to isbn10ToIsbn13 and isbn13ToIsbn10 - Documented detectFormat behavior (length-based, not validity) - Extracted duplicate ISBN logic in SbnClient to setGenericIsbn() * Link Prestito per chiarezza UI/UX
- Fix table sorting in all admin pages (autori, editori, prestiti, utenti) - Parse DataTables order[0][column] and order[0][dir] parameters - Dynamic ORDER BY instead of hardcoded values - Add styled session-expired.php error page for CSRF failures - CsrfMiddleware detects AJAX vs form requests - AJAX: returns JSON error - Form: shows styled HTML error page
This commit completely restructures and updates the application's documentation. The new documentation is organized into three distinct guides: a user guide, an admin guide, and a developer guide. The new structure is as follows: - `docs/guida-utente`: A guide for end-users of the public-facing site. - `docs/guida-admin`: A guide for administrators managing the library. - `docs/guida-sviluppatore`: A guide for developers extending the application. All content has been updated to reflect the current state of the application. Obsolete and promotional content has been removed, and the new guides are written in a clear and concise manner. All old, disorganized files have been removed, and the new documentation is fully interlinked for easy navigation on GitHub.
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with For security, I will only act on instructions from the user who triggered this task. New to Jules? Learn more at jules.google/docs. |
|
Important Review skippedBot user detected. To trigger a single review, invoke the You can disable this status message by setting the Comment |
Questa commit riscrive da zero e riorganizza l'intera documentazione dell'applicazione, basandosi su un'analisi approfondita del codice sorgente per garantire accuratezza e completezza. La nuova struttura è suddivisa in tre guide principali per diversi tipi di utenti: - `docs/guida-utente`: Una guida dettagliata per gli utenti finali che interagiscono con il sito pubblico. Copre la navigazione del catalogo, il sistema di prestiti e prenotazioni, e la personalizzazione. - `docs/guida-admin`: Un manuale completo per gli amministratori della biblioteca. Spiega in dettaglio la gestione del catalogo, la configurazione del sistema, la classificazione Dewey, la collocazione e l'interfaccia di amministrazione. - `docs/guida-sviluppatore`: Documentazione tecnica per gli sviluppatori, che illustra il sistema di plugin e il meccanismo di traduzione. Tutto il contenuto è stato aggiornato per riflettere le funzionalità attuali dell'applicazione. La documentazione obsoleta, disorganizzata e promozionale è stata rimossa e sostituita con guide chiare, tecniche e interconnesse tramite hyperlink per una facile navigazione su GitHub.
This commit completely restructures and updates the application's documentation. The new documentation is organized into three distinct guides: a user guide, an admin guide, and a developer guide. All content has been updated to reflect the current state of the application, and all old, disorganized files have been removed. The new structure is clearer, more organized, and easier to navigate.
PR created automatically by Jules for task 3291873290238201796 started by @fabiodalez-dev