Commit Graph

43 Commits

Author SHA1 Message Date
jekkos
f0f288797a Add migration to fix existing image filenames with spaces (#4372)
This migration will:
- Scan all items for filenames containing spaces
- Rename both original and thumbnail files on the filesystem
- Update database records with sanitized filenames
- Only process files that actually exist on the filesystem
2026-03-06 17:09:52 +01:00
jekkos
6705420373 Fix incorrect argument types in migration round_number() methods (#4403)
The round_number() method signature declares $amount as string, but the
HALF_FIVE case and other rounding operations pass string values to round()
and other arithmetic operations which expect numeric types. This causes
type errors when strict type checking is enabled.

Fix by casting $amount to float before arithmetic operations in both
migration files:
- 20170502221506_sales_tax_data.php (line 268)
- 20200202000000_taxamount.php (line 244)

Also cast sale_tax_amount to float in round_sales_taxes() method before
passing to round() operations (lines 381 in sales_tax_data.php and 358 in
taxamount.php).

Fixes #4324
2026-03-06 13:07:24 +01:00
jekkos
690f43578d Use Content-Type application/json for AJAX responses (#4357)
Complete Content-Type application/json fix for all AJAX responses

- Add missing return statements to all ->response->setJSON() calls
- Fix Items.php method calls from JSON() to setJSON()
- Convert echo statements to proper JSON responses
- Ensure consistent Content-Type headers across all controllers
- Fix 46+ instances across 12 controller files
- Change Config.php methods to : ResponseInterface (all return setJSON only):
  - postSaveRewards(), postSaveBarcode(), postSaveReceipt()
  - postSaveInvoice(), postRemoveLogo()
  - Update PHPDoc @return tags

- Change Receivings.php _reload() to : string (only returns view)
- Change Receivings.php methods to : string (all return _reload()):
  - getIndex(), postSelectSupplier(), postChangeMode(), postAdd()
  - postEditItem(), getDeleteItem(), getRemoveSupplier()
  - postComplete(), postRequisitionComplete(), getReceipt(), postCancelReceiving()
- Change postSave() to : ResponseInterface (returns setJSON)
- Update all PHPDoc @return tags

Fix XSS vulnerabilities in sales templates, login, and config pages

This commit addresses 5 XSS vulnerabilities by adding proper escaping
to all user-controlled configuration values in HTML contexts.

Fixed Files:
- app/Views/sales/invoice.php: Escaped company_logo (URL context) and company (HTML)
- app/Views/sales/work_order.php: Escaped company_logo (URL context)
- app/Views/sales/receipt_email.php: Added file path validation and escaping for logo
- app/Views/login.php: Escaped all config values in title, logo src, and alt
- app/Views/configs/info_config.php: Escaped company_logo (URL context)

Security Impact:
- Prevents stored XSS attacks if configuration is compromised
- Defense-in-depth principle applied to administrative interfaces
- Follows OWASP best practices for output encoding

Testing:
- Verified no script execution with XSS payloads in config values
- Confirmed proper escaping in HTML, URL, and file contexts
- All templates render correctly with valid configuration

Severity: High (4 files), Medium-High (1 file)
CVSS Score: ~6.1
CWE: CWE-79 (Improper Neutralization of Input During Web Page Generation)

Fix critical password validation bypass and add unit tests

This commit addresses a critical security vulnerability where the password
minimum length check was performed on the HASHED password (always 60
characters for bcrypt) instead of the actual password before hashing.

Vulnerability Details:
- Original code: strlen($employee_data['password']) >= 8
- This compared the hash length (always 60) instead of raw password
- Impact: Users could set 1-character passwords like "a"
- Severity: Critical (enables brute force attacks on weak passwords)
- CVE-like issue: CWE-307 (Improper Restriction of Excessive Authentication Attempts)

Fix Applied:
- Validate password length BEFORE hashing
- Clear error message when password is too short
- Added unit tests to verify minimum length enforcement
- Regression test to prevent future vulnerability re-introduction

Test Coverage:
- testPasswordMinLength_Rejects7Characters: Verify 7 chars rejected
- testPasswordMinLength_Accepts8Characters: Verify 8 chars accepted
- testPasswordMinLength_RejectsEmptyString: Verify empty rejected
- testPasswordMinLength_RejectsWhitespaceOnly: Verify whitespace rejected
- testPasswordMinLength_AcceptsSpecialCharacters: Verify special chars OK
- testPasswordMinLength_RejectsPreviousBehavior: Regression test for bug

Files Modified:
- app/Controllers/Home.php: Fixed password validation logic
- tests/Controllers/HomeTest.php: Added comprehensive unit tests

Security Impact:
- Enforces 8-character minimum password policy
- Prevents extremely weak passwords that facilitate brute-force attacks
- Critical for credential security and user account protection

Breaking Changes:
- Users with passwords < 8 characters will need to reset their password
- This is the intended security improvement

Severity: Critical
CVSS Score: ~7.5
CWE: CWE-305 (Authentication Bypass by Primary Weakness), CWE-307

Add GitHub Actions workflow to run PHPUnit tests

Move business logic from views to controllers for better separation of concerns

- Move logo URL computation from info_config view to Config::getIndex()
- Move image base64 encoding from receipt_email view to Sales controller
- Improves separation of concerns by keeping business logic in controllers
- Simplifies view templates to only handle presentation

Fix XSS vulnerabilities in report views - escape user-controllable summary data and labels

Fix base64 encoding URL issue in delete payment - properly URL encode base64 string

Fix remaining return type declarations for Sales controller

Fixed additional methods that call _reload():
- postAdd() - returns _reload($data)
- postAddPayment() - returns _reload($data)
- postEditItem() - returns _reload($data)
- postSuspend() - returns _reload($data)
- postSetPaymentType() - returns _reload()

All methods now return ResponseInterface|string to match _reload() signature.
This resolves PHP TypeError errors.
2026-03-04 21:42:35 +01:00
jekkos
2acdec431f Fix wrong migration script location (#4285) 2025-12-08 23:06:48 +01:00
Joe Williams
bcddf482fe [Feature] Add logging to migrations (#4327)
* `execute_script()` now returns a boolean for error handling.

* Added transaction to `Migration_MissingConfigKeys.up()`.

* Added logging to various migrations.

* Added transaction to `Migration_MissingConfigKeys.up()`.

* Added logging to various migrations.

* Formatting and function call fixes

Fixed a minor formatting issue in the migration helper.
Replaced a few remaining error_log() calls.
Updated executeScriptWithTransaction() to use log_message()

* Function call fix

Replaced the last error_log() calls with log_message().

---------

Co-authored-by: Joe Williams <hey-there-joe@outlook.com>
2025-10-19 22:10:28 -07:00
Joe Williams
759356288b Add transactions to missing config keys migration. (#4318)
* `execute_script()` now returns a boolean for error handling.

* Added transaction to `Migration_MissingConfigKeys.up()`.

* Added `executeScriptWithTransaction()` to migration helpers.

* Many changes for testing; also minor formatting fixes.

* Removed test code and pointed the `NullableTaxCategoryId` migration at the right SQL file.

* Fixed header.php

* Code cleanup from code review:
- Added IGNORE to SQL scripts.
- Added try-catch to executeScriptWithTransaction().
- Various comment changes.

* Fixed naming issue

Nullable tax category ID migration now runs the correct script.

* Updated SQL

Replaced INSERT WHERE NOT EXISTS in missing config keys sql script to use a single INSERT IGNORE.

* Updated migration helper

Updated executeScriptWithTransaction to use transRollback

---------

Co-authored-by: Joe Williams <hey-there-joe@outlook.com>
2025-10-15 22:53:14 -07:00
jekkos
e08367aaae Allow empty tax category id (#4285) (#4288) 2025-07-29 23:59:23 +02:00
jekkos
d4ab56b742 Fix migration 20250522000000 (#4284)
* Fix migration errors

Add dropColumnIfExists to migration_helper

* Add config key/values if missing (#4282)
2025-07-16 23:28:24 +02:00
objecttothis
e1fedab9b7 Bugfix: constraint migration fixes (#4230)
- Refactored function names for PSR-12 compliance
- Programmatically cascade delete attribute_link rows when a drop-down attribute is deleted but leave attribute_link rows associated with transactions.
- Added `WHERE item_id IS NOT NULL` to migration to prevent failure on MySQL databases during migration
- Retroactive correction of migration to prevent MySQL databases from failing.
- Refactored generic functions to helper
- Reverted attribute_links foreign key to ON DELETE RESTRICT which is required for a unique constraint on this table. Cascading deletes are now handled programmatically.
- Migration Session table to match Code Igniter 4.6
- Add index to attribute_links to prevent query timeout in items view on large databases
- Added overridePrefix() function to the migration_helper. Any time QueryBuilder is adding a prefix to the query when we don't want it to, this query can be used to override the prefix then set it back after you're done.
- Added dropAllForeignKeyConstraints() helper function.
- Added deleteIndex() helper function.
- Added indexExists() helper function.
- Added primaryKeyExists() helper function.
- Added recreateForeignKeyConstraints() helper function.
- Added CRUD section headings to the Attribute model.
- Replaced `==` with `===` to prevent type juggling.
- Removed unused delete_value function.
- Reworked deleteDefinition() and deleteDefinitionList() functions to delete rows from the attribute_links table which are associated.
- Added deleteAttributeLinksByDefinitionId() function

Implement Cascading Delete
- Function to delete attribute links with one or more attribute definitions.
- Call function to implement an effective cascading delete.
- Refactor function naming to meet PSR-12 conventions

Fix Migration
- Add drop of Generated Column to prevent failure of migration on MySQL databases.

Fix Migration
- Removed blank lines
- Refactored function naming for PSR compliance
- Reformatted code for PSR compliance
- Added logic to drop dependent foreign key constraints before deleting an index then recreating them.

Migrate ospos_sessions table
- DROP and CREATE session table to prevent migration problems on populated databases

Fixed Bug in Migration
- In the event that item_id = null (e.g., it's a dropdown) it should not be included in the results.

Fixed bug in Dropdown deletes
- Removed delete_value function in Attributes Controller as it is unused.
- Renamed postDelete_attribute_value function for PSR-12 compliance.
- Renamed delete_value Attribute model function for PSR-12 compliance.
- Refactored out function to getAttributeIdByValue
- Replaced == with === to prevent type juggling
- Reorganized parts of model to make it easier to find CRUD functions.

Refactoring
- PSR-12 Compliance formatting changes
- Refactored several generic functions into the migration_helper.php
- First check if primary key exists before attempting to create it.
- Grouped functions together in migration_helper.php
- phpdoc commenting functions

Optimizing Indices
- There are two queries run while opening the Items view which time out on large databases with weak hardware. These indices cut the query execution in half or better.

Add Unique constraint back into attribute_links
- This migration reverts ospos_attribute_links_ibfk_1 and 2 to ON DELETE RESTRICT. Cascade delete is done programmatically. This is needed to have a unique column on the attribute_links table which prevents duplicate attributes from begin created with the same item_id-attribute_id-definition_id combination

Correct spacing after if for PSR-12

Minor code cleanup.
- Removed Comments separating sections of code in Attribute model
- Removed extra log line to prevent cluttering of the log
2025-05-29 15:24:08 +04:00
BudsieBuds
e83c23cf0c Improve code style and PSR-12 compliance (#4204)
* Improve code style and PSR-12 compliance
- refactored code formatting to adhere to PSR-12 guidelines
- standardized coding conventions across the codebase
- added missing framework files and reverted markup changes
- reformatted arrays for enhanced readability
- updated language files for consistent styling and clarity
- minor miscellaneous improvements
2025-05-02 19:37:06 +02:00
objecttothis
e90b5b87da Replace tabs with spaces (#4196)
Signed-off-by: objecttothis <objecttothis@gmail.com>
2025-03-28 21:24:21 +04:00
jekkos
cf73ffa825 Fix attribute dropdown delete (#4176) 2025-03-01 00:37:23 +01:00
objecttothis
d946b31cf4 Bugfix Attributes not saving (#4080)
Fixed issue with Attribute Values not saving correctly

This issue was caused by the Attribute->attributeValueExists function receiving a date which was already in Y-m-d format, so the conversion was returning false. Added logic to pass the date through if it was already in Y-m-d format.

Signed-off-by: objecttothis <objecttothis@gmail.com>
2024-11-05 22:37:47 +01:00
objecttothis
0aaac04344 Fixed Only Group By problem (#4073)
Signed-off-by: objecttothis <objecttothis@gmail.com>
2024-09-24 14:20:46 +04:00
jekkos
7003b124d4 Revert to english (#3995) 2024-09-17 00:54:26 +02:00
jekkos
b41196966c Remove duplicate attribute_links constraint (#4012) 2024-09-16 14:18:17 +02:00
jekkos
8a346b0b4c Use sqlscript container to read init script (#3826) 2024-09-16 14:18:17 +02:00
jekkos
2e56cf766f Move queries to new migration script (#4012)
Iterate over empty array if no query result
Switch compose back to master
Only remove index if no pk
Remove drop indices
Only person_id changes in this migration
Do not name primary key
2024-09-16 14:18:17 +02:00
Steve Ireland
1c95d35a74 This is intended to start resolving #3634. CIR4 query() now returns false for failed queries
Minor improvements to migrations to report to the log any failures and remove unnecessary key definitions. (#4043)
2024-09-16 14:18:17 +02:00
objecttothis
6eb22276f3 Locale handling of decimals in attribute saves
- Added check in controller to convert locale-specific decimal formats to use a period decimal separator.
- Added PHPdoc explanation

Signed-off-by: objecttothis <objecttothis@gmail.com>

Add TODO to clarify workaround

Signed-off-by: objecttothis <objecttothis@gmail.com>

Fixed bugs in SQL

- Added checks before attempting to delete non-existing values.
- Corrected function which deletes duplicate attribute values and replaces the attribute_ids

Signed-off-by: objecttothis <objecttothis@gmail.com>
2024-09-16 14:18:17 +02:00
objecttothis
e1f8b73005 Add check to migration to prevent errors (#4032)
* Add check to migration

- Only drop the constraint if it exists.

Signed-off-by: objecttothis <objecttothis@gmail.com>

* Automatic bump of package-lock.json

Signed-off-by: objecttothis <objecttothis@gmail.com>

---------

Signed-off-by: objecttothis <objecttothis@gmail.com>
2024-07-27 00:08:49 +04:00
Steve Ireland
c972cdfaf4 Correct a constraint that wasn't using the full unique key based on composite keys. (#4014) 2024-07-01 13:25:11 -04:00
Steve Ireland
a1e8841129 Missed a comma (#4012) 2024-06-27 19:38:47 +02:00
Steve Ireland
0b889ec443 Clean up install.md a bit (#4012)
Corrected primary keys involving person_id.
Corrected a couple of errors in constraints involving compound keys.
2024-06-27 19:38:09 +02:00
BudsieBuds
c39b733c90 Language fallback improvement
- Changes for following best practice for CI4 localization
- Norwegian and Urdu languages now working again
- Sort languages by alphabet in config
2024-06-15 17:19:15 +02:00
objecttothis
1328b4d9b8 - Removed TODOs that had been completed
- Added TODO where we need to convert to querybuilder
- Converted to switch statement.
- Removed unnecessary local variable
- Replaced Qualifiers with imports
- Replaced isset() call with null coalescing operator
- Replaced strpos function calls in if statements with str_contains calls
- Removed unnecessary leading \ in use statement
- Replaced deprecated functions
- Updated PHPdocs to match function signature
- Added missing type declarations
- Made class variables private.
- Explicitly declared dynamic properties
- use https:// links instead of http://
- Fixed type error from sending null when editing transactions
- Fixed Search Suggestion function name in Employees, Persons, Suppliers controller
- Fixed function name on Receivings Controller

Signed-off-by: objecttothis <objecttothis@gmail.com>
2024-06-15 17:19:15 +02:00
objecttothis
0fbbc26ab6 Convert Barcode to new Types 2024-06-15 17:19:15 +02:00
objecttothis
5b725d04d5 Company logo upload
- Added conversion to migration file for delimiter in image_allowed_types
- Corrected business logic for image upload in items form.
- Removed log message used for debugging.
- Replaced '|' with ',' in image_allowed_types save/populate.
2024-06-15 17:19:15 +02:00
objecttothis
d18d2cf814 PHPdocs
- Removed unnecessary ReflectionException in PHPdoc
- Corrected return details of insert function
- Replaced deprecated class
- Removed Inventory model's insert function because it wasn't providing functionality that the Model class wasn't.
- Corrected the calling method signature for Inventory->insert()
2024-06-15 17:19:15 +02:00
objecttothis
cc58cecff0 Compatibility changes
- Removed `mixed` function return type from some functions for backward compatibility with php 7.4
- Refactored string concatination for readability.
- Added TODO for later
- Corrected PHPdocs
- Removed unneeded TODO
- Refactored function names with mixed snake and pascal case names
2024-06-15 17:19:15 +02:00
objecttothis
ba9bcd7786 PHPdocs
- Added missing PHPdocs
- Corrected Syntax
- Added noinspection parameters to PHPdoc for AJAX called functions
- Added missing function return types
- Added missing parameter types
- Added public keyword to functions without visibility modifier
- Corrected incorrectly formatted PHPdocs
- Added public to constants and functions missing a visibility keyword
2024-06-15 17:19:15 +02:00
objecttothis
7b224be665 PSR compliance and formatting changes
- Replaced TRUE/FALSE constants with true/false keywords
- Replaced NULL constant with null keyword
- Replaced `<?php echo` in views with shortened `<?=`
- Added missing variable declaration
- Added missing function return type in declaration
- replaced `== true`, `== false`, `=== true` and `=== false` in if statements with simplified forms
2024-06-15 17:19:15 +02:00
objecttothis
405583c832 Attributes fixes and warning removal
- when the payments array was folded into sale_data there was an earlier payments[] reference in the foreach loop that didn't get folded in.
- Update PHPdoc
- Added ::class to remove polymorphic call warning
- Removed unreachable 'break;' statement after return statement.
- Added missing return type
- fixed missing assignment of mailchimp_api_key
2024-06-15 17:19:15 +02:00
Doug Hutcheson
8ea5fc5078 CI4: Bugfix to correct two config issues
Adds 'payment_message' to the app_config table and corrects a typo in Views/login.php where 'Login.form' should have been 'login_form'.
2024-06-15 17:19:15 +02:00
Doug Hutcheson
310585d8af CI4: Bugfix - add function to remove .env.bak issue #3826
Added function remove_backup() to security_helper.php. Added a call to this from the two places that call check_encryption where the backup is created. Added more defensive code to Config.php to ensure the encrypter  objectexists before it is called to avoid a crash.
2024-06-15 17:19:15 +02:00
Steve Ireland
f5094d62a2 Restore the tables.sql to its virgin state. 2024-06-15 17:19:15 +02:00
jarebear6expepjozn6rakjq5iczi3irqwphcvbswgkahd6b6twnxxid
a2610c3bc9 update int(1) columns in _customers and _cash_up tables to use tinyint (#3709) 2024-06-15 17:19:15 +02:00
Steve Ireland
4798041408 Tack on the void return type onto the Employee:logout method. 2024-06-15 17:19:15 +02:00
objecttothis
525c65ffb3 Convert encryption to CI4
- automatic upgrade of encryption key.
- automatic decryption of CI3 data, then re-encryption in CI4 and update of table.
- Fixing save function in app_config model
2024-06-15 17:19:15 +02:00
objecttothis
ae357cab4a Formatting
- Convert indents to tabs
- Remove unnecessary else statement
- Correct PHPDoc formatting
2024-06-15 17:19:15 +02:00
objecttothis
1dd58e922f Corrected link in README.md 2024-06-15 17:19:15 +02:00
objecttothis
f84b795ee6 Upgrade to CodeIgniter 4.1.3 2024-06-15 17:19:15 +02:00
jekkos
73b189b6d4 Prepare rebase: move files to new folder structure 2024-06-15 17:19:15 +02:00