Compare commits

...

298 Commits

Author SHA1 Message Date
snipe 5fba8202d6 Updated translations
Signed-off-by: snipe <snipe@snipe.net>
2022-04-11 15:40:58 +01:00
snipe 61f5825c69 Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2022-04-11 15:37:38 +01:00
snipe 5314ef97e5 Updated assets
Signed-off-by: snipe <snipe@snipe.net>
2022-04-11 15:08:39 +01:00
snipe b7fbc5d018 Merge pull request #10927 from uberbrady/fix_columns_master
Fixes #10482 - Downgrade bootstrap-table so columns stay remembered
2022-04-11 15:03:08 +01:00
Brady Wetherington 211a0820e5 Downgrade bootstrap-table so columns stay remembered 2022-04-11 14:29:59 +01:00
snipe 7b891f0952 Merge pull request #10913 from inietov/fixes/bulk_user_edit_not_updating_asset_locations
Fixes Bulk user edit not updating checked out asset locations
2022-04-07 19:41:01 +01:00
snipe 6c1bb89776 Merge pull request #10920 from Godmartinz/Fixed_#10866_-_Checkin_time_always_shows_12am-master
Fixed #10866 - action_date for check-in not including H:i:s
2022-04-07 19:39:59 +01:00
Godfrey M 3eb7a87a66 fixes action_date for check-in not including H:i:s 2022-04-07 11:24:12 -07:00
snipe 0cb4caa4cf Merge pull request #10918 from uberbrady/bs_tables_export_without_html_master
This disables the display of HTML content during exports (cherry-picked for master)
2022-04-07 16:44:21 +01:00
Brady Wetherington 4db7cb0e21 This disables the display of HTML content during exports, without enabling XSS attacks 2022-04-07 16:37:32 +01:00
Ivan Nieto Vivanco 6529a75683 Update Assets locations when user's location changes whey they got bulk-edited 2022-04-06 19:12:02 -05:00
snipe 4b255ada70 Removed first()
Signed-off-by: snipe <snipe@snipe.net>
2022-04-06 12:08:51 +01:00
snipe 01342ca266 Fixed activity report
Signed-off-by: snipe <snipe@snipe.net>
2022-04-05 22:58:25 +01:00
snipe 87fc856361 Merge pull request #10902 from snipe/fixes/added_primary_key_to_custom_fields_pivot
Fixed #10892 - MySQL 8 compatibilty requires primary key
2022-04-05 20:35:14 +01:00
snipe 3dd7c00a0b Update migration back in time
Signed-off-by: snipe <snipe@snipe.net>
2022-04-05 20:31:17 +01:00
snipe 0c31e840c4 Merge pull request #10903 from inietov/fixes/erroneous_checkout_date_in_print_all_assigned_report
Fixes Dates in Print All Assigned report doesn't match to history
2022-04-05 20:19:10 +01:00
snipe c12ef19fcc Fixed #10892 - MySQL 8 compatibilty requires primary key
Signed-off-by: snipe <snipe@snipe.net>
2022-04-05 18:58:14 +01:00
Ivan Nieto Vivanco 2d213a9c77 Make the report take the dates of pivot table instead of asset log 2022-04-05 12:57:49 -05:00
snipe 0882cfede2 Merge pull request #10895 from ubc-cpsc/master
Security fixes to master branch
2022-04-05 18:29:25 +01:00
Joël Pittet 96cd90f842 Security fixes to master branch 2022-04-04 11:04:06 -07:00
snipe d56552a8af Merge pull request #10876 from snipe/fixes/huntr_ebc26354_logout_user_when_deactivated
Logout user when their activated status is switched to off
2022-03-29 15:57:24 +01:00
snipe bdabbbd4e9 Logout user when their activated status is switched to off
Signed-off-by: snipe <snipe@snipe.net>
2022-03-29 13:44:53 +01:00
snipe ab18ceb2f9 Add @QveenSi as a contributor 2022-03-29 11:54:51 +01:00
snipe e046db6d1e Merge pull request #10874 from QveenSi/patch-1
Fix problem with static paths
2022-03-29 11:52:32 +01:00
Yevhenii Huzii 863ea62551 Fix problem with static paths 2022-03-27 23:12:38 +03:00
snipe 70059f6f80 Merge pull request #10873 from uberbrady/fix_dashboard
Don't crash JS when there are no data-export-options (as is true in Dashboard) Fixes #10872
2022-03-27 07:21:34 +01:00
Brady Wetherington e50ad8a442 Don't crash JS when there are no data-export-options (as is true in Dashboard) 2022-03-27 07:18:12 +01:00
snipe 639409fb3f Backporting #10829 to master
Signed-off-by: snipe <snipe@snipe.net>
2022-03-25 13:00:16 +00:00
snipe 20e65804ef Removed comment
Signed-off-by: snipe <snipe@snipe.net>
2022-03-22 18:12:08 +00:00
snipe 729b23c0cf Merge pull request #10857 from uberbrady/fix_bs_tables_export_options
Fix bs tables export options
2022-03-22 17:03:18 +00:00
Brady Wetherington af9f3d5e1e Clean up the bootstrap table export options 2022-03-22 16:05:08 +00:00
Brady Wetherington 00ca30a205 WIP: fix bootstrap table export options 2022-03-22 15:12:11 +00:00
snipe 8c92198636 Possible fix for boolean field check
Signed-off-by: snipe <snipe@snipe.net>
2022-03-22 13:47:43 +00:00
snipe 169973e697 Merge pull request #10853 from inietov/fixes/customfields_boolean_format_not_saving_master
Fixes Customfields with boolean format not saving master[sc-9973]
2022-03-22 00:57:41 +00:00
Ivan Nieto Vivanco 7571c0b850 Add support for boolean type customfields 2022-03-21 18:48:42 -06:00
snipe 7cbcd2d95c Merge pull request #10814 from snipe/features/add_clear_sessions_artisan_command
Added session killer artisan command
2022-03-10 13:35:55 -08:00
snipe 1ac293a12a Add a force override
Signed-off-by: snipe <snipe@snipe.net>
2022-03-10 13:30:03 -08:00
snipe 3e3c277a3f Better phrasing
Signed-off-by: snipe <snipe@snipe.net>
2022-03-10 13:29:52 -08:00
snipe 93d6ce1a6a Added session killer artisan command
Signed-off-by: snipe <snipe@snipe.net>
2022-03-10 13:20:23 -08:00
snipe dadc80d558 Merge pull request #10811 from inietov/fixes/CarbonExceptions_InvalidFormatException_DateTime
Fixes Carbon\Exceptions\InvalidFormatException: DateTime::__construct(): Failed to parse time string
2022-03-10 10:40:46 -08:00
Ivan Nieto Vivanco 9caf27ce60 Sanitize dates input in the importer before saving 2022-03-10 11:48:57 -06:00
snipe 968de7e469 Merge pull request #10804 from inietov/fixes/date_localization_not_working_custom_fields
Fixes #8143 Date localization not work in custom fields
2022-03-08 20:11:49 -08:00
Ivan Nieto Vivanco 2410b1a146 Add a condition to show customfields as the user wants in localization settings 2022-03-08 18:25:15 -06:00
snipe ed39df349f Merge pull request #10799 from snipe/fixes/check_if_tables_exist_before_trying_to_create
Check if table exists before trying to create in migrations
2022-03-07 20:22:28 -08:00
snipe 86a2312a31 Check if table exists before trying to create
Signed-off-by: snipe <snipe@snipe.net>
2022-03-07 20:13:10 -08:00
snipe e30d814ece Merge pull request #10798 from snipe/features/add_qr_and_barcode_urls_to_asset_transformer
Added QR and alt barcode urls to asset transformer
2022-03-07 19:53:08 -08:00
snipe e9d297e97d Added cache comment
Signed-off-by: snipe <snipe@snipe.net>
2022-03-07 19:37:06 -08:00
snipe 9269d5945e Added QR and alt barcode urls to asset transformer
Signed-off-by: snipe <snipe@snipe.net>
2022-03-07 19:32:18 -08:00
snipe 33ee63f985 Merge pull request #10797 from snipe/features/use_max_results_in_pagination
Use the max_results env value in the paginator
2022-03-07 19:14:49 -08:00
snipe def570db4b Finer grain for > 200
Signed-off-by: snipe <snipe@snipe.net>
2022-03-07 18:51:49 -08:00
snipe fcb81b9505 Use the max_results env value in the paginator
Signed-off-by: snipe <snipe@snipe.net>
2022-03-07 18:39:39 -08:00
snipe 3e2fe10480 Fixed getAssetBySerial
Signed-off-by: snipe <snipe@snipe.net>
2022-03-05 09:03:29 -08:00
snipe f840652395 Suppress errors for missing signatures
Signed-off-by: snipe <snipe@snipe.net>
2022-03-04 03:18:28 -08:00
snipe afd83311aa Fixed version number (vV)
Signed-off-by: snipe <snipe@snipe.net>
2022-03-03 20:58:54 -08:00
snipe 29a2e80984 Merge pull request #10771 from uberbrady/retry_fix_bad_metadata_display
Retry fix bad metadata display
2022-03-03 20:49:30 -08:00
snipe fa576bc78f Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2022-03-03 20:45:34 -08:00
snipe 3e22dce117 Merge pull request #10774 from snipe/features/added_notes_to_accessories_etc
Fixed #6918 - added notes to accessories, components, consumables
2022-03-03 20:41:18 -08:00
snipe 9adcf58ae5 Added notes migration
Signed-off-by: snipe <snipe@snipe.net>
2022-03-03 20:30:58 -08:00
snipe 5266b2c71f Added notes field to view blades
Signed-off-by: snipe <snipe@snipe.net>
2022-03-03 20:30:27 -08:00
snipe 94dded3785 Added notes field to presenters for table view show/hide columns
Signed-off-by: snipe <snipe@snipe.net>
2022-03-03 20:30:07 -08:00
snipe ac8a7d0bc9 Made notes field fillable and searchable
Signed-off-by: snipe <snipe@snipe.net>
2022-03-03 20:29:48 -08:00
snipe 6fca8350f9 Added notes field to transformers
Signed-off-by: snipe <snipe@snipe.net>
2022-03-03 20:29:35 -08:00
snipe 9acb5413f6 Added notes field to controllers
Signed-off-by: snipe <snipe@snipe.net>
2022-03-03 20:29:25 -08:00
snipe 08a2fe4edb Merge pull request #10773 from snipe/features/adds_ldap_import_and_assets_count_to_user_api
Features/adds ldap import and assets count to user api
2022-03-03 19:15:14 -08:00
snipe 6abe8f296b We don’t need the users table here
Signed-off-by: snipe <snipe@snipe.net>
2022-03-03 19:12:03 -08:00
snipe a53a67be4a Added consumables, licenses, accessories count filters too
Signed-off-by: snipe <snipe@snipe.net>
2022-03-03 19:08:08 -08:00
snipe b72cac3511 Adds ldap_import and assets_count filter to user API endpoint
Signed-off-by: snipe <snipe@snipe.net>
2022-03-03 19:03:35 -08:00
snipe 698b7301b6 Merge pull request #10772 from snipe/fixes/use_correct_gate_for_maintainances
Use “update” instead of edit in gate
2022-03-03 18:50:33 -08:00
snipe c940d36fff Updated maintenance gate in API
Signed-off-by: snipe <snipe@snipe.net>
2022-03-03 18:49:54 -08:00
snipe cd12028845 Use “update” instead of edit in gate
Signed-off-by: snipe <snipe@snipe.net>
2022-03-03 18:47:20 -08:00
Brady Wetherington 3225605ef3 Handling the old weirdly-formatted data wasn't quite working. 2022-03-03 18:17:29 -08:00
Brady Wetherington 31dde20a2b Actually, re-introduce this code comment as it's still relevant and tricky 2022-03-03 15:48:04 -08:00
Brady Wetherington aa36ebc947 Merge branch 'fix_bad_metadata_display' into retry_fix_bad_metadata_display 2022-03-03 15:46:19 -08:00
Brady Wetherington 92434fa943 Revert "Revert "refactor and clean up attribute-changing logic for assets""
This reverts commit bdc737ce0c.
2022-03-03 15:45:54 -08:00
Brady Wetherington 0164354463 Fix for the weird error that blew up the demo when my PR got merged 2022-03-02 15:15:16 -08:00
snipe bdc737ce0c Revert "refactor and clean up attribute-changing logic for assets"
This reverts commit 290baf1c8d.

Signed-off-by: snipe <snipe@snipe.net>
2022-03-02 14:45:14 -08:00
snipe 733b3a7550 Merge pull request #10682 from uberbrady/fix_bad_metadata_display
Fixed weird JSON-handling on log_meta updates
2022-03-02 14:36:38 -08:00
snipe 3339a691e1 Merge pull request #10721 from snipe/features/adds_users_consumables_endpoint
Added consumables endpoint to user API
2022-03-02 14:33:45 -08:00
snipe 2eef43e8bf Applies develop fix to master for location drop downs 2022-03-01 12:43:35 -08:00
snipe 336d8e6574 Updated version 2022-02-24 18:17:15 -08:00
snipe dfbff27483 Updated sample CSVs
Signed-off-by: snipe <snipe@snipe.net>
2022-02-24 14:19:35 -08:00
snipe 24ce34c8d7 Updated assets
Signed-off-by: snipe <snipe@snipe.net>
2022-02-24 14:19:27 -08:00
snipe 7abb1f960c Merge branch 'master' of https://github.com/snipe/snipe-it 2022-02-24 14:16:00 -08:00
snipe ec7df11d73 Merge pull request #10736 from inietov/fixes/imported_assets_duplicate_model_notes_from_assets_master
Separate notes on assets and asset models on master branch [sc-18810]
2022-02-24 14:15:48 -08:00
Ivan Nieto Vivanco 64fa7e23fc Separate notes on assets and asset models 2022-02-24 16:05:03 -06:00
snipe 93ad59466b Fixed typo
Signed-off-by: snipe <snipe@snipe.net>
2022-02-24 13:52:33 -08:00
snipe 4b7f45a15e Merge pull request #10734 from snipe/fixes/api_throttling
Fixed API throttling
2022-02-24 13:43:49 -08:00
snipe 83f21d0ddf Added a comment about why we use the middleware there
Signed-off-by: snipe <snipe@snipe.net>
2022-02-24 13:41:16 -08:00
snipe 2906a89442 Make the 429 error less stupid
Signed-off-by: snipe <snipe@snipe.net>
2022-02-24 13:10:34 -08:00
snipe 50f55b4308 Fixes broken API throttling
Signed-off-by: snipe <snipe@snipe.net>
2022-02-24 13:10:10 -08:00
snipe a8028e7dd0 Merge pull request #10727 from uberbrady/master
Fix for negative CORS/SAML interaction
2022-02-23 11:17:17 -08:00
Brady Wetherington 15abc84ab0 Migrate to Fruitcake/laravel-cors which has path-exclusion built-in 2022-02-23 11:06:19 -08:00
snipe 8a09211310 Merge pull request #10722 from snipe/features/add_force_saml_to_master
Fixes Restricted Logins to SAML controlled via environment variable #10436 - applies #10449 to master
2022-02-22 21:45:19 -08:00
snipe 42fcd29200 Fixed #10436 on master, applies #10449
Signed-off-by: snipe <snipe@snipe.net>
2022-02-22 21:06:54 -08:00
snipe dc2e6c2b06 Adds consumables endpoint to user API
Signed-off-by: snipe <snipe@snipe.net>
2022-02-22 20:44:34 -08:00
snipe 0cfc0a4bee Merge pull request #10718 from uberbrady/fix_cors_option_1_master
Fix CORS requests on master (option *ONE*)
2022-02-22 19:24:18 -08:00
Brady Wetherington 64f83f9a5f Move HandleCors middleware to be universal 2022-02-22 17:43:40 -08:00
snipe dc2b58f865 Merge pull request #10691 from snipe/fixes/update_audit_date_when_settings_update
Fixed #10690 - Initial audit date fix
2022-02-20 11:16:54 -08:00
snipe 34ebc629c2 Remove unusued translation string
Signed-off-by: snipe <snipe@snipe.net>
2022-02-20 11:15:56 -08:00
snipe d1b45a83b8 Blergh, one more linebreak
Signed-off-by: snipe <snipe@snipe.net>
2022-02-17 14:51:06 -08:00
snipe 01a8701a8c Removed extra linebreaks
Signed-off-by: snipe <snipe@snipe.net>
2022-02-17 14:50:38 -08:00
snipe 67fe53e32a Removed debugging, added comments
Signed-off-by: snipe <snipe@snipe.net>
2022-02-17 14:50:07 -08:00
snipe 7f6b8cc43d Removed carbon, since we went with PHP's datetime instead
Signed-off-by: snipe <snipe@snipe.net>
2022-02-17 14:48:12 -08:00
snipe 5fe999eb02 Shored up the date math, updated the explanation
Signed-off-by: snipe <snipe@snipe.net>
2022-02-17 14:34:33 -08:00
snipe ea429d650e Initial audit date fix
Signed-off-by: snipe <snipe@snipe.net>
2022-02-16 20:19:38 -08:00
snipe 7fe7d56999 Merge pull request #10656 from snipe/snyk-upgrade-0005397ba83c98631126ff98d5471e6d
[Snyk] Upgrade jquery-ui from 1.13.0 to 1.13.1
2022-02-16 11:19:00 -07:00
snipe 4f89dfee49 Merge pull request #10679 from snipe/fixes/timing_attack_mitigation_for_forgot_password
Added usleep random to forgotten password method to mitigate timing attacks
2022-02-16 11:17:00 -07:00
snipe 017534bc07 Added deleted_at to license transformer
Signed-off-by: snipe <snipe@snipe.net>
2022-02-16 09:33:28 -08:00
snipe 5540069cce Be more specific with deleted license point
Require this value to be "true" speciically to get the deleted list

Signed-off-by: snipe <snipe@snipe.net>
2022-02-16 09:14:04 -08:00
snipe e9a4ff8e74 Merge pull request #10683 from snipe/features/add_deleted_only_endpoint_for_licenses
Adds delete endpoint for licenses
2022-02-16 10:10:22 -07:00
snipe 1ad56760ce Adds delete endpoint for licenses
Signed-off-by: snipe <snipe@snipe.net>
2022-02-16 09:08:50 -08:00
snipe 5582949008 Merge pull request #10681 from snipe/fixes/2fa_cookie_fix
Fixes 2FA cookie -> user issue
2022-02-15 19:34:13 -07:00
Brady Wetherington 290baf1c8d refactor and clean up attribute-changing logic for assets 2022-02-15 18:29:45 -08:00
snipe f878e0ad66 Fixes 2FA cookie -> user issue
Signed-off-by: snipe <snipe@snipe.net>
2022-02-15 18:29:23 -08:00
snipe 178e440951 Added usleep :(
Signed-off-by: snipe <snipe@snipe.net>
2022-02-15 18:09:58 -08:00
snipe 321be4733d Merge pull request #10672 from snipe/fixes/missing_gates_for_maintenances
Added Asset edit/delete gates to maintenances
2022-02-14 15:58:19 -08:00
snipe cab4fa1687 Fixes some conceptual gates
Signed-off-by: snipe <snipe@snipe.net>
2022-02-14 15:42:23 -08:00
snipe 4804e5b3ab Added Asset edit/delete gates to maintenances
Signed-off-by: snipe <snipe@snipe.net>
2022-02-14 15:34:06 -08:00
snipe 885ab64c2e Merge branch 'master' of https://github.com/snipe/snipe-it 2022-02-13 12:01:59 -07:00
snipe 8624531f78 Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2022-02-13 12:01:37 -07:00
snipe db0c0e7908 Merge pull request #10665 from snipe/fixes/adds_gate_to_supplier_view
Adds gate to supplier
2022-02-13 10:56:55 -08:00
snipe d77a47765e Adds gate to supplier
Signed-off-by: snipe <snipe@snipe.net>
2022-02-13 11:53:45 -07:00
snipe 05c0819776 Updated language string
Signed-off-by: snipe <snipe@snipe.net>
2022-02-11 15:55:42 -08:00
snipe 16f963fa3d Merge branch 'master' of https://github.com/snipe/snipe-it 2022-02-11 13:07:29 -08:00
snipe e032cf1fda Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2022-02-11 13:07:26 -08:00
snipe 10c26f38c4 Merge pull request #10662 from snipe/fixes/tighter_security_on_select_lists
Added additional gate for selectlists
2022-02-11 12:48:55 -08:00
snipe d6b8222371 Refactor to combine permissions
Signed-off-by: snipe <snipe@snipe.net>
2022-02-11 12:48:30 -08:00
snipe 2c5abaaea4 Fixed copypasta
Signed-off-by: snipe <snipe@snipe.net>
2022-02-11 12:32:09 -08:00
snipe c1a0653847 Restrict to update or create gate methods for select lists
Signed-off-by: snipe <snipe@snipe.net>
2022-02-11 12:31:11 -08:00
snipe 9226c8292d Fixed typos in comments
Signed-off-by: snipe <snipe@snipe.net>
2022-02-11 12:02:14 -08:00
snipe 5fafa81dc1 Forgot components
Signed-off-by: snipe <snipe@snipe.net>
2022-02-11 11:57:29 -08:00
snipe b30d1dce89 Removed selectlist
Signed-off-by: snipe <snipe@snipe.net>
2022-02-11 11:55:24 -08:00
snipe 2dad27eed6 Added additional gate for selectlists
Signed-off-by: snipe <snipe@snipe.net>
2022-02-11 11:46:14 -08:00
snipe f5ffda8053 Ahem.
Signed-off-by: snipe <snipe@snipe.net>
2022-02-10 22:43:51 -08:00
snipe 5703b95de3 Merge pull request #10657 from snipe/fixes/handle_deleted_auditor
Fixed - Check for valid user before trying to present the auditor name
2022-02-10 20:14:24 -08:00
snipe d406dc43c2 Check for valid user before trying to present the auditor name
Signed-off-by: snipe <snipe@snipe.net>
2022-02-10 20:13:02 -08:00
snipe 2ce44bd4e6 Line break for easier debugging
Signed-off-by: snipe <snipe@snipe.net>
2022-02-10 20:06:55 -08:00
snyk-bot 15b96f304b fix: upgrade jquery-ui from 1.13.0 to 1.13.1
Snyk has created this PR to upgrade jquery-ui from 1.13.0 to 1.13.1.

See this package in npm:
https://www.npmjs.com/package/jquery-ui

See this project in Snyk:
https://app.snyk.io/org/snipe/project/3d53e1dd-b8bf-46b5-ba61-18ce26933166?utm_source=github&utm_medium=referral&page=upgrade-pr
2022-02-11 01:11:13 +00:00
snipe ed931ef0cd Merge pull request #10654 from inietov/fixes/trying_to_get_property_checkin_email_of_non-object
Fixes  ErrorException: Trying to get property 'checkin_email' of non-object [sc-17568]
2022-02-10 12:23:50 -08:00
Ivan Nieto Vivanco bf4ee18123 Validates if model and model->category exist before return the checkin_email property 2022-02-10 11:58:55 -06:00
snipe 70af10ae6c Merge pull request #10640 from JonathonReinhart/10552-add-checkin-api-date
Fix #10552: Add checkin_at parameter to /hardware/:id/checkin API
2022-02-10 09:54:20 -08:00
snipe 9892e5bf60 Merge pull request #10646 from snipe/fixes/check_field_exist_before_detaching
Check that the field exists before trying to detach it from the fieldset
2022-02-09 16:33:02 -08:00
snipe b9a8d45c07 Better messaging
Signed-off-by: snipe <snipe@snipe.net>
2022-02-09 16:30:42 -08:00
snipe 7794c2f44b Check that the fieldset exists before trying to detach it from the fieldset
Signed-off-by: snipe <snipe@snipe.net>
2022-02-09 16:16:16 -08:00
snipe eedc14401a Switch to searching on semicolon instead of &
Signed-off-by: snipe <snipe@snipe.net>
2022-02-09 15:55:22 -08:00
snipe 4e14d70427 Added jobtitle to unescaper
Signed-off-by: snipe <snipe@snipe.net>
2022-02-09 15:50:44 -08:00
snipe 2a71690aaf Added license_name to unescaper
Signed-off-by: snipe <snipe@snipe.net>
2022-02-09 15:17:57 -08:00
snipe e4da00ca82 Catch potential validation errors on unescape tool
Signed-off-by: snipe <snipe@snipe.net>
2022-02-09 15:09:49 -08:00
snipe 4fd14e5859 Added slightly more output because wtf?
Signed-off-by: snipe <snipe@snipe.net>
2022-02-09 15:05:28 -08:00
snipe 441f1fbb64 Remove html_entities_decode restriction
Signed-off-by: snipe <snipe@snipe.net>
2022-02-09 14:56:36 -08:00
snipe bf194d7794 Regenerate JS assets
Signed-off-by: snipe <snipe@snipe.net>
2022-02-09 14:43:30 -08:00
snipe d06e3dd892 Merge branch 'master' of https://github.com/snipe/snipe-it 2022-02-09 14:40:33 -08:00
snipe 6b25b53462 Merge pull request #10628 from inietov/fixes/default_values_dont_allow_checkbox_radio
Fixes #10299 Default Values do not allow Checkbox/Radio Buttons
2022-02-09 14:39:46 -08:00
Ivan Nieto Vivanco 6d79c9f3e2 Save the default values for custom fields with same format than Assets do for actual values 2022-02-09 13:41:33 -06:00
Ivan Nieto Vivanco a36957dd77 Finish the implementation of custom fields default values for checkboxes 2022-02-09 13:12:42 -06:00
Ivan Nieto Vivanco 2f3499e4b9 Show checkboxes a little less assy, actually save the data checked by them 2022-02-09 10:49:10 -06:00
Jonathon Reinhart 3536d08477 Add checkin_at parameter to /hardware/:id/checkin API
Fixes #10552
2022-02-08 20:23:09 -05:00
snipe ee3166cdc2 Add @savornicesei as a contributor 2022-02-08 15:38:20 -08:00
snipe 7a117a22c8 Merge pull request #10637 from uberbrady/report_invalid_json
Alert when invalid JSON is submitted to something that wants it
2022-02-08 12:17:20 -08:00
Brady Wetherington 9a66f6a254 Remove extraneous backslash 2022-02-08 12:09:40 -08:00
Brady Wetherington 5e94726ec1 Properly alert when invalid JSON is submitted to something that wants JSON 2022-02-08 12:05:05 -08:00
snipe 66c3559e1c Merge pull request #10636 from inietov/fixes/inconsistencies_between_checkout_checkin_dates_master
Fixes #10627 Inconsistencies between checkout/checkin dates on asset history and activity log for master branch
2022-02-08 10:19:16 -08:00
Ivan Nieto Vivanco 413e44be2f Add custom date to checkin actionlogs and show it in the history of the asset tab 2022-02-08 11:58:23 -06:00
snipe ebc35c4519 Merge pull request #10630 from JonathonReinhart/10629-checkin-API-error-status
Fix /hardware/{id}/checkin API response on error
2022-02-08 08:54:17 -08:00
Jonathon Reinhart cd963179fd Fix /hardware/{id}/checkin API response on error
Fixes #10629
2022-02-08 01:08:42 -05:00
Ivan Nieto Vivanco 796a0ebdaa Add initial support for default values in checkboxes customfields 2022-02-07 22:17:40 -06:00
snipe 474f24e40e Merge branch 'master' of https://github.com/snipe/snipe-it 2022-02-07 18:27:59 -08:00
snipe b3a0f86431 Temp fix for weird JSON format in history
Signed-off-by: snipe <snipe@snipe.net>
2022-02-07 18:27:55 -08:00
snipe 1a31231569 Merge pull request #10623 from uberbrady/fix_secure_hosts_in_subdirectory
Fixes #10577 - Fix "secure hostnames" feature for subdirectory-based Snipe-IT installs
2022-02-07 11:33:33 -08:00
Brady Wetherington f1d4087317 Fix "secure hostnames" feature for subdirectory-based Snipe-IT installs 2022-02-07 11:26:54 -08:00
snipe f4069e00cd Merge pull request #10611 from uberbrady/master
D'oh! Migration fails on empty settings table :(
2022-02-03 20:07:01 -08:00
Brady Wetherington 8650faf0d8 D'oh! Migration fails on empty settings table :( 2022-02-03 20:04:33 -08:00
snipe 796ef741e8 Merge pull request #10610 from uberbrady/fixes/ldap_active_status
Fixes #10563 - Rework the LDAP sync command to better handle the active flag
2022-02-03 19:45:41 -08:00
Brady Wetherington 36ae6f9430 Yanked debugging code, tightened up comments. 2022-02-03 19:41:16 -08:00
Brady Wetherington 1945b97b72 Just trying to really tighten up on the LDAP Active Flag and how we parse it. 2022-02-03 19:04:56 -08:00
Brady Wetherington 392e61688d Rework the LDAP sync command to better handle the active flag 2022-02-03 15:01:45 -08:00
snipe db82e06665 Fixed migration with invalid LDAP prepopulation value
Signed-off-by: snipe <snipe@snipe.net>
2022-02-02 18:22:51 -08:00
snipe ac5c6123bc Fixes #10563 - LDAP active flag - hopefully?
Signed-off-by: snipe <snipe@snipe.net>
2022-02-02 18:07:34 -08:00
snipe 8add47739e Merge pull request #10604 from inietov/fixes/column_activated_cannot_be_null
Fixes: Column activated cannot be null [sc-18528]
2022-02-02 12:21:31 -08:00
Ivan Nieto Vivanco eac8e0bdba Add a casting to a truthy/falsy that needs to be integer 2022-02-02 13:54:57 -06:00
snipe 2815e0d36e Fixed audit email template (applies #10592 to master)
Signed-off-by: snipe <snipe@snipe.net>
2022-02-01 17:27:32 -08:00
snipe 2e998b110f Add @TenOfTens as a contributor 2022-02-01 13:40:31 -08:00
snipe f45c963428 Merge pull request #10586 from inietov/fixes/bulkedit_does_not_show_in_history
Fixes Bulk edit doesn't show in Asset's history nor Activity report [sc-16550]
2022-01-31 23:07:02 -08:00
Ivan Nieto Vivanco 2fec40d7df Adds actionlog for bulk edits 2022-02-01 00:00:12 -06:00
snipe 215beb9d8a Merge pull request #10580 from misilot/fix-10176-webui-master
Replace .my.cnf with column-statistics.cnf at the system level for mysqldump (master)
2022-01-29 07:16:24 -08:00
Tom Misilo b0c61ee044 Replace .my.cnf with column-statistics.cnf at the system level for mysqldump
Fixes #10176

The `column-statistics.cnf` file is copied to `/etc/mysql/conf.d/column-statistics.cnf` for each Dockerfile that exists.

This puts it as a system level mysql client change, so the web ui interface also works.
2022-01-29 07:28:12 -06:00
snipe 16fb2213b5 Updated language strings
Signed-off-by: snipe <snipe@snipe.net>
2022-01-28 12:40:03 -08:00
snipe a0d0645453 Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2022-01-28 12:38:42 -08:00
snipe 1ef336a08b Merge pull request #10576 from snipe/features/add_custom_fields_search
Added #9576 - Lookup Asset by Custom Field via API [sc-18632]
2022-01-28 09:51:28 -08:00
snipe aa3aa78204 Adds Lookup Asset by Custom Field via API [sc-18632]
Signed-off-by: snipe <snipe@snipe.net>
2022-01-28 09:08:48 -08:00
snipe db0a078c0b Merge pull request #10573 from uberbrady/fix_force_root_url
Add some guardrails around very-badly formatted APP_URL settings
2022-01-27 11:29:29 -08:00
Brady Wetherington 1cf1278b3b Fix whitespace issues 2022-01-27 11:28:51 -08:00
Brady Wetherington 70648dedd3 Add some guardrails around very-badly formatted APP_URL settings 2022-01-27 11:21:46 -08:00
snipe 9634dde0dd Merge pull request #10567 from inietov/fixes/importing_and_checking_out_licenses_master
Fixes Importing licenses without product key duplicates the license
2022-01-27 10:58:06 -08:00
snipe 077caa29f8 Merge pull request #10570 from inietov/fixes/donked_layout_required_field_error_depreciation
Fixes donked layout required field error depreciation [sc-17111]
2022-01-26 21:23:51 -08:00
Ivan Nieto Vivanco a87478d3ac Set the actual field we are evaluating as required (months) 2022-01-26 23:02:27 -06:00
Ivan Nieto Vivanco 44349db597 Fixes the appearance of some error messages 2022-01-26 22:58:02 -06:00
snipe c70ae19c28 Merge pull request #10529 from uberbrady/fix_insecure_host_headers
Force UrlGenerator's Root URL to be the base of APP_URL unless overriden (v5)
2022-01-26 16:59:55 -08:00
Ivan Nieto Vivanco 55fdc86e02 Tweak query in the License Importer to not require a Product Key 2022-01-26 17:51:04 -06:00
snipe 0721ab8bbf Regenerated production assets
Signed-off-by: snipe <snipe@snipe.net>
2022-01-20 11:01:04 -08:00
snipe 00c8a1ee21 Merge pull request #10533 from inietov/feature/add_remaining_address_field_to_user_import
Add Zip field in the User Importer [sc-18556]
2022-01-19 12:07:18 -08:00
Ivan Nieto Vivanco 1fc71a4111 Add Zip field in the User Importer 2022-01-19 13:35:54 -06:00
Brady Wetherington 0c4768fd2a Force UrlGenerator's Root URL to be the base of APP_URL unless overriden
(For v5)
2022-01-18 15:52:59 -08:00
snipe f9647614ab Merge pull request #10527 from inietov/fixes/pdo_exception_syntax_error_when_sendexpirationalers_is_called
Fixes PDO exeception syntax error when Expiring Alerts Threshold is not set
2022-01-18 12:43:08 -08:00
Ivan Nieto Vivanco a05795420a Respect the default value of 60 days in expiring licenses 2022-01-18 14:34:14 -06:00
Ivan Nieto Vivanco 42d86bf57b Adds default values if the expiring alerts threshold is null 2022-01-18 14:21:49 -06:00
snipe 201b52baf8 Merge pull request #10523 from inietov/fixes/depreciation_report_shows_assets_that_not_deprecate_master
Fixes bug where the depreciation report shows assets that not deprecate for master
2022-01-18 10:37:21 -08:00
Ivan Nieto Vivanco f510b9c2a9 Add query to filter non-deprecable assets when the Depreciation Report is called 2022-01-15 14:21:31 -06:00
snipe 75bd365ca1 Merge pull request #10521 from inietov/fixes/sc-14356/importer_creating_duplicate_asset_models_master
Fixes an issue where importer is creating duplicate asset models for Master Branch
2022-01-15 07:46:39 -08:00
Ivan Nieto Vivanco 153c30eda8 Add to Importer the capacity to search Models only with Model Name since Model Number is not required 2022-01-15 04:32:47 -06:00
snipe be7e6ed847 Merge pull request #10502 from uberbrady/ldap_useraccountcontrol_dont_req_preauth
Add new UserAccountControl to permitted UAC's for AD.
2022-01-13 17:01:47 -08:00
snipe 115109f612 Merge pull request #10510 from misilot/fix-10176-master
Looks great, thanks!
2022-01-13 13:22:22 -08:00
Thomas Misilo 037a912e21 Adding .my.cnf to disable column-statistics backup
Fixes #10176

The ```.my.cnf``` file is copied to ```/root/.my.cnf``` for each
Dockerfile that exists
2022-01-13 15:16:59 -06:00
snipe 984db1ef44 Apply personal API token fix to master
Signed-off-by: snipe <snipe@snipe.net>
2022-01-13 01:39:56 -08:00
Brady Wetherington c8fe929e09 Add new UserAccountControl to permitted UAC's for AD. 2022-01-12 12:07:51 -08:00
snipe 181dc5127f Add @UniversalSuperBox as a contributor 2022-01-11 15:03:08 -08:00
snipe 303fc39966 Regenerated assets to pikc up #10089 changes
Signed-off-by: snipe <snipe@snipe.net>
2022-01-11 14:38:17 -08:00
snipe 730c2a6821 Merge pull request #10496 from UniversalSuperBox/fix/improve-asset-card-view
Fixed #10089 (partially): Back to master: Added some BS tables style overrides for mobile
2022-01-11 14:10:18 -08:00
snipe bc10761b49 Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2022-01-11 12:44:16 -08:00
snipe cf14a0222c Merge pull request #10498 from Haxatron/master
Fix access control
2022-01-10 19:24:31 -08:00
snipe b18b3812df Back to master: Added some BS tables style overrides for mobile
This repeats 06e8e826, which alone improves the mobile view immensely,
on master.
2022-01-10 15:23:43 -06:00
Haxatron bb095641c2 Update BulkAssetModelsController.php
https://huntr.dev/bounties/efdf2ead-f9d1-4767-9f02-d11f762d15e7
2022-01-06 09:50:11 +08:00
snipe b78e610ce3 Merge pull request #10480 from snipe/fixes/check_for_valid_custom_field
Fixed format property on invalid custom field object when trying to edit a field that doesn't exist
2022-01-03 19:28:25 -08:00
snipe 884b6b0270 Fixes format property on invalid custom field object
Signed-off-by: snipe <snipe@snipe.net>
2022-01-03 19:14:50 -08:00
snipe 7a1ab1292c Merge pull request #10479 from adagioajanes/fixes/auto_asset_tag_phrasing
Fixed auto asset tag phrasing
2021-12-31 15:17:59 -08:00
Alex Janes 87bb741013 Merge branch 'snipe:master' into fixes/auto_asset_tag_phrasing 2021-12-31 16:34:57 -05:00
Alex Janes 5fe2083688 Adjusted the phrasing around auto-incrementing asset tags. 2021-12-31 16:33:30 -05:00
snipe 2ee84c2675 Added a few more comments
Signed-off-by: snipe <snipe@snipe.net>
2021-12-30 18:33:28 -08:00
snipe 39a5b6b426 Merge pull request #10478 from snipe/fixes/whitelist_modal_views
Added allow list to modal view options
2021-12-30 18:29:30 -08:00
snipe c6ce928567 Added allow list to modal view options
Signed-off-by: snipe <snipe@snipe.net>
2021-12-30 18:16:49 -08:00
snipe 950a23b0f4 Merge pull request #10476 from snipe/fixes/custom_fieldsets_index
Fixed missing index for fieldsets
2021-12-30 13:18:13 -08:00
snipe b4fac3e4ae Fixed missing index for fieldsets
Signed-off-by: snipe <snipe@snipe.net>
2021-12-30 13:16:44 -08:00
snipe 548e483ef8 Merge pull request #10475 from snipe/fixes/wrong_default_sort_on_kits
Fixed assets_count doesnt exist as a column on kits
2021-12-30 13:02:12 -08:00
snipe bad6b862ca assets_count doesnt exist as a column
Signed-off-by: snipe <snipe@snipe.net>
2021-12-30 12:59:16 -08:00
snipe 4e336e11ee Merge pull request #10470 from snipe/increase_address_length_for_supplier
Fixed #10469 - increased size of supplier address field
2021-12-27 12:29:13 -08:00
snipe 8588e9ebf1 Fixed #10469 - increased size of supplier address field
Signed-off-by: snipe <snipe@snipe.net>
2021-12-27 12:28:02 -08:00
snipe 11524d0f7d Merge pull request #10463 from adagioajanes/fixes/pass_total_to_GroupsTransformer
Fixed #10461: Groups management page did not paginate correctly
2021-12-24 10:39:22 -08:00
Alex Janes d0bfd8dfd2 Fixed the collection of the groups total to GroupsTransformer.php. Groups page should now paginate correctly. 2021-12-23 20:54:34 -05:00
snipe 312200bf44 Removed duplicate "department" entry in importer, pulls #10460 to master
Signed-off-by: snipe <snipe@snipe.net>
2021-12-21 13:37:20 -08:00
snipe 04f4bb83e9 Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2021-12-16 20:37:22 -08:00
snipe 9b2dd6522f Switch GET to POST for asset request
Signed-off-by: snipe <snipe@snipe.net>
2021-12-16 20:36:08 -08:00
snipe a05fe9c1f7 Add @exula as a contributor 2021-12-15 09:30:36 -08:00
snipe 395401e9db Merge pull request #10439 from exula/exula-fix-slack-settings
Update SettingsController.php to save Slack Settings
2021-12-15 08:36:18 -08:00
Bradley Coudriet dbdc1c7f3f Update SettingsController.php to save Slack Settings
This goes with #10438 that I just submitted about Slack Settings not saving.

This adds the necessary code to actually save the Slack Settings,
As they are already validated by the SlackSettingsRequest, this seems like an easy and low-impact fix.
2021-12-15 10:38:51 -05:00
snipe ace4a00e29 Merge pull request #10433 from inietov/features/adding_title_to_custom_report_master
Add title column to custom reports on master branch
2021-12-14 10:28:18 -08:00
Ivan Nieto Vivanco c80aa2a289 Add title column to custom reports 2021-12-14 12:05:33 -06:00
snipe 25e2e7ecc6 Merge pull request #10418 from inietov/fixes/bulk_edit_count_more_users_than_selected
Fixes bulk edit message counts more users than the actual selected users number
2021-12-13 14:13:14 -08:00
snipe 02be4773de Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2021-12-13 12:07:34 -08:00
snipe c988d84271 Merge pull request #10426 from snipe/fixes/added_escape_to_asset_api_assigned_to
Added escape to assigned_to API response
2021-12-13 12:06:08 -08:00
snipe 9d5d1a9f9a Added escape to assigned_to API response
Signed-off-by: snipe <snipe@snipe.net>
2021-12-13 12:03:03 -08:00
snipe 3a7cef15bd Merge pull request #10423 from misilot/automated-image-build-github-actions
Automatic Building of Docker Images and Pushing to DockerHub
2021-12-13 11:32:57 -08:00
snipe 44d3a425cb Merge pull request #10422 from misilot/docker-alpine-build-automatic
Adds an automatic build for Alpine Linux based Image
2021-12-13 11:32:42 -08:00
snipe 1854d7d668 Updated language strings
Signed-off-by: snipe <snipe@snipe.net>
2021-12-13 11:28:01 -08:00
snipe e5f4048e9e Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2021-12-13 11:01:02 -08:00
Thomas Misilo 5e58f60845 Adds an automatic build for Alpine Linux based Image
This Fixes #10339, and allows for automatic building of the Alpine Linux
image, and push to docker-hub.

This will push a "latest-alpine" based on the master branch, a
"develop-alpine" based on the develop branch, and a v##.##.##-alpine
image based on any released version.

`DOCKER_USERNAME` and `DOCKER_ACCESS_TOKEN` do both need
to be added to the repository as secrets.
2021-12-13 10:39:55 -06:00
Thomas Misilo a7760b331b Automatic Building of Docker Images and Pushing to DockerHub
This allows for building and pushing of the Snipe-IT docker images
directly from GitHub to DockerHub.

This will push a "latest" based on the master branch, a
"develop" based on the develop branch, and a v##.##.##
image based on any released version.

`DOCKER_USERNAME` and `DOCKER_ACCESS_TOKEN` do both need
to be added to the repository as secrets.
2021-12-13 10:39:04 -06:00
Ivan Nieto Vivanco a419a690d4 Add a variable to better control the selected user's ids 2021-12-11 18:01:38 -06:00
snipe 39b0dc136c Added LDAP strings back
Signed-off-by: snipe <snipe@snipe.net>
2021-12-11 10:14:35 -08:00
snipe d0e7879c89 Merge pull request #10415 from uberbrady/fix_actionlog_memory_exhaustion
Remove 'actionlog' from the ::with() clause in the asset query API
2021-12-10 19:10:40 -08:00
Brady Wetherington acfb41f129 Remove 'actionlog' from the ::with() clause in the asset query API 2021-12-10 18:42:56 -08:00
snipe 5381aa3fbd Merge branch 'master' of https://github.com/snipe/snipe-it 2021-12-10 15:17:45 -08:00
snipe e20a10a6a1 Add @Haxatron as a contributor 2021-12-10 15:17:26 -08:00
snipe 949141a8e7 Merge pull request #10414 from snipe/added_model_to_accessory_report
Added model number to accessory report
2021-12-10 15:10:02 -08:00
snipe e1bf3b50f4 Added model number to accessory report
Signed-off-by: snipe <snipe@snipe.net>
2021-12-10 15:09:29 -08:00
snipe cf5e3da3a5 Merge pull request #10406 from Haxatron/fix-access-control
security fix
2021-12-09 11:23:35 -08:00
Haxatron 1699c09758 Update AssetModelsController.php 2021-12-09 21:42:18 +08:00
Haxatron 918e7c8dae Fix access control - https://huntr.dev/bounties/19453ef1-4d77-4cff-b7e8-1bc8f3af0862/ 2021-12-09 12:57:04 +08:00
snipe 86afe6c4b1 Cleanup slack validation
Signed-off-by: snipe <snipe@snipe.net>
2021-12-08 18:03:56 -08:00
snipe ff97b359ad Removed form request on ajax, cleaned up some other things
Signed-off-by: snipe <snipe@snipe.net>
2021-12-08 17:58:46 -08:00
snipe 81b66d0039 Change validation failure to 422 to make it consistent with Laravel's default
Signed-off-by: snipe <snipe@snipe.net>
2021-12-08 17:54:35 -08:00
snipe 8fa690b635 Reverting form request because it doesn't seem to work (????!!)
Signed-off-by: snipe <snipe@snipe.net>
2021-12-08 17:54:15 -08:00
snipe 8c1cd87831 Added slacksettingsrequest as use statement
Signed-off-by: snipe <snipe@snipe.net>
2021-12-08 15:56:22 -08:00
snipe cde2bad297 Small mods to slack jquery
Signed-off-by: snipe <snipe@snipe.net>
2021-12-08 15:56:05 -08:00
snipe 80d36cd72b Added slack settings request
Signed-off-by: snipe <snipe@snipe.net>
2021-12-08 15:53:05 -08:00
snipe a579353198 Add @bestlong as a contributor 2021-11-24 20:04:26 -08:00
snipe 7360e15d4e Add @sneak-it as a contributor 2021-11-24 20:04:05 -08:00
snipe 9dc2fa61b8 Add @adamboutcher as a contributor 2021-11-24 20:03:52 -08:00
snipe 80fd49a59e Add @leitwerk-ag as a contributor 2021-11-24 20:03:40 -08:00
snipe d30fa9199c Merge branch 'master' of https://github.com/snipe/snipe-it 2021-11-24 19:58:52 -08:00
snipe 8028b39b43 Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2021-11-24 19:58:43 -08:00
snipe ff81e6d536 Merge pull request #10361 from snipe/fixes/xss_in_accessories_checkout_notes
Escape notes in transformCheckedOutAccessory
2021-11-24 19:56:36 -08:00
snipe 00fad35c2a Escape notes in transformCheckedOutAccessory
Signed-off-by: snipe <snipe@snipe.net>
2021-11-24 19:54:45 -08:00
snipe 3b68a6f1be Merge pull request #10345 from leitwerk-ag/master
Fixed #10344 and #9135: don't prepand fields with a whitespace in text based export formats
2021-11-24 19:43:21 -08:00
snipe bc91aef47d Merge pull request #10352 from adamboutcher/install_rocky
Improved Installer: Added Rocky Linux Support
2021-11-24 19:42:37 -08:00
snipe 3debe78574 Merge pull request #10350 from inietov/fixes/trim_custom_fields_names
Apply trim() function when storing Custom Fields names
2021-11-24 19:42:04 -08:00
snipe fc1b3b31b5 Merge pull request #10358 from sneak-it/bullseye
Improved Installer: Add Debian 11 (Bullseye) install script support
2021-11-24 19:41:37 -08:00
snipe 4afd598df7 Merge pull request #10356 from bestlong/fix_modal_dialog_html_typo
fix modal-title html tag unpaired.
2021-11-24 19:39:58 -08:00
snipe d1d3f893ac Merge pull request #10360 from snipe/fixes/escaped_characters_on_asset_create_checkout
Removed escaping on input save for asset checkout on creation
2021-11-24 19:20:54 -08:00
snipe 830d07f84f Removed escaping on input save for asset checkout on creation
Signed-off-by: snipe <snipe@snipe.net>
2021-11-24 19:19:32 -08:00
snipe 0e30b9aef7 Merge pull request #10355 from inietov/fixes/customfields_with_date_format_doesnt_display_default_value_master
Fixes Default Values - Date not applying for master branch
2021-11-24 18:22:02 -08:00
sneaK b937aedc30 Add Debian 11 (Bullseye) install script support 2021-11-24 10:24:05 -05:00
Shao Yu-Lung 55d05eeae3 fix modal-title html tag unpaired. 2021-11-24 10:28:10 +08:00
Ivan Nieto Vivanco d95d3dc282 Add the call to defaultValue() function in custom fields with date format 2021-11-23 17:21:46 -06:00
Adam ab06c26527 Rocky Linux Support
Addition to enable Rocky Linux installation.
2021-11-23 16:13:38 +00:00
Ivan Nieto Vivanco 1ca770895a Apply trim() function when storing Custom Fields names 2021-11-22 18:43:21 -06:00
Klaus J. Mueller a85fa14f9c fix #10344 and #9135 2021-11-22 17:58:26 +01:00
snipe b058d84f2c Merge pull request #10322 from snipe/uberbrady-patch-2
Change the `[END]` directive in `.htaccess` to `[L]`
2021-11-17 18:01:52 -08:00
Brady Wetherington 5fb05d8b1c Change the [END] directive in .htaccess to [L]
This allows backwards-compatibility with older Apache versions (which we _used_ to have), and should do the exact same thing.
2021-11-17 15:29:51 -08:00
1899 changed files with 35558 additions and 12229 deletions
+90
View File
@@ -2468,6 +2468,96 @@
"contributions": [
"code"
]
},
{
"login": "leitwerk-ag",
"name": "LEITWERK AG",
"avatar_url": "https://avatars.githubusercontent.com/u/24418301?v=4",
"profile": "https://www.leitwerk.de/",
"contributions": [
"code"
]
},
{
"login": "adamboutcher",
"name": "Adam",
"avatar_url": "https://avatars.githubusercontent.com/u/1911435?v=4",
"profile": "http://www.aboutcher.co.uk",
"contributions": [
"code"
]
},
{
"login": "sneak-it",
"name": "Ian",
"avatar_url": "https://avatars.githubusercontent.com/u/16104273?v=4",
"profile": "https://snksrv.com",
"contributions": [
"code"
]
},
{
"login": "bestlong",
"name": "Shao Yu-Lung (Allen)",
"avatar_url": "https://avatars.githubusercontent.com/u/4023909?v=4",
"profile": "http://blog.bestlong.idv.tw/",
"contributions": [
"code"
]
},
{
"login": "Haxatron",
"name": "Haxatron",
"avatar_url": "https://avatars.githubusercontent.com/u/76475453?v=4",
"profile": "https://github.com/Haxatron",
"contributions": [
"code"
]
},
{
"login": "exula",
"name": "Bradley Coudriet",
"avatar_url": "https://avatars.githubusercontent.com/u/3842948?v=4",
"profile": "http://bjcpgd.cias.rit.edu",
"contributions": [
"code"
]
},
{
"login": "UniversalSuperBox",
"name": "Dalton Durst",
"avatar_url": "https://avatars.githubusercontent.com/u/21966173?v=4",
"profile": "https://daltondur.st",
"contributions": [
"code"
]
},
{
"login": "TenOfTens",
"name": "TenOfTens",
"avatar_url": "https://avatars.githubusercontent.com/u/48162670?v=4",
"profile": "https://github.com/TenOfTens",
"contributions": [
"code"
]
},
{
"login": "savornicesei",
"name": "Simona Avornicesei",
"avatar_url": "https://avatars.githubusercontent.com/u/917232?v=4",
"profile": "http://www.avornicesei.com",
"contributions": [
"test"
]
},
{
"login": "QveenSi",
"name": "Yevhenii Huzii",
"avatar_url": "https://avatars.githubusercontent.com/u/19945501?v=4",
"profile": "https://github.com/QveenSi",
"contributions": [
"code"
]
}
]
}
+3 -1
View File
@@ -145,10 +145,12 @@ APP_LOG_MAX_FILES=10
APP_LOCKED=false
APP_CIPHER=AES-256-CBC
APP_FORCE_TLS=false
APP_ALLOW_INSECURE_HOSTS=false
GOOGLE_MAPS_API=
LDAP_MEM_LIM=500M
LDAP_TIME_LIM=600
IMPORT_TIME_LIMIT=600
IMPORT_MEMORY_LIMIT=500M
REPORT_TIME_LIMIT=12000
REQUIRE_SAML=false
API_THROTTLE_PER_MINUTE=120
+82
View File
@@ -0,0 +1,82 @@
# Snipe-IT (Alpine) Docker image build for hub.docker.com
name: Docker images (Alpine)
# Run this Build for all pushes to 'master' or develop branch, or tagged releases.
# Also run for PRs to ensure PR doesn't break Docker build process
on:
push:
branches:
- master
- develop
tags:
- 'v**'
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
pull_request:
jobs:
docker:
# Ensure this job never runs on forked repos. It's only executed for 'snipe/snipe-it'
if: github.repository == 'snipe/snipe-it'
runs-on: ubuntu-latest
env:
# Define tags to use for Docker images based on Git tags/branches (for docker/metadata-action)
# For a new commit on default branch (master), use the literal tag 'latest' on Docker image.
# For a new commit on other branches, use the branch name as the tag for Docker image.
# For a new tag, copy that tag name as the tag for Docker image.
IMAGE_TAGS: |
type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }},suffix=-alpine
type=ref,event=branch,enable=${{ !endsWith(github.ref, github.event.repository.default_branch) }},suffix=-alpine
type=ref,event=tag,suffix=-alpine
# Define default tag "flavor" for docker/metadata-action per
# https://github.com/docker/metadata-action#flavor-input
# We turn off 'latest' tag by default.
TAGS_FLAVOR: |
latest=false
steps:
# https://github.com/actions/checkout
- name: Checkout codebase
uses: actions/checkout@v2
# https://github.com/docker/setup-buildx-action
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v1
# https://github.com/docker/login-action
- name: Login to DockerHub
# Only login if not a PR, as PRs only trigger a Docker build and not a push
if: github.event_name != 'pull_request'
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
###############################################
# Build/Push the 'snipe/snipe-it' image
###############################################
# https://github.com/docker/metadata-action
# Get Metadata for docker_build step below
- name: Sync metadata (tags, labels) from GitHub to Docker for 'snipe-it' image
id: meta_build
uses: docker/metadata-action@v3
with:
images: snipe/snipe-it
tags: ${{ env.IMAGE_TAGS }}
flavor: ${{ env.TAGS_FLAVOR }}
# https://github.com/docker/build-push-action
- name: Build and push 'snipe-it' image
id: docker_build
uses: docker/build-push-action@v2
with:
context: .
file: ./Dockerfile.alpine
platforms: linux/amd64
# For pull requests, we run the Docker build (to ensure no PR changes break the build),
# but we ONLY do an image push to DockerHub if it's NOT a PR
push: ${{ github.event_name != 'pull_request' }}
# Use tags / labels provided by 'docker/metadata-action' above
tags: ${{ steps.meta_build.outputs.tags }}
labels: ${{ steps.meta_build.outputs.labels }}
+82
View File
@@ -0,0 +1,82 @@
# Snipe-IT Docker image build for hub.docker.com
name: Docker images
# Run this Build for all pushes to 'master' or develop branch, or tagged releases.
# Also run for PRs to ensure PR doesn't break Docker build process
on:
push:
branches:
- master
- develop
tags:
- 'v**'
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
pull_request:
jobs:
docker:
# Ensure this job never runs on forked repos. It's only executed for 'snipe/snipe-it'
if: github.repository == 'snipe/snipe-it'
runs-on: ubuntu-latest
env:
# Define tags to use for Docker images based on Git tags/branches (for docker/metadata-action)
# For a new commit on default branch (master), use the literal tag 'latest' on Docker image.
# For a new commit on other branches, use the branch name as the tag for Docker image.
# For a new tag, copy that tag name as the tag for Docker image.
IMAGE_TAGS: |
type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }}
type=ref,event=branch,enable=${{ !endsWith(github.ref, github.event.repository.default_branch) }}
type=ref,event=tag
# Define default tag "flavor" for docker/metadata-action per
# https://github.com/docker/metadata-action#flavor-input
# We turn off 'latest' tag by default.
TAGS_FLAVOR: |
latest=false
steps:
# https://github.com/actions/checkout
- name: Checkout codebase
uses: actions/checkout@v2
# https://github.com/docker/setup-buildx-action
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v1
# https://github.com/docker/login-action
- name: Login to DockerHub
# Only login if not a PR, as PRs only trigger a Docker build and not a push
if: github.event_name != 'pull_request'
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
###############################################
# Build/Push the 'snipe/snipe-it' image
###############################################
# https://github.com/docker/metadata-action
# Get Metadata for docker_build step below
- name: Sync metadata (tags, labels) from GitHub to Docker for 'snipe-it' image
id: meta_build
uses: docker/metadata-action@v3
with:
images: snipe/snipe-it
tags: ${{ env.IMAGE_TAGS }}
flavor: ${{ env.TAGS_FLAVOR }}
# https://github.com/docker/build-push-action
- name: Build and push 'snipe-it' image
id: docker_build
uses: docker/build-push-action@v2
with:
context: .
file: ./Dockerfile
platforms: linux/amd64
# For pull requests, we run the Docker build (to ensure no PR changes break the build),
# but we ONLY do an image push to DockerHub if it's NOT a PR
push: ${{ github.event_name != 'pull_request' }}
# Use tags / labels provided by 'docker/metadata-action' above
tags: ${{ steps.meta_build.outputs.tags }}
labels: ${{ steps.meta_build.outputs.labels }}
+2
View File
@@ -77,6 +77,8 @@ COPY . /var/www/html
RUN a2enmod rewrite
COPY docker/column-statistics.cnf /etc/mysql/conf.d/column-statistics.cnf
############ INITIAL APPLICATION SETUP #####################
WORKDIR /var/www/html
+2
View File
@@ -32,6 +32,8 @@ RUN apk add --no-cache \
mysql-client \
tini
COPY docker/column-statistics.cnf /etc/mysql/conf.d/column-statistics.cnf
# Where apache's PID lives
RUN mkdir -p /run/apache2 && chown apache:apache /run/apache2
+1
View File
@@ -98,5 +98,6 @@ VOLUME [ "/var/lib/snipeit" ]
COPY --chown=www-data:www-data docker/docker-secrets.env /var/www/html/.env
COPY --chmod=655 docker/docker-entrypoint.sh /usr/local/bin/docker-snipeit-entrypoint
COPY docker/column-statistics.cnf /etc/mysql/conf.d/column-statistics.cnf
ENTRYPOINT [ "/usr/local/bin/docker-snipeit-entrypoint" ]
CMD [ "/usr/local/bin/docker-php-entrypoint", "php-fpm" ]
+4 -2
View File
@@ -1,5 +1,5 @@
![Build Status](https://app.chipperci.com/projects/0e5f8979-31eb-4ee6-9abf-050b76ab0383/status/master) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/snipe-it/localized.svg)](https://crowdin.com/project/snipe-it) [![Docker Pulls](https://img.shields.io/docker/pulls/snipe/snipe-it.svg)](https://hub.docker.com/r/snipe/snipe-it/) [![Twitter Follow](https://img.shields.io/twitter/follow/snipeitapp.svg?style=social)](https://twitter.com/snipeitapp) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/553ce52037fc43ea99149785afcfe641)](https://www.codacy.com/app/snipe/snipe-it?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=snipe/snipe-it&amp;utm_campaign=Badge_Grade)
[![All Contributors](https://img.shields.io/badge/all_contributors-271-orange.svg?style=flat-square)](#contributors) [![Discord](https://badgen.net/badge/icon/discord?icon=discord&label)](https://discord.gg/yZFtShAcKk) [![huntr](https://cdn.huntr.dev/huntr_security_badge_mono.svg)](https://huntr.dev)
[![All Contributors](https://img.shields.io/badge/all_contributors-281-orange.svg?style=flat-square)](#contributors) [![Discord](https://badgen.net/badge/icon/discord?icon=discord&label)](https://discord.gg/yZFtShAcKk) [![huntr](https://cdn.huntr.dev/huntr_security_badge_mono.svg)](https://huntr.dev)
## Snipe-IT - Open Source Asset Management System
@@ -129,7 +129,9 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
| [<img src="https://avatars.githubusercontent.com/u/36065681?v=4" width="110px;"/><br /><sub>David Valin Alonso</sub>](https://github.com/deivishome)<br />[💻](https://github.com/snipe/snipe-it/commits?author=deivishome "Code") | [<img src="https://avatars.githubusercontent.com/u/8290389?v=4" width="110px;"/><br /><sub>andreaci</sub>](https://github.com/andreaci)<br />[💻](https://github.com/snipe/snipe-it/commits?author=andreaci "Code") | [<img src="https://avatars.githubusercontent.com/u/1828542?v=4" width="110px;"/><br /><sub>Jelle Sebreghts</sub>](http://www.jellesebreghts.be)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Jelle-S "Code") | [<img src="https://avatars.githubusercontent.com/u/11180862?v=4" width="110px;"/><br /><sub>Michael Pietsch</sub>](https://github.com/Skywalker-11)<br /> | [<img src="https://avatars.githubusercontent.com/u/22068886?v=4" width="110px;"/><br /><sub>Masudul Haque Shihab</sub>](https://github.com/sh1hab)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sh1hab "Code") | [<img src="https://avatars.githubusercontent.com/u/16099942?v=4" width="110px;"/><br /><sub>Supapong Areeprasertkul</sub>](http://www.freedomdive.com/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=zybersup "Code") | [<img src="https://avatars.githubusercontent.com/u/207358?v=4" width="110px;"/><br /><sub>Peter Sarossy</sub>](https://github.com/psarossy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=psarossy "Code") |
| [<img src="https://avatars.githubusercontent.com/u/11823649?v=4" width="110px;"/><br /><sub>Renee Margaret McConahy</sub>](https://github.com/nepella)<br />[💻](https://github.com/snipe/snipe-it/commits?author=nepella "Code") | [<img src="https://avatars.githubusercontent.com/u/5553884?v=4" width="110px;"/><br /><sub>JohnnyPicnic</sub>](https://github.com/JohnnyPicnic)<br />[💻](https://github.com/snipe/snipe-it/commits?author=JohnnyPicnic "Code") | [<img src="https://avatars.githubusercontent.com/u/8799594?v=4" width="110px;"/><br /><sub>markbrule</sub>](https://github.com/markbrule)<br />[💻](https://github.com/snipe/snipe-it/commits?author=markbrule "Code") | [<img src="https://avatars.githubusercontent.com/u/1962801?v=4" width="110px;"/><br /><sub>Mike Campbell</sub>](https://github.com/mikecmpbll)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mikecmpbll "Code") | [<img src="https://avatars.githubusercontent.com/u/11973217?v=4" width="110px;"/><br /><sub>tbrconnect</sub>](https://github.com/tbrconnect)<br />[💻](https://github.com/snipe/snipe-it/commits?author=tbrconnect "Code") | [<img src="https://avatars.githubusercontent.com/u/12447225?v=4" width="110px;"/><br /><sub>kcoyo</sub>](https://github.com/kcoyo)<br />[💻](https://github.com/snipe/snipe-it/commits?author=kcoyo "Code") | [<img src="https://avatars.githubusercontent.com/u/494017?v=4" width="110px;"/><br /><sub>Travis Miller</sub>](https://travismiller.com/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=travismiller "Code") |
| [<img src="https://avatars.githubusercontent.com/u/8735148?v=4" width="110px;"/><br /><sub>Petri Asikainen</sub>](https://github.com/PetriAsi)<br />[💻](https://github.com/snipe/snipe-it/commits?author=PetriAsi "Code") | [<img src="https://avatars.githubusercontent.com/u/11424540?v=4" width="110px;"/><br /><sub>derdeagle</sub>](https://github.com/derdeagle)<br />[💻](https://github.com/snipe/snipe-it/commits?author=derdeagle "Code") | [<img src="https://avatars.githubusercontent.com/u/176950?v=4" width="110px;"/><br /><sub>Mike Frysinger</sub>](https://wh0rd.org/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=vapier "Code") | [<img src="https://avatars.githubusercontent.com/u/22044358?v=4" width="110px;"/><br /><sub>ALPHA</sub>](https://github.com/AL4AL)<br />[💻](https://github.com/snipe/snipe-it/commits?author=AL4AL "Code") | [<img src="https://avatars.githubusercontent.com/u/1042587?v=4" width="110px;"/><br /><sub>FliegenKLATSCH</sub>](https://www.ifern.de)<br />[💻](https://github.com/snipe/snipe-it/commits?author=FliegenKLATSCH "Code") | [<img src="https://avatars.githubusercontent.com/u/442138?v=4" width="110px;"/><br /><sub>Jeremy Price</sub>](https://github.com/jerm)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jerm "Code") | [<img src="https://avatars.githubusercontent.com/u/84392209?v=4" width="110px;"/><br /><sub>Toreg87</sub>](https://github.com/Toreg87)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Toreg87 "Code") |
| [<img src="https://avatars.githubusercontent.com/u/67638596?v=4" width="110px;"/><br /><sub>Matthew Nickson</sub>](https://github.com/Computroniks)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Computroniks "Code") | [<img src="https://avatars.githubusercontent.com/u/1646397?v=4" width="110px;"/><br /><sub>Jethro Nederhof</sub>](https://jethron.id.au)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jethron "Code") | [<img src="https://avatars.githubusercontent.com/u/23289826?v=4" width="110px;"/><br /><sub>Oskar Stenberg</sub>](https://github.com/01ste02)<br />[💻](https://github.com/snipe/snipe-it/commits?author=01ste02 "Code") | [<img src="https://avatars.githubusercontent.com/u/82208283?v=4" width="110px;"/><br /><sub>Robert-Azelis</sub>](https://github.com/Robert-Azelis)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Robert-Azelis "Code") | [<img src="https://avatars.githubusercontent.com/u/60648387?v=4" width="110px;"/><br /><sub>Alexander William Smith</sub>](https://github.com/alwism)<br />[💻](https://github.com/snipe/snipe-it/commits?author=alwism "Code") |
| [<img src="https://avatars.githubusercontent.com/u/67638596?v=4" width="110px;"/><br /><sub>Matthew Nickson</sub>](https://github.com/Computroniks)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Computroniks "Code") | [<img src="https://avatars.githubusercontent.com/u/1646397?v=4" width="110px;"/><br /><sub>Jethro Nederhof</sub>](https://jethron.id.au)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jethron "Code") | [<img src="https://avatars.githubusercontent.com/u/23289826?v=4" width="110px;"/><br /><sub>Oskar Stenberg</sub>](https://github.com/01ste02)<br />[💻](https://github.com/snipe/snipe-it/commits?author=01ste02 "Code") | [<img src="https://avatars.githubusercontent.com/u/82208283?v=4" width="110px;"/><br /><sub>Robert-Azelis</sub>](https://github.com/Robert-Azelis)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Robert-Azelis "Code") | [<img src="https://avatars.githubusercontent.com/u/60648387?v=4" width="110px;"/><br /><sub>Alexander William Smith</sub>](https://github.com/alwism)<br />[💻](https://github.com/snipe/snipe-it/commits?author=alwism "Code") | [<img src="https://avatars.githubusercontent.com/u/24418301?v=4" width="110px;"/><br /><sub>LEITWERK AG</sub>](https://www.leitwerk.de/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=leitwerk-ag "Code") | [<img src="https://avatars.githubusercontent.com/u/1911435?v=4" width="110px;"/><br /><sub>Adam</sub>](http://www.aboutcher.co.uk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=adamboutcher "Code") |
| [<img src="https://avatars.githubusercontent.com/u/16104273?v=4" width="110px;"/><br /><sub>Ian</sub>](https://snksrv.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sneak-it "Code") | [<img src="https://avatars.githubusercontent.com/u/4023909?v=4" width="110px;"/><br /><sub>Shao Yu-Lung (Allen)</sub>](http://blog.bestlong.idv.tw/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=bestlong "Code") | [<img src="https://avatars.githubusercontent.com/u/76475453?v=4" width="110px;"/><br /><sub>Haxatron</sub>](https://github.com/Haxatron)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Haxatron "Code") | [<img src="https://avatars.githubusercontent.com/u/3842948?v=4" width="110px;"/><br /><sub>Bradley Coudriet</sub>](http://bjcpgd.cias.rit.edu)<br />[💻](https://github.com/snipe/snipe-it/commits?author=exula "Code") | [<img src="https://avatars.githubusercontent.com/u/21966173?v=4" width="110px;"/><br /><sub>Dalton Durst</sub>](https://daltondur.st)<br />[💻](https://github.com/snipe/snipe-it/commits?author=UniversalSuperBox "Code") | [<img src="https://avatars.githubusercontent.com/u/48162670?v=4" width="110px;"/><br /><sub>TenOfTens</sub>](https://github.com/TenOfTens)<br />[💻](https://github.com/snipe/snipe-it/commits?author=TenOfTens "Code") | [<img src="https://avatars.githubusercontent.com/u/917232?v=4" width="110px;"/><br /><sub>Simona Avornicesei</sub>](http://www.avornicesei.com)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=savornicesei "Tests") |
| [<img src="https://avatars.githubusercontent.com/u/19945501?v=4" width="110px;"/><br /><sub>Yevhenii Huzii</sub>](https://github.com/QveenSi)<br />[💻](https://github.com/snipe/snipe-it/commits?author=QveenSi "Code") |
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
+10 -6
View File
@@ -40,7 +40,7 @@ class FixDoubleEscape extends Command
$tables = [
'\App\Models\Asset' => ['name'],
'\App\Models\License' => ['name'],
'\App\Models\License' => ['name', 'license_name'],
'\App\Models\Consumable' => ['name'],
'\App\Models\Accessory' => ['name'],
'\App\Models\Component' => ['name'],
@@ -53,7 +53,7 @@ class FixDoubleEscape extends Command
'\App\Models\Group' => ['name'],
'\App\Models\Department' => ['name'],
'\App\Models\Location' => ['name'],
'\App\Models\User' => ['first_name', 'last_name'],
'\App\Models\User' => ['first_name', 'last_name', 'jobtitle'],
];
$count = array();
@@ -69,10 +69,14 @@ class FixDoubleEscape extends Command
$count[$classname]['classname']++;
$count[$classname][$field] = 0;
foreach($classname::where("$field",'LIKE','%&%')->get() as $row) {
$this->info('Updating '.$field.' for '.$classname);
$row->{$field} = html_entity_decode($row->{$field},ENT_QUOTES);
$row->save();
foreach($classname::where("$field",'LIKE','%;%')->get() as $row) {
$fixed = html_entity_decode($row->{$field});
if ($row->save()) {
$this->info('Updating '.$field.' for '.$classname.' to '.$row->{$field}.' to '.$fixed);
} else {
$this->error('Could NOT update '.$field.' for '.$classname.' to '.$row->{$field}.' to '.$fixed.': '.$row->getErrors());
}
$count[$classname][$field]++;
}
+59
View File
@@ -0,0 +1,59 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class KillAllSessions extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'snipeit:global-logout {--force : Skip the danger prompt; assuming you enter "y"} ';
/**
* The console command description.
*
* @var string
*/
protected $description = 'This command will destroy all web sessions on disk and will force a re-login for all users.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
if (!$this->option('force') && !$this->confirm("****************************************************\nTHIS WILL FORCE A LOGIN FOR ALL LOGGED IN USERS.\n\nAre you SURE you wish to continue? ")) {
return $this->error("Session loss not confirmed");
}
$session_files = glob(storage_path("framework/sessions/*"));
$count = 0;
foreach ($session_files as $file) {
if (is_file($file))
unlink($file);
$count++;
}
\DB::table('users')->update(['remember_token' => null]);
$this->info($count. ' sessions cleared!');
}
}
+19 -11
View File
@@ -49,7 +49,7 @@ class LdapSync extends Command
$ldap_result_last_name = Setting::getSettings()->ldap_lname_field;
$ldap_result_first_name = Setting::getSettings()->ldap_fname_field;
$ldap_result_active_flag = Setting::getSettings()->ldap_active_flag_field;
$ldap_result_active_flag = Setting::getSettings()->ldap_active_flag;
$ldap_result_emp_num = Setting::getSettings()->ldap_emp_num;
$ldap_result_email = Setting::getSettings()->ldap_email;
$ldap_result_phone = Setting::getSettings()->ldap_phone_field;
@@ -170,7 +170,6 @@ class LdapSync extends Command
$pass = bcrypt($tmp_pass);
for ($i = 0; $i < $results["count"]; $i++) {
if (empty($ldap_result_active_flag) || $results[$i][$ldap_result_active_flag][0] == "TRUE") {
$item = array();
$item["username"] = isset($results[$i][$ldap_result_username][0]) ? $results[$i][$ldap_result_username][0] : "";
@@ -192,6 +191,7 @@ class LdapSync extends Command
$user = User::where('username', $item["username"])->first();
if ($user) {
// Updating an existing user.
$item["createorupdate"] = 'updated';
@@ -199,7 +199,7 @@ class LdapSync extends Command
// Creating a new user.
$user = new User;
$user->password = $pass;
$user->activated = 0;
$user->activated = 1; // newly created users can log in by default, unless AD's UAC is in use, or an active flag is set (below)
$item["createorupdate"] = 'created';
}
@@ -213,8 +213,19 @@ class LdapSync extends Command
$user->country = $item["country"];
$user->department_id = $department->id;
// Sync activated state for Active Directory.
if ( array_key_exists('useraccountcontrol', $results[$i]) ) {
if ( !empty($ldap_result_active_flag)) { // IF we have an 'active' flag set....
// ....then *most* things that are truthy will activate the user. Anything falsey will deactivate them.
// (Specifically, we don't handle a value of '0.0' correctly)
$raw_value = @$results[$i][$ldap_result_active_flag][0];
$filter_var = filter_var($raw_value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
$boolean_cast = (bool)$raw_value;
$user->activated = $filter_var ?? $boolean_cast; // if filter_var() was true or false, use that. If it's null, use the $boolean_cast
} elseif ( array_key_exists('useraccountcontrol', $results[$i]) ) {
// ....otherwise, (ie if no 'active' LDAP flag is defined), IF the UAC setting exists,
// ....then use the UAC setting on the account to determine can-log-in vs. cannot-log-in
/* The following is _probably_ the correct logic, but we can't use it because
some users may have been dependent upon the previous behavior, and this
could cause additional access to be available to users they don't want
@@ -240,16 +251,14 @@ class LdapSync extends Command
'262688', // 0x40220 NORMAL_ACCOUNT, PASSWD_NOTREQD, SMARTCARD_REQUIRED
'328192', // 0x50200 NORMAL_ACCOUNT, SMARTCARD_REQUIRED, DONT_EXPIRE_PASSWORD
'328224', // 0x50220 NORMAL_ACCOUNT, PASSWD_NOT_REQD, SMARTCARD_REQUIRED, DONT_EXPIRE_PASSWORD
'4194816',// 0x400200 NORMAL_ACCOUNT, DONT_REQ_PREAUTH
'4260352',// 0x410200 NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD, DONT_REQ_PREAUTH
'1049088',// 0x100200 NORMAL_ACCOUNT, NOT_DELEGATED
];
$user->activated = ( in_array($results[$i]['useraccountcontrol'][0], $enabled_accounts) ) ? 1 : 0;
}
// If we're not using AD, and there isn't an activated flag set, activate all users
elseif (empty($ldap_result_active_flag)) {
$user->activated = 1;
}
} /* implied 'else' here - leave the $user->activated flag alone. Newly-created accounts will be active.
already-existing accounts will be however the administrator has set them */
if ($item['ldap_location_override'] == true) {
$user->location_id = $item['location_id'];
@@ -279,7 +288,6 @@ class LdapSync extends Command
}
array_push($summary, $item);
}
}
+14 -14
View File
@@ -47,18 +47,18 @@ class MoveUploadsToNewDisk extends Command
}
$delete_local = $this->argument('delete_local');
$public_uploads['accessories'] = glob('public/accessories'."/*.*");
$public_uploads['assets'] = glob('public/assets'."/*.*");
$public_uploads['avatars'] = glob('public/avatars'."/*.*");
$public_uploads['categories'] = glob('public/categories'."/*.*");
$public_uploads['companies'] = glob('public/companies'."/*.*");
$public_uploads['components'] = glob('public/components'."/*.*");
$public_uploads['consumables'] = glob('public/consumables'."/*.*");
$public_uploads['departments'] = glob('public/departments'."/*.*");
$public_uploads['locations'] = glob('public/locations'."/*.*");
$public_uploads['manufacturers'] = glob('public/manufacturers'."/*.*");
$public_uploads['suppliers'] = glob('public/suppliers'."/*.*");
$public_uploads['assetmodels'] = glob('public/models'."/*.*");
$public_uploads['accessories'] = glob('public/uploads/accessories'."/*.*");
$public_uploads['assets'] = glob('public/uploads/assets'."/*.*");
$public_uploads['avatars'] = glob('public/uploads/avatars'."/*.*");
$public_uploads['categories'] = glob('public/uploads/categories'."/*.*");
$public_uploads['companies'] = glob('public/uploads/companies'."/*.*");
$public_uploads['components'] = glob('public/uploads/components'."/*.*");
$public_uploads['consumables'] = glob('public/uploads/consumables'."/*.*");
$public_uploads['departments'] = glob('public/uploads/departments'."/*.*");
$public_uploads['locations'] = glob('public/uploads/locations'."/*.*");
$public_uploads['manufacturers'] = glob('public/uploads/manufacturers'."/*.*");
$public_uploads['suppliers'] = glob('public/uploads/suppliers'."/*.*");
$public_uploads['assetmodels'] = glob('public/uploads/models'."/*.*");
// iterate files
@@ -72,7 +72,7 @@ class MoveUploadsToNewDisk extends Command
$filename = basename($public_upload[$i]);
try {
Storage::disk('public')->put('uploads/'.public_type.'/'.$filename, file_get_contents($public_upload[$i]));
Storage::disk('public')->put('uploads/'.$public_type.'/'.$filename, file_get_contents($public_upload[$i]));
$new_url = Storage::disk('public')->url('uploads/'.$public_type.'/'.$filename, $filename);
$this->info($type_count.'. PUBLIC: '.$filename.' was copied to '.$new_url);
} catch (\Exception $e) {
@@ -103,7 +103,7 @@ class MoveUploadsToNewDisk extends Command
$private_uploads['imports'] = glob('storage/private_uploads/imports'."/*.*");
$private_uploads['licenses'] = glob('storage/private_uploads/licenses'."/*.*");
$private_uploads['users'] = glob('storage/private_uploads/users'."/*.*");
$private_uploads['backups'] = glob('storage/private_uploads/users'."/*.*");
$private_uploads['backups'] = glob('storage/private_uploads/backups'."/*.*");
foreach($private_uploads as $private_type => $private_upload)
+1 -1
View File
@@ -14,7 +14,7 @@ class RestoreFromBackup extends Command
* @var string
*/
protected $signature = 'snipeit:restore
{--force : Skip the danger prompt; assuming you hit "y"}
{--force : Skip the danger prompt; assuming you enter "y"}
{filename : The zip file to be migrated}
{--no-progress : Don\'t show a progress bar}';
+13 -3
View File
@@ -8,6 +8,7 @@ use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use App\Helpers\Helper;
use Illuminate\Validation\ValidationException;
use Log;
use JsonException;
class Handler extends ExceptionHandler
@@ -26,6 +27,7 @@ class Handler extends ExceptionHandler
\Illuminate\Validation\ValidationException::class,
\Intervention\Image\Exception\NotSupportedException::class,
\League\OAuth2\Server\Exception\OAuthServerException::class,
JsonException::class
];
/**
@@ -60,6 +62,12 @@ class Handler extends ExceptionHandler
return redirect()->back()->with('error', trans('general.token_expired'));
}
// Invalid JSON exception
// TODO: don't understand why we have to do this when we have the invalidJson() method, below, but, well, whatever
if ($e instanceof JsonException) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'invalid JSON'), 422);
}
// Handle Ajax requests that fail because the model doesn't exist
if ($request->ajax() || $request->wantsJson()) {
@@ -76,10 +84,12 @@ class Handler extends ExceptionHandler
switch ($e->getStatusCode()) {
case '404':
return response()->json(Helper::formatStandardApiResponse('error', null, $statusCode . ' endpoint not found'), 404);
case '405':
case '429':
return response()->json(Helper::formatStandardApiResponse('error', null, 'Too many requests'), 429);
case '405':
return response()->json(Helper::formatStandardApiResponse('error', null, 'Method not allowed'), 405);
default:
return response()->json(Helper::formatStandardApiResponse('error', null, $statusCode), 405);
return response()->json(Helper::formatStandardApiResponse('error', null, $statusCode), $statusCode);
}
}
@@ -121,6 +131,6 @@ class Handler extends ExceptionHandler
*/
protected function invalidJson($request, ValidationException $exception)
{
return response()->json(Helper::formatStandardApiResponse('error', null, $exception->errors(), 400));
return response()->json(Helper::formatStandardApiResponse('error', null, $exception->errors(), 422));
}
}
@@ -78,6 +78,8 @@ class AccessoriesController extends Controller
$accessory->qty = request('qty');
$accessory->user_id = Auth::user()->id;
$accessory->supplier_id = request('supplier_id');
$accessory->notes = request('notes');
$accessory = $request->handleImages($accessory);
@@ -140,6 +142,7 @@ class AccessoriesController extends Controller
$accessory->purchase_cost = Helper::ParseCurrency(request('purchase_cost'));
$accessory->qty = request('qty');
$accessory->supplier_id = request('supplier_id');
$accessory->notes = request('notes');
$accessory = $request->handleImages($accessory);
+14 -3
View File
@@ -9,10 +9,21 @@ class ActionlogController extends Controller
{
public function displaySig($filename)
{
// PHP doesn't let you handle file not found errors well with
// file_get_contents, so we set the error reporting for just this class
error_reporting(0);
$this->authorize('view', \App\Models\Asset::class);
$file = config('app.private_uploads') . '/signatures/' . $filename;
$file = config('app.private_uploads').'/signatures/'.$filename;
$filetype = Helper::checkUploadIsImage($file);
$contents = file_get_contents($file);
return Response::make($contents)->header('Content-Type', $filetype);
$contents = file_get_contents($file, false, stream_context_create(['http' => ['ignore_errors' => true]]));
if ($contents === false) {
\Log::warn('File '.$file.' not found');
return false;
} else {
return Response::make($contents)->header('Content-Type', $filetype);
}
}
}
@@ -39,7 +39,8 @@ class AccessoriesController extends Controller
'notes',
'created_at',
'min_amt',
'company_id'
'company_id',
'notes',
];
@@ -69,6 +70,10 @@ class AccessoriesController extends Controller
$accessories->where('location_id','=',$request->input('location_id'));
}
if ($request->filled('notes')) {
$accessories->where('notes','=',$request->input('notes'));
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($accessories) && ($request->get('offset') > $accessories->count())) ? $accessories->count() : $request->get('offset', 0);
@@ -33,6 +33,7 @@ class AssetMaintenancesController extends Controller
*/
public function index(Request $request)
{
$this->authorize('view', Asset::class);
$maintenances = AssetMaintenance::with('asset', 'asset.model','asset.location', 'supplier', 'asset.company', 'admin');
if ($request->filled('search')) {
@@ -101,6 +102,7 @@ class AssetMaintenancesController extends Controller
*/
public function store(Request $request)
{
$this->authorize('update', Asset::class);
// create a new model instance
$assetMaintenance = new AssetMaintenance();
$assetMaintenance->supplier_id = $request->input('supplier_id');
@@ -153,6 +155,7 @@ class AssetMaintenancesController extends Controller
*/
public function update(Request $request, $assetMaintenanceId = null)
{
$this->authorize('update', Asset::class);
// Check if the asset maintenance exists
$assetMaintenance = AssetMaintenance::findOrFail($assetMaintenanceId);
@@ -216,6 +219,7 @@ class AssetMaintenancesController extends Controller
*/
public function destroy($assetMaintenanceId)
{
$this->authorize('update', Asset::class);
// Check if the asset maintenance exists
$assetMaintenance = AssetMaintenance::findOrFail($assetMaintenanceId);
@@ -241,6 +245,7 @@ class AssetMaintenancesController extends Controller
*/
public function show($assetMaintenanceId)
{
$this->authorize('view', Asset::class);
$assetMaintenance = AssetMaintenance::findOrFail($assetMaintenanceId);
if (!Company::isCurrentUserHasAccess($assetMaintenance->asset)) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot view a maintenance for that asset'));
@@ -234,6 +234,7 @@ class AssetModelsController extends Controller
public function selectlist(Request $request)
{
$this->authorize('view.selectlists');
$assetmodels = AssetModel::select([
'models.id',
'models.name',
+26 -5
View File
@@ -55,7 +55,7 @@ class AssetsController extends Controller
{
\Log::debug(Route::currentRouteName());
$filter_non_deprecable_assets = false;
/**
* This looks MAD janky (and it is), but the AssetsController@index does a LOT of heavy lifting throughout the
@@ -69,6 +69,7 @@ class AssetsController extends Controller
* which would have been far worse of a mess. *sad face* - snipe (Sept 1, 2021)
*/
if (Route::currentRouteName()=='api.depreciation-report.index') {
$filter_non_deprecable_assets = true;
$transformer = 'App\Http\Transformers\DepreciationReportTransformer';
$this->authorize('reports.view');
} else {
@@ -115,13 +116,28 @@ class AssetsController extends Controller
}
$assets = Company::scopeCompanyables(Asset::select('assets.*'),"company_id","assets")
->with('location', 'assetstatus', 'assetlog', 'company', 'defaultLoc','assignedTo',
'model.category', 'model.manufacturer', 'model.fieldset','supplier');
->with('location', 'assetstatus', 'company', 'defaultLoc','assignedTo',
'model.category', 'model.manufacturer', 'model.fieldset','supplier'); //it might be tempting to add 'assetlog' here, but don't. It blows up update-heavy users.
if ($filter_non_deprecable_assets) {
$non_deprecable_models = AssetModel::select('id')->whereNotNull('depreciation_id')->get();
$assets->InModelList($non_deprecable_models->toArray());
}
// These are used by the API to query against specific ID numbers.
// They are also used by the individual searches on detail pages like
// locations, etc.
// Search custom fields by column name
foreach ($all_custom_fields as $field) {
if ($request->filled($field->db_column_name())) {
$assets->where($field->db_column_name(), '=', $request->input($field->db_column_name()));
}
}
if ($request->filled('status_id')) {
$assets->where('assets.status_id', '=', $request->input('status_id'));
}
@@ -844,13 +860,18 @@ class AssetsController extends Controller
$asset->status_id = $request->input('status_id');
}
$checkin_at = null;
if ($request->filled('checkin_at')) {
$checkin_at = $request->input('checkin_at');
}
if ($asset->save()) {
event(new CheckoutableCheckedIn($asset, $target, Auth::user(), $request->input('note')));
event(new CheckoutableCheckedIn($asset, $target, Auth::user(), $request->input('note'), $checkin_at));
return response()->json(Helper::formatStandardApiResponse('success', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkin.success')));
}
return response()->json(Helper::formatStandardApiResponse('success', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkin.error')));
return response()->json(Helper::formatStandardApiResponse('error', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkin.error')));
}
@@ -148,7 +148,7 @@ class CategoriesController extends Controller
*/
public function selectlist(Request $request, $category_type = 'asset')
{
$this->authorize('view.selectlists');
$categories = Category::select([
'id',
'name',
@@ -159,7 +159,7 @@ class CompaniesController extends Controller
*/
public function selectlist(Request $request)
{
$this->authorize('view.selectlists');
$companies = Company::select([
'companies.id',
'companies.name',
@@ -40,6 +40,7 @@ class ComponentsController extends Controller
'purchase_cost',
'qty',
'image',
'notes',
];
@@ -62,6 +63,10 @@ class ComponentsController extends Controller
$components->where('location_id','=',$request->input('location_id'));
}
if ($request->filled('notes')) {
$components->where('notes','=',$request->input('notes'));
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($components) && ($request->get('offset') > $components->count())) ? $components->count() : $request->get('offset', 0);
@@ -42,6 +42,7 @@ class ConsumablesController extends Controller
'item_no',
'qty',
'image',
'notes',
];
@@ -74,6 +75,10 @@ class ConsumablesController extends Controller
$consumables->where('location_id','=',$request->input('location_id'));
}
if ($request->filled('notes')) {
$consumables->where('notes','=',$request->input('notes'));
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
@@ -168,6 +168,7 @@ class DepartmentsController extends Controller
public function selectlist(Request $request)
{
$this->authorize('view.selectlists');
$departments = Department::select([
'id',
'name',
@@ -82,6 +82,10 @@ class LicensesController extends Controller
$licenses = $licenses->TextSearch($request->input('search'));
}
if ($request->input('deleted')=='true') {
$licenses->onlyTrashed();
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
@@ -223,6 +223,8 @@ class LocationsController extends Controller
public function selectlist(Request $request)
{
$this->authorize('view.selectlists');
$locations = Location::select([
'locations.id',
'locations.name',
@@ -155,6 +155,7 @@ class ManufacturersController extends Controller
public function selectlist(Request $request)
{
$this->authorize('view.selectlists');
$manufacturers = Manufacturer::select([
'id',
'name',
@@ -31,8 +31,8 @@ class PredefinedKitsController extends Controller
$offset = $request->input('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'assets_count';
$order = $request->input('order') === 'desc' ? 'desc' : 'asc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'name';
$kits->orderBy($sort, $order);
$total = $kits->count();
+31 -20
View File
@@ -17,6 +17,7 @@ use GuzzleHttp\Client;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use App\Models\Ldap; // forward-port of v4 LDAP model for Sync
use App\Http\Requests\SlackSettingsRequest;
class SettingsController extends Controller
@@ -165,31 +166,41 @@ class SettingsController extends Controller
public function slacktest(Request $request)
{
$slack = new Client([
'base_url' => e($request->input('slack_endpoint')),
'defaults' => [
'exceptions' => false
]
$validator = Validator::make($request->all(), [
'slack_endpoint' => 'url|required_with:slack_channel|starts_with:https://hooks.slack.com/|nullable',
'slack_channel' => 'required_with:slack_endpoint|starts_with:#|nullable',
]);
$payload = json_encode(
[
'channel' => e($request->input('slack_channel')),
'text' => trans('general.slack_test_msg'),
'username' => e($request->input('slack_botname')),
'icon_emoji' => ':heart:'
]);
try {
$slack->post($request->input('slack_endpoint'),['body' => $payload]);
return response()->json(['message' => 'Success'], 200);
} catch (\Exception $e) {
return response()->json(['message' => 'Oops! Please check the channel name and webhook endpoint URL. Slack responded with: '.$e->getMessage()], 400);
if ($validator->fails()) {
return response()->json(['message' => 'Validation failed', 'errors' => $validator->errors()], 422);
}
return response()->json(['message' => 'Something went wrong :( '], 400);
// If validation passes, continue to the curl request
$slack = new Client([
'base_url' => e($request->input('slack_endpoint')),
'defaults' => [
'exceptions' => false,
],
]);
$payload = json_encode(
[
'channel' => e($request->input('slack_channel')),
'text' => trans('general.slack_test_msg'),
'username' => e($request->input('slack_botname')),
'icon_emoji' => ':heart:',
]);
try {
$slack->post($request->input('slack_endpoint'), ['body' => $payload]);
return response()->json(['message' => 'Success'], 200);
} catch (\Exception $e) {
return response()->json(['message' => 'Please check the channel name and webhook endpoint URL ('.$request->input('slack_endpoint').'). Slack responded with: '.$e->getMessage()], 400);
}
//}
return response()->json(['message' => 'Something went wrong :( '], 400);
}
@@ -30,6 +30,19 @@ class StatuslabelsController extends Controller
$statuslabels = $statuslabels->TextSearch($request->input('search'));
}
// if a status_type is passed, filter by that
if ($request->filled('status_type')) {
if (strtolower($request->input('status_type')) == 'pending') {
$statuslabels = $statuslabels->Pending();
} elseif (strtolower($request->input('status_type')) == 'archived') {
$statuslabels = $statuslabels->Archived();
} elseif (strtolower($request->input('status_type')) == 'deployable') {
$statuslabels = $statuslabels->Deployable();
} elseif (strtolower($request->input('status_type')) == 'undeployable') {
$statuslabels = $statuslabels->Undeployable();
}
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($statuslabels) && ($request->get('offset') > $statuslabels->count())) ? $statuslabels->count() : $request->get('offset', 0);
@@ -155,6 +155,8 @@ class SuppliersController extends Controller
public function selectlist(Request $request)
{
$this->authorize('view.selectlists');
$suppliers = Supplier::select([
'id',
'name',
@@ -7,6 +7,7 @@ use App\Http\Controllers\Controller;
use App\Http\Requests\SaveUserRequest;
use App\Http\Transformers\AccessoriesTransformer;
use App\Http\Transformers\AssetsTransformer;
use App\Http\Transformers\ConsumablesTransformer;
use App\Http\Transformers\LicensesTransformer;
use App\Http\Transformers\SelectlistTransformer;
use App\Http\Transformers\UsersTransformer;
@@ -131,6 +132,26 @@ class UsersController extends Controller
$users = $users->where('users.manager_id','=',$request->input('manager_id'));
}
if ($request->filled('ldap_import')) {
$users = $users->where('ldap_import', '=', $request->input('ldap_import'));
}
if ($request->filled('assets_count')) {
$users->has('assets', '=', $request->input('assets_count'));
}
if ($request->filled('consumables_count')) {
$users->has('consumables', '=', $request->input('consumables_count'));
}
if ($request->filled('licenses_count')) {
$users->has('licenses', '=', $request->input('licenses_count'));
}
if ($request->filled('accessories_count')) {
$users->has('accessories', '=', $request->input('accessories_count'));
}
if ($request->filled('search')) {
$users = $users->TextSearch($request->input('search'));
}
@@ -448,6 +469,24 @@ class UsersController extends Controller
return (new AssetsTransformer)->transformAssets($assets, $assets->count(), $request);
}
/**
* Return JSON containing a list of consumables assigned to a user.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @param $userId
* @return string JSON
*/
public function consumables(Request $request, $id)
{
$this->authorize('view', User::class);
$this->authorize('view', Consumable::class);
$user = User::findOrFail($id);
$consumables = $user->consumables;
return (new ConsumablesTransformer)->transformConsumables($consumables, $consumables->count(), $request);
}
/**
* Return JSON containing a list of accessories assigned to a user.
*
@@ -50,6 +50,7 @@ class AssetMaintenancesController extends Controller
*/
public function index()
{
$this->authorize('view', Asset::class);
return view('asset_maintenances/index');
}
@@ -66,6 +67,7 @@ class AssetMaintenancesController extends Controller
*/
public function create()
{
$this->authorize('update', Asset::class);
$asset = null;
if ($asset = Asset::find(request('asset_id'))) {
@@ -96,6 +98,7 @@ class AssetMaintenancesController extends Controller
*/
public function store(Request $request)
{
$this->authorize('update', Asset::class);
// create a new model instance
$assetMaintenance = new AssetMaintenance();
$assetMaintenance->supplier_id = $request->input('supplier_id');
@@ -148,6 +151,7 @@ class AssetMaintenancesController extends Controller
*/
public function edit($assetMaintenanceId = null)
{
$this->authorize('update', Asset::class);
// Check if the asset maintenance exists
if (is_null($assetMaintenance = AssetMaintenance::find($assetMaintenanceId))) {
// Redirect to the improvement management page
@@ -200,6 +204,7 @@ class AssetMaintenancesController extends Controller
*/
public function update(Request $request, $assetMaintenanceId = null)
{
$this->authorize('update', Asset::class);
// Check if the asset maintenance exists
if (is_null($assetMaintenance = AssetMaintenance::find($assetMaintenanceId))) {
// Redirect to the asset maintenance management page
@@ -266,6 +271,7 @@ class AssetMaintenancesController extends Controller
*/
public function destroy($assetMaintenanceId)
{
$this->authorize('update', Asset::class);
// Check if the asset maintenance exists
if (is_null($assetMaintenance = AssetMaintenance::find($assetMaintenanceId))) {
// Redirect to the asset maintenance management page
@@ -294,6 +300,8 @@ class AssetMaintenancesController extends Controller
*/
public function show($assetMaintenanceId)
{
$this->authorize('view', Asset::class);
// Check if the asset maintenance exists
if (is_null($assetMaintenance = AssetMaintenance::find($assetMaintenanceId))) {
// Redirect to the asset maintenance management page
@@ -155,7 +155,6 @@ class AssetModelsController extends Controller
$model->requestable = $request->input('requestable', '0');
$this->removeCustomFieldsDefaultValues($model);
if ($request->input('custom_fieldset')=='') {
@@ -168,7 +167,6 @@ class AssetModelsController extends Controller
}
}
if ($model->save()) {
return redirect()->route("models.index")->with('success', trans('admin/models/message.update.success'));
}
@@ -269,6 +267,7 @@ class AssetModelsController extends Controller
*/
public function getClone($modelId = null)
{
$this->authorize('create', AssetModel::class);
// Check if the model exists
if (is_null($model_to_clone = AssetModel::find($modelId))) {
return redirect()->route('models.index')->with('error', trans('admin/models/message.does_not_exist'));
@@ -462,7 +461,9 @@ class AssetModelsController extends Controller
private function assignCustomFieldsDefaultValues(AssetModel $model, array $defaultValues)
{
foreach ($defaultValues as $customFieldId => $defaultValue) {
if ($defaultValue) {
if(is_array($defaultValue)){
$model->defaultValues()->attach($customFieldId, ['default_value' => implode(', ', $defaultValue)]);
}elseif ($defaultValue) {
$model->defaultValues()->attach($customFieldId, ['default_value' => $defaultValue]);
}
}
@@ -105,9 +105,9 @@ class AssetCheckinController extends Controller
$asset->location_id = e($request->get('location_id'));
}
$checkin_at = date('Y-m-d');
if($request->filled('checkin_at')){
$checkin_at = $request->input('checkin_at');
$checkin_at = date('Y-m-d H:i:s');
if (($request->filled('checkin_at')) && ($request->get('checkin_at') != date('Y-m-d'))) {
$checkin_at = $request->get('checkin_at');
}
// Was the asset updated?
@@ -196,7 +196,7 @@ class AssetsController extends Controller
}
if (isset($target)) {
$asset->checkOut($target, Auth::user(), date('Y-m-d H:i:s'), $request->input('expected_checkin', null), 'Checked out on asset creation', e($request->get('name')), $location);
$asset->checkOut($target, Auth::user(), date('Y-m-d H:i:s'), $request->input('expected_checkin', null), 'Checked out on asset creation', $request->get('name'), $location);
}
$success = true;
@@ -410,7 +410,23 @@ class AssetsController extends Controller
return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.delete.success'));
}
/**
* Searches the assets table by serial, and redirects if it finds one
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return Redirect
*/
public function getAssetBySerial(Request $request)
{
$topsearch = ($request->get('topsearch')=="true");
if (!$asset = Asset::where('serial', '=', $request->get('serial'))->first()) {
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
}
$this->authorize('view', $asset);
return redirect()->route('hardware.show', $asset->id)->with('topsearch', $topsearch);
}
/**
* Searches the assets table by asset tag, and redirects if it finds one
@@ -429,6 +445,8 @@ class AssetsController extends Controller
$this->authorize('view', $asset);
return redirect()->route('hardware.show', $asset->id)->with('topsearch', $topsearch);
}
/**
* Return a QR code for the asset
*
@@ -5,6 +5,7 @@ namespace App\Http\Controllers\Assets;
use App\Helpers\Helper;
use App\Http\Controllers\CheckInOutRequest;
use App\Http\Controllers\Controller;
use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\Setting;
use Illuminate\Http\Request;
@@ -121,6 +122,24 @@ class BulkAssetsController extends Controller
}
}
$changed = [];
$asset = Asset::where('id' ,$assetId)->get();
foreach ($this->update_array as $key => $value) {
if ($this->update_array[$key] != $asset->toArray()[0][$key]) {
$changed[$key]['old'] = $asset->toArray()[0][$key];
$changed[$key]['new'] = $this->update_array[$key];
}
}
$logAction = new Actionlog();
$logAction->item_type = Asset::class;
$logAction->item_id = $assetId;
$logAction->created_at = date("Y-m-d H:i:s");
$logAction->user_id = Auth::id();
$logAction->log_meta = json_encode($changed);
$logAction->logaction('update');
DB::table('assets')
->where('id', $assetId)
->update($this->update_array);
@@ -87,6 +87,8 @@ class ForgotPasswordController extends Controller
\Log::info('Password reset attempt: User '.$request->input('username').'failed with exception: '.$e );
}
// Prevent timing attack to enumerate users.
usleep(500000 + random_int(0, 1500000));
if ($response === \Password::RESET_LINK_SENT) {
\Log::info('Password reset attempt: User '.$request->input('username').' WAS found, password reset sent');
+14 -1
View File
@@ -75,6 +75,13 @@ class LoginController extends Controller
return redirect()->intended('/');
}
// If the environment is set to ALWAYS require SAML, go straight to the SAML route.
// We don't need to check other settings, as this should override those.
if (config('app.require_saml')) {
return redirect()->route('saml.login');
}
if ($this->saml->isEnabled() && Setting::getSettings()->saml_forcelogin == "1" && !($request->has('nosaml') || $request->session()->has('error'))) {
return redirect()->route('saml.login');
}
@@ -197,6 +204,12 @@ class LoginController extends Controller
*/
public function login(Request $request)
{
//If the environment is set to ALWAYS require SAML, return access denied
if (config('app.require_saml')) {
return view('errors.403');
}
if (Setting::getSettings()->login_common_disabled == "1") {
return view('errors.403');
}
@@ -363,7 +376,7 @@ class LoginController extends Controller
if (Google2FA::verifyKey($user->two_factor_secret, $secret)) {
$user->two_factor_enrolled = 1;
$user->save();
$request->session()->put('2fa_authed', 'true');
$request->session()->put('2fa_authed', $user->id);
return redirect()->route('home')->with('success', 'You are logged in!');
}
@@ -32,6 +32,7 @@ class BulkAssetModelsController extends Controller
// If deleting....
if ($request->input('bulk_actions')=='delete') {
$this->authorize('delete', AssetModel::class);
$valid_count = 0;
foreach ($models as $model) {
if ($model->assets_count == 0) {
@@ -42,7 +43,7 @@ class BulkAssetModelsController extends Controller
// Otherwise display the bulk edit screen
}
$this->authorize('update', AssetModel::class);
$nochange = ['NC' => 'No Change'];
return view('models/bulk-edit', compact('models'))
->with('fieldset_list', $nochange + Helper::customFieldsetList())
@@ -63,7 +64,8 @@ class BulkAssetModelsController extends Controller
*/
public function update(Request $request)
{
$this->authorize('update', AssetModel::class);
$models_raw_array = $request->input('ids');
$update_array = array();
@@ -103,6 +105,8 @@ class BulkAssetModelsController extends Controller
*/
public function destroy(Request $request)
{
$this->authorize('delete', AssetModel::class);
$models_raw_array = $request->input('ids');
if ((is_array($models_raw_array)) && (count($models_raw_array) > 0)) {
@@ -78,6 +78,7 @@ class ComponentsController extends Controller
$component->purchase_cost = Helper::ParseCurrency($request->input('purchase_cost', null));
$component->qty = $request->input('qty');
$component->user_id = Auth::id();
$component->notes = $request->input('notes');
$component = $request->handleImages($component);
@@ -147,6 +148,7 @@ class ComponentsController extends Controller
$component->purchase_date = $request->input('purchase_date');
$component->purchase_cost = Helper::ParseCurrency(request('purchase_cost'));
$component->qty = $request->input('qty');
$component->notes = $request->input('notes');
$component = $request->handleImages($component);
@@ -78,6 +78,8 @@ class ConsumablesController extends Controller
$consumable->purchase_cost = Helper::ParseCurrency($request->input('purchase_cost'));
$consumable->qty = $request->input('qty');
$consumable->user_id = Auth::id();
$consumable->notes = $request->input('notes');
$consumable = $request->handleImages($consumable);
@@ -143,6 +145,7 @@ class ConsumablesController extends Controller
$consumable->purchase_date = $request->input('purchase_date');
$consumable->purchase_cost = Helper::ParseCurrency($request->input('purchase_cost'));
$consumable->qty = Helper::ParseFloat($request->input('qty'));
$consumable->notes = $request->input('notes');
$consumable = $request->handleImages($consumable);
+33 -17
View File
@@ -92,7 +92,7 @@ class CustomFieldsController extends Controller
$this->authorize('create', CustomField::class);
$field = new CustomField([
"name" => $request->get("name"),
"name" => trim($request->get("name")),
"element" => $request->get("element"),
"help_text" => $request->get("help_text"),
"field_values" => $request->get("field_values"),
@@ -133,12 +133,23 @@ class CustomFieldsController extends Controller
$this->authorize('update', $field);
if ($field->fieldset()->detach($fieldset_id)) {
return redirect()->route('fieldsets.show', ['fieldset' => $fieldset_id])
->with("success", trans('admin/custom_fields/message.field.delete.success'));
// Check that the field exists - this is mostly related to the demo, where we
// rewrite the data every x minutes, so it's possible someone might be disassociating
// a field from a fieldset just as we're wiping the database
if (($field) && ($fieldset_id)) {
if ($field->fieldset()->detach($fieldset_id)) {
return redirect()->route('fieldsets.show', ['fieldset' => $fieldset_id])
->with("success", trans('admin/custom_fields/message.field.delete.success'));
} else {
return redirect()->back()->withErrors(['message' => "Field is in use and cannot be deleted."]);
}
}
return redirect()->back()->withErrors(['message' => "Field is in-use"]);
return redirect()->back()->withErrors(['message' => "Error deleting field from fieldset"]);
}
/**
@@ -178,20 +189,25 @@ class CustomFieldsController extends Controller
*/
public function edit($id)
{
$field = CustomField::find($id);
if ($field = CustomField::find($id)) {
$this->authorize('update', $field);
$this->authorize('update', $field);
$customFormat = '';
if((stripos($field->format, 'regex') === 0) && ($field->format !== CustomField::PREDEFINED_FORMATS['MAC'])) {
$customFormat = $field->format;
}
$customFormat = '';
if((stripos($field->format, 'regex') === 0) && ($field->format !== CustomField::PREDEFINED_FORMATS['MAC'])) {
$customFormat = $field->format;
}
return view("custom_fields.fields.edit",[
'field' => $field,
'customFormat' => $customFormat,
'predefinedFormats' => Helper::predefined_formats()
]);
return view("custom_fields.fields.edit",[
'field' => $field,
'customFormat' => $customFormat,
'predefinedFormats' => Helper::predefined_formats()
]);
}
return redirect()->route("fields.index")
->with("error", trans('admin/custom_fields/message.field.invalid'));
}
@@ -212,7 +228,7 @@ class CustomFieldsController extends Controller
$this->authorize('update', $field);
$field->name = e($request->get("name"));
$field->name = trim(e($request->get("name")));
$field->element = e($request->get("element"));
$field->field_values = e($request->get("field_values"));
$field->user_id = Auth::id();
@@ -23,6 +23,12 @@ use Redirect;
class CustomFieldsetsController extends Controller
{
public function index()
{
return redirect()->route("fields.index")
->with("error", trans('admin/custom_fields/message.fieldset.does_not_exist'));
}
/**
* Validates and stores a new custom field.
*
+42 -8
View File
@@ -6,15 +6,49 @@ use App\Helpers\Helper;
class ModalController extends Controller
{
function show($type, $itemId = null) {
$view = view("modals.${type}");
if($type == "statuslabel") {
$view->with('statuslabel_types', Helper::statusTypeList());
/**
* Load the modal views after confirming they are in the allowed_types array.
* The allowed types away just prevents shithead skiddies from fuzzing the urls
* with automated scripts and junking up the logs. - snipe
*
* @version v5.3.7-pre
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
* @author [A. Gianotto] [<snipe@snipe.net]
* @return View
*/
function show ($type, $itemId = null) {
// These values should correspond to a file in resources/views/modals/
$allowed_types = [
'category',
'kit-model',
'kit-license',
'kit-consumable',
'kit-accessory',
'location',
'manufacturer',
'model',
'statuslabel',
'supplier',
'upload-file',
'user',
];
if (in_array($type, $allowed_types)) {
$view = view("modals.${type}");
if ($type == "statuslabel") {
$view->with('statuslabel_types', Helper::statusTypeList());
}
if (in_array($type, ['kit-model', 'kit-license', 'kit-consumable', 'kit-accessory'])) {
$view->with('kitId', $itemId);
}
return $view;
}
if(in_array($type, ['kit-model', 'kit-license', 'kit-consumable', 'kit-accessory'])) {
$view->with('kitId', $itemId);
}
return $view;
abort(404,'Page not found');
}
}
@@ -113,6 +113,12 @@ class ProfileController extends Controller
* @return View
*/
public function api() {
// Make sure the self.api permission has been granted
if (!Gate::allows('self.api')) {
abort(403);
}
return view('account/api');
}
+12 -1
View File
@@ -515,6 +515,10 @@ class ReportsController extends Controller
$header[] = trans('general.department');
}
if ($request->filled('title')) {
$header[] = trans('admin/users/table.title');
}
if ($request->filled('status')) {
$header[] = trans('general.status');
}
@@ -754,7 +758,6 @@ class ReportsController extends Controller
}
}
if ($request->filled('department')) {
if ($asset->checkedOutToUser()) {
$row[] = (($asset->assignedto) && ($asset->assignedto->department)) ? $asset->assignedto->department->name : '';
@@ -763,6 +766,14 @@ class ReportsController extends Controller
}
}
if ($request->filled('title')) {
if ($asset->checkedOutToUser()) {
$row[] = ($asset->assignedto) ? $asset->assignedto->jobtitle : '';
} else {
$row[] = ''; // Empty string if unassigned
}
}
if ($request->filled('status')) {
$row[] = ($asset->assetstatus) ? $asset->assetstatus->name.' ('.$asset->present()->statusMeta.')' : '';
}
+27 -14
View File
@@ -8,6 +8,7 @@ use App\Http\Requests\ImageUploadRequest;
use App\Http\Requests\SettingsSamlRequest;
use App\Http\Requests\SetupUserRequest;
use App\Models\Setting;
use App\Models\Asset;
use App\Models\User;
use App\Notifications\FirstAdminNotification;
use App\Notifications\MailTest;
@@ -22,6 +23,7 @@ use Input;
use Redirect;
use Response;
use App\Helpers\StorageHelper;
use App\Http\Requests\SlackSettingsRequest;
/**
* This controller handles all actions related to Settings for
@@ -620,6 +622,26 @@ class SettingsController extends Controller
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
}
// Check if the audit interval has changed - if it has, we want to update ALL of the assets audit dates
if ($request->input('audit_interval') != $setting->audit_interval) {
// Be careful - this could be a negative number
$audit_diff_months = ((int)$request->input('audit_interval') - (int)($setting->audit_interval));
// Grab all of the assets that have an existing next_audit_date
$assets = Asset::whereNotNull('next_audit_date')->get();
// Update all of the assets' next_audit_date values
foreach ($assets as $asset) {
if ($asset->next_audit_date != '') {
$old_next_audit = new \DateTime($asset->next_audit_date);
$asset->next_audit_date = $old_next_audit->modify($audit_diff_months.' month')->format('Y-m-d');
$asset->forceSave();
}
}
}
$alert_email = rtrim($request->input('alert_email'), ',');
$alert_email = trim($alert_email);
$admin_cc_email = rtrim($request->input('admin_cc_email'), ',');
@@ -667,25 +689,16 @@ class SettingsController extends Controller
*
* @return View
*/
public function postSlack(Request $request)
public function postSlack(SlackSettingsRequest $request)
{
if (is_null($setting = Setting::getSettings())) {
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
}
$validatedData = $request->validate([
'slack_channel' => 'regex:/(?<!\w)#\w+/|required_with:slack_endpoint|nullable',
]);
if ($validatedData) {
$setting->slack_endpoint = $request->input('slack_endpoint');
$setting->slack_channel = $request->input('slack_channel');
$setting->slack_botname = $request->input('slack_botname');
}
$setting->slack_endpoint = $request->input('slack_endpoint');
$setting->slack_channel = $request->input('slack_channel');
$setting->slack_botname = $request->input('slack_botname');
if ($setting->save()) {
return redirect()->route('settings.index')
->with('success', trans('admin/settings/message.update.success'));
@@ -184,6 +184,7 @@ class SuppliersController extends Controller
*/
public function show($supplierId = null)
{
$this->authorize('view', Supplier::class);
$supplier = Supplier::find($supplierId);
if (isset($supplier->id)) {
@@ -34,7 +34,8 @@ class BulkUsersController extends Controller
// Make sure there were users selected
if (($request->filled('ids')) && (count($request->input('ids')) > 0)) {
// Get the list of affected users
$users = User::whereIn('id', array_keys(request('ids')))
$user_raw_array = request('ids');
$users = User::whereIn('id', $user_raw_array)
->with('groups', 'assets', 'licenses', 'accessories')->get();
if ($request->input('bulk_actions') == 'edit') {
@@ -108,12 +109,15 @@ class BulkUsersController extends Controller
if (!$manager_conflict) {
$this->conditionallyAddItem('manager_id');
}
// Save the updated info
User::whereIn('id', $user_raw_array)
->where('id', '!=', Auth::id())->update($this->update_array);
if(array_key_exists('location_id', $this->update_array)){
Asset::where('assigned_type', User::class)
->whereIn('assigned_to', $user_raw_array)
->update(['location_id' => $this->update_array['location_id']]);
}
// Only sync groups if groups were selected
if ($request->filled('groups')) {
foreach ($users as $user) {
@@ -484,7 +484,6 @@ class UsersController extends Controller
$user->first_name = '';
$user->last_name = '';
$user->email = substr($user->email, ($pos = strpos($user->email, '@')) !== false ? $pos : 0);
$user->id = null;
// Get this user groups
@@ -179,7 +179,7 @@ class ViewAssetsController extends Controller
$logaction->logaction('request canceled');
$settings->notify(new RequestAssetCancelation($data));
return redirect()->route('requestable-assets')
->with('success')->with('success', trans('admin/hardware/message.requests.cancel-success'));
->with('success')->with('success', trans('admin/hardware/message.requests.cancel'));
}
$logaction->logaction('requested');
+2 -2
View File
@@ -24,6 +24,7 @@ class Kernel extends HttpKernel
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\App\Http\Middleware\SecurityHeaders::class,
\App\Http\Middleware\PreventBackHistory::class,
\Fruitcake\Cors\HandleCors::class,
];
@@ -38,14 +39,13 @@ class Kernel extends HttpKernel
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\App\Http\Middleware\CheckLocale::class,
\App\Http\Middleware\CheckUserIsActivated::class,
\App\Http\Middleware\CheckForTwoFactor::class,
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
\App\Http\Middleware\AssetCountForSidebar::class,
],
'api' => [
\Barryvdh\Cors\HandleCors::class,
'throttle:120,1',
'auth:api',
],
];
+1 -1
View File
@@ -32,7 +32,7 @@ class CheckForTwoFactor
if ($settings = Setting::getSettings()) {
if (Auth::check() && ($settings->two_factor_enabled != '')) {
// This user is already 2fa-authed
if ($request->session()->get('2fa_authed')) {
if ($request->session()->get('2fa_authed')==Auth::user()->id) {
return $next($request);
}
@@ -4,8 +4,9 @@ namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\Guard;
use Auth;
class Authenticate
class CheckUserIsActivated
{
/**
* The Guard implementation.
@@ -34,14 +35,16 @@ class Authenticate
*/
public function handle($request, Closure $next)
{
if ($this->auth->guest()) {
if ($request->ajax()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('login');
}
// If there is a user AND the user is NOT activated, send them to the login page
// This prevents people who still have active sessions logged in and their status gets toggled
// to inactive (aka unable to login)
if (($request->user()) && (!$request->user()->isActivated())) {
Auth::logout();
return redirect()->guest('login');
}
return $next($request);
}
}
+8
View File
@@ -8,6 +8,14 @@ abstract class Request extends FormRequest
{
protected $rules = [];
public function json($key = null, $default = null)
{
if ($this->ajax() || $this->wantsJson()) {
json_decode($this->getContent(), false, 512, JSON_THROW_ON_ERROR); // ignore output, just throw
}
return parent::json($key, $default);
}
public function rules()
{
return $this->rules;
@@ -0,0 +1,33 @@
<?php
namespace App\Http\Requests;
class SlackSettingsRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'slack_endpoint' => 'url|required_with:slack_channel|starts_with:"https://hooks.slack.com"|nullable',
'slack_channel' => 'required_with:slack_endpoint|starts_with:#|nullable',
'slack_botname' => 'string|nullable',
];
}
}
@@ -82,7 +82,7 @@ class AccessoriesTransformer
'first_name'=> e($user->first_name),
'last_name'=> e($user->last_name),
'employee_number' => e($user->employee_num),
'checkout_notes' => $user->pivot->note,
'checkout_notes' => e($user->pivot->note),
'last_checkout' => Helper::getFormattedDateObject($user->pivot->created_at, 'datetime'),
'type' => 'user',
'available_actions' => ['checkin' => true]
+20 -39
View File
@@ -19,6 +19,22 @@ class ActionlogsTransformer
return (new DatatablesTransformer)->transformDatatables($array, $total);
}
private function clean_field($value)
{
// This object stuff is weird, and is used to make up for the fact that
// older data can get strangely formatted if an asset existed,
// then a new custom field is added, and the asset is saved again.
// It can result in funnily-formatted strings like:
//
// {"_snipeit_right_sized_fault_tolerant_localareanetwo_1":
// {"old":null,"new":{"value":"1579490695972","_snipeit_new_field_2":2,"_snipeit_new_field_3":"Monday, 20 January 2020 2:24:55 PM"}}
// so we have to walk down that next level
if(is_object($value) && isset($value->value)) {
return $this->clean_field($value->value);
}
return is_scalar($value) || is_null($value) ? e($value) : e(json_encode($value));
}
public function transformActionlog (Actionlog $actionlog, $settings = null)
{
$icon = $actionlog->present()->icon();
@@ -31,45 +47,9 @@ class ActionlogsTransformer
$meta_array = json_decode($actionlog->log_meta);
if ($meta_array) {
foreach ($meta_array as $key => $value) {
foreach ($value as $meta_key => $meta_value) {
if (is_array($meta_value)) {
foreach ($meta_value as $meta_value_key => $meta_value_value) {
$clean_meta[$key][$meta_value_key] = e($meta_value_value);
}
} else {
// This object stuff is weird, and is used to make up for the fact that
// older data can get strangely formatted if an asset existed,
// then a new custom field is added, and the asset is saved again.
// It can result in funnily-formatted strings like:
//
// {"_snipeit_right_sized_fault_tolerant_localareanetwo_1":
// {"old":null,"new":{"value":"1579490695972","_snipeit_new_field_2":2,"_snipeit_new_field_3":"Monday, 20 January 2020 2:24:55 PM"}}
// so we have to walk down that next level
if (is_object($meta_value)) {
foreach ($meta_value as $meta_value_key => $meta_value_value) {
if ($meta_value_key == 'value') {
$clean_meta[$key]['old'] = null;
$clean_meta[$key]['new'] = e($meta_value->value);
} else {
$clean_meta[$meta_value_key]['old'] = null;
$clean_meta[$meta_value_key]['new'] = e($meta_value_value);
}
}
} else {
$clean_meta[$key][$meta_key] = e($meta_value);
}
}
}
foreach ($meta_array as $fieldname => $fieldata) {
$clean_meta[$fieldname]['old'] = $this->clean_field($fieldata->old);
$clean_meta[$fieldname]['new'] = $this->clean_field($fieldata->new);
}
}
@@ -118,6 +98,7 @@ class ActionlogsTransformer
'action_date' => ($actionlog->action_date) ? Helper::getFormattedDateObject($actionlog->action_date, 'datetime'): Helper::getFormattedDateObject($actionlog->created_at, 'datetime'),
];
//\Log::info("Clean Meta is: ".print_r($clean_meta,true));
return $array;
}
+7 -1
View File
@@ -3,6 +3,7 @@ namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\Asset;
use App\Models\Setting;
use Gate;
use Illuminate\Database\Eloquent\Collection;
@@ -20,6 +21,9 @@ class AssetsTransformer
public function transformAsset(Asset $asset)
{
// This uses the getSettings() method so we're pulling from the cache versus querying the settings on single asset
$setting = Setting::getSettings();
$array = [
'id' => (int) $asset->id,
'name' => e($asset->name),
@@ -64,6 +68,8 @@ class AssetsTransformer
'name'=> e($asset->defaultLoc->name)
] : null,
'image' => ($asset->getImageUrl()) ? $asset->getImageUrl() : null,
'qr' => ($setting->qr_code=='1') ? config('app.url').'/uploads/barcodes/qr-'.str_slug($asset->asset_tag).'-'.str_slug($asset->id).'.png' : null,
'alt_barcode' => ($setting->alt_barcode_enabled=='1') ? config('app.url').'/uploads/barcodes/'.str_slug($setting->alt_barcode).'-'.str_slug($asset->asset_tag).'.png' : null,
'assigned_to' => $this->transformAssignedTo($asset),
'warranty_months' => ($asset->warranty_months > 0) ? e($asset->warranty_months . ' ' . trans('admin/hardware/form.months')) : null,
'warranty_expires' => ($asset->warranty_months > 0) ? Helper::getFormattedDateObject($asset->warranty_expires, 'date') : null,
@@ -170,7 +176,7 @@ class AssetsTransformer
}
return $asset->assigned ? [
'id' => $asset->assigned->id,
'name' => $asset->assigned->display_name,
'name' => e($asset->assigned->display_name),
'type' => $asset->assignedType()
] : null;
}
@@ -43,6 +43,7 @@ class ComponentsTransformer
'id' => (int) $component->company->id,
'name' => e($component->company->name)
] : null,
'notes' => ($component->notes) ? e($component->notes) : null,
'created_at' => Helper::getFormattedDateObject($component->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($component->updated_at, 'datetime'),
'user_can_checkout' => ($component->numRemaining() > 0) ? 1 : 0,
@@ -37,6 +37,7 @@ class ConsumablesTransformer
'purchase_cost' => Helper::formatCurrencyOutput($consumable->purchase_cost),
'purchase_date' => Helper::getFormattedDateObject($consumable->purchase_date, 'date'),
'qty' => (int) $consumable->qty,
'notes' => ($consumable->notes) ? e($consumable->notes) : null,
'created_at' => Helper::getFormattedDateObject($consumable->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($consumable->updated_at, 'datetime'),
];
+2 -2
View File
@@ -9,13 +9,13 @@ use Illuminate\Database\Eloquent\Collection;
class GroupsTransformer
{
public function transformGroups (Collection $groups)
public function transformGroups (Collection $groups, $total = null)
{
$array = array();
foreach ($groups as $group) {
$array[] = self::transformGroup($group);
}
return (new DatatablesTransformer)->transformDatatables($array);
return (new DatatablesTransformer)->transformDatatables($array, $total);
}
public function transformGroup (Group $group)
@@ -45,7 +45,9 @@ class LicensesTransformer
'category' => ($license->category) ? ['id' => (int) $license->category->id,'name'=> e($license->category->name)] : null,
'created_at' => Helper::getFormattedDateObject($license->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($license->updated_at, 'datetime'),
'deleted_at' => Helper::getFormattedDateObject($license->deleted_at, 'datetime'),
'user_can_checkout' => (bool) ($license->free_seats_count > 0),
];
$permissions_array['available_actions'] = [
+1 -1
View File
@@ -71,7 +71,7 @@ class AssetImporter extends ItemImporter
$this->log("No Matching Asset, Creating a new one");
$asset = new Asset;
}
$this->item['notes'] = $this->findCsvMatch($row, 'asset_notes');
$this->item['image'] = $this->findCsvMatch($row, "image");
$this->item['requestable'] = $this->fetchHumanBoolean($this->findCsvMatch($row, "requestable"));;
$asset->requestable = $this->fetchHumanBoolean($this->findCsvMatch($row, "requestable"));
+17 -3
View File
@@ -177,7 +177,7 @@ class ItemImporter extends Importer
*/
public function createOrFetchAssetModel(array $row)
{
$condition = array();
$asset_model_name = $this->findCsvMatch($row, "asset_model");
$asset_modelNumber = $this->findCsvMatch($row, "model_number");
// TODO: At the moment, this means we can't update the model number if the model name stays the same.
@@ -189,8 +189,16 @@ class ItemImporter extends Importer
} elseif ((empty($asset_model_name)) && (empty($asset_modelNumber))) {
$asset_model_name ='Unknown';
}
if ((!empty($asset_model_name)) && (empty($asset_modelNumber))) {
$condition[] = ['name', '=', $asset_model_name];
} elseif ((!empty($asset_model_name)) && (!empty($asset_modelNumber))) {
$condition[] = ['name', '=', $asset_model_name];
$condition[] = ['model_number', '=', $asset_modelNumber];
}
$editingModel = $this->updating;
$asset_model = AssetModel::where(['name' => $asset_model_name, 'model_number' => $asset_modelNumber])->first();
$asset_model = AssetModel::where($condition)->first();
if ($asset_model) {
if (!$this->updating) {
@@ -200,7 +208,12 @@ class ItemImporter extends Importer
$this->log("Matching Model found, updating it.");
$item = $this->sanitizeItemForStoring($asset_model, $editingModel);
$item['name'] = $asset_model_name;
$item['model_number'] = $asset_modelNumber;
$item['notes'] = $this->findCsvMatch($row, 'model_notes');
if(!empty($asset_modelNumber)){
$item['model_number'] = $asset_modelNumber;
}
$asset_model->update($item);
$asset_model->save();
$this->log("Asset Model Updated");
@@ -212,6 +225,7 @@ class ItemImporter extends Importer
$item = $this->sanitizeItemForStoring($asset_model, $editingModel);
$item['name'] = $asset_model_name;
$item['model_number'] = $asset_modelNumber;
$item['notes'] = $this->findCsvMatch($row, 'model_notes');
$asset_model->fill($item);
$item = null;
+10 -3
View File
@@ -32,7 +32,6 @@ class LicenseImporter extends ItemImporter
{
$editingLicense = false;
$license = License::where('name', $this->item['name'])
->where('serial', $this->item['serial'])
->first();
if ($license) {
if (!$this->updating) {
@@ -47,14 +46,22 @@ class LicenseImporter extends ItemImporter
$license = new License;
}
$asset_tag = $this->item['asset_tag'] = $this->findCsvMatch($row, 'asset_tag'); // used for checkout out to an asset.
$this->item['expiration_date'] = $this->findCsvMatch($row, 'expiration_date');
$this->item["expiration_date"] = null;
if ($this->findCsvMatch($row, "expiration_date")!='') {
$this->item["expiration_date"] = date("Y-m-d 00:00:01", strtotime($this->findCsvMatch($row, "expiration_date")));
}
$this->item['license_email'] = $this->findCsvMatch($row, "license_email");
$this->item['license_name'] = $this->findCsvMatch($row, "license_name");
$this->item['maintained'] = $this->findCsvMatch($row, 'maintained');
$this->item['purchase_order'] = $this->findCsvMatch($row, 'purchase_order');
$this->item['reassignable'] = $this->findCsvMatch($row, 'reassignable');
$this->item['seats'] = $this->findCsvMatch($row, 'seats');
$this->item['termination_date'] = $this->findCsvMatch($row, 'termination_date');
$this->item["termination_date"] = null;
if ($this->findCsvMatch($row, "termination_date")!='') {
$this->item["termination_date"] = date("Y-m-d 00:00:01", strtotime($this->findCsvMatch($row, "termination_date")));
}
if ($editingLicense) {
$license->update($this->sanitizeItemForUpdating($license));
+1
View File
@@ -52,6 +52,7 @@ class UserImporter extends ItemImporter
$this->item['city'] = $this->findCsvMatch($row, 'city');
$this->item['state'] = $this->findCsvMatch($row, 'state');
$this->item['country'] = $this->findCsvMatch($row, 'country');
$this->item['zip'] = $this->findCsvMatch($row, 'zip');
$this->item['activated'] = ($this->fetchHumanBoolean($this->findCsvMatch($row, 'activated')) == 1) ? '1' : 0;
$this->item['employee_num'] = $this->findCsvMatch($row, 'employee_num');
$this->item['department_id'] = $this->createOrFetchDepartment($this->findCsvMatch($row, 'department'));
+3 -2
View File
@@ -35,7 +35,7 @@ class Accessory extends SnipeModel
*
* @var array
*/
protected $searchableAttributes = ['name', 'model_number', 'order_number', 'purchase_date'];
protected $searchableAttributes = ['name', 'model_number', 'order_number', 'purchase_date', 'notes'];
/**
* The relations and their attributes that should be included when searching the model.
@@ -92,7 +92,8 @@ class Accessory extends SnipeModel
'image',
'qty',
'min_amt',
'requestable'
'requestable',
'notes',
];
+3 -2
View File
@@ -30,7 +30,7 @@ class Actionlog extends SnipeModel
*
* @var array
*/
protected $searchableAttributes = ['action_type', 'note', 'log_meta'];
protected $searchableAttributes = ['action_type', 'note', 'log_meta','user_id'];
/**
* The relations and their attributes that should be included when searching the model.
@@ -38,7 +38,8 @@ class Actionlog extends SnipeModel
* @var array
*/
protected $searchableRelations = [
'company' => ['name']
'company' => ['name'],
'user' => ['first_name','last_name','username'],
];
/**
+15 -2
View File
@@ -185,10 +185,19 @@ class Asset extends Depreciable
$model = AssetModel::find($this->model_id);
if (($model) && ($model->fieldset)) {
foreach ($model->fieldset->fields as $field){
if($field->format == 'BOOLEAN'){
$this->{$field->db_column} = filter_var($this->{$field->db_column}, FILTER_VALIDATE_BOOLEAN);
}
}
$this->rules += $model->fieldset->validation_rules();
}
}
return parent::save($params);
}
@@ -665,13 +674,15 @@ class Asset extends Depreciable
*/
public static function getExpiringWarrantee($days = 30)
{
$days = (is_null($days)) ? 30 : $days;
return Asset::where('archived', '=', '0')
->whereNotNull('warranty_months')
->whereNotNull('purchase_date')
->whereNull('deleted_at')
->whereRaw(\DB::raw('DATE_ADD(`purchase_date`,INTERVAL `warranty_months` MONTH) <= DATE(NOW() + INTERVAL '
. $days
. ' DAY) AND DATE_ADD(`purchase_date`,INTERVAL `warranty_months` MONTH) > NOW()'))
. ' DAY) AND DATE_ADD(`purchase_date`, INTERVAL `warranty_months` MONTH) > NOW()'))
->orderBy('purchase_date', 'ASC')
->get();
}
@@ -814,7 +825,9 @@ class Asset extends Depreciable
*/
public function checkin_email()
{
return $this->model->category->checkin_email;
if (($this->model) && ($this->model->category)) {
return $this->model->category->checkin_email;
}
}
/**
+2 -1
View File
@@ -60,6 +60,7 @@ class Component extends SnipeModel
'order_number',
'qty',
'serial',
'notes',
];
use Searchable;
@@ -69,7 +70,7 @@ class Component extends SnipeModel
*
* @var array
*/
protected $searchableAttributes = ['name', 'order_number', 'serial', 'purchase_cost', 'purchase_date'];
protected $searchableAttributes = ['name', 'order_number', 'serial', 'purchase_cost', 'purchase_date', 'notes'];
/**
* The relations and their attributes that should be included when searching the model.
+3 -2
View File
@@ -69,7 +69,8 @@ class Consumable extends SnipeModel
'purchase_date',
'qty',
'min_amt',
'requestable'
'requestable',
'notes',
];
use Searchable;
@@ -79,7 +80,7 @@ class Consumable extends SnipeModel
*
* @var array
*/
protected $searchableAttributes = ['name', 'order_number', 'purchase_cost', 'purchase_date', 'item_no', 'model_number'];
protected $searchableAttributes = ['name', 'order_number', 'purchase_cost', 'purchase_date', 'item_no', 'model_number', 'notes'];
/**
* The relations and their attributes that should be included when searching the model.
+1
View File
@@ -627,6 +627,7 @@ class License extends Depreciable
*/
public static function getExpiringLicenses($days = 60)
{
$days = (is_null($days)) ? 60 : $days;
return License::whereNotNull('expiration_date')
->whereNull('deleted_at')
+4
View File
@@ -115,6 +115,10 @@ trait Loggable
$log->location_id = null;
$log->note = $note;
$log->action_date = $action_date;
if (! $log->action_date) {
$log->action_date = date('Y-m-d H:i:s');
}
if (Auth::user()) {
$log->user_id = Auth::user()->id;
-3
View File
@@ -52,10 +52,7 @@ class Setting extends Model
'admin_cc_email' => 'email|nullable',
'default_currency' => 'required',
'locale' => 'required',
'slack_endpoint' => 'url|required_with:slack_channel|nullable',
'labels_per_page' => 'numeric',
'slack_channel' => 'regex:/^[\#\@]?\w+/|required_with:slack_endpoint|nullable',
'slack_botname' => 'string|nullable',
'labels_width' => 'numeric',
'labels_height' => 'numeric',
'labels_pmargin_left' => 'numeric|nullable',
+12
View File
@@ -121,6 +121,18 @@ class Statuslabel extends SnipeModel
->where('deployable', '=', 1);
}
/**
* Query builder scope for undeployable status types
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeUndeployable()
{
return $this->where('pending', '=', 0)
->where('archived', '=', 0)
->where('deployable', '=', 0);
}
/**
* Helper function to determine type attributes
*
+2 -2
View File
@@ -14,8 +14,8 @@ class Supplier extends SnipeModel
protected $rules = array(
'name' => 'required|min:1|max:255|unique_undeleted',
'address' => 'max:50|nullable',
'address2' => 'max:50|nullable',
'address' => 'max:250|nullable',
'address2' => 'max:250|nullable',
'city' => 'max:255|nullable',
'state' => 'max:32|nullable',
'country' => 'max:3|nullable',
+2 -3
View File
@@ -70,7 +70,6 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
* @var array
*/
// 'username' => 'required|string|min:1|unique:users,username,NULL,id,deleted_at,NULL',
protected $rules = [
'first_name' => 'required|string|min:1',
'username' => 'required|string|min:1|unique_undeleted',
@@ -306,7 +305,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
*/
public function consumables()
{
return $this->belongsToMany('\App\Models\Consumable', 'consumables_users', 'assigned_to', 'consumable_id')->withPivot('id')->withTrashed();
return $this->belongsToMany('\App\Models\Consumable', 'consumables_users', 'assigned_to', 'consumable_id')->withPivot('id', 'created_at')->withTrashed();
}
/**
@@ -318,7 +317,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
*/
public function licenses()
{
return $this->belongsToMany('\App\Models\License', 'license_seats', 'assigned_to', 'license_id')->withPivot('id');
return $this->belongsToMany('\App\Models\License', 'license_seats', 'assigned_to', 'license_id')->withPivot('id', 'created_at');
}
/**
+8 -1
View File
@@ -109,7 +109,14 @@ class AccessoryPresenter extends Presenter
"sortable" => true,
"visible" => false,
"title" => trans('general.order_number'),
],[
], [
"field" => "notes",
"searchable" => true,
"sortable" => true,
"visible" => false,
"title" => trans('general.notes'),
"formatter" => "notesFormatter"
], [
"field" => "change",
"searchable" => false,
"sortable" => false,
+8 -1
View File
@@ -104,7 +104,14 @@ class ComponentPresenter extends Presenter
"title" => trans('general.purchase_cost'),
"visible" => true,
"footerFormatter" => 'sumFormatter',
],
], [
"field" => "notes",
"searchable" => true,
"sortable" => true,
"visible" => false,
"title" => trans('general.notes'),
"formatter" => "notesFormatter"
]
];
$layout[] = [
+8 -1
View File
@@ -118,13 +118,20 @@ class ConsumablePresenter extends Presenter
"visible" => true,
"footerFormatter" => 'sumFormatter',
],[
"field" => "notes",
"searchable" => true,
"sortable" => true,
"visible" => false,
"title" => trans('general.notes'),
"formatter" => "notesFormatter"
], [
"field" => "change",
"searchable" => false,
"sortable" => false,
"visible" => true,
"title" => trans('general.change'),
"formatter" => "consumablesInOutFormatter",
], [
], [
"field" => "actions",
"searchable" => false,
"sortable" => false,
+11
View File
@@ -43,6 +43,17 @@ class AppServiceProvider extends ServiceProvider
\Log::warning("'APP_FORCE_TLS' is set to true, but 'APP_URL' does not start with 'https://'. Will not force TLS on connections.");
}
}
// TODO - isn't it somehow 'gauche' to check the environment directly; shouldn't we be using config() somehow?
if ( ! env('APP_ALLOW_INSECURE_HOSTS')) { // unless you set APP_ALLOW_INSECURE_HOSTS, you should PROHIBIT forging domain parts of URL via Host: headers
$url_parts = parse_url(config('app.url'));
if ($url_parts && array_key_exists('scheme', $url_parts) && array_key_exists('host', $url_parts)) { // check for the *required* parts of a bare-minimum URL
\URL::forceRootUrl(config('app.url'));
} else {
\Log::error("Your APP_URL in your .env is misconfigured - it is: ".config('app.url').". Many things will work strangely unless you fix it.");
}
}
Schema::defaultStringLength(191);
Asset::observe(AssetObserver::class);
Accessory::observe(AccessoryObserver::class);
+26 -1
View File
@@ -156,6 +156,8 @@ class AuthServiceProvider extends ServiceProvider
return $user->hasAccess('self.checkout_assets');
});
// This is largely used to determine whether to display the gear icon sidenav
// in the left-side navigation
Gate::define('backend.interact', function ($user) {
return $user->can('view', Statuslabel::class)
|| $user->can('view', AssetModel::class)
@@ -168,7 +170,30 @@ class AuthServiceProvider extends ServiceProvider
|| $user->can('view', Manufacturer::class)
|| $user->can('view', CustomField::class)
|| $user->can('view', CustomFieldset::class)
|| $user->can('view', Depreciation::class);
|| $user->can('view', Depreciation::class);
});
// This determines whether or not an API user should be able to get the selectlists.
// This can seem a little confusing, since view properties may not have been granted
// to the logged in API user, but creating assets, licenses, etc won't work
// if the user can't view and interact with the select lists.
Gate::define('view.selectlists', function ($user) {
return $user->can('update', Asset::class)
|| $user->can('create', Asset::class)
|| $user->can('checkout', Asset::class)
|| $user->can('checkin', Asset::class)
|| $user->can('audit', Asset::class)
|| $user->can('update', License::class)
|| $user->can('create', License::class)
|| $user->can('update', Component::class)
|| $user->can('create', Component::class)
|| $user->can('update', Consumable::class)
|| $user->can('create', Consumable::class)
|| $user->can('update', Accessory::class)
|| $user->can('create', Accessory::class)
|| $user->can('update', User::class)
|| $user->can('create', User::class);
});
}
}
+1
View File
@@ -47,6 +47,7 @@ class LdapAd extends LdapAdConfiguration
'262688', // 0x40220 NORMAL_ACCOUNT, PASSWD_NOTREQD, SMARTCARD_REQUIRED
'328192', // 0x50200 NORMAL_ACCOUNT, SMARTCARD_REQUIRED, DONT_EXPIRE_PASSWORD
'328224', // 0x50220 NORMAL_ACCOUNT, PASSWD_NOT_REQD, SMARTCARD_REQUIRED, DONT_EXPIRE_PASSWORD
'4194816',// 0x400200 NORMAL_ACCOUNT, DONT_REQ_PREAUTH
'4260352',// 0x410200 NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD, DONT_REQ_PREAUTH
'1049088',// 0x100200 NORMAL_ACCOUNT, NOT_DELEGATED
'1114624',// 0x110200 NORMAL_ACCOUNT, NOT_DELEGATED, DONT_EXPIRE_PASSWORD
+3 -2
View File
@@ -20,7 +20,6 @@
"adldap2/adldap2": "^10.2",
"alek13/slack": "^1.12",
"bacon/bacon-qr-code": "^1.0",
"barryvdh/laravel-cors": "^0.11.3",
"barryvdh/laravel-debugbar": "^3.2",
"doctrine/cache": "^1.10",
"doctrine/common": "^2.12",
@@ -28,9 +27,10 @@
"doctrine/inflector": "^1.3",
"doctrine/instantiator": "^1.3",
"eduardokum/laravel-mail-auto-embed": "^1.0",
"enshrined/svg-sanitize": "^0.13.3",
"enshrined/svg-sanitize": "^0.15.0",
"erusev/parsedown": "^1.7",
"fideloper/proxy": "^4.3",
"fruitcake/laravel-cors": "^2.2",
"guzzlehttp/guzzle": "^6.5",
"intervention/image": "^2.5",
"javiereguiluz/easyslugger": "^1.0",
@@ -70,6 +70,7 @@
"overtrue/phplint": "^2.2",
"phpunit/php-token-stream": "^3.1",
"phpunit/phpunit": "^8.5",
"roave/security-advisories": "dev-latest",
"squizlabs/php_codesniffer": "^3.5",
"symfony/css-selector": "^4.4",
"symfony/dom-crawler": "^4.4"
Generated
+1060 -515
View File
File diff suppressed because it is too large Load Diff
+24
View File
@@ -255,7 +255,20 @@ return [
'enable_csp' => env('ENABLE_CSP', false),
/*
|--------------------------------------------------------------------------
| Require SAML Login
|--------------------------------------------------------------------------
|
| Disable the ability to login via form login, and disables the 'nosaml'
| workaround. It requires all logins to process via SAML login.
| (This is for high security setups. If your SAML configuration is not
| working, this option should be set to false. This option is not needed
| to successfully configure SAML authentication.)
|
*/
'require_saml' => env('REQUIRE_SAML', false),
/*
|--------------------------------------------------------------------------
@@ -412,4 +425,15 @@ return [
],
/*
|--------------------------------------------------------------------------
| API Throttling
|--------------------------------------------------------------------------
|
| This value determines the number of API requests permitted per minute
|
*/
'api_throttle_per_minute' => env('API_THROTTLE_PER_MINUTE', 120),
];
+8 -7
View File
@@ -37,12 +37,13 @@ return [
|
*/
'supportsCredentials' => false,
'allowedOrigins' => $allowed_origins,
'allowedOriginsPatterns' => [],
'allowedHeaders' => ['*'],
'allowedMethods' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
'exposedHeaders' => [],
'maxAge' => 0,
'supports_credentials' => false,
'allowed_origins' => $allowed_origins,
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'allowed_methods' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
'exposed_headers' => [],
'max_age' => 0,
'paths' => ['api/*', 'sanctum/csrf-cookie'],
];
+5 -5
View File
@@ -1,10 +1,10 @@
<?php
return array (
'app_version' => 'v5.3.2',
'full_app_version' => 'v5.3.2 - build 6508-g7ce5993f5',
'build_version' => '6508',
'app_version' => 'v5.4.2',
'full_app_version' => 'v5.4.2 - build 6805-g5314ef97e',
'build_version' => '6805',
'prerelease_version' => '',
'hash_version' => 'g7ce5993f5',
'full_hash' => 'v5.3.2-15-g7ce5993f5',
'hash_version' => 'g5314ef97e',
'full_hash' => 'v5.4.2-52-g5314ef97e',
'branch' => 'master',
);
@@ -22,12 +22,12 @@ class UpdateGroupFieldForReporting extends Migration {
if (Schema::hasTable('permission_groups')) {
Group::where('id', 1)->update(['permissions' => '{"users-poop":1,"reports":1}']);
Group::where('id', 2)->update(['permissions' => '{"users-pop":1,"reports":1}']);
Group::where('id', 1)->update(['permissions' => '{"users-foo":1,"reports":1}']);
Group::where('id', 2)->update(['permissions' => '{"users-foo":1,"reports":1}']);
} elseif (Schema::hasTable('groups')) {
DB::update('update '.DB::getTablePrefix().'groups set permissions = ? where id = ?', ['{"admin-farts":1,"users":1,"reports":1}', 1]);
DB::update('update '.DB::getTablePrefix().'groups set permissions = ? where id = ?', ['{"users-farts":1,"reports":1}', 2]);
DB::update('update '.DB::getTablePrefix().'groups set permissions = ? where id = ?', ['{"admin-foo":1,"users":1,"reports":1}', 1]);
DB::update('update '.DB::getTablePrefix().'groups set permissions = ? where id = ?', ['{"users-foo":1,"reports":1}', 2]);
}
}
@@ -14,13 +14,14 @@ class CreateCustomFieldCustomFieldset extends Migration {
{
Schema::create('custom_field_custom_fieldset', function(Blueprint $table)
{
$table->bigIncrements('id');
$table->integer('custom_field_id');
$table->integer('custom_fieldset_id');
$table->integer('order');
$table->boolean('required');
$table->engine = 'InnoDB';
$table->engine = 'InnoDB';
});
}
/**
@@ -23,7 +23,7 @@ class AddLdapFieldsToSettings extends Migration {
$table->string('ldap_username_field')->nullable()->default('samaccountname');
$table->string('ldap_lname_field')->nullable()->default('sn');
$table->string('ldap_fname_field')->nullable()->default('givenname');
$table->string('ldap_auth_filter_query')->nullable()->default('uid=samaccountname');
$table->string('ldap_auth_filter_query')->nullable()->default('uid=');
$table->integer('ldap_version')->nullable()->default(3);
$table->string('ldap_active_flag')->nullable()->default(NULL);
$table->string('ldap_emp_num')->nullable()->default(NULL);
@@ -13,20 +13,22 @@ class CreateCheckoutAcceptancesTable extends Migration
*/
public function up()
{
Schema::create('checkout_acceptances', function (Blueprint $table) {
$table->increments('id');
if (!Schema::hasTable('checkout_acceptances')) {
Schema::create('checkout_acceptances', function (Blueprint $table) {
$table->increments('id');
$table->morphs('checkoutable');
$table->integer('assigned_to_id')->nullable();
$table->morphs('checkoutable');
$table->integer('assigned_to_id')->nullable();
$table->string('signature_filename')->nullable();
$table->string('signature_filename')->nullable();
$table->timestamp('accepted_at')->nullable();
$table->timestamp('declined_at')->nullable();
$table->timestamp('accepted_at')->nullable();
$table->timestamp('declined_at')->nullable();
$table->timestamps();
$table->softDeletes();
});
$table->timestamps();
$table->softDeletes();
});
}
}
/**
@@ -36,6 +38,8 @@ class CreateCheckoutAcceptancesTable extends Migration
*/
public function down()
{
Schema::dropIfExists('checkout_acceptances');
if (Schema::hasTable('checkout_acceptances')) {
Schema::dropIfExists('checkout_acceptances');
}
}
}
@@ -12,14 +12,15 @@ class AddKitsLicensesTable extends Migration {
*/
public function up()
{
//
Schema::create('kits_licenses', function ($table) {
$table->increments('id');
$table->integer('kit_id')->nullable()->default(NULL);
$table->integer('license_id')->nullable()->default(NULL);
$table->integer('quantity')->default(1);
$table->timestamps();
});
if (!Schema::hasTable('kits_licenses')) {
Schema::create('kits_licenses', function ($table) {
$table->increments('id');
$table->integer('kit_id')->nullable()->default(NULL);
$table->integer('license_id')->nullable()->default(NULL);
$table->integer('quantity')->default(1);
$table->timestamps();
});
}
}
/**
@@ -29,8 +30,9 @@ class AddKitsLicensesTable extends Migration {
*/
public function down()
{
//
Schema::drop('kits_licenses');
if (Schema::hasTable('kits_licenses')) {
Schema::drop('kits_licenses');
}
}
}
@@ -12,13 +12,14 @@ class AddKitsTable extends Migration {
*/
public function up()
{
//
Schema::create('kits', function ($table) {
$table->increments('id');
$table->string('name')->nullable()->default(NULL);
$table->timestamps();
$table->engine = 'InnoDB';
});
if (!Schema::hasTable('kits')) {
Schema::create('kits', function ($table) {
$table->increments('id');
$table->string('name')->nullable()->default(NULL);
$table->timestamps();
$table->engine = 'InnoDB';
});
}
}
@@ -29,8 +30,9 @@ class AddKitsTable extends Migration {
*/
public function down()
{
//
Schema::drop('kits');
if (Schema::hasTable('kits')) {
Schema::drop('kits');
}
}
@@ -12,14 +12,15 @@ class AddKitsModelsTable extends Migration {
*/
public function up()
{
//
Schema::create('kits_models', function ($table) {
$table->increments('id');
$table->integer('kit_id')->nullable()->default(NULL);
$table->integer('model_id')->nullable()->default(NULL);
$table->integer('quantity')->default(1);
$table->timestamps();
});
if (!Schema::hasTable('kits_models')) {
Schema::create('kits_models', function ($table) {
$table->increments('id');
$table->integer('kit_id')->nullable()->default(NULL);
$table->integer('model_id')->nullable()->default(NULL);
$table->integer('quantity')->default(1);
$table->timestamps();
});
}
}
/**
@@ -29,8 +30,9 @@ class AddKitsModelsTable extends Migration {
*/
public function down()
{
//
Schema::drop('kits_models');
if (Schema::hasTable('kits_models')) {
Schema::drop('kits_models');
}
}
}
@@ -13,14 +13,15 @@ class AddKitsConsumablesTable extends Migration
*/
public function up()
{
//
Schema::create('kits_consumables', function ($table) {
$table->increments('id');
$table->integer('kit_id')->nullable()->default(NULL);
$table->integer('consumable_id')->nullable()->default(NULL);
$table->integer('quantity')->default(1);
$table->timestamps();
});
if (!Schema::hasTable('kits_consumables')) {
Schema::create('kits_consumables', function ($table) {
$table->increments('id');
$table->integer('kit_id')->nullable()->default(NULL);
$table->integer('consumable_id')->nullable()->default(NULL);
$table->integer('quantity')->default(1);
$table->timestamps();
});
}
}
/**
@@ -30,7 +31,8 @@ class AddKitsConsumablesTable extends Migration
*/
public function down()
{
//
Schema::drop('kits_consumables');
if (Schema::hasTable('kits_consumables')) {
Schema::drop('kits_consumables');
}
}
}
@@ -13,14 +13,15 @@ class AddKitsAccessoriesTable extends Migration
*/
public function up()
{
//
Schema::create('kits_accessories', function ($table) {
$table->increments('id');
$table->integer('kit_id')->nullable()->default(NULL);
$table->integer('accessory_id')->nullable()->default(NULL);
$table->integer('quantity')->default(1);
$table->timestamps();
});
if (!Schema::hasTable('kits_accessories')) {
Schema::create('kits_accessories', function ($table) {
$table->increments('id');
$table->integer('kit_id')->nullable()->default(NULL);
$table->integer('accessory_id')->nullable()->default(NULL);
$table->integer('quantity')->default(1);
$table->timestamps();
});
}
}
/**
@@ -30,7 +31,8 @@ class AddKitsAccessoriesTable extends Migration
*/
public function down()
{
//
Schema::drop('kits_accessories');
if (Schema::hasTable('kits_accessories')) {
Schema::drop('kits_accessories');
}
}
}

Some files were not shown because too many files have changed in this diff Show More