Commit Graph
6801 Commits
Author SHA1 Message Date
objecttothis aec39955be refactor(config): modularize stock location management logic
- Extracted `sanitizeSubmittedLocations`, `deleteRemovedLocations`, `saveSubmittedLocations`, and `saveLocationOrderAndDefault` into dedicated helper methods for improved readability and maintainability.
- Consolidated transaction handling around stock location operations.
- Enhanced inline documentation for key methods.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-28 15:29:56 +04:00
objecttothis a0d1273e71 Merge branch 'master' into feature-stock-location-dropdown-order 2026-08-28 11:24:50 +04:00
objecttothis d63d31700d Ensure payload data is escaped to prevent XSS (#4664)
fix(barcode): escape payload fields to prevent XSS; PSR-12 refactor

- Apply `esc()` to name, ID, item number, category, and company name in `Barcode_lib` payloads
- Remove redundant `urldecode()` in `Item_kitsController` to prevent triple decoding
- Rename variables and methods to camelCase across barcode, item_kits, and tests
- Add type hint for `$layoutType` parameter in `manageDisplayLayout`
- Add/update unit tests covering escaping and HTTP response assertions

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-28 10:08:31 +04:00
objecttothis 2589d7d812 Merge branch 'master' into feature-stock-location-dropdown-order 2026-08-27 14:04:42 +04:00
objecttothis 84bddcdd88 Feature admin account safeguards (#4657)
fix(employees): harden permissions UI and access control

- Prevent admins from removing their own minimum module grants (employees, home, office)
- Add session_status check before session regeneration
- Disable submit button and return no_access view for AJAX requests
- Replace fade class with active-only for Bootstrap compatibility
- Update permission toggle selectors to .module-toggle
- Add error_cannot_remove_own_minimum_grant translations for Armenian, Bulgarian, Georgian, Swedish, and Ukrainian

---------

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-27 11:29:32 +04:00
objecttothis 462e2150b0 Merge branch 'master' into feature-stock-location-dropdown-order 2026-08-25 18:33:54 +04:00
objecttothis 8b0f8533de fix(email): update method call to camelCase for PSR-12 compliance (#4659)
Corrected `check_encryption()` to `checkEncryption()` to align with coding standards.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-24 21:46:12 +04:00
objecttothis c701d21886 fix(sales): gate per-record endpoints behind reports_sales grant (#4627)
fix(sales): gate per-record endpoints behind reports_sales grant (REDACTED)

Cashiers holding only the base `sales` grant could reach per-sale endpoints
(getRow, getEdit, postSave, getReceipt, getInvoice, getSendPdf, getSendReceipt)
that require `reports_sales`. getManage() enforced this at the list level, but
individual endpoints did not re-check. Regression tests added.

Auth:
- Introduce `IsLoggedIn` filter to centralize login checks across controllers
- Replace custom `AccessDeniedRedirectException` with built-in `RedirectException`

Employees:
- Add `DISALLOW_PASSWORD_CHANGE` and `DISALLOW_GRANT_CHANGE` env vars to restrict
  credential and permission changes in locked-down environments
- Extract `hasGrantsChanged()` to streamline `postSave`

Refactor:
- Rename snake_case variables to camelCase in Sales, Items, and Employees
  controllers for PSR-12 compliance
- Use explicit `db_connect()` for transaction clarity in Items controller

Fixes:
- SMTP config entries fall back to defaults via null coalescing
- Migration uses `DROP FOREIGN KEY` instead of `DROP CONSTRAINT`
- Password hash upgrade only sets session on successful `hash_version` update
- Correct lang key for unknown error in Module model

Language:
- Translate `error_grant_change_disallowed` / `error_password_change_disallowed`
  across all 44 supported locales with => alignment matching en reference
- Fix "cannot be deleted" messages and misc typos across ~15 language files

Tests:
- Bootstrap seeder only once in ItemsCsvImportTest; close connection after
- Restore `DISALLOW_GRANT_CHANGE` in teardown to prevent side effects
- Use `uniqid()` for test user data to avoid collisions

Signed-off-by: 17935339+objecttothis@users.noreply.github.com
2026-08-23 17:40:06 +04:00
objecttothis 223f4c6345 Merge branch 'master' into feature-stock-location-dropdown-order 2026-08-21 21:01:09 +04:00
objecttothis 9ee530e454 Hotfix: Fix CI3 database migration caused by regression (#4649)
* refactor: standardize function and variable names to camelCase and improve naming consistency across files

* refactor(config): remove spaces around `=` in configuration files for improved consistency and formatting as is required by .env formatting rules.

* refactor(security): extract `.env` key management logic into reusable `writeEnvKey` helper, add throttle key provisioning logic, and streamline encryption key updates

* fix(migration): improve error handling in CI3 to CI4 encryption data migration
- Secure `up` and `convertCI3EncryptedData` methods with detailed exception handling for script execution and data saving.

* fix(migration): ensure empty string is correctly handled in CI3 to CI4 encryption data conversion

* refactor(security): enhance `.env` management with durable writes, better locking, and helper abstraction
- Update `writeEnvKey` to return a success flag and handle file locks robustly.
- Introduce `atomicWriteFile` for atomic writes to prevent partial file updates.
- Add `applyEnvKeyReplacement` to streamline `.env` key insertion and updates.
- Improve throttle key provisioning with validation and runtime persistence safeguards.

* refactor(security): implement dedicated `.env` file locking for robust and cross-platform safe write operations
- Add `lockEnvFile` and `unlockEnvFile` helpers to manage `.env` mutex files.
- Refactor `.env` write logic to use lock helpers, improving reliability and preventing race conditions.
- Enhance `atomicWriteFile` for better handling of file overwrites on Windows and POSIX systems.

* fix(migration): improve encryption error handling during CI3 to CI4 data conversion
- Add conditional checks for `checkEncryption` to prevent failed key persistence.
- Introduce `abortEncryptionConversion` for cleanup on failure.
- Update `writeEnvKey` to handle and return errors gracefully.

* refactor(security): improve `atomicWriteFile` for better file locking and cross-platform durability
- Replace `uniqid` with `bin2hex(random_bytes())` for more secure temp file naming.
- Add explicit file permissions and locking for safe concurrent writes.
- Enhance error handling to ensure atomicity on both Windows and POSIX systems.

* Add env temp files to gitignore so they don't get tracked.

---------

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-21 21:00:48 +04:00
objecttothis 51617d14ce Merge branch 'master' into feature-stock-location-dropdown-order 2026-08-21 11:29:37 +04:00
objecttothis d081346528 Codeigniter changes between 4.7.2 and 4.7.4 (#4650)
Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-21 11:28:19 +04:00
objecttothis b676369bd4 Merge remote-tracking branch 'OpensourcePOS/master' into feature-stock-location-dropdown-order 2026-08-20 11:51:55 +04:00
objecttothis cc93c31355 fix(items): add explicit sentinel value for clearing supplier in bulk edit (#4617)
* fix(items): add explicit sentinel value for clearing supplier in bulk edit

This fixes a regression introduced in the fix for [REDACTED]
Introduce `Item::CLEAR_SUPPLIER_OPTION = 'NONE'` to distinguish between
\"leave supplier_id unchanged\" (empty string) and \"clear supplier_id\"
(sentinel). Previously, empty string was ambiguous.

- Add `CLEAR_SUPPLIER_OPTION` constant with doc comment explaining intent
- Update supplier dropdown to include sentinel as first real option
- Shift empty string to mean \"do nothing\" across all bulk edit fields

* test(items): add regression tests for mass assignment in bulk edit

Cover [REDACTED]: Item::update_multiple() bypasses model
$allowedFields via Query Builder, allowing unintended field writes
during bulk edit operations.

* fix(items): add type validation to bulk-edit field filter

filterBulkEditFields now validates field values before accepting them:
- Non-scalar values are rejected (array injection guard)
- Price/quantity fields are locale-parsed to floats, invalid strings skipped
- Boolean fields must be 0 or 1, other values skipped
- supplier_id must be numeric; CLEAR_SUPPLIER_OPTION still nulls it

Update tests to assert parsed types (float for prices, int for
supplier_id) and replace the fill-all-fields fixture with a realistic
input that only covers fields a form would actually submit.

* test(items): add supplier cleanup and helper methods to bulk update tests

- Track created supplier person IDs for teardown cleanup
- Delete supplier records in tearDown to prevent test pollution
- Extract item/supplier creation into reusable helper methods

* style(tests): rename variables to camelCase in ItemBulkUpdateTest

* refactor(items): rename snake_case variables to camelCase

Convert Item model, Items controller, and bulk update tests to
PSR-compliant camelCase naming per project conventions.

- Rename update_multiple to updateMultiple in Item model
- Rename local variables (item_data, items_to_update, tax_names, etc.)
  to camelCase across Items controller and Item model
- Update ItemBulkUpdateTest to use new updateMultiple method name
- Reorder and update AGENTS.md naming conventions

* style(tests): convert snake_case variables to camelCase in ItemBulkUpdateTest

Rename local variables and property names to camelCase for PSR-12
consistency, matching convention used elsewhere in new test code.
2026-08-20 11:24:50 +04:00
objecttothis 72f170f8be Merge branch 'master' into feature-stock-location-dropdown-order 2026-08-20 10:16:16 +04:00
objecttothis 61bb1a2c2a hotfix(auth): hash throttler keys to improve security (#4646)
* fix(auth): hash throttler keys to improve security

- Use MD5 hashing for IP and username-based throttler keys to obfuscate sensitive data while maintaining functionality.

* test(auth): add IPv6 throttling test and hash used throttler keys

- Add a test to ensure throttling works correctly with IPv6 addresses.
- Update throttler keys to use MD5 hashes for IPs and usernames for improved security and consistency.

* fix(auth): handle non-scalar usernames in throttler keys

- Ensure username input is validated as scalar before processing to prevent errors and maintain throttling logic integrity.

* fix(auth): enhance throttler key security with HMAC hashing

- Replace MD5 with HMAC-SHA256 for generating throttler keys.
- Include encryption key from app configuration for added security.

* test(filters): update ThrottleTest to use HMAC-SHA256 for throttler keys

- Replace MD5 with HMAC-SHA256 for generating throttler keys in tests.
- Introduce `check_encryption()` to ensure encryption configuration is available.

* fix(events): validate encryption key on app initialization

- Throw ConfigException if encryption key is missing or invalid during `pre_system` event.
- Remove redundant `check_encryption()` call from Throttle filter and tests.

* fix(events): improve encryption key validation in `pre_system`

- Add `check_encryption()` helper call for additional security verification.
- Update error message to highlight `.env` writability issues if the key is invalid.

* test(filters): handle non-scalar usernames in ThrottleTest

- Update `makeRequest` to validate usernames as scalar and cast them to strings before processing.
- Add a test to ensure array usernames are ignored, and throttling is applied only based on IP.
- Improve status code assertions for throttled requests.

---------

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-20 02:27:13 +04:00
objecttothis 29a9b1a7e7 Bugfix: Resolve Race Condition in Rewards and Gift Card Spending (#4640)
* Implement atomic updates for gift card and reward point decrements, enhance error handling for insufficient balances, and add regression tests for concurrency safety.

* Add translations for insufficient gift card balance and reward points error messages across all supported languages.

* Reorder `clear_suspended_sale_detail` call to ensure transactional consistency.

* Reorder `clear_all` call to align with success and error handling logic.

* Ensure soft-deleted gift cards are excluded in balance updates.

* Refactor change_quantity logic with atomic upserts, improve error handling for insufficient stock, and update related tests and constants.

* Added check for NEW_ENTRY

* Added unit tests to test changes.

* Fix class name casing in ItemQuantityTest for consistency.

* Fix Bulgarian translations for insufficient balance error messages in Sales module.

* Fix Greek translations for insufficient balance error messages in Sales module.

* Fix Armenian translations for insufficient balance error messages in Sales module.

* Fix Tamil translations for insufficient balance error messages in Sales module.

* Implement race condition testing for database methods with concurrent process support.

* Fix class name casing in ItemTest for consistency.

* Improve concurrent process handling in race condition tests; add readiness and synchronization barriers.

* Improve handling of process I/O streams and timeout management in race condition tests.

* Add test for decrementing gift card value when marked as deleted

* Add `finally` block to ensure proper cleanup in async database race condition tests

* Improve error handling and timeout management in async database race condition tests.

* Refactor test utilities to use shared `EmployeeFixtureTrait` and `ItemFixtureTrait`.

* Track process exit codes explicitly in race condition tests for improved error detection and debugging.

* Improve error handling in `ConcurrentDbRaceTrait` by adding exceptions for `mysqli_poll` and `mysqli_reap_async_query`.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>

---------

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-20 02:24:23 +04:00
objecttothis 028179e6de fix(models): compact sort order after deletion to prevent gaps
- Updated `delete` method in `Stock_location` model to compact remaining `sort_order` values after a location is deleted.
- Added a test to ensure subsequent inserts assign the correct `sort_order`.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-19 18:02:02 +04:00
objecttothis b09b51439f fix(controllers): abort stock location processing on save failure
- Introduced a safeguard to halt location processing if `saveValue` fails.
- Prevented further operations like sort order updates and default location setting upon failure.
- Added `saveFailed` flag to track failure state in the save loop.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-19 17:55:27 +04:00
objecttothis fc9f9afc29 fix(controllers): validate and sanitize submitted stock locations before saving
- Added validation to ensure `stock_location` is an array.
- Filtered and sanitized submitted location data to prevent invalid keys or values.
- Improved handling of empty location names and skipped saving invalid entries.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-19 17:49:09 +04:00
objecttothis ddf8d5df96 fix(models): use explicit SQL query to ensure atomic sort_order calculation
- Replaced query builder logic with an explicit SQL SELECT COUNT statement to calculate `sort_order` atomically within a transaction.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-19 17:45:39 +04:00
objecttothis a7f1994404 fix(view): conditionally reload stock locations on success response
- Updated AJAX response handler to reload stock locations only when the operation is successful.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-19 17:37:52 +04:00
objecttothis 39124e8132 fix(controllers, views): handle new stock locations in sort order and default selection
- Updated controller to resolve 'new-*' placeholders in sort order to actual IDs.
- Adjusted view logic to assign 'new-*' IDs to new stock location rows.
- Improved default selection logic to exclude new rows with unresolved IDs.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-19 17:36:03 +04:00
objecttothis 2115fda4e5 fix(models): validate existence of stock location before setting as default
- Added check to ensure that the stock location exists and is not deleted before attempting to set it as the default.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-19 17:17:08 +04:00
objecttothis d103790568 fix(libraries): update get_stock_destination() to allow nullable return type
Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-19 17:12:02 +04:00
objecttothis 593a2f0d7d fix(view): add aria-label for default stock location and update element IDs
- Improved accessibility by adding an `aria-label` to default stock location radio inputs.
- Updated ID formatting for stock location input elements.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-19 17:10:08 +04:00
objecttothis a6076c9068 fix(view): use stock location-specific quantity or fallback to default
- Updated quantity input to fetch value for current stock location if available, with a fallback to the default quantity.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-19 17:06:09 +04:00
objecttothis f18524af57 fix(view): handle undefined stock location with fallback to default
- Updated `form_count_details.php` to use the current stock location if defined, or fallback to the default.
- Ensured `display_stock` JavaScript function handles undefined stock location IDs gracefully.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-19 17:04:25 +04:00
objecttothis f315163a18 fix(view): disable default checkbox for new stock locations and improve row selection logic
Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-19 17:01:03 +04:00
objecttothis 4f25bb540f fix(libraries): validate default location ID before assigning it in session
Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-19 16:57:41 +04:00
objecttothis 99b42f0800 fix(models): ensure dense sort_order range and clear values for deleted locations
- Simplified sort_order assignment logic to maintain dense 0..N-1 range for active locations.
- Updated deleted rows to set sort_order as NULL instead of pushing to a higher value.
- Adjusted tests and migrations to reflect the new behavior.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-19 16:50:24 +04:00
objecttothis fa9bc0bbf3 fix(controllers): validate default stock location ID before setting it
Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-19 16:06:37 +04:00
objecttothis b14492c850 fix(view): escape dynamic stock location IDs to prevent potential XSS
Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-19 15:50:53 +04:00
objecttothis bdfcf07fe1 fix(models): handle empty location IDs in saveSortOrder method
Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-19 15:46:55 +04:00
objecttothis bd66506ce4 fix(security): escape location ID to prevent potential XSS in stock locations view
Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-19 15:45:15 +04:00
objecttothis 94adc90ee0 fix(libraries): update methods to return nullable int and handle default location assignment cautiously
Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-19 15:20:45 +04:00
Travis Garrison a8219942e2 Merge remote-tracking branch 'OpensourcePOS/master' into feature-stock-location-dropdown-order 2026-08-19 10:39:21 +04:00
objecttothis a2b91493c7 Feature: CodeIgniter Throttler (#4619)
* fix(auth): throttle login attempts to prevent brute-force attacks

Add Throttle filter and wire into login route to mitigate
credential-stuffing/brute-force risk (redacted).

- Register App\\Filters\\Throttle in Filters config
- Add \"too_many_attempts\" language string for throttled responses
- Add tests for Throttle filter and Login controller throttling

* Correct bug causing error to not display.


* i18n(login): add too_many_attempts translation for login throttling

Add localized \"too many attempts\" message across all language files
to support login throttling feature. Message informs users to wait
before retrying after exceeding attempt limit.

* fix(auth): rate limit login attempts to prevent brute-force attacks

Add Throttle filter that rate limits login/migrate POST requests,
keyed by IP and submitted username, using CodeIgniter's cache-based
Throttler (redacted).

- Wire filter into login/migrate routes
- Show localized error message when rate limit exceeded
- Broaden writable/cache ignore pattern to cover throttler cache file

* Update app/Language/ar-EG/Login.php

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* style(i18n): use single quotes for translation array keys and values

Convert double-quoted array keys and string values to single quotes
across all Login.php language files for style consistency.

* test(auth): update LoginTest to use throttler service directly

Replace clearThrottleState's Services::resetSingle('throttler') call
with Services::throttler() to reset state via the service instance.
Add usedKeys property to track throttle keys used across test cases.

* test(auth): skip login test assertion when migration required

LoginTest now check migration-required response state before
asserting HTTP 200. Prevent false failures when app force
pending-migration redirect during test run.

* Added missing return statements
2026-08-19 00:25:22 +04:00
Travis Garrison d4c295d1d8 Add unit tests for Stock_location model, covering default location handling, sort order management, and deletion behavior.
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
2026-08-18 21:08:59 +04:00
Travis Garrison 11836c9d3a Refactor Stock_location model to adopt camelCase method naming, introduce is_default and sort_order support, add migration, UI updates, default location handling, and item synchronization.
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
2026-08-18 20:09:52 +04:00
objecttothis 8bd2a51cb5 fix(items): validate item_number and skip receiving quantity default for temp items (#4621)
* fix(items): validate item_number and skip receiving quantity default for temp items

- Validate item_number against alpha_numeric_punct rule, return JSON error on failure
- Add item_number_invalid language string

* i18n: reorder Items language keys and add item_number_invalid string

Add item_number_invalid translation across all locale files and
resort surrounding keys alphabetically to match key ordering
convention.

* PSR-12 refactoring.

- Change local variable to camelCase.
- Use single quote in language files.

* i18n: translate item_number_invalid string in ta, th, tl, zh-Hans

Item_number_invalid key had English placeholder text in Tamil,
Thai, Tagalog, Chinese Simplified language files. Translate to
match each locale.

* fix(items): use FormatRules for item_number validation

* refactor(items): use camelCase for variable names

* refactor(items): use camelCase for variable names in Items controller
2026-08-18 02:51:42 +04:00
Sai Asish Yandobjecttothis 0e8fc0963a Reject item CSV imports whose header row is missing required columns (#4597)
* Reject item CSV imports whose header row is missing required columns

Signed-off-by: Sai Asish Y <say.apm35@gmail.com>

* Require all template columns when validating CSV import headers

Signed-off-by: Sai Asish Y <say.apm35@gmail.com>

* fix: derive required CSV import headers from the template generator

---------

Signed-off-by: Sai Asish Y <say.apm35@gmail.com>
Co-authored-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-14 14:05:43 +04:00
dependabot[bot] 65b99fea97 chore(deps): bump dompurify from 3.4.12 to 3.4.13 (#4639)
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 3.4.12 to 3.4.13.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/3.4.12...3.4.13)

---
updated-dependencies:
- dependency-name: dompurify
  dependency-version: 3.4.13
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-10 21:42:43 +04:00
dependabot[bot] 29f8f16459 chore(deps): bump codeigniter4/framework from 4.7.2 to 4.7.4 (#4638)
Bumps [codeigniter4/framework](https://github.com/codeigniter4/framework) from 4.7.2 to 4.7.4.
- [Release notes](https://github.com/codeigniter4/framework/releases)
- [Commits](https://github.com/codeigniter4/framework/compare/v4.7.2...v4.7.4)

---
updated-dependencies:
- dependency-name: codeigniter4/framework
  dependency-version: 4.7.4
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-09 19:58:14 +02:00
objecttothisandTravis Garrison 5c9b1b81e6 fix(xss): remove redundant escaping that double-encoded item attribute values (#4628)
* fix(xss): remove redundant escaping that double-encoded item attribute values

- Remove esc()/html_entity_decode() calls now that output is escaped
  at render time by the framework, preventing double-encoding of
  special characters in attribute names, units, and definition values
- Fix employee_name form_input value fields to stop pre-escaping
  before form_input applies its own escaping
- Reorder Items.php use statements and add missing BaseConnection import
- Change items/manage.php start_date from let to plain assignment for
  proper reassignment scope

Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>

* test(sales): add regression tests for permission checks on sales endpoints

- Ensure role-based permissions correctly restrict access to sensitive actions like price edits, receipt/invoice views, and report generation.
- Add tests for both granted and restricted user scenarios to validate the behavior.

Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>

* fix(attributes): validate `attribute_value` before processing

- Add checks to ensure `attribute_value` is a non-empty string in `postSaveAttributeValue` and `postDeleteDropdownAttributeValue` methods.
- Return error response if validation fails to prevent invalid data handling.

Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>

* fix(attributes): improve error handling and optimize affected items processing

- Use `array_column` for extracting item IDs to streamline logic.
- Add JSON validation with `JSON_THROW_ON_ERROR` and return proper error response for invalid `definition_values`.

Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>

* test(sales): enable database refresh for consistent test state

Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>

* test(sales): assert unauthorized message is displayed on restricted access

Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>

* refactor(attributes): use camelCase for `attributeValue` in controller methods

- Standardize variable naming in `postSaveAttributeValue` and `postDeleteDropdownAttributeValue` methods by switching to camelCase.

Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>

---------

Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
Co-authored-by: Travis Garrison <travis@chiraqbookstore.com>
2026-08-09 11:37:38 +04:00
richardmilles 08b0951a84 fix: use db_connect() for item save transactions (#4636)
postSave() called $this->db which is not set on the Items controller, causing Undefined property errors when saving items. Match the CSV import path and obtain the connection via db_connect().

Fixes #4623
2026-08-09 00:10:53 +02:00
objecttothisandTravis Garrison f5ba1709eb fix(security): sanitize filenames and escape logo path in config (#4630)
* fix(security): sanitize filenames and escape logo path in config

- Sanitize uploaded filename in Config.php via preg_replace, strip
  chars outside [a-zA-Z0-9_-] before storing raw_name
- Escape $logo_src with esc(..., 'attr') in info_config.php view to
  prevent XSS via crafted logo path/filename

Prevents stored XSS and path traversal from unsanitized filenames
used in config uploads.

Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>

* fix(config): sanitize uploaded config filenames

Replace inline regex filename sanitization with sanitize_filename()
helper to prevent path traversal via crafted upload filenames.

Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>

---------

Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
Co-authored-by: Travis Garrison <travis@chiraqbookstore.com>
2026-08-07 20:30:02 +04:00
Rayan Abdul Caderandobjecttothis aa96ad0284 refactor: apply PSR-12 naming to Attribute definition methods (#4624)
Renames the Attribute-specific definition methods from snake_case to
camelCase and updates every call site:

  get_definition_by_name   -> getDefinitionByName
  get_definition_names     -> getDefinitionNames
  get_definition_values    -> getDefinitionValues
  get_definitions_by_type  -> getDefinitionsByType
  get_definitions_by_flags -> getDefinitionsByFlags
  get_definition_flags     -> getDefinitionFlags

Also documents getDefinitionByName()'s return contract: a single
definition row as an associative array, or [] when none matches,
matching the getRowArray() behaviour introduced in #4464.

get_found_rows() and get_total_rows() are deliberately left alone -
they are declared across 15 models and renaming them only here would
break that shared convention.

Refs #4622

Co-authored-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-08-07 13:13:05 +04:00
objecttothisandTravis Garrison a5d70c07bb fix(auth): validate gcaptcha before password to prevent bypass (#4618)
* fix(auth): validate gcaptcha before password to prevent bypass

Move gcaptcha check before credential validation so a valid captcha
is required prior to any login attempt. Previously, password auth
ran first, allowing timing-based enumeration without captcha.

Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>

* test(auth): add regression tests for gcaptcha validation order in OSPOSRules

Guards fix from 5dea748b0: gcaptcha must be validated before
Employee::login() is attempted to prevent auth bypass.

Change gcaptcha_check visibility to protected to allow testing.

Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>

---------

Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
Co-authored-by: Travis Garrison <travis@chiraqbookstore.com>
2026-08-07 02:27:33 +04:00
objecttothisandTravis Garrison 35f056ce69 refactor(migrations): rename execute_script to executeScript across all migrations (#4611)
Align migration helper function calls with PSR-12 camelCase naming convention.
Affects all migration files from initial schema through recent upgrades.

Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
Co-authored-by: Travis Garrison <travis@chiraqbookstore.com>
2026-08-07 02:26:43 +04:00