Compare commits

...

297 Commits

Author SHA1 Message Date
snipe 685cc86d71 Sets the ldap_default_group field to nullable and default null
Signed-off-by: snipe <snipe@snipe.net>
2022-12-20 17:24:01 -08:00
snipe fb10a6f218 Merge pull request #12268 from inietov/fixes/people_count
Fixed: Dashboard user count scoping when full company support is enabled
2022-12-20 17:05:18 -08:00
Ivan Nieto Vivanco 3a9b8a4993 Calculate the proper amount of people in the dashboard if Full Company Support is enabled 2022-12-20 18:39:17 -06:00
snipe 128c21a905 Merge pull request #12266 from uberbrady/fix-select-all-bug
Fixed: There was a bug with BS tables' select-all which showed an incorrect list of elements
2022-12-20 15:09:30 -08:00
Brady Wetherington 75a757d6f5 There was a bug with select-all where some bits didn't quite work 2022-12-20 14:57:58 -08:00
snipe 88291cadc1 Merge pull request #12254 from akemidx/documentating_something
Commenting on a scope in Models/Company.php
2022-12-19 12:41:32 -08:00
akemidx 94afe2bc6a edits & typo fixes 2022-12-19 14:48:43 -05:00
snipe 399c7590cd Merge pull request #12209 from snipe/fixes/error_downloading_unaccepted_assets
Fixed 500 when downloading the Unaccepted Assets report  [sc-19555]
2022-12-15 14:19:41 -08:00
snipe d0c5ba70f6 Merge pull request #12242 from inietov/features/add_purchase_cost_column
Added `purchase_cost` to user's default view [sc-19680]
2022-12-15 12:42:29 -08:00
akemidx 133d6ffa50 Commenting on a scope in Models/Company.php 2022-12-15 15:18:24 -05:00
Ivan Nieto Vivanco d9a21cce00 Add other items' purchase_cost columns to the same permission 2022-12-15 14:12:05 -06:00
snipe 29c2ff56ec Merge pull request #12188 from snipe/fixes/decrease_logging_for_saml_when_not_enabled
Removed extra logging case that was very noisy
2022-12-15 11:26:49 -08:00
snipe 3e7975b2c3 Merge pull request #12250 from akemidx/grey_out_pw_reset_button
Fixed: Grey out pw reset button for consistency
2022-12-15 11:25:53 -08:00
akemidx d870bc3b02 nested if loop 2022-12-15 14:19:51 -05:00
snipe 227fef76ee Merge pull request #11736 from Godmartinz/gh6508_ldap_default_group
Adds a permission group selection for directory sync
2022-12-15 11:06:53 -08:00
Godfrey M 9d44720ffd reverted changes to composer.lock 2022-12-15 11:02:34 -08:00
Godfrey M 9f3f0a25ed reverted changes to composer.lock 2022-12-15 10:53:45 -08:00
Godfrey M 2e228ccb0b redid a few things. should be good now :) 2022-12-15 10:45:42 -08:00
Godfrey M 3ee413f379 removes livewire stuff 2022-12-15 09:20:30 -08:00
Ivan Nieto Vivanco b142f8e012 Add the permission to show purchase cost column to non-admin sessions 2022-12-14 23:00:35 -06:00
snipe 418ddcfac3 Merge pull request #9876 from Toreg87/fixes/locations-deletable
Fixed #9875: Make locations deletable for non Superuser-Accounts with FullMultipleCompanySupport
2022-12-14 17:46:53 -08:00
snipe c342668f0f Update @scoo73r as a contributor 2022-12-14 17:25:39 -08:00
snipe 2f6a26ec7d Add @scoo73r as a contributor 2022-12-14 17:25:25 -08:00
snipe f635278010 Merge pull request #12251 from snipe/security/upgrade_font_awesome
Upgraded font awesome to 6.2.1
2022-12-14 16:42:41 -08:00
snipe 8043b86786 Upgraded font awesome to 6.2.1
Signed-off-by: snipe <snipe@snipe.net>
2022-12-14 16:41:56 -08:00
snipe d13a237000 Merge pull request #12205 from Godmartinz/sc19675_add_remote_to_importer
Adds remote field to the user importer
2022-12-14 12:13:18 -08:00
akemidx b114ffd2c3 Grey out button pw reset button for consistency
When user has no email in their profile, the box is greyed out for
consistency accross all buttons on the user profile
2022-12-14 14:48:59 -05:00
snipe fabefa61b0 Merge pull request #12243 from akemidx/new_grey_out_when_no_assets
Created method in users.php for adding up all assigned to user and pr…
2022-12-13 14:00:48 -08:00
akemidx f3e57d7dc0 fixing PR 2022-12-13 16:00:59 -05:00
snipe 389ec3a3cb Merge pull request #12247 from Godmartinz/gh12225_serial_added_to_components
adds serial to components tab of assets
2022-12-13 12:57:50 -08:00
Godfrey M 6a72c344b7 removed the cuddlers 2022-12-13 12:32:30 -08:00
Godfrey M 4442b446b9 adds serial to components tab of assets 2022-12-13 10:30:37 -08:00
snipe c432fb9d70 Merge pull request #12181 from Godmartinz/gh12163_asset_age
Adds asset age to asset index and asset view pages
2022-12-13 10:28:17 -08:00
akemi 07ae91b00f Created method in users.php for adding up all assigned to user and providing an integer value. this then used to grey out buttons on user view if user has nothing assigned. 2022-12-12 15:47:53 -05:00
Ivan Nieto Vivanco 450ad3dcec Added the column purchase_cost to user's default view 2022-12-12 14:17:08 -06:00
Godfrey M fa872b09a9 fixes a typo, the world is great again 2022-12-12 10:38:31 -08:00
snipe 9e8fff6e5b Merge pull request #12238 from snipe/features/add_email_to_endpoint
Add email in assigned_to on asset transformer
2022-12-09 16:08:35 -08:00
snipe 4ac09ff4e4 Add email in assigned_to on asset transformer
Signed-off-by: snipe <snipe@snipe.net>
2022-12-09 16:07:17 -08:00
snipe 1017148bad Merge pull request #12233 from snipe/fixes/translation_placeholder_for_ola_pt-BR
Fixed #12215 - string for “Hello, :name” in pt-BR was using `%`
2022-12-08 17:25:19 -08:00
snipe 00ed197651 Fixed #12215 - string for “Hello, :name” in pt-BR was using %
Signed-off-by: snipe <snipe@snipe.net>
2022-12-08 17:21:55 -08:00
snipe 775df0ab60 Merge pull request #12221 from snipe/fixes/throttles_reset_password_form
Add throttle for password reset form
2022-12-08 14:51:22 -08:00
snipe bc2a455a89 Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2022-12-08 14:48:55 -08:00
snipe 97c28d9adc Add @oguzbilgic as a contributor 2022-12-08 14:44:28 -08:00
snipe 9b3df40ed6 Merge pull request #12231 from oguzbilgic/patch-2
Use `heroku-redis:mini` instead of `hobby` as It is deprecated
2022-12-08 11:22:14 -08:00
Oguz Bilgic 1c8ee0f706 Use heroku-redis:mini instead of hobby as It is deprecated
Heroku has renamed it's plan to `mini`.
2022-12-08 11:20:33 -08:00
snipe d7c5a6af71 Merge pull request #12224 from Godmartinz/gh12211_img_barcode_adjustment
Fixes the margin and padding for img barcode in labels
2022-12-07 16:35:04 -08:00
snipe f7da87520c Merge pull request #12134 from Godmartinz/custom_report_user_fields_missing
fixes a regression with the csv assigned to fields
2022-12-07 16:18:32 -08:00
Godfrey M ec854ddc1d adjusts the margin and padding for img barcode in labels 2022-12-07 14:52:23 -08:00
snipe 1a8b2a169b Merge pull request #12219 from snipe/fixes/typo_in_sr_text_for_apple
Fixed typo in screen reader text
2022-12-07 13:12:07 -08:00
snipe 43acd3b488 Fixed typo
Signed-off-by: snipe <snipe@snipe.net>
2022-12-07 13:11:17 -08:00
snipe c3a6874b16 Add throttle for password reset form
Signed-off-by: snipe <snipe@snipe.net>
2022-12-06 20:42:40 -08:00
Ivan Nieto Vivanco eb67d1b064 Filter items from the report if null returned 2022-12-06 18:00:16 -06:00
Godfrey M d0d0058e79 removed unwanted changes 2022-12-06 11:19:28 -08:00
Godfrey M bbd04f8876 adds the rest of the fields for Remote 2022-12-06 11:13:24 -08:00
Godfrey M 36901d271b adds csvmatch for remote. Im a bit lost though lol 2022-12-05 16:28:19 -08:00
snipe b7a5467f8b Merge pull request #12204 from akemidx/fixcurlyquotes
Fixed: curly quotes in #12182
2022-12-05 15:33:47 -08:00
akemi 2f8a435e18 fixing curly quotes 2022-12-05 18:06:28 -05:00
snipe 9ca40716ce Merge pull request #12197 from inietov/fixes/custom_regex_defaults_to_any
Fixed #11682  Custom field type of CUSTOM REGEX defaults back to ANY on editing
2022-12-05 13:24:22 -08:00
snipe 7518cab7c8 Merge pull request #12194 from Godmartinz/FDD32094_Icon_color_change
changes the life-ring icon color with themes
2022-12-01 10:04:55 -08:00
Ivan Nieto Vivanco 8d36971c8b Properly select 'CUSTOM REGEX' from the select list if the format declares onee 2022-11-30 16:21:23 -06:00
Godfrey M 371a5bf4d6 changes the icon color with themes 2022-11-30 10:37:47 -08:00
snipe cfc4229308 Add @akemidx as a contributor 2022-11-29 13:15:28 -08:00
snipe 8bf01715a9 Merge pull request #12182 from akemidx/translate_inventory_notification
Fixed #12119 - updated user inventory language to use strings
2022-11-29 13:14:32 -08:00
akemi 55f5e7866d edits for PR 2022-11-29 15:59:36 -05:00
Godfrey M 3206929ee4 adds AgeFormatter, not working yet 2022-11-29 09:51:42 -08:00
snipe 1fe0bfe17e Removed extra logging case that was very noisy
Signed-off-by: snipe <snipe@snipe.net>
2022-11-28 19:27:42 -08:00
snipe 0cc7389b85 Merge pull request #12187 from snipe/features/added_jobtitle_to_print
Fixed #12133 - Added job title to header in print assets view
2022-11-28 19:20:46 -08:00
snipe e21d0729c1 Add jobh title to header in print assets view
Signed-off-by: snipe <snipe@snipe.net>
2022-11-28 19:19:42 -08:00
snipe 64a8d1d207 Merge pull request #12185 from snipe/features/add_serial_to_inventory_email
Added serial number to emailed inventory report
2022-11-28 17:20:34 -08:00
snipe 8de59d117f Added serial number to emailed inventory report
Signed-off-by: snipe <snipe@snipe.net>
2022-11-28 17:14:38 -08:00
snipe 6113afe36e Merge pull request #12125 from inietov/fixes/email_issues
Fixed #11699 and #12065 Email issues
2022-11-28 14:09:42 -08:00
snipe 305df42f92 Merge pull request #12167 from inietov/features/no_submit_until_status_selected
Fixed #11980 Submit button deactivated in Users' Bulk Checkin if no status selected
2022-11-28 13:17:33 -08:00
snipe 9aa0356de7 Merge pull request #12159 from uberbrady/upgrade_scim_server_to_upstream
Pulled in latest upstream changes for improved standards-compliance
2022-11-28 13:15:27 -08:00
akemi 39e06a8856 Update to PR#12119, adding inventory notification to messages and changing code to be dynamicaly translated 2022-11-28 14:16:22 -05:00
Godfrey M 8d861cfd82 adds age to the asset table 2022-11-28 10:59:18 -08:00
Godfrey M 078e7281cd adds asset age to asset view 2022-11-28 10:45:58 -08:00
snipe 3ef578eb56 Merge pull request #12164 from Robert-Azelis/patch-7
Fix categories view columns matching
2022-11-23 18:47:02 -08:00
snipe 11a1ab971c Merge pull request #12166 from inietov/fixes/custom_fields_values_develop
Fixed #12046 #12137 Custom field checkboxes not holding value for develop
2022-11-23 18:44:23 -08:00
snipe d226cf189b Merge pull request #12168 from inietov/fixes/error_accepting_assets
Fixed #12161 500 error when accepting assets
2022-11-23 18:41:42 -08:00
Ivan Nieto Vivanco c082d8b90e Return empty string if no MAIL_REPLYTO_ADDR var set 2022-11-23 18:22:31 -06:00
Ivan Nieto Vivanco b1985a08c4 Checks the status before activate the submit button on users bulk-checkin 2022-11-23 17:45:59 -06:00
Ivan Nieto Vivanco 9bafe795b0 Corrected the view when editing custom fields values 2022-11-23 16:34:29 -06:00
Robert-Azelis c2cfd8ff53 Update CategoryPresenter.php 2022-11-23 19:00:08 +01:00
Robert-Azelis 20ad4fb681 Update CategoryPresenter.php
Fix snipe#12153
2022-11-23 18:42:38 +01:00
Brady Wetherington 06a1fe5b38 Pulled in latest upstream changes for improved standards-compliance 2022-11-22 12:52:11 -08:00
snipe e426846c23 Merge pull request #12157 from snipe/fixes/inherit_bgcolor_for_readonly
Fixed background color for readonly date picker fields
2022-11-22 16:57:34 +00:00
snipe 27898e660c Inherit the background color, since the field isn’t actually technically readonly
Signed-off-by: snipe <snipe@snipe.net>
2022-11-22 08:54:48 -08:00
snipe 0d9d02c6d6 Merge pull request #12148 from whalehub/develop
Fix restore icon in table view
2022-11-19 10:25:48 +00:00
Aaron 7c854c0a5c Fix restore icon in table view
Signed-off-by: Aaron <admin@datahoarder.dev>
2022-11-19 10:45:10 +01:00
snipe ba4c37a7f4 Merge pull request #12139 from snipe/fixes/custom_fields_api_patches
Fixed #9949 - PATCH to custom fields failing on validation (alt approach to #12011)
2022-11-17 21:28:39 +00:00
snipe f0c5560c1b Merge pull request #12141 from Godmartinz/adds_serial_number_to_history
Added `serial` column to the user history page
2022-11-17 21:15:26 +00:00
snipe 774962c122 Fixed typo
Signed-off-by: snipe <snipe@snipe.net>
2022-11-17 21:14:35 +00:00
Godfrey M 0a9fd0b867 adds serial to activity report page 2022-11-17 13:09:06 -08:00
Godfrey M 5c94ca1403 removes dead space 2022-11-17 13:06:07 -08:00
Godfrey M 86bc409d3a adds serial column to the action logs 2022-11-17 12:57:53 -08:00
snipe 24841a75d4 Move common things into the model level validation
Signed-off-by: snipe <snipe@snipe.net>
2022-11-17 19:41:10 +00:00
Godfrey M a02a04d601 fixes a regression with the csv assigned to fields 2022-11-16 16:34:57 -08:00
snipe 3997085faf Merge pull request #12122 from Godmartinz/fixes_checkout_to_all_description
fixes checkout to all description
2022-11-16 21:56:53 +00:00
snipe 3ac92e1425 Merge pull request #12127 from deloz/fix-Asset-checked-in-Email-Asset-Picture-Not-Displaying
Fixed #12095 - email logo still linking even if settings deny it
2022-11-16 21:55:59 +00:00
snipe cdcd19a7d8 Merge pull request #12132 from snipe/fixes/view_assets_page_error_when_no_custom_fields
Handle use case where there are no custom fields for any assigned models
2022-11-16 17:48:53 +00:00
snipe 489895a5fa Added comments and spacing for readability
Signed-off-by: snipe <snipe@snipe.net>
2022-11-16 17:48:28 +00:00
snipe 1122562b4e Handle use case where there are no custom fields for any assigned models
Signed-off-by: snipe <snipe@snipe.net>
2022-11-16 17:45:50 +00:00
snipe 4ffe13d3c2 Merge pull request #12131 from snipe/fixes/check_for_format_index_in_custom_field_api_call
Fixed 500 if `format` is not passed to the create custom field endpoint payload
2022-11-16 15:57:07 +00:00
snipe 5df76155ce Check for the format index in the $data array when creating a new custom field via API
Signed-off-by: snipe <snipe@snipe.net>
2022-11-16 15:53:16 +00:00
snipe e1c33d4eff Merge pull request #12129 from deloz/fix-remove-duplicate-column-checkin_email
Fixed #12109 - Duplicate column on Category listing
2022-11-16 11:41:55 +00:00
Instead of looking elsewhere, it is better to come here together 2fc7a15372 Fixed: #12109 2022-11-16 18:22:11 +08:00
Instead of looking elsewhere, it is better to come here together 9056d48775 Fixed: 12095 2022-11-16 18:16:45 +08:00
Godfrey M 9fefdea9de fixes checkout to all description 2022-11-15 12:50:46 -08:00
snipe da0efaa278 Add @fernando-almeida as a contributor 2022-11-15 17:56:19 +00:00
snipe 69bde0443e Add @lukasfehling as a contributor 2022-11-15 17:56:01 +00:00
snipe 6400bdc266 Merge pull request #12120 from snipe/features/added_deleted_filter_to_search_by_tag
Added ability to include deleted items in tag search endpoint
2022-11-15 17:54:34 +00:00
snipe ffd252a00c Merge pull request #12119 from lukasfehling/feature/added-endpoint-for-user-notification
Added: API endpoint to trigger a user email notification with their assigned assets
2022-11-15 17:51:15 +00:00
snipe 7fcf6f2463 Removed deleted parameter
Signed-off-by: snipe <snipe@snipe.net>
2022-11-15 17:47:21 +00:00
snipe 5103f28598 Merge pull request #12121 from snipe/fixes/safer_file_existance_checking_for_model_files
Replace error suppression with better logic
2022-11-15 17:43:39 +00:00
snipe 60d7128a5e Replace error suppression with better logic
Signed-off-by: snipe <snipe@snipe.net>
2022-11-15 17:41:57 +00:00
snipe 2c5a0d370c Clean up API byserial and bytag, allow deleted param
Signed-off-by: snipe <snipe@snipe.net>
2022-11-15 17:33:56 +00:00
snipe bcbe517446 Added ability to include deleted items in tag search endpoint
Signed-off-by: snipe <snipe@snipe.net>
2022-11-15 17:18:09 +00:00
lukasfehling d9a9bd1c0d Added a api endpoint for sending email notifications to users with their assigned assets 2022-11-15 18:17:51 +01:00
snipe 2166fcec41 Merge pull request #12118 from snipe/features/adds_asset_tag_and_serial_to_api
Allow searching firectly for asset tag and serial
2022-11-15 17:16:17 +00:00
snipe 9a5d431962 Allow searching firectly for asset tag and serial
Signed-off-by: snipe <snipe@snipe.net>
2022-11-15 17:13:26 +00:00
snipe 6dc0846f38 Merge pull request #12117 from snipe/fixes/pr_12106_missing_slash_for_stdClass
Fixes PR #12106 missing slash for std class
2022-11-15 17:04:58 +00:00
snipe 50431c046f Fixed missing slash in stdClass
Signed-off-by: snipe <snipe@snipe.net>
2022-11-15 17:04:06 +00:00
Ivan Nieto Vivanco f0ecab7bb1 Fix typo in variable (ah-hyuck!) 2022-11-15 11:00:40 -06:00
Ivan Nieto Vivanco 7cc8b39863 Checks if settings let URL's be shown in email notifications 2022-11-15 10:55:54 -06:00
snipe ae259f36ae Merge pull request #12106 from fernando-almeida/develop
Fix HTTP AssetTransformer to generate an empty object for missing custom fields
2022-11-15 15:54:43 +00:00
Ivan Nieto Vivanco cd2997b674 Determine if email_logo or logo setting needs to be used in the Forgot Password email 2022-11-15 08:08:26 -06:00
snipe 8122236944 Merge pull request #12096 from snipe/features/add_custom_field_option_to_view_assets
Added custom field option to view assets
2022-11-14 22:45:26 +00:00
snipe 56c4fa7c27 Override display settings if field is encrypted
Signed-off-by: snipe <snipe@snipe.net>
2022-11-14 22:41:31 +00:00
snipe 602c2698d2 Fixed broken table header tag
Signed-off-by: snipe <snipe@snipe.net>
2022-11-14 22:06:23 +00:00
snipe ff0b68724f Merge pull request #12107 from snipe/fixes/500_on_missing_model_file
Fixed 500 error if model files are missing
2022-11-14 22:04:31 +00:00
snipe d4ac7530b6 Removed download button for files that don’t exist on the server
Signed-off-by: snipe <snipe@snipe.net>
2022-11-14 22:04:06 +00:00
snipe 4aded5e117 FIxed 500 error if model files are missing
Signed-off-by: snipe <snipe@snipe.net>
2022-11-14 22:01:33 +00:00
snipe 15da39d44a Merge pull request #12105 from snipe/fixes/500_on_missing_license_files
Fixed 500 on missing license files
2022-11-14 17:44:16 +00:00
snipe 077d343f01 Prevent 500 if license file is missing
Signed-off-by: snipe <snipe@snipe.net>
2022-11-14 17:42:40 +00:00
Fernando Almeida 47ee2a8153 Fix HTTP AssetTransformer to generate an empty object for missing custom_fields instead of an empty array. 2022-11-14 16:31:08 +00:00
snipe ae95ee49f1 Hide the option if the field is encrypted
Signed-off-by: snipe <snipe@snipe.net>
2022-11-10 17:56:50 +00:00
snipe 2ac558494d Set column width instead of letting BS tables guess
Signed-off-by: snipe <snipe@snipe.net>
2022-11-10 17:21:07 +00:00
snipe ede16ad2c2 Removed unused block
Signed-off-by: snipe <snipe@snipe.net>
2022-11-10 17:19:35 +00:00
snipe 1e34398c99 Permissions check on the field itself
Signed-off-by: snipe <snipe@snipe.net>
2022-11-10 17:19:12 +00:00
snipe 7a5fcfb87a Loop through fields array
Signed-off-by: snipe <snipe@snipe.net>
2022-11-10 16:46:59 +00:00
snipe 1fa624420e Removed unneeded relationships
Signed-off-by: snipe <snipe@snipe.net>
2022-11-10 16:46:49 +00:00
snipe 6a9131e771 Merge pull request #12088 from uberbrady/minimal_scim_upgrade
Added new SCIM env vars; and upgraded SCIM library
2022-11-09 19:30:50 +00:00
Brady Wetherington 383bd6bb45 Add new SCIM env vars; upgrade SCIM library 2022-11-09 19:08:15 +00:00
snipe 097821b818 Slight revamping of column layouts and also added new general.display_in_user_view column
Signed-off-by: snipe <snipe@snipe.net>
2022-11-08 15:28:19 +00:00
snipe 2e56c9b521 Added new general.display_in_user_view field to form
Signed-off-by: snipe <snipe@snipe.net>
2022-11-08 15:27:59 +00:00
snipe b95d24b5eb Additional translations
Signed-off-by: snipe <snipe@snipe.net>
2022-11-08 15:27:44 +00:00
snipe f91e1d58ad Migration to add the field to the custom_fields table
Signed-off-by: snipe <snipe@snipe.net>
2022-11-08 15:27:34 +00:00
snipe 7c37c70164 Added new field to allowed_fields so that the API can change them if needed
Signed-off-by: snipe <snipe@snipe.net>
2022-11-08 15:27:22 +00:00
snipe 52dc5aa4ba Added field to controller and tranformer
Signed-off-by: snipe <snipe@snipe.net>
2022-11-08 15:26:59 +00:00
snipe 7c21158680 Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2022-11-03 14:18:13 -07:00
snipe b1fa50cde2 Merge pull request #12067 from snipe/fixes/modelfile_image_path
Fixed model file image path/variable
2022-11-03 14:13:54 -07:00
snipe 236684ec92 Fixed model file image path/variable
Signed-off-by: snipe <snipe@snipe.net>
2022-11-03 14:12:49 -07:00
snipe 53499b1e29 Merge pull request #12066 from snipe/fixes/small_uploads_fixes
Fixed - small uploads fixes
2022-11-03 14:08:52 -07:00
snipe 04b6f023ae Use new upload string
Signed-off-by: snipe <snipe@snipe.net>
2022-11-03 13:57:50 -07:00
snipe 3c7d63c060 Disallow uploads if app is locked
Signed-off-by: snipe <snipe@snipe.net>
2022-11-03 13:52:23 -07:00
snipe 7cb1ca8754 Fixed image path to show preview
Signed-off-by: snipe <snipe@snipe.net>
2022-11-03 13:51:48 -07:00
snipe 6d5ace0458 Merge pull request #12049 from uberbrady/improve_scim_externalid_support
Fixed writes to the `externalId` from SCIM
2022-11-02 15:43:55 -07:00
snipe 6f14355cbc Merge pull request #12060 from snipe/features/added_accessories_file_uploads
Added accessories file uploads
2022-11-01 19:51:38 -07:00
snipe eb81c290dc Accessory file upload
Signed-off-by: snipe <snipe@snipe.net>
2022-11-01 19:50:39 -07:00
snipe 2f9e097854 Merge pull request #12059 from snipe/fixes/consumables_files_translations
Use the generic file uploads strings
2022-11-01 19:32:35 -07:00
snipe 97aeb1fcec Use the generic file uploads strings
Signed-off-by: snipe <snipe@snipe.net>
2022-11-01 19:31:23 -07:00
snipe e6d259bac0 Merge pull request #12058 from snipe/features/added_uploads_to_components
Added uploads to components
2022-11-01 19:30:17 -07:00
snipe 8887d40b86 Added gitignore
Signed-off-by: snipe <snipe@snipe.net>
2022-11-01 19:29:21 -07:00
snipe 3d8e0b707e Fixed component file route controller names
Signed-off-by: snipe <snipe@snipe.net>
2022-11-01 19:29:13 -07:00
snipe 71a7176a6e Updated component blade
Signed-off-by: snipe <snipe@snipe.net>
2022-11-01 19:28:57 -07:00
snipe def89bfa0c Added some generic file translations
Signed-off-by: snipe <snipe@snipe.net>
2022-11-01 19:28:49 -07:00
snipe f1cb7ee410 Fixed some translations
Signed-off-by: snipe <snipe@snipe.net>
2022-11-01 19:28:39 -07:00
snipe 84c0f50266 Added ComponentFilesController
Signed-off-by: snipe <snipe@snipe.net>
2022-11-01 19:10:04 -07:00
snipe f51b312843 Added component routes for uploads
Signed-off-by: snipe <snipe@snipe.net>
2022-11-01 19:09:51 -07:00
snipe 3d3a4b02fc Added helper method for uploads
Signed-off-by: snipe <snipe@snipe.net>
2022-11-01 19:09:34 -07:00
snipe 276f534ded Updated permissions
Signed-off-by: snipe <snipe@snipe.net>
2022-11-01 19:09:21 -07:00
snipe 1d47d9e52b Merge pull request #12057 from snipe/features/add_uploads_to_components
Added uploads to components
2022-11-01 19:07:42 -07:00
snipe 2106b64da6 Fixed some layout issues
Signed-off-by: snipe <snipe@snipe.net>
2022-11-01 19:06:49 -07:00
snipe fa79a6c15f Skip storage:: facade on missing images
Signed-off-by: snipe <snipe@snipe.net>
2022-11-01 18:19:13 -07:00
snipe 761da534f3 Updated consumables UI to allow uploads and display files
Signed-off-by: snipe <snipe@snipe.net>
2022-11-01 17:53:08 -07:00
snipe b362951c95 Added consumables permissions
Signed-off-by: snipe <snipe@snipe.net>
2022-11-01 17:52:45 -07:00
snipe 25f69a7bd2 Added consumable methods for uploads
Signed-off-by: snipe <snipe@snipe.net>
2022-11-01 17:52:28 -07:00
snipe f6a6478804 Added consumable uploads gitignore
Signed-off-by: snipe <snipe@snipe.net>
2022-11-01 17:52:04 -07:00
snipe 3282702c73 Added consumables upload routes
Signed-off-by: snipe <snipe@snipe.net>
2022-11-01 17:51:53 -07:00
Brady Wetherington 4e5c878b73 Needed to fix the way we write externalId from SCIM 2022-10-31 19:15:08 -07:00
snipe a930661150 Check for valid category
Signed-off-by: snipe <snipe@snipe.net>
2022-10-31 12:16:39 -07:00
snipe 7cb4740359 Merge pull request #11766 from snipe/fixes/wtf_method_names_derp
Fixed (?) method name?
2022-10-26 17:39:11 -07:00
snipe d0b9e956df Merge pull request #12042 from snipe/fixes/added_missing_hashed_password_string
Corrected string for invalid current password
2022-10-26 12:20:35 -07:00
snipe c1eee2cc72 Corrected string for invalid current password
Signed-off-by: snipe <snipe@snipe.net>
2022-10-26 12:18:29 -07:00
snipe 73f30c0a41 Merge pull request #12041 from snipe/features/reflect_status_label_color_in_sidenav
Fixed #12009 - Added ability to reflect color in sidenav if one is given
2022-10-26 10:58:19 -07:00
snipe c233d7fb1c Removed extra spaces
Signed-off-by: snipe <snipe@snipe.net>
2022-10-26 10:51:06 -07:00
snipe dea0fcefbd Reflect color in sidenav if one is given
Signed-off-by: snipe <snipe@snipe.net>
2022-10-26 10:48:42 -07:00
snipe 476a5cbc02 Bumped hash
Signed-off-by: snipe <snipe@snipe.net>
2022-10-26 09:49:50 -07:00
snipe 73f61ce032 Merge pull request #12040 from snipe/fixes/locations_asset_count
Renamed column back to assets_count for legacy
2022-10-26 09:43:01 -07:00
snipe 12c7223bcd Renamed column back to assets_count for legacy
Signed-off-by: snipe <snipe@snipe.net>
2022-10-26 09:39:03 -07:00
snipe b7efb58733 Merge pull request #12038 from snipe/fixes/clear_expected_checkin_on_checkin_action
Added - set `expected_checkin` to `null` on user bulk checkin and delete
2022-10-26 00:56:43 -07:00
snipe 28b0d8cf0f Null expected_checkin on user bulk checkin and delete
Signed-off-by: snipe <snipe@snipe.net>
2022-10-26 00:54:37 -07:00
snipe 0bc0a116aa Merge pull request #12035 from snipe/features/added_new_tab_to_locations
Features/added new tab to locations
2022-10-26 00:32:07 -07:00
snipe e670ffe349 Added Assets Assigned to tab
Signed-off-by: snipe <snipe@snipe.net>
2022-10-26 00:16:06 -07:00
snipe a94f1c4a64 Cleaned up and added comments
Signed-off-by: snipe <snipe@snipe.net>
2022-10-26 00:15:52 -07:00
snipe b503b672ba Merge pull request #11951 from Godmartinz/AccessKey_shortcuts
adds shortcuts for listing, creating, and saving
2022-10-25 15:53:57 -07:00
snipe bc023a2566 Add @eltociear as a contributor 2022-10-25 15:46:07 -07:00
snipe 2f7e22be1e Fixed all-contributors type
Signed-off-by: snipe <snipe@snipe.net>
2022-10-25 15:46:07 -07:00
snipe 9409965239 Merge pull request #11928 from eltociear/patch-1
Fix typo in Dockerfile.fpm-alpine
2022-10-25 15:45:42 -07:00
snipe f54c92ade2 Merge pull request #12028 from StarlessNights/feature/add-memcached-php-extensions-to-docker-images
Fixed #12027: Add memcached php extensions to docker images
2022-10-25 15:42:15 -07:00
snipe 9e08936cbc Merge pull request #12030 from uberbrady/scim_externalid_support
Added externalId support to SCIM integration
2022-10-25 14:51:52 -07:00
Brady Wetherington cd385e0865 Set scim_externalid to nullable, default null 2022-10-25 14:38:19 -07:00
Brady Wetherington 1e3281c76c Add externalId support to SCIM integration 2022-10-25 14:19:01 -07:00
Iisakki Jaakkola af4d62759f Added php memcached extension to docker Alpine image. 2022-10-25 16:16:25 +03:00
Iisakki Jaakkola 9452973845 Added php memcached extension to the docker image. 2022-10-25 16:16:25 +03:00
snipe 3b16157d6b Fixed typo
Signed-off-by: snipe <snipe@snipe.net>
2022-10-21 17:43:53 -07:00
snipe ae430959a4 Merge pull request #12015 from snipe/fixes/revert_processing_button
Changed button icon for importer
2022-10-21 17:00:22 -07:00
snipe 85a85082b7 Changed button icon for importer
Signed-off-by: snipe <snipe@snipe.net>
2022-10-21 16:59:19 -07:00
snipe 5acb493efd Merge pull request #12008 from snipe/features/add_default_loc_to_location_view
Added default tab to locations
2022-10-21 16:43:24 -07:00
snipe 515b14a001 Updated JS to better handle input IDs
Signed-off-by: snipe <snipe@snipe.net>
2022-10-20 19:21:09 -07:00
snipe 4eed2baa31 Added default tab to locations
Signed-off-by: snipe <snipe@snipe.net>
2022-10-20 19:06:58 -07:00
snipe 453f2c3b0e Merge pull request #12006 from uberbrady/ldap_manager_cache
Added cache manager lookups in LDAP for performance boost
2022-10-20 17:06:23 -07:00
Brady Wetherington bc78d341a0 Caches manager lookups in LDAP for performance boost 2022-10-20 16:52:40 -07:00
snipe edf191b724 Merge pull request #11995 from uberbrady/ldap_manager_fix
Fixed: Okta LDAP Manager Attribute - Try to better-handle LDAP Manager settings
2022-10-19 19:04:10 -07:00
Brady Wetherington 12d86bd6e2 Erroneous line-break removal - re-add 2022-10-19 19:01:52 -07:00
Brady Wetherington c4f11de90d Remove incorrect comment. 2022-10-19 18:49:19 -07:00
Brady Wetherington 8fb61cf5f8 Try to better handle LDAP Manager settings that don't line up with what we expect 2022-10-19 18:36:16 -07:00
Godfrey M f2d4a61e3c removes dead space 2022-10-18 15:31:37 -07:00
Godfrey M 3f25a1bf61 removes dead code 2022-10-18 15:25:38 -07:00
Godfrey M f9ac447dd1 adds default group to LDAP 2022-10-18 15:18:09 -07:00
snipe 23e613f903 Fixed kit parse error on model edit
Signed-off-by: snipe <snipe@snipe.net>
2022-10-18 15:00:33 -07:00
snipe f1c82ca732 Merge pull request #11988 from snipe/fixes/wrong_icons_for_mobile_location_view
Fixed wrong icons for mobile view for locations listing
2022-10-17 20:14:01 -07:00
snipe 2543fa6b98 Fixed user icon for tab
Signed-off-by: snipe <snipe@snipe.net>
2022-10-17 20:04:42 -07:00
snipe 7c34652da0 Fixed incorrect icons for mobile view on location tabs
Signed-off-by: snipe <snipe@snipe.net>
2022-10-17 20:02:27 -07:00
snipe 1ec303931a Merge pull request #11986 from Godmartinz/FD31357_depreciation
Fixes the calc of months and fixes typo of the word depreciation
2022-10-17 14:44:46 -07:00
Godfrey M d359bcb88d adds proper spacing 2022-10-17 13:15:10 -07:00
Godfrey M 28059c878a gets the proper amount of months and fixes typo of the word depreciation 2022-10-17 11:16:29 -07:00
snipe b7bcfaccc9 Merge pull request #11834 from uberbrady/try_catch_notifications
try/catch wrap notifications on checkin/checkout
2022-10-13 14:20:22 -07:00
snipe 0303df4b25 Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2022-10-13 13:19:51 -07:00
snipe 8c6aaec9ce Merge pull request #11971 from snipe/localization/new_translations
Added new translations
2022-10-13 13:06:16 -07:00
snipe fb228d6ded Updated strings
Signed-off-by: snipe <snipe@snipe.net>
2022-10-13 12:57:10 -07:00
snipe 1360ce90a5 Updated strings
Signed-off-by: snipe <snipe@snipe.net>
2022-10-13 12:52:45 -07:00
snipe 3549afe157 Added strings
Signed-off-by: snipe <snipe@snipe.net>
2022-10-13 12:43:24 -07:00
snipe cfb780b20b Remove unused files
Signed-off-by: snipe <snipe@snipe.net>
2022-10-13 12:39:10 -07:00
snipe eb9f17122e Updated strings
Signed-off-by: snipe <snipe@snipe.net>
2022-10-13 12:21:09 -07:00
snipe 2ef45afb2b Removed extraneous files
Signed-off-by: snipe <snipe@snipe.net>
2022-10-13 12:18:57 -07:00
snipe ecc6bd8a24 Updated dev assets
Signed-off-by: snipe <snipe@snipe.net>
2022-10-12 16:24:31 -07:00
snipe 80279a95ae Merge pull request #11964 from snipe/fixes/audit_admin_presenting
Use admin ID for audit log notification
2022-10-12 16:00:50 -07:00
snipe ac055c01dc Use admin ID for audit log notification
Signed-off-by: snipe <snipe@snipe.net>
2022-10-12 15:59:43 -07:00
snipe 5ff72420a6 Set branch back to develop
I hads to switch branches because the automated GH action script always targets masterb

Signed-off-by: snipe <snipe@snipe.net>
2022-10-12 11:00:06 -07:00
snipe 55b33c1042 Merge pull request #11944 from snipe/dependabot/github_actions/actions/checkout-3.1.0
Bump actions/checkout from 2 to 3.1.0
2022-10-12 10:59:21 -07:00
snipe a499a92bb7 Added @nh314 as a contributor
Signed-off-by: snipe <snipe@snipe.net>
2022-10-12 10:57:50 -07:00
snipe e7ae7742b0 Merge pull request #11949 from nh314/Remove-required-mark
Remove required mark
2022-10-12 10:55:49 -07:00
snipe 98f2e0271b Merge pull request #11942 from nh314/develop
Correct comparison logic
2022-10-12 10:55:29 -07:00
snipe cd43fc50fb Merge pull request #11960 from snipe/fixes/better_validation_for_ldap_filter
Sets nullable attribute on validation
2022-10-12 10:53:08 -07:00
snipe 06803092c5 Merge pull request #11952 from snipe/features/clearer_activated_helptext
Added clearer LDAP activated helptext
2022-10-12 10:52:56 -07:00
snipe 0312ecf09d Sets nullable attribute on validation
Signed-off-by: snipe <snipe@snipe.net>
2022-10-12 10:30:47 -07:00
snipe 3f105cd3b2 Merge pull request #11959 from inietov/fixes/depreciation_date
Fixed Depreciation date diff readable precision
2022-10-12 10:21:37 -07:00
Ivan Nieto Vivanco ab0c5bcd9d Add precision parameter to the diffForHumans() Carbon function to report 2022-10-12 12:16:13 -05:00
snipe 5ba01728d9 More text tweaking
Signed-off-by: snipe <snipe@snipe.net>
2022-10-11 12:51:25 -07:00
snipe ae0eb378e4 Additional clarification
Signed-off-by: snipe <snipe@snipe.net>
2022-10-11 12:43:54 -07:00
snipe ad8a2387f0 Updated help text to be more clear
Signed-off-by: snipe <snipe@snipe.net>
2022-10-11 12:38:37 -07:00
Godfrey M 4fa01350c3 adds shortcuts for listing, creating, and saving 2022-10-11 12:00:15 -07:00
Phan Nguyen d3161fad02 Remove required mark
Because it actually not required by model.
2022-10-11 15:49:56 +07:00
dependabot[bot] 36eb51b52f Bump actions/checkout from 2 to 3.1.0
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.1.0.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v3.1.0)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-10 08:36:34 +00:00
Phan Nguyen 8ff109e9da Correct comparison logic
Comparison operator should be greater than or equal
2022-10-08 12:54:15 +07:00
snipe 15da3b831d Merge pull request #11937 from Godmartinz/gh11868_sidebar_unclickable
Fixes the margin top adjustment for desktop
2022-10-06 10:43:27 -07:00
Godfrey M 0c6441ebed removes the margin top adjustment for desktop 2022-10-06 10:35:28 -07:00
snipe fbfc9d123c Merge remote-tracking branch 'origin/develop' 2022-10-06 09:26:07 -07:00
snipe cd942196cc Merge pull request #11933 from inietov/fixes/500_creating_new_user_undefined_variable_item
Fixed Error 500 undefined variable item creating a new user.
2022-10-06 09:07:18 -07:00
Ivan Nieto Vivanco f1edbc9810 Send item variable that the datepicker needs 2022-10-06 09:15:00 -05:00
Ikko Ashimine 66e64cb136 Fix typo in Dockerfile.fpm-alpine
enviroment -> environment
2022-10-06 11:53:13 +09:00
snipe 1ef3eb94db Merge remote-tracking branch 'origin/develop' 2022-10-05 17:55:33 -07:00
snipe 25e4b7d59d Merge pull request #11927 from uberbrady/use_improved_scim
Use the new scim-trace feature from our fork of laravel-scim-server lib
2022-10-05 17:53:20 -07:00
Brady Wetherington 9605dec22a Use the new scim-trace feature from our fork of laravel-scim-server lib 2022-10-05 17:43:59 -07:00
snipe ca937667b4 Indented divs per @uberbrady
Signed-off-by: snipe <snipe@snipe.net>
2022-10-05 17:21:39 -07:00
snipe e9c61903f1 Merge pull request #11926 from snipe/features/add_start_and_term_dates_to_users
Added start and end dates to users
2022-10-05 17:20:37 -07:00
snipe 14b7319b63 Added start/end to sortable columns
Signed-off-by: snipe <snipe@snipe.net>
2022-10-05 17:07:07 -07:00
snipe 9d641573b5 Make the APU return null instead of blank
Signed-off-by: snipe <snipe@snipe.net>
2022-10-05 17:01:04 -07:00
snipe 3605aa8f5a Added clear button to generic datepicker and made it wider
Signed-off-by: snipe <snipe@snipe.net>
2022-10-05 16:59:06 -07:00
snipe 0817308822 Added start/end to edit/view screens
Signed-off-by: snipe <snipe@snipe.net>
2022-10-05 16:58:49 -07:00
snipe bdfac1a345 Added start/end to the users API
Signed-off-by: snipe <snipe@snipe.net>
2022-10-05 16:58:37 -07:00
snipe f7a9be92ca Store data for start and end
Signed-off-by: snipe <snipe@snipe.net>
2022-10-05 16:58:26 -07:00
snipe 56ba8a7e24 Added API select fields and filters
Signed-off-by: snipe <snipe@snipe.net>
2022-10-05 16:58:16 -07:00
snipe cf62761d18 Added date casting and fillable to models
Signed-off-by: snipe <snipe@snipe.net>
2022-10-05 16:57:59 -07:00
snipe d23e178c62 Adde language strings
Signed-off-by: snipe <snipe@snipe.net>
2022-10-05 16:56:10 -07:00
snipe 7353ecd388 Added start_date and end_date migration to users table
Signed-off-by: snipe <snipe@snipe.net>
2022-10-05 16:55:59 -07:00
snipe 18663c2599 Merge pull request #11925 from inietov/fixes/checkbox_customfields_comma_issues
Fixed #11710 - Validation of checkbox data with multiple values
2022-10-05 16:48:32 -07:00
Ivan Nieto Vivanco 5b8e0b3af1 Use a regex (gulp) to admit ',' (comma) and ', '(comma plus space) as customfields checkbox value delimiter 2022-10-05 18:40:07 -05:00
snipe dab83091d2 Merge remote-tracking branch 'origin/develop' 2022-10-05 12:12:27 -07:00
snipe 4c0be7ec98 Merge pull request #11924 from snipe/features/autoglossonym_locales
Added autoglossonyms for locales and translations for countries
2022-10-05 12:09:29 -07:00
snipe 018f71a157 Switched to translations for better autoglossonym support
Signed-off-by: snipe <snipe@snipe.net>
2022-10-05 11:46:42 -07:00
snipe 9f03f0f6f6 Updated link
Signed-off-by: snipe <snipe@snipe.net>
2022-10-04 23:39:47 -07:00
snipe da40c0ad48 Dev assets
Signed-off-by: snipe <snipe@snipe.net>
2022-10-04 18:09:18 -07:00
snipe c70c8ce856 Merge pull request #11916 from Godmartinz/gh11868_sidebar_unclickable
fixes mobile views and clickability of sidebar menu
2022-10-04 18:07:02 -07:00
snipe fe49ac79d1 Updated all contributors
Signed-off-by: snipe <snipe@snipe.net>
2022-10-04 18:06:09 -07:00
Godfrey M e21660ae05 off by a pixel 2022-10-04 12:11:37 -07:00
Godfrey M 53392d6069 fixes mobile views and clickability of sidebar menu 2022-10-04 12:01:13 -07:00
Brady Wetherington 1899e4d1e8 try/catch wrap notifications on checkin/checkout 2022-09-15 13:18:42 -07:00
Godfrey M 9b448227f7 tinkering to no avail 2022-09-13 11:40:10 -07:00
Godfrey M 28bc97f29f one line away from this being over with 2022-09-12 11:40:16 -07:00
snipe ae505ef44d Literally have no idea how this ever worked
Signed-off-by: snipe <snipe@snipe.net>
2022-08-31 19:20:35 -07:00
Godfrey M 193b31e427 select options working, testing sync then done 2022-08-31 12:58:33 -07:00
Godfrey M 70ac8af9c4 . 2022-08-31 09:53:20 -07:00
Godfrey M 0c362e8b57 gets the groups selector to appear but options are blank 2022-08-29 12:09:56 -07:00
Godfrey M fc6fefdb4e adds migration, variables, checkbox,working on groups 2022-08-25 15:19:38 -07:00
Tobias Regnery 1a908e361e Make locations deletable for non Superuser-Accounts with FullMultipleCompanySupport
locations->isDeletable() checks via gate::allows if a locations is deletable.
This calls SnipePermissionsPolicy->before() and checks for !Company::isCurrentUserHasAccess($item).
This returns false because locations don't have a company_id.

Check for this and return true if the item don't have a company_id.
2021-07-29 10:43:01 +02:00
410 changed files with 23298 additions and 1309 deletions
+91 -1
View File
@@ -2736,7 +2736,97 @@
"avatar_url": "https://avatars.githubusercontent.com/u/111710123?v=4",
"profile": "https://github.com/Vautia",
"contributions": [
"security"
"code"
]
},
{
"login": "chartjes",
"name": "Chris Hartjes",
"avatar_url": "https://avatars.githubusercontent.com/u/28321?v=4",
"profile": "http://www.littlehart.net/atthekeyboard",
"contributions": [
"code"
]
},
{
"login": "geo-chen",
"name": "geo-chen",
"avatar_url": "https://avatars.githubusercontent.com/u/2404584?v=4",
"profile": "https://github.com/geo-chen",
"contributions": [
"code"
]
},
{
"login": "nh314",
"name": "Phan Nguyen",
"avatar_url": "https://avatars.githubusercontent.com/u/6006620?v=4",
"profile": "https://github.com/nh314",
"contributions": [
"code"
]
},
{
"login": "StarlessNights",
"name": "Iisakki Jaakkola",
"avatar_url": "https://avatars.githubusercontent.com/u/115993812?v=4",
"profile": "https://github.com/StarlessNights",
"contributions": [
"code"
]
},
{
"login": "eltociear",
"name": "Ikko Ashimine",
"avatar_url": "https://avatars.githubusercontent.com/u/22633385?v=4",
"profile": "https://bandism.net/",
"contributions": [
"code"
]
},
{
"login": "lukasfehling",
"name": "Lukas Fehling",
"avatar_url": "https://avatars.githubusercontent.com/u/56871540?v=4",
"profile": "https://github.com/lukasfehling",
"contributions": [
"code"
]
},
{
"login": "fernando-almeida",
"name": "Fernando Almeida",
"avatar_url": "https://avatars.githubusercontent.com/u/1975990?v=4",
"profile": "https://github.com/fernando-almeida",
"contributions": [
"code"
]
},
{
"login": "akemidx",
"name": "akemidx",
"avatar_url": "https://avatars.githubusercontent.com/u/116301219?v=4",
"profile": "https://github.com/akemidx",
"contributions": [
"code"
]
},
{
"login": "oguzbilgic",
"name": "Oguz Bilgic",
"avatar_url": "https://avatars.githubusercontent.com/u/144778?v=4",
"profile": "http://oguz.site",
"contributions": [
"code"
]
},
{
"login": "scoo73r",
"name": "Scooter Crawford",
"avatar_url": "https://avatars.githubusercontent.com/u/9262438?v=4",
"profile": "https://github.com/scoo73r",
"contributions": [
"code"
]
}
]
+6
View File
@@ -174,3 +174,9 @@ REPORT_TIME_LIMIT=12000
REQUIRE_SAML=false
API_THROTTLE_PER_MINUTE=120
CSV_ESCAPE_FORMULAS=true
# --------------------------------------------
# OPTIONAL: SCIM
# --------------------------------------------
SCIM_TRACE=false
SCIM_STANDARDS_COMPLIANCE=false
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
language: [ 'javascript' ]
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v3.1.0
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
+1 -1
View File
@@ -32,7 +32,7 @@ jobs:
steps:
# Checkout the repository to the GitHub Actions runner
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v3.1.0
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
- name: Run Codacy Analysis CLI
+1 -1
View File
@@ -41,7 +41,7 @@ jobs:
steps:
# https://github.com/actions/checkout
- name: Checkout codebase
uses: actions/checkout@v2
uses: actions/checkout@v3.1.0
# https://github.com/docker/setup-buildx-action
- name: Setup Docker Buildx
+1 -1
View File
@@ -41,7 +41,7 @@ jobs:
steps:
# https://github.com/actions/checkout
- name: Checkout codebase
uses: actions/checkout@v2
uses: actions/checkout@v3.1.0
# https://github.com/docker/setup-buildx-action
- name: Setup Docker Buildx
+2 -1
View File
@@ -24,6 +24,7 @@ php7.4-mbstring \
php7.4-zip \
php7.4-bcmath \
php7.4-redis \
php-memcached \
patch \
curl \
wget \
@@ -139,4 +140,4 @@ RUN chmod +x /startup.sh /usr/bin/supervisor-exit-event-listener
CMD ["/startup.sh"]
EXPOSE 80
EXPOSE 443
EXPOSE 443
+2 -1
View File
@@ -28,6 +28,7 @@ RUN apk add --no-cache \
php7-xmlreader \
php7-sodium \
php7-redis \
php7-pecl-memcached \
curl \
wget \
vim \
@@ -85,4 +86,4 @@ ENTRYPOINT ["/sbin/tini", "--"]
CMD ["/entrypoint.sh"]
EXPOSE 80
EXPOSE 80
+3 -3
View File
@@ -75,14 +75,14 @@ RUN set -eux; \
rm snipeit.tar.gz; \
# Install composer php dependencies
if [ "$ENVIRONMENT" = "production" ]; then \
echo "production enviroment detected!"; \
echo "production environment detected!"; \
composer update \
--no-cache \
--no-dev \
--optimize-autoloader \
--working-dir=/var/www/html; \
else \
echo "development enviroment detected!"; \
echo "development environment detected!"; \
apk add --no-cache \
${DEV_PACKAGES}; \
composer update \
@@ -100,4 +100,4 @@ 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" ]
CMD [ "/usr/local/bin/docker-php-entrypoint", "php-fpm" ]
+5 -3
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-300-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-311-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
@@ -59,7 +59,7 @@ Since the release of the JSON REST API, several third-party developers have been
- [SnipeSharp - .NET module in C#](https://github.com/barrycarey/SnipeSharp) by [@barrycarey](https://github.com/barrycarey)
- [InQRy -unmaintained-](https://github.com/Microsoft/InQRy) by [@Microsoft](https://github.com/Microsoft)
- [SnipeitPS](https://github.com/snazy2000/SnipeitPS) by [@snazy2000](https://github.com/snazy2000) - Powershell API Wrapper for Snipe-it
- [jamf2snipe](https://github.com/ParadoxGuitarist/jamf2snipe) by [@ParadoxGuitarist](https://github.com/ParadoxGuitarist) - Python script to sync assets between a JAMFPro instance and a Snipe-IT instance
- [jamf2snipe](https://github.com/grokability/jamf2snipe) - Python script to sync assets between a JAMFPro instance and a Snipe-IT instance
- [Marksman](https://github.com/Scope-IT/marksman) - A Windows agent for Snipe-IT
- [Snipe-IT plugin for Jira Service Desk](https://marketplace.atlassian.com/apps/1220964/snipe-it-for-jira)
- [Python 3 CSV importer](https://github.com/gastamper/snipeit-csvimporter) - allows importing assets into Snipe-IT based on Item Name rather than Asset Tag.
@@ -137,7 +137,9 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
| [<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/88776392?v=4" width="110px;"/><br /><sub>PlaneNuts</sub>](https://github.com/PlaneNuts)<br />[💻](https://github.com/snipe/snipe-it/commits?author=PlaneNuts "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/38761237?v=4" width="110px;"/><br /><sub>Alex Janes</sub>](https://adagiohealth.org)<br />[💻](https://github.com/snipe/snipe-it/commits?author=adagioajanes "Code") | [<img src="https://avatars.githubusercontent.com/u/32387849?v=4" width="110px;"/><br /><sub>Nuraeil</sub>](https://github.com/nuraeil)<br />[💻](https://github.com/snipe/snipe-it/commits?author=nuraeil "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/9415391?v=4" width="110px;"/><br /><sub>waffle</sub>](https://ditisjens.be/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=insert-waffle "Code") | [<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") | [<img src="https://avatars.githubusercontent.com/u/3839381?v=4" width="110px;"/><br /><sub>Achmad Fienan Rahardianto</sub>](https://github.com/veenone)<br />[💻](https://github.com/snipe/snipe-it/commits?author=veenone "Code") | [<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") |
| [<img src="https://avatars.githubusercontent.com/u/97299851?v=4" width="110px;"/><br /><sub>Christian Weirich</sub>](https://github.com/chrisweirich)<br />[💻](https://github.com/snipe/snipe-it/commits?author=chrisweirich "Code") | [<img src="https://avatars.githubusercontent.com/u/1294403?v=4" width="110px;"/><br /><sub>denzfarid</sub>](https://github.com/denzfarid)<br /> | [<img src="https://avatars.githubusercontent.com/u/94018771?v=4" width="110px;"/><br /><sub>ntbutler-nbcs</sub>](https://github.com/ntbutler-nbcs)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ntbutler-nbcs "Code") | [<img src="https://avatars.githubusercontent.com/u/172697?v=4" width="110px;"/><br /><sub>Naveen</sub>](https://naveensrinivasan.dev)<br />[💻](https://github.com/snipe/snipe-it/commits?author=naveensrinivasan "Code") | [<img src="https://avatars.githubusercontent.com/u/55674383?v=4" width="110px;"/><br /><sub>Mike Roquemore</sub>](https://github.com/mikeroq)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mikeroq "Code") | [<img src="https://avatars.githubusercontent.com/u/7991086?v=4" width="110px;"/><br /><sub>Daniel Reeder</sub>](https://github.com/reederda)<br />[🌍](#translation-reederda "Translation") [🌍](#translation-reederda "Translation") [💻](https://github.com/snipe/snipe-it/commits?author=reederda "Code") | [<img src="https://avatars.githubusercontent.com/u/109422491?v=4" width="110px;"/><br /><sub>vickyjaura183</sub>](https://github.com/vickyjaura183)<br />[💻](https://github.com/snipe/snipe-it/commits?author=vickyjaura183 "Code") |
| [<img src="https://avatars.githubusercontent.com/u/32363424?v=4" width="110px;"/><br /><sub>Peace</sub>](https://github.com/julian-piehl)<br />[💻](https://github.com/snipe/snipe-it/commits?author=julian-piehl "Code") | [<img src="https://avatars.githubusercontent.com/u/231528?v=4" width="110px;"/><br /><sub>Kyle Gordon</sub>](https://github.com/kylegordon)<br />[💻](https://github.com/snipe/snipe-it/commits?author=kylegordon "Code") | [<img src="https://avatars.githubusercontent.com/u/53009155?v=4" width="110px;"/><br /><sub>Katharina Drexel</sub>](http://www.bfh.ch)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sunflowerbofh "Code") | [<img src="https://avatars.githubusercontent.com/u/1931963?v=4" width="110px;"/><br /><sub>David Sferruzza</sub>](https://david.sferruzza.fr/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=dsferruzza "Code") | [<img src="https://avatars.githubusercontent.com/u/19511639?v=4" width="110px;"/><br /><sub>Rick Nelson</sub>](https://github.com/rnelsonee)<br />[💻](https://github.com/snipe/snipe-it/commits?author=rnelsonee "Code") | [<img src="https://avatars.githubusercontent.com/u/94169344?v=4" width="110px;"/><br /><sub>BasO12</sub>](https://github.com/BasO12)<br />[💻](https://github.com/snipe/snipe-it/commits?author=BasO12 "Code") |
| [<img src="https://avatars.githubusercontent.com/u/32363424?v=4" width="110px;"/><br /><sub>Peace</sub>](https://github.com/julian-piehl)<br />[💻](https://github.com/snipe/snipe-it/commits?author=julian-piehl "Code") | [<img src="https://avatars.githubusercontent.com/u/231528?v=4" width="110px;"/><br /><sub>Kyle Gordon</sub>](https://github.com/kylegordon)<br />[💻](https://github.com/snipe/snipe-it/commits?author=kylegordon "Code") | [<img src="https://avatars.githubusercontent.com/u/53009155?v=4" width="110px;"/><br /><sub>Katharina Drexel</sub>](http://www.bfh.ch)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sunflowerbofh "Code") | [<img src="https://avatars.githubusercontent.com/u/1931963?v=4" width="110px;"/><br /><sub>David Sferruzza</sub>](https://david.sferruzza.fr/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=dsferruzza "Code") | [<img src="https://avatars.githubusercontent.com/u/19511639?v=4" width="110px;"/><br /><sub>Rick Nelson</sub>](https://github.com/rnelsonee)<br />[💻](https://github.com/snipe/snipe-it/commits?author=rnelsonee "Code") | [<img src="https://avatars.githubusercontent.com/u/94169344?v=4" width="110px;"/><br /><sub>BasO12</sub>](https://github.com/BasO12)<br />[💻](https://github.com/snipe/snipe-it/commits?author=BasO12 "Code") | [<img src="https://avatars.githubusercontent.com/u/111710123?v=4" width="110px;"/><br /><sub>Vautia</sub>](https://github.com/Vautia)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Vautia "Code") |
| [<img src="https://avatars.githubusercontent.com/u/28321?v=4" width="110px;"/><br /><sub>Chris Hartjes</sub>](http://www.littlehart.net/atthekeyboard)<br />[💻](https://github.com/snipe/snipe-it/commits?author=chartjes "Code") | [<img src="https://avatars.githubusercontent.com/u/2404584?v=4" width="110px;"/><br /><sub>geo-chen</sub>](https://github.com/geo-chen)<br />[💻](https://github.com/snipe/snipe-it/commits?author=geo-chen "Code") | [<img src="https://avatars.githubusercontent.com/u/6006620?v=4" width="110px;"/><br /><sub>Phan Nguyen</sub>](https://github.com/nh314)<br />[💻](https://github.com/snipe/snipe-it/commits?author=nh314 "Code") | [<img src="https://avatars.githubusercontent.com/u/115993812?v=4" width="110px;"/><br /><sub>Iisakki Jaakkola</sub>](https://github.com/StarlessNights)<br />[💻](https://github.com/snipe/snipe-it/commits?author=StarlessNights "Code") | [<img src="https://avatars.githubusercontent.com/u/22633385?v=4" width="110px;"/><br /><sub>Ikko Ashimine</sub>](https://bandism.net/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=eltociear "Code") | [<img src="https://avatars.githubusercontent.com/u/56871540?v=4" width="110px;"/><br /><sub>Lukas Fehling</sub>](https://github.com/lukasfehling)<br />[💻](https://github.com/snipe/snipe-it/commits?author=lukasfehling "Code") | [<img src="https://avatars.githubusercontent.com/u/1975990?v=4" width="110px;"/><br /><sub>Fernando Almeida</sub>](https://github.com/fernando-almeida)<br />[💻](https://github.com/snipe/snipe-it/commits?author=fernando-almeida "Code") |
| [<img src="https://avatars.githubusercontent.com/u/116301219?v=4" width="110px;"/><br /><sub>akemidx</sub>](https://github.com/akemidx)<br />[💻](https://github.com/snipe/snipe-it/commits?author=akemidx "Code") | [<img src="https://avatars.githubusercontent.com/u/144778?v=4" width="110px;"/><br /><sub>Oguz Bilgic</sub>](http://oguz.site)<br />[💻](https://github.com/snipe/snipe-it/commits?author=oguzbilgic "Code") | [<img src="https://avatars.githubusercontent.com/u/9262438?v=4" width="110px;"/><br /><sub>Scooter Crawford</sub>](https://github.com/scoo73r)<br />[💻](https://github.com/snipe/snipe-it/commits?author=scoo73r "Code") |
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
+2 -2
View File
@@ -148,7 +148,7 @@
"image": "heroku/php",
"addons": [
"cleardb:ignite",
"heroku-redis:hobby-dev",
"heroku-redis:mini",
"papertrail:choklad"
]
}
}
@@ -22,7 +22,7 @@ class CheckoutLicenseToAllUsers extends Command
*
* @var string
*/
protected $description = 'Command description';
protected $description = 'Checks out licenses to all users';
/**
* Create a new command instance.
+48 -13
View File
@@ -3,6 +3,7 @@
namespace App\Console\Commands;
use App\Models\Department;
use App\Models\Group;
use Illuminate\Console\Command;
use App\Models\Setting;
use App\Models\Ldap;
@@ -57,6 +58,7 @@ class LdapSync extends Command
$ldap_result_country = Setting::getSettings()->ldap_country;
$ldap_result_dept = Setting::getSettings()->ldap_dept;
$ldap_result_manager = Setting::getSettings()->ldap_manager;
$ldap_default_group = Setting::getSettings()->ldap_default_group;
try {
$ldapconn = Ldap::connectToLdap();
@@ -175,6 +177,8 @@ class LdapSync extends Command
$tmp_pass = substr(str_shuffle('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'), 0, 20);
$pass = bcrypt($tmp_pass);
$manager_cache = [];
for ($i = 0; $i < $results['count']; $i++) {
$item = [];
$item['username'] = isset($results[$i][$ldap_result_username][0]) ? $results[$i][$ldap_result_username][0] : '';
@@ -190,6 +194,7 @@ class LdapSync extends Command
$item['department'] = isset($results[$i][$ldap_result_dept][0]) ? $results[$i][$ldap_result_dept][0] : '';
$item['manager'] = isset($results[$i][$ldap_result_manager][0]) ? $results[$i][$ldap_result_manager][0] : '';
$department = Department::firstOrCreate([
'name' => $item['department'],
]);
@@ -216,21 +221,50 @@ class LdapSync extends Command
$user->country = $item['country'];
$user->department_id = $department->id;
if($ldap_default_group != null) {
$default = Group::select()->where('id', $ldap_default_group)->first();
$user->permissions = $default->permissions;
}
if($item['manager'] != null) {
// Get the LDAP Manager
$ldap_manager = Ldap::findLdapUsers($item['manager'], -1, $this->option('filter'));
if($ldap_manager["count"] > 0) {
// Get the Managers username
$ldapManagerUsername = $ldap_manager[0][$ldap_result_username][0];
// Get User from Manager username.
$ldap_manager = User::where('username', $ldapManagerUsername)->first();
if ( $ldap_manager && isset($ldap_manager->id) ) {
// Link user to manager id.
$user->manager_id = $ldap_manager->id;
// Check Cache first
if (isset($manager_cache[$item['manager']])) {
// found in cache; use that and avoid extra lookups
$user->manager_id = $manager_cache[$item['manager']];
} else {
// Get the LDAP Manager
try {
$ldap_manager = Ldap::findLdapUsers($item['manager'], -1, $this->option('filter'));
} catch (\Exception $e) {
\Log::warning("Manager lookup caused an exception: " . $e->getMessage() . ". Falling back to direct username lookup");
// Hail-mary for Okta manager 'shortnames' - will only work if
// Okta configuration is using full email-address-style usernames
$ldap_manager = [
"count" => 1,
0 => [
$ldap_result_username => [$item['manager']]
]
];
}
if ($ldap_manager["count"] > 0) {
// Get the Manager's username
// PHP LDAP returns every LDAP attribute as an array, and 90% of the time it's an array of just one item. But, hey, it's an array.
$ldapManagerUsername = $ldap_manager[0][$ldap_result_username][0];
// Get User from Manager username.
$ldap_manager = User::where('username', $ldapManagerUsername)->first();
if ($ldap_manager && isset($ldap_manager->id)) {
// Link user to manager id.
$user->manager_id = $ldap_manager->id;
}
}
$manager_cache[$item['manager']] = $ldap_manager && isset($ldap_manager->id) ? $ldap_manager->id : null; // Store results in cache, even if 'failed'
}
}
@@ -302,6 +336,7 @@ class LdapSync extends Command
if ($user->save()) {
$item['note'] = $item['createorupdate'];
$item['status'] = 'success';
} else {
foreach ($user->getErrors()->getMessages() as $key => $err) {
$errors .= $err[0];
+21
View File
@@ -12,6 +12,7 @@ use App\Models\Statuslabel;
use Crypt;
use Illuminate\Contracts\Encryption\DecryptException;
use Image;
use Carbon\Carbon;
class Helper
{
@@ -1125,5 +1126,25 @@ class Helper
return $settings;
}
public static function AgeFormat($date) {
$year = Carbon::parse($date)
->diff(now())->y;
$month = Carbon::parse($date)
->diff(now())->m;
$days = Carbon::parse($date)
->diff(now())->d;
$age='';
if ($year) {
$age .= $year.'y ';
}
if ($month) {
$age .= $month.'m ';
}
if ($days) {
$age .= $days.'d';
}
return $age;
}
}
@@ -0,0 +1,186 @@
<?php
namespace App\Http\Controllers\Accessories;
use App\Helpers\StorageHelper;
use App\Http\Controllers\Controller;
use App\Http\Requests\AssetFileRequest;
use App\Models\Actionlog;
use App\Models\Accessory;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Storage;
use Symfony\Accessory\HttpFoundation\JsonResponse;
use enshrined\svgSanitize\Sanitizer;
class AccessoriesFilesController extends Controller
{
/**
* Validates and stores files associated with a accessory.
*
* @todo Switch to using the AssetFileRequest form request validator.
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @param AssetFileRequest $request
* @param int $accessoryId
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function store(AssetFileRequest $request, $accessoryId = null)
{
if (config('app.lock_passwords')) {
return redirect()->route('accessories.show', ['accessory'=>$accessoryId])->with('error', trans('general.feature_disabled'));
}
$accessory = Accessory::find($accessoryId);
if (isset($accessory->id)) {
$this->authorize('accessories.files', $accessory);
if ($request->hasFile('file')) {
if (! Storage::exists('private_uploads/accessories')) {
Storage::makeDirectory('private_uploads/accessories', 775);
}
foreach ($request->file('file') as $file) {
$extension = $file->getClientOriginalExtension();
$file_name = 'accessory-'.$accessory->id.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
// Check for SVG and sanitize it
if ($extension == 'svg') {
\Log::debug('This is an SVG');
\Log::debug($file_name);
$sanitizer = new Sanitizer();
$dirtySVG = file_get_contents($file->getRealPath());
$cleanSVG = $sanitizer->sanitize($dirtySVG);
try {
Storage::put('private_uploads/accessories/'.$file_name, $cleanSVG);
} catch (\Exception $e) {
\Log::debug('Upload no workie :( ');
\Log::debug($e);
}
} else {
Storage::put('private_uploads/accessories/'.$file_name, file_get_contents($file));
}
//Log the upload to the log
$accessory->logUpload($file_name, e($request->input('notes')));
}
return redirect()->route('accessories.show', $accessory->id)->with('success', trans('general.file_upload_success'));
}
return redirect()->route('accessories.show', $accessory->id)->with('error', trans('general.no_files_uploaded'));
}
// Prepare the error message
return redirect()->route('accessories.index')
->with('error', trans('general.file_does_not_exist'));
}
/**
* Deletes the selected accessory file.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @param int $accessoryId
* @param int $fileId
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function destroy($accessoryId = null, $fileId = null)
{
$accessory = Accessory::find($accessoryId);
// the asset is valid
if (isset($accessory->id)) {
$this->authorize('update', $accessory);
$log = Actionlog::find($fileId);
// Remove the file if one exists
if (Storage::exists('accessories/'.$log->filename)) {
try {
Storage::delete('accessories/'.$log->filename);
} catch (\Exception $e) {
\Log::debug($e);
}
}
$log->delete();
return redirect()->back()
->with('success', trans('admin/hardware/message.deletefile.success'));
}
// Redirect to the licence management page
return redirect()->route('accessories.index')->with('error', trans('general.file_does_not_exist'));
}
/**
* Allows the selected file to be viewed.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.4]
* @param int $accessoryId
* @param int $fileId
* @return \Symfony\Accessory\HttpFoundation\Response
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function show($accessoryId = null, $fileId = null, $download = true)
{
\Log::debug('Private filesystem is: '.config('filesystems.default'));
$accessory = Accessory::find($accessoryId);
// the accessory is valid
if (isset($accessory->id)) {
$this->authorize('view', $accessory);
$this->authorize('accessories.files', $accessory);
if (! $log = Actionlog::find($fileId)) {
return response('No matching record for that asset/file', 500)
->header('Content-Type', 'text/plain');
}
$file = 'private_uploads/accessories/'.$log->filename;
if (Storage::missing($file)) {
\Log::debug('FILE DOES NOT EXISTS for '.$file);
\Log::debug('URL should be '.Storage::url($file));
return response('File '.$file.' ('.Storage::url($file).') not found on server', 404)
->header('Content-Type', 'text/plain');
} else {
// We have to override the URL stuff here, since local defaults in Laravel's Flysystem
// won't work, as they're not accessible via the web
if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer?
return StorageHelper::downloader($file);
} else {
if ($download != 'true') {
\Log::debug('display the file');
if ($contents = file_get_contents(Storage::url($file))) { // TODO - this will fail on private S3 files or large public ones
return Response::make(Storage::url($file)->header('Content-Type', mime_content_type($file)));
}
return JsonResponse::create(['error' => 'Failed validation: '], 500);
}
return StorageHelper::downloader($file);
}
}
}
return redirect()->route('accessories.index')->with('error', trans('general.file_does_not_exist', ['id' => $fileId]));
}
}
+32 -20
View File
@@ -120,7 +120,6 @@ class AssetsController extends Controller
if ($filter_non_deprecable_assets) {
$non_deprecable_models = AssetModel::select('id')->whereNotNull('depreciation_id')->get();
$assets->InModelList($non_deprecable_models->toArray());
}
@@ -141,6 +140,14 @@ class AssetsController extends Controller
$assets->where('assets.status_id', '=', $request->input('status_id'));
}
if ($request->filled('asset_tag')) {
$assets->where('assets.asset_tag', '=', $request->input('asset_tag'));
}
if ($request->filled('serial')) {
$assets->where('assets.serial', '=', $request->input('serial'));
}
if ($request->input('requestable') == 'true') {
$assets->where('assets.requestable', '=', '1');
}
@@ -357,19 +364,28 @@ class AssetsController extends Controller
/**
* Returns JSON with information about an asset (by tag) for detail view.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param string $tag
* @since [v4.2.1]
* @return JsonResponse
* @author [A. Gianotto] [<snipe@snipe.net>]
* @return \Illuminate\Http\JsonResponse
*/
public function showByTag(Request $request, $tag)
{
if ($asset = Asset::with('assetstatus')->with('assignedTo')->where('asset_tag', $tag)->first()) {
$this->authorize('view', $asset);
$this->authorize('index', Asset::class);
$assets = Asset::where('asset_tag', $tag)->with('assetstatus')->with('assignedTo');
return (new AssetsTransformer)->transformAsset($asset, $request);
// Check if they've passed ?deleted=true
if ($request->input('deleted', 'false') == 'true') {
$assets = $assets->withTrashed();
}
$assets = $assets->get();
if (($assets) && ($assets->count() > 0)) {
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
} else {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
}
return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 200);
}
@@ -379,28 +395,24 @@ class AssetsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param string $serial
* @since [v4.2.1]
* @return JsonResponse
* @return \Illuminate\Http\JsonResponse
*/
public function showBySerial(Request $request, $serial)
{
$this->authorize('index', Asset::class);
if ($assets = Asset::with('assetstatus')->with('assignedTo')
->withTrashed()->where('serial', $serial)->get()) {
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
}
return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 200);
$assets = Asset::where('serial', $serial)->with('assetstatus')->with('assignedTo');
$assets = Asset::with('assetstatus')->with('assignedTo');
if ($request->input('deleted', 'false') === 'true') {
// Check if they've passed ?deleted=true
if ($request->input('deleted', 'false') == 'true') {
$assets = $assets->withTrashed();
}
}
$assets = $assets->where('serial', $serial)->get();
if ($assets) {
$assets = $assets->get();
if (($assets) && ($assets->count() > 0)) {
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
} else {
return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 200);
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
}
}
@@ -228,6 +228,7 @@ class ConsumablesController extends Controller
foreach ($consumable->consumableAssignments as $consumable_assignment) {
$rows[] = [
'avatar' => ($consumable_assignment->user) ? e($consumable_assignment->user->present()->gravatar) : '',
'name' => ($consumable_assignment->user) ? $consumable_assignment->user->present()->nameUrl() : 'Deleted User',
'created_at' => Helper::getFormattedDateObject($consumable_assignment->created_at, 'datetime'),
'note' => ($consumable_assignment->note) ? e($consumable_assignment->note) : null,
@@ -96,7 +96,7 @@ class CustomFieldsController extends Controller
$data = $request->all();
$regex_format = null;
if (str_contains($data['format'], 'regex:')) {
if ((array_key_exists('format', $data)) && (str_contains($data['format'], 'regex:'))) {
$regex_format = $data['format'];
}
@@ -39,7 +39,7 @@ class LicenseSeatsController extends Controller
}
$total = $seats->count();
$offset = (($seats) && (request('offset') > $total)) ? 0 : request('offset', 0);
$offset = (($seats) && (request('offset') >= $total)) ? 0 : request('offset', 0);
$limit = request('limit', 50);
$seats = $seats->skip($offset)->take($limit)->get();
@@ -27,7 +27,7 @@ class LocationsController extends Controller
$allowed_columns = [
'id', 'name', 'address', 'address2', 'city', 'state', 'country', 'zip', 'created_at',
'updated_at', 'manager_id', 'image',
'assigned_assets_count', 'users_count', 'assets_count', 'currency', 'ldap_ou', ];
'assigned_assets_count', 'users_count', 'assets_count','assigned_assets_count', 'assets_count', 'rtd_assets_count', 'currency', 'ldap_ou', ];
$locations = Location::with('parent', 'manager', 'children')->select([
'locations.id',
@@ -47,6 +47,7 @@ class LocationsController extends Controller
'locations.currency',
])->withCount('assignedAssets as assigned_assets_count')
->withCount('assets as assets_count')
->withCount('rtd_assets as rtd_assets_count')
->withCount('users as users_count');
if ($request->filled('search')) {
@@ -157,7 +158,9 @@ class LocationsController extends Controller
])
->withCount('assignedAssets as assigned_assets_count')
->withCount('assets as assets_count')
->withCount('users as users_count')->findOrFail($id);
->withCount('rtd_assets as rtd_assets_count')
->withCount('users as users_count')
->findOrFail($id);
return (new LocationsTransformer)->transformLocation($location);
}
+33 -1
View File
@@ -15,6 +15,7 @@ use App\Models\Asset;
use App\Models\Company;
use App\Models\License;
use App\Models\User;
use App\Notifications\CurrentInventory;
use Auth;
use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest;
@@ -66,6 +67,8 @@ class UsersController extends Controller
'users.zip',
'users.remote',
'users.ldap_import',
'users.start_date',
'users.end_date',
])->with('manager', 'groups', 'userloc', 'company', 'department', 'assets', 'licenses', 'accessories', 'consumables', 'createdBy',)
->withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count');
@@ -146,6 +149,15 @@ class UsersController extends Controller
$users = $users->where('remote', '=', $request->input('remote'));
}
if ($request->filled('start_date')) {
$users = $users->where('users.start_date', '=', $request->input('start_date'));
}
if ($request->filled('end_date')) {
$users = $users->where('users.end_date', '=', $request->input('end_date'));
}
if ($request->filled('assets_count')) {
$users->has('assets', '=', $request->input('assets_count'));
}
@@ -200,7 +212,7 @@ class UsersController extends Controller
'assets', 'accessories', 'consumables', 'licenses', 'groups', 'activated', 'created_at',
'two_factor_enrolled', 'two_factor_optin', 'last_login', 'assets_count', 'licenses_count',
'consumables_count', 'accessories_count', 'phone', 'address', 'city', 'state',
'country', 'zip', 'id', 'ldap_import', 'remote',
'country', 'zip', 'id', 'ldap_import', 'remote', 'start_date', 'end_date',
];
$sort = in_array($request->get('sort'), $allowed_columns) ? $request->get('sort') : 'first_name';
@@ -479,6 +491,26 @@ class UsersController extends Controller
return (new AssetsTransformer)->transformAssets($assets, $assets->count(), $request);
}
/**
* Notify a specific user via email with all of their assigned assets.
*
* @author [Lukas Fehling] [<lukas.fehling@adabay.rocks>]
* @since [v6.0.13]
* @param Request $request
* @param $id
* @return string JSON
*/
public function emailAssetList(Request $request, $id)
{
$user = User::findOrFail($id);
if (empty($user->email)) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.inventorynotification.error')));
}
return response()->Helper::formatStandardApiResponse('success', null, trans('admin/users/message.inventorynotification.success'));
}
/**
* Return JSON containing a list of consumables assigned to a user.
@@ -62,7 +62,7 @@ class AssetModelsFilesController extends Controller
$model->logUpload($file_name, e($request->get('notes')));
}
return redirect()->back()->with('success', trans('admin/hardware/message.upload.success'));
return redirect()->back()->with('success', trans('general.file_upload_success'));
}
return redirect()->back()->with('error', trans('admin/hardware/message.upload.nofiles'));
@@ -33,7 +33,6 @@ class BulkAssetsController extends Controller
if (! $request->filled('ids')) {
return redirect()->back()->with('error', trans('admin/hardware/message.update.no_assets_selected'));
}
// Figure out where we need to send the user after the update is complete, and store that in the session
@@ -135,9 +135,7 @@ class LoginController extends Controller
} else {
// Better logging
if (!$saml->isEnabled()) {
\Log::debug("SAML page requested, but SAML does not seem to enabled.");
} else {
if (empty($samlData)) {
\Log::debug("SAML page requested, but samlData seems empty.");
}
}
@@ -41,6 +41,7 @@ class ResetPasswordController extends Controller
public function __construct()
{
$this->middleware('guest');
$this->middleware('throttle:10,1');
}
protected function rules()
@@ -116,7 +117,7 @@ class ResetPasswordController extends Controller
}
\Log::debug('Password reset for '.$user->username.' FAILED - this user exists but the token is not valid');
return redirect()->back()->withInput($request->only('email'))->with('error', trans('passwords.token'));
return redirect()->back()->withInput($request->only('email'))->with('success', trans('passwords.reset'));
}
@@ -0,0 +1,180 @@
<?php
namespace App\Http\Controllers\Components;
use App\Helpers\StorageHelper;
use App\Http\Controllers\Controller;
use App\Http\Requests\AssetFileRequest;
use App\Models\Actionlog;
use App\Models\Component;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\HttpFoundation\JsonResponse;
use enshrined\svgSanitize\Sanitizer;
class ComponentsFilesController extends Controller
{
/**
* Validates and stores files associated with a component.
*
* @todo Switch to using the AssetFileRequest form request validator.
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @param AssetFileRequest $request
* @param int $componentId
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function store(AssetFileRequest $request, $componentId = null)
{
if (config('app.lock_passwords')) {
return redirect()->route('components.show', ['component'=>$componentId])->with('error', trans('general.feature_disabled'));
}
$component = Component::find($componentId);
if (isset($component->id)) {
$this->authorize('update', $component);
if ($request->hasFile('file')) {
if (! Storage::exists('private_uploads/components')) {
Storage::makeDirectory('private_uploads/components', 775);
}
foreach ($request->file('file') as $file) {
$extension = $file->getClientOriginalExtension();
$file_name = 'component-'.$component->id.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
// Check for SVG and sanitize it
if ($extension == 'svg') {
\Log::debug('This is an SVG');
\Log::debug($file_name);
$sanitizer = new Sanitizer();
$dirtySVG = file_get_contents($file->getRealPath());
$cleanSVG = $sanitizer->sanitize($dirtySVG);
try {
Storage::put('private_uploads/components/'.$file_name, $cleanSVG);
} catch (\Exception $e) {
\Log::debug('Upload no workie :( ');
\Log::debug($e);
}
} else {
Storage::put('private_uploads/components/'.$file_name, file_get_contents($file));
}
//Log the upload to the log
$component->logUpload($file_name, e($request->input('notes')));
}
return redirect()->route('components.show', $component->id)->with('success', trans('general.file_upload_success'));
}
return redirect()->route('components.show', $component->id)->with('error', trans('general.no_files_uploaded'));
}
// Prepare the error message
return redirect()->route('components.index')
->with('error', trans('general.file_does_not_exist'));
}
/**
* Deletes the selected component file.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @param int $componentId
* @param int $fileId
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function destroy($componentId = null, $fileId = null)
{
$component = Component::find($componentId);
// the asset is valid
if (isset($component->id)) {
$this->authorize('update', $component);
$log = Actionlog::find($fileId);
// Remove the file if one exists
if (Storage::exists('components/'.$log->filename)) {
try {
Storage::delete('components/'.$log->filename);
} catch (\Exception $e) {
\Log::debug($e);
}
}
$log->delete();
return redirect()->back()
->with('success', trans('admin/hardware/message.deletefile.success'));
}
// Redirect to the licence management page
return redirect()->route('components.index')->with('error', trans('general.file_does_not_exist'));
}
/**
* Allows the selected file to be viewed.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.4]
* @param int $componentId
* @param int $fileId
* @return \Symfony\Component\HttpFoundation\Response
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function show($componentId = null, $fileId = null, $download = true)
{
\Log::debug('Private filesystem is: '.config('filesystems.default'));
$component = Component::find($componentId);
// the component is valid
if (isset($component->id)) {
$this->authorize('view', $component);
$this->authorize('components.files', $component);
if (! $log = Actionlog::find($fileId)) {
return response('No matching record for that asset/file', 500)
->header('Content-Type', 'text/plain');
}
$file = 'private_uploads/components/'.$log->filename;
if (Storage::missing($file)) {
\Log::debug('FILE DOES NOT EXISTS for '.$file);
\Log::debug('URL should be '.Storage::url($file));
return response('File '.$file.' ('.Storage::url($file).') not found on server', 404)
->header('Content-Type', 'text/plain');
} else {
if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer?
return StorageHelper::downloader($file);
} else {
if ($download != 'true') {
\Log::debug('display the file');
if ($contents = file_get_contents(Storage::url($file))) { // TODO - this will fail on private S3 files or large public ones
return Response::make(Storage::url($file)->header('Content-Type', mime_content_type($file)));
}
return JsonResponse::create(['error' => 'Failed validation: '], 500);
}
return StorageHelper::downloader($file);
}
}
}
return redirect()->route('components.index')->with('error', trans('general.file_does_not_exist', ['id' => $fileId]));
}
}
@@ -0,0 +1,180 @@
<?php
namespace App\Http\Controllers\Consumables;
use App\Helpers\StorageHelper;
use App\Http\Controllers\Controller;
use App\Http\Requests\AssetFileRequest;
use App\Models\Actionlog;
use App\Models\Consumable;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Storage;
use Symfony\Consumable\HttpFoundation\JsonResponse;
use enshrined\svgSanitize\Sanitizer;
class ConsumablesFilesController extends Controller
{
/**
* Validates and stores files associated with a consumable.
*
* @todo Switch to using the AssetFileRequest form request validator.
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @param AssetFileRequest $request
* @param int $consumableId
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function store(AssetFileRequest $request, $consumableId = null)
{
if (config('app.lock_passwords')) {
return redirect()->route('consumables.show', ['consumable'=>$consumableId])->with('error', trans('general.feature_disabled'));
}
$consumable = Consumable::find($consumableId);
if (isset($consumable->id)) {
$this->authorize('update', $consumable);
if ($request->hasFile('file')) {
if (! Storage::exists('private_uploads/consumables')) {
Storage::makeDirectory('private_uploads/consumables', 775);
}
foreach ($request->file('file') as $file) {
$extension = $file->getClientOriginalExtension();
$file_name = 'consumable-'.$consumable->id.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
// Check for SVG and sanitize it
if ($extension == 'svg') {
\Log::debug('This is an SVG');
\Log::debug($file_name);
$sanitizer = new Sanitizer();
$dirtySVG = file_get_contents($file->getRealPath());
$cleanSVG = $sanitizer->sanitize($dirtySVG);
try {
Storage::put('private_uploads/consumables/'.$file_name, $cleanSVG);
} catch (\Exception $e) {
\Log::debug('Upload no workie :( ');
\Log::debug($e);
}
} else {
Storage::put('private_uploads/consumables/'.$file_name, file_get_contents($file));
}
//Log the upload to the log
$consumable->logUpload($file_name, e($request->input('notes')));
}
return redirect()->route('consumables.show', $consumable->id)->with('success', trans('general.file_upload_success'));
}
return redirect()->route('consumables.show', $consumable->id)->with('error', trans('general.no_files_uploaded'));
}
// Prepare the error message
return redirect()->route('consumables.index')
->with('error', trans('general.file_does_not_exist'));
}
/**
* Deletes the selected consumable file.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @param int $consumableId
* @param int $fileId
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function destroy($consumableId = null, $fileId = null)
{
$consumable = Consumable::find($consumableId);
// the asset is valid
if (isset($consumable->id)) {
$this->authorize('update', $consumable);
$log = Actionlog::find($fileId);
// Remove the file if one exists
if (Storage::exists('consumables/'.$log->filename)) {
try {
Storage::delete('consumables/'.$log->filename);
} catch (\Exception $e) {
\Log::debug($e);
}
}
$log->delete();
return redirect()->back()
->with('success', trans('admin/hardware/message.deletefile.success'));
}
// Redirect to the licence management page
return redirect()->route('consumables.index')->with('error', trans('general.file_does_not_exist'));
}
/**
* Allows the selected file to be viewed.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.4]
* @param int $consumableId
* @param int $fileId
* @return \Symfony\Consumable\HttpFoundation\Response
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function show($consumableId = null, $fileId = null, $download = true)
{
$consumable = Consumable::find($consumableId);
// the consumable is valid
if (isset($consumable->id)) {
$this->authorize('view', $consumable);
$this->authorize('consumables.files', $consumable);
if (! $log = Actionlog::find($fileId)) {
return response('No matching record for that asset/file', 500)
->header('Content-Type', 'text/plain');
}
$file = 'private_uploads/consumables/'.$log->filename;
if (Storage::missing($file)) {
\Log::debug('FILE DOES NOT EXISTS for '.$file);
\Log::debug('URL should be '.Storage::url($file));
return response('File '.$file.' ('.Storage::url($file).') not found on server', 404)
->header('Content-Type', 'text/plain');
} else {
// We have to override the URL stuff here, since local defaults in Laravel's Flysystem
// won't work, as they're not accessible via the web
if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer?
return StorageHelper::downloader($file);
} else {
if ($download != 'true') {
\Log::debug('display the file');
if ($contents = file_get_contents(Storage::url($file))) { // TODO - this will fail on private S3 files or large public ones
return Response::make(Storage::url($file)->header('Content-Type', mime_content_type($file)));
}
return JsonResponse::create(['error' => 'Failed validation: '], 500);
}
return StorageHelper::downloader($file);
}
}
}
return redirect()->route('consumables.index')->with('error', trans('general.file_does_not_exist', ['id' => $fileId]));
}
}
@@ -86,14 +86,24 @@ class CustomFieldsController extends Controller
{
$this->authorize('create', CustomField::class);
$show_in_email = $request->get("show_in_email", 0);
$display_in_user_view = $request->get("display_in_user_view", 0);
// Override the display settings if the field is encrypted
if ($request->get("field_encrypted") == '1') {
$show_in_email = '0';
$display_in_user_view = '0';
}
$field = new CustomField([
"name" => trim($request->get("name")),
"element" => $request->get("element"),
"help_text" => $request->get("help_text"),
"field_values" => $request->get("field_values"),
"field_encrypted" => $request->get("field_encrypted", 0),
"show_in_email" => $request->get("show_in_email", 0),
"show_in_email" => $show_in_email,
"is_unique" => $request->get("is_unique", 0),
"display_in_user_view" => $display_in_user_view,
"user_id" => Auth::id()
]);
@@ -221,13 +231,24 @@ class CustomFieldsController extends Controller
$this->authorize('update', $field);
$show_in_email = $request->get("show_in_email", 0);
$display_in_user_view = $request->get("display_in_user_view", 0);
// Override the display settings if the field is encrypted
if ($request->get("field_encrypted") == '1') {
$show_in_email = '0';
$display_in_user_view = '0';
}
$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();
$field->help_text = $request->get("help_text");
$field->show_in_email = $request->get("show_in_email", 0);
$field->show_in_email = $show_in_email;
$field->is_unique = $request->get("is_unique", 0);
$field->display_in_user_view = $display_in_user_view;
if ($request->get('format') == 'CUSTOM REGEX') {
$field->format = e($request->get('custom_format'));
+1 -1
View File
@@ -34,7 +34,7 @@ class DashboardController extends Controller
$counts['license'] = \App\Models\License::assetcount();
$counts['consumable'] = \App\Models\Consumable::count();
$counts['component'] = \App\Models\Component::count();
$counts['user'] = \App\Models\User::count();
$counts['user'] = \App\Models\Company::scopeCompanyables(Auth::user())->count();
$counts['grand_total'] = $counts['asset'] + $counts['accessory'] + $counts['license'] + $counts['consumable'];
if ((! file_exists(storage_path().'/oauth-private.key')) || (! file_exists(storage_path().'/oauth-public.key'))) {
+1 -1
View File
@@ -164,7 +164,7 @@ class ProfileController extends Controller
$validator = \Validator::make($request->all(), $rules);
$validator->after(function ($validator) use ($request, $user) {
if (! Hash::check($request->input('current_password'), $user->password)) {
$validator->errors()->add('current_password', trans('validation.hashed_pass'));
$validator->errors()->add('current_password', trans('validation.custom.hashed_pass'));
}
// This checks to make sure that the user's password isn't the same as their username,
+13 -7
View File
@@ -1110,13 +1110,19 @@ class ReportsController extends Controller
$rows[] = implode(',', $header);
foreach ($assetsForReport as $item) {
$row = [ ];
$row[] = str_replace(',', '', e($item['assetItem']->model->category->name));
$row[] = str_replace(',', '', e($item['assetItem']->model->name));
$row[] = str_replace(',', '', e($item['assetItem']->name));
$row[] = str_replace(',', '', e($item['assetItem']->asset_tag));
$row[] = str_replace(',', '', e(($item['acceptance']->assignedTo) ? $item['acceptance']->assignedTo->present()->name() : trans('admin/reports/general.deleted_user')));
$rows[] = implode(',', $row);
if ($item['assetItem'] != null){
$row = [ ];
$row[] = str_replace(',', '', e($item['assetItem']->model->category->name));
$row[] = str_replace(',', '', e($item['assetItem']->model->name));
$row[] = str_replace(',', '', e($item['assetItem']->name));
$row[] = str_replace(',', '', e($item['assetItem']->asset_tag));
$row[] = str_replace(',', '', e(($item['acceptance']->assignedTo) ? $item['acceptance']->assignedTo->present()->name() : trans('admin/reports/general.deleted_user')));
$rows[] = implode(',', $row);
} else {
// Log the error maybe?
}
}
// spit out a csv
+7 -3
View File
@@ -7,6 +7,7 @@ use App\Helpers\StorageHelper;
use App\Http\Requests\ImageUploadRequest;
use App\Http\Requests\SettingsSamlRequest;
use App\Http\Requests\SetupUserRequest;
use App\Models\Group;
use App\Models\Setting;
use App\Models\Asset;
use App\Models\User;
@@ -911,6 +912,8 @@ class SettingsController extends Controller
public function getLdapSettings()
{
$setting = Setting::getSettings();
$groups = Group::pluck('name', 'id');
/**
* This validator is only temporary (famous last words.) - @snipe
@@ -923,13 +926,13 @@ class SettingsController extends Controller
$validator = Validator::make($setting->toArray(), [
'ldap_username_field' => 'not_in:sAMAccountName',
'ldap_auth_filter_query' => 'not_in:uid=samaccountname',
'ldap_filter' => 'regex:"^[^(]"',
'ldap_auth_filter_query' => 'not_in:uid=samaccountname|required_if:ldap_enabled,1',
'ldap_filter' => 'nullable|regex:"^[^(]"|required_if:ldap_enabled,1',
], $messages);
return view('settings.ldap', compact('setting'))->withErrors($validator);
return view('settings.ldap', compact('setting', 'groups'))->withErrors($validator);
}
/**
@@ -956,6 +959,7 @@ class SettingsController extends Controller
$setting->ldap_pword = Crypt::encrypt($request->input('ldap_pword'));
}
$setting->ldap_basedn = $request->input('ldap_basedn');
$setting->ldap_default_group = $request->input('ldap_default_group');
$setting->ldap_filter = $request->input('ldap_filter');
$setting->ldap_username_field = $request->input('ldap_username_field');
$setting->ldap_lname_field = $request->input('ldap_lname_field');
@@ -197,6 +197,7 @@ class BulkUsersController extends Controller
'status_id' => e(request('status_id')),
'assigned_to' => null,
'assigned_type' => null,
'expected_checkin' => null,
]);
@@ -234,10 +235,10 @@ class BulkUsersController extends Controller
$item_id = $item->id;
$logAction = new Actionlog();
if($itemType == License::class){
if ($itemType == License::class){
$item_id = $item->license_id;
}
$logAction->item_id = $item_id;
// We can't rely on get_class here because the licenses/accessories fetched above are not eloquent models, but simply arrays.
$logAction->item_type = $itemType;
@@ -119,6 +119,8 @@ class UsersController extends Controller
$user->remote = $request->input('remote', 0);
$user->website = $request->input('website', null);
$user->created_by = Auth::user()->id;
$user->start_date = $request->input('start_date', null);
$user->end_date = $request->input('end_date', null);
// Strip out the superuser permission if the user isn't a superadmin
$permissions_array = $request->input('permission');
@@ -270,6 +272,8 @@ class UsersController extends Controller
$user->zip = $request->input('zip', null);
$user->remote = $request->input('remote', 0);
$user->website = $request->input('website', null);
$user->start_date = $request->input('start_date', null);
$user->end_date = $request->input('end_date', null);
// Update the location of any assets checked out to this user
Asset::where('assigned_type', User::class)
+27 -8
View File
@@ -8,6 +8,7 @@ use App\Models\AssetModel;
use App\Models\Company;
use App\Models\Setting;
use App\Models\User;
use App\Models\CustomField;
use App\Notifications\RequestAssetCancelation;
use App\Notifications\RequestAssetNotification;
use Illuminate\Http\Request;
@@ -29,23 +30,41 @@ class ViewAssetsController extends Controller
public function getIndex()
{
$user = User::with(
'assets',
'assets.model',
'assets.model.fieldset.fields',
'consumables',
'accessories',
'licenses',
'userloc',
'userlog'
)->withTrashed()->find(Auth::user()->id);
)->find(Auth::user()->id);
$userlog = $user->userlog->load('item', 'user', 'target');
$field_array = array();
// Loop through all the custom fields that are applied to any model the user has assigned
foreach ($user->assets as $asset) {
// Make sure the model has a custom fieldset before trying to loop through the associated fields
if ($asset->model->fieldset) {
foreach ($asset->model->fieldset->fields as $field) {
// check and make sure they're allowed to see the value of the custom field
if ($field->display_in_user_view == '1') {
$field_array[$field->db_column] = $field->name;
}
}
}
}
// Since some models may re-use the same fieldsets/fields, let's make the array unique so we don't repeat columns
array_unique($field_array);
if (isset($user->id)) {
return view('account/view-assets', compact('user', 'userlog'))
return view('account/view-assets', compact('user', 'field_array' ))
->with('settings', Setting::getSettings());
} else {
// Redirect to the user management page
return redirect()->route('users.index')->with('error', trans('admin/users/message.user_not_found', compact('id')));
}
// Redirect to the user management page
return redirect()->route('users.index')
->with('error', trans('admin/users/message.user_not_found', $user->id));
@@ -85,6 +85,7 @@ class ActionlogsTransformer
'id' => (int) $actionlog->item->id,
'name' => ($actionlog->itemType()=='user') ? e($actionlog->item->getFullNameAttribute()) : e($actionlog->item->getDisplayNameAttribute()),
'type' => e($actionlog->itemType()),
'serial' =>e($actionlog->item->serial) ? e($actionlog->item->serial) : null
] : null,
'location' => ($actionlog->location) ? [
'id' => (int) $actionlog->location->id,
+4 -1
View File
@@ -8,6 +8,7 @@ use App\Models\Setting;
use Gate;
use Illuminate\Database\Eloquent\Collection;
class AssetsTransformer
{
public function transformAssets(Collection $assets, $total)
@@ -80,6 +81,7 @@ class AssetsTransformer
'next_audit_date' => Helper::getFormattedDateObject($asset->next_audit_date, 'date'),
'deleted_at' => Helper::getFormattedDateObject($asset->deleted_at, 'datetime'),
'purchase_date' => Helper::getFormattedDateObject($asset->purchase_date, 'date'),
'age' => $asset->purchase_date ? Helper::AgeFormat($asset->purchase_date) : '',
'last_checkout' => Helper::getFormattedDateObject($asset->last_checkout, 'datetime'),
'expected_checkin' => Helper::getFormattedDateObject($asset->expected_checkin, 'date'),
'purchase_cost' => Helper::formatCurrencyOutput($asset->purchase_cost),
@@ -131,7 +133,7 @@ class AssetsTransformer
$array['custom_fields'] = $fields_array;
}
} else {
$array['custom_fields'] = [];
$array['custom_fields'] = new \stdClass; // HACK to force generation of empty object instead of empty list
}
$permissions_array['available_actions'] = [
@@ -185,6 +187,7 @@ class AssetsTransformer
'name' => e($asset->assigned->getFullNameAttribute()),
'first_name'=> e($asset->assigned->first_name),
'last_name'=> ($asset->assigned->last_name) ? e($asset->assigned->last_name) : null,
'email'=> ($asset->assigned->email) ? e($asset->assigned->email) : null,
'employee_number' => ($asset->assigned->employee_num) ? e($asset->assigned->employee_num) : null,
'type' => 'user',
] : null;
@@ -47,6 +47,7 @@ class CustomFieldsTransformer
'field_values_array' => ($field->field_values) ? explode("\r\n", e($field->field_values)) : null,
'type' => e($field->element),
'required' => (($field->pivot) && ($field->pivot->required=='1')) ? true : false,
'display_in_user_view' => ($field->display_in_user_view =='1') ? true : false,
'created_at' => Helper::getFormattedDateObject($field->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($field->updated_at, 'datetime'),
];
@@ -45,6 +45,7 @@ class LocationsTransformer
'zip' => ($location->zip) ? e($location->zip) : null,
'assigned_assets_count' => (int) $location->assigned_assets_count,
'assets_count' => (int) $location->assets_count,
'rtd_assets_count' => (int) $location->rtd_assets_count,
'users_count' => (int) $location->users_count,
'currency' => ($location->currency) ? e($location->currency) : null,
'ldap_ou' => ($location->ldap_ou) ? e($location->ldap_ou) : null,
+4 -2
View File
@@ -30,7 +30,7 @@ class UsersTransformer
'username' => e($user->username),
'remote' => ($user->remote == '1') ? true : false,
'locale' => ($user->locale) ? e($user->locale) : null,
'employee_num' => e($user->employee_num),
'employee_num' => ($user->employee_num) ? e($user->employee_num) : null,
'manager' => ($user->manager) ? [
'id' => (int) $user->manager->id,
'name'=> e($user->manager->first_name).' '.e($user->manager->last_name),
@@ -43,7 +43,7 @@ class UsersTransformer
'state' => ($user->state) ? e($user->state) : null,
'country' => ($user->country) ? e($user->country) : null,
'zip' => ($user->zip) ? e($user->zip) : null,
'email' => e($user->email),
'email' => ($user->email) ? e($user->email) : null,
'department' => ($user->department) ? [
'id' => (int) $user->department->id,
'name'=> e($user->department->name),
@@ -69,6 +69,8 @@ class UsersTransformer
] : null,
'created_at' => Helper::getFormattedDateObject($user->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($user->updated_at, 'datetime'),
'start_date' => Helper::getFormattedDateObject($user->start_date, 'date'),
'end_date' => Helper::getFormattedDateObject($user->end_date, 'date'),
'last_login' => Helper::getFormattedDateObject($user->last_login, 'datetime'),
'deleted_at' => ($user->deleted_at) ? Helper::getFormattedDateObject($user->deleted_at, 'datetime') : null,
];
+2
View File
@@ -77,6 +77,7 @@ abstract class Importer
'manager_first_name' => 'manager first name',
'manager_last_name' => 'manager last name',
'min_amt' => 'minimum quantity',
'remote' => 'remote',
];
/**
* Map of item fields->csv names
@@ -288,6 +289,7 @@ abstract class Importer
'department_id' => '',
'username' => $this->findCsvMatch($row, 'username'),
'activated' => $this->fetchHumanBoolean($this->findCsvMatch($row, 'activated')),
'remote' => $this->fetchHumanBoolean(($this->findCsvMatch($row, 'remote'))),
];
// Maybe we're lucky and the user already exists.
+1
View File
@@ -57,6 +57,7 @@ class UserImporter extends ItemImporter
$this->item['employee_num'] = $this->findCsvMatch($row, 'employee_num');
$this->item['department_id'] = $this->createOrFetchDepartment($this->findCsvMatch($row, 'department'));
$this->item['manager_id'] = $this->fetchManager($this->findCsvMatch($row, 'manager_first_name'), $this->findCsvMatch($row, 'manager_last_name'));
$this->item['remote'] =($this->fetchHumanBoolean($this->findCsvMatch($row, 'remote')) ==1 ) ? '1' : 0;
$user_department = $this->findCsvMatch($row, 'department');
if ($this->shouldUpdateField($user_department)) {
+31 -21
View File
@@ -20,6 +20,8 @@ use App\Notifications\CheckoutConsumableNotification;
use App\Notifications\CheckoutLicenseNotification;
use App\Notifications\CheckoutLicenseSeatNotification;
use Illuminate\Support\Facades\Notification;
use Exception;
use Log;
class CheckoutableListener
{
@@ -43,16 +45,20 @@ class CheckoutableListener
*/
$acceptance = $this->getCheckoutAcceptance($event);
if (! $event->checkedOutTo->locale) {
Notification::locale(Setting::getSettings()->locale)->send(
$this->getNotifiables($event),
$this->getCheckoutNotification($event, $acceptance)
);
} else {
Notification::send(
$this->getNotifiables($event),
$this->getCheckoutNotification($event, $acceptance)
);
try {
if (! $event->checkedOutTo->locale) {
Notification::locale(Setting::getSettings()->locale)->send(
$this->getNotifiables($event),
$this->getCheckoutNotification($event, $acceptance)
);
} else {
Notification::send(
$this->getNotifiables($event),
$this->getCheckoutNotification($event, $acceptance)
);
}
} catch (Exception $e) {
Log::error("Exception caught during checkout notification: ".$e->getMessage());
}
}
@@ -83,17 +89,21 @@ class CheckoutableListener
}
}
// Use default locale
if (! $event->checkedOutTo->locale) {
Notification::locale(Setting::getSettings()->locale)->send(
$this->getNotifiables($event),
$this->getCheckinNotification($event)
);
} else {
Notification::send(
$this->getNotifiables($event),
$this->getCheckinNotification($event)
);
try {
// Use default locale
if (! $event->checkedOutTo->locale) {
Notification::locale(Setting::getSettings()->locale)->send(
$this->getNotifiables($event),
$this->getCheckinNotification($event)
);
} else {
Notification::send(
$this->getNotifiables($event),
$this->getCheckinNotification($event)
);
}
} catch (Exception $e) {
Log::error("Exception caught during checkin notification: ".$e->getMessage());
}
}
+17
View File
@@ -101,6 +101,23 @@ class Accessory extends SnipeModel
/**
* Establishes the accessories -> action logs -> uploads relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v6.1.13]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function uploads()
{
return $this->hasMany(\App\Models\Actionlog::class, 'item_id')
->where('item_type', '=', self::class)
->where('action_type', '=', 'uploaded')
->whereNotNull('filename')
->orderBy('created_at', 'desc');
}
/**
* Establishes the accessory -> supplier relationship
*
+1 -1
View File
@@ -21,7 +21,7 @@ class CheckoutAcceptance extends Model
{
// At this point the endpoint is the same for everything.
// In the future this may want to be adapted for individual notifications.
return config('mail.reply_to.address');
return (config('mail.reply_to.address')) ? config('mail.reply_to.address') : '' ;
}
/**
+9
View File
@@ -73,6 +73,10 @@ final class Company extends SnipeModel
}
}
/**
* Scoping table queries, determining if a logged in user is part of a company, and only allows
* that user to see items associated with that company
*/
private static function scopeCompanyablesDirectly($query, $column = 'company_id', $table_name = null)
{
if (Auth::user()) {
@@ -127,6 +131,11 @@ final class Company extends SnipeModel
return false;
} elseif (! static::isFullMultipleCompanySupportEnabled()) {
return true;
} elseif (!$companyable instanceof Company && !\Schema::hasColumn($companyable->getModel()->getTable(), 'company_id')) {
// This is primary for the gate:allows-check in location->isDeletable()
// Locations don't have a company_id so without this it isn't possible to delete locations with FullMultipleCompanySupport enabled
// because this function is called by SnipePermissionsPolicy->before()
return true;
} else {
if (Auth::user()) {
$current_user_company_id = Auth::user()->company_id;
+18
View File
@@ -88,6 +88,24 @@ class Component extends SnipeModel
'location' => ['name'],
];
/**
* Establishes the components -> action logs -> uploads relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v6.1.13]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function uploads()
{
return $this->hasMany(\App\Models\Actionlog::class, 'item_id')
->where('item_type', '=', self::class)
->where('action_type', '=', 'uploaded')
->whereNotNull('filename')
->orderBy('created_at', 'desc');
}
/**
* Establishes the component -> location relationship
*
+18
View File
@@ -96,6 +96,24 @@ class Consumable extends SnipeModel
'manufacturer' => ['name'],
];
/**
* Establishes the components -> action logs -> uploads relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v6.1.13]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function uploads()
{
return $this->hasMany(\App\Models\Actionlog::class, 'item_id')
->where('item_type', '=', self::class)
->where('action_type', '=', 'uploaded')
->whereNotNull('filename')
->orderBy('created_at', 'desc');
}
/**
* Sets the attribute of whether or not the consumable is requestable
*
+7 -8
View File
@@ -48,7 +48,11 @@ class CustomField extends Model
*
* @var array
*/
protected $rules = [];
protected $rules = [
'name' => 'required|unique:custom_fields',
'element' => 'required|in:text,listbox,textarea,checkbox,radio',
'field_encrypted' => 'nullable|boolean',
];
/**
* The attributes that are mass assignable.
@@ -64,6 +68,7 @@ class CustomField extends Model
'help_text',
'show_in_email',
'is_unique',
'display_in_user_view',
];
/**
@@ -356,15 +361,9 @@ class CustomField extends Model
public function validationRules($regex_format = null)
{
return [
'name' => 'required|unique:custom_fields',
'element' => [
'required',
Rule::in(['text', 'listbox', 'textarea', 'checkbox', 'radio']),
],
'format' => [
Rule::in(array_merge(array_keys(self::PREDEFINED_FORMATS), self::PREDEFINED_FORMATS, [$regex_format])),
],
'field_encrypted' => 'nullable|boolean',
]
];
}
+2 -2
View File
@@ -69,14 +69,14 @@ class Depreciable extends SnipeModel
public function getLinearDepreciatedValue() // TODO - for testing it might be nice to have an optional $relative_to param here, defaulted to 'now'
{
if ($this->purchase_date) {
$months_passed = $this->purchase_date->diff(now())->m;
$months_passed = ($this->purchase_date->diff(now())->m)+($this->purchase_date->diff(now())->y*12);
} else {
return null;
}
if ($months_passed >= $this->get_depreciation()->months){
//if there is a floor use it
if($this->get_depreciation()->deprecation_min->isNotEmpty()) {
if(!$this->get_depreciation()->depreciation_min == null) {
$current_value = $this->get_depreciation()->depreciation_min;
+81 -7
View File
@@ -90,6 +90,14 @@ class Location extends SnipeModel
'parent' => ['name'],
];
/**
* Determine whether or not this location can be deleted
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v3.0]
* @return bool
*/
public function isDeletable()
{
return Gate::allows('delete', $this)
@@ -98,12 +106,25 @@ class Location extends SnipeModel
&& ($this->users()->count() === 0);
}
/**
* Establishes the user -> location relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function users()
{
return $this->hasMany(\App\Models\User::class, 'location_id');
}
/**
* Find assets with this location as their location_id
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assets()
{
return $this->hasMany(\App\Models\Asset::class, 'location_id')
@@ -114,6 +135,14 @@ class Location extends SnipeModel
});
}
/**
* Establishes the asset -> rtd_location relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function rtd_assets()
{
/* This used to have an ...->orHas() clause that referred to
@@ -123,48 +152,93 @@ class Location extends SnipeModel
It is arguable that we should have a '...->whereNull('assigned_to')
bit in there, but that isn't always correct either (in the case
where a user has no location, for example).
In all likelyhood, we need to denorm an "effective_location" column
into Assets to make this slightly less miserable.
*/
return $this->hasMany(\App\Models\Asset::class, 'rtd_location_id');
}
/**
* Establishes the consumable -> location relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function consumables()
{
return $this->hasMany(\App\Models\Consumable::class, 'location_id');
}
/**
* Establishes the component -> location relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function components()
{
return $this->hasMany(\App\Models\Component::class, 'location_id');
}
/**
* Establishes the component -> accessory relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function accessories()
{
return $this->hasMany(\App\Models\Accessory::class, 'location_id');
}
/**
* Find the parent of a location
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function parent()
{
return $this->belongsTo(self::class, 'parent_id', 'id')
->with('parent');
}
/**
* Find the manager of a location
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function manager()
{
return $this->belongsTo(\App\Models\User::class, 'manager_id');
}
/**
* Find children of a location
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function children()
{
return $this->hasMany(self::class, 'parent_id')
->with('children');
}
// I don't think we need this anymore since we de-normed location_id in assets?
/**
* Establishes the asset -> location assignment relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assignedAssets()
{
return $this->morphMany(\App\Models\Asset::class, 'assigned', 'assigned_type', 'assigned_to')->withTrashed();
+1 -1
View File
@@ -189,7 +189,7 @@ trait Loggable
$params = [
'item' => $log->item,
'filename' => $log->filename,
'admin' => $log->user,
'admin' => $log->admin,
'location' => ($location) ? $location->name : '',
'note' => $note,
];
+5
View File
@@ -41,6 +41,11 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig
}
);
// externalId support
$config['validations'][$core.'externalId'] = 'string|nullable'; // not required, but supported mostly just for Okta
// note that the mapping is *not* namespaced like the other $mappings
$config['mapping']['externalId'] = AttributeMapping::eloquent('scim_externalid');
$config['validations'][$core.'emails'] = 'nullable|array'; // emails are not required in Snipe-IT...
$config['validations'][$core.'emails.*.value'] = 'email'; // ...(had to remove the recommended 'required' here)
+33
View File
@@ -59,6 +59,9 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
'username',
'zip',
'remote',
'start_date',
'end_date',
'scim_externalid'
];
protected $casts = [
@@ -68,6 +71,16 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
'company_id' => 'integer',
];
protected $dates = [
'created_at',
'updated_at',
'deleted_at',
'start_date',
'end_date',
];
/**
* Model validation rules
*
@@ -83,6 +96,8 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
'website' => 'url|nullable|max:191',
'manager_id' => 'nullable|exists:users,id|cant_manage_self',
'location_id' => 'exists:locations,id|nullable',
'start_date' => 'nullable|date',
'end_date' => 'nullable|date|after_or_equal:start_date',
];
/**
@@ -323,6 +338,24 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
return $this->belongsToMany(\App\Models\License::class, 'license_seats', 'assigned_to', 'license_id')->withPivot('id');
}
/**
* Establishes a count of all items assigned
*
* @author J. Vinsmoke
* @since [v6.1]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
Public function allAssignedCount() {
$assetsCount = $this->assets()->count();
$licensesCount = $this->licenses()->count();
$accessoriesCount = $this->accessories()->count();
$consumablesCount = $this->consumables()->count();
$totalCount = $assetsCount + $licensesCount + $accessoriesCount + $consumablesCount;
return (int) $totalCount;
}
/**
* Establishes the user -> actionlogs relationship
*
+6
View File
@@ -140,6 +140,12 @@ class AssetPresenter extends Presenter
'visible' => false,
'title' => trans('general.purchase_date'),
'formatter' => 'dateDisplayFormatter',
], [
'field' => 'age',
'searchable' => true,
'sortable' => true,
'visible' => false,
'title' => trans('general.age'),
], [
'field' => 'purchase_cost',
'searchable' => true,
+9 -23
View File
@@ -70,47 +70,33 @@ class CategoryPresenter extends Presenter
'visible' => true,
'formatter' => 'trueFalseFormatter',
], [
'field' => 'actions',
'searchable' => false,
'sortable' => false,
'switchable' => false,
'title' => trans('table.actions'),
],[
"field" => "use_default_eula",
"searchable" => false,
"sortable" => true,
"title" => trans('admin/categories/general.use_default_eula_column'),
'visible' => true,
"formatter" => 'trueFalseFormatter',
],[
"field" => "checkin_email",
"searchable" => false,
"sortable" => true,
"class" => 'css-envelope',
"title" => 'Send Email',
"visible" => true,
"formatter" => 'trueFalseFormatter',
],[
"field" => "require_acceptance",
"searchable" => false,
"sortable" => true,
'formatter' => 'categoriesActionsFormatter',
],
[
], [
'field' => 'created_at',
'searchable' => true,
'sortable' => true,
'visible' => false,
'title' => trans('general.created_at'),
'formatter' => 'dateDisplayFormatter',
],
[
], [
'field' => 'updated_at',
'searchable' => true,
'sortable' => true,
'visible' => false,
'title' => trans('general.updated_at'),
'formatter' => 'dateDisplayFormatter',
], [
'field' => 'actions',
'searchable' => false,
'sortable' => false,
'switchable' => false,
'title' => trans('table.actions'),
'formatter' => 'categoriesActionsFormatter',
],
];
+13 -2
View File
@@ -55,17 +55,28 @@ class LocationPresenter extends Presenter
'searchable' => false,
'sortable' => true,
'switchable' => true,
'title' => trans('admin/locations/table.assets_rtd'),
'title' => trans('admin/locations/message.current_location'),
'visible' => true,
],
[
'field' => 'rtd_assets_count',
'searchable' => false,
'sortable' => true,
'switchable' => true,
'title' => trans('admin/hardware/form.default_location'),
'visible' => false,
],
[
'field' => 'assigned_assets_count',
'searchable' => false,
'sortable' => true,
'switchable' => true,
'title' => trans('admin/locations/table.assets_checkedout'),
'title' => trans('admin/locations/message.assigned_assets'),
'visible' => true,
],
[
'field' => 'users_count',
'searchable' => false,
+18
View File
@@ -302,6 +302,24 @@ class UserPresenter extends Presenter
'visible' => false,
'formatter' => 'dateDisplayFormatter',
],
[
'field' => 'start_date',
'searchable' => true,
'sortable' => true,
'switchable' => true,
'title' => trans('general.start_date'),
'visible' => false,
'formatter' => 'dateDisplayFormatter',
],
[
'field' => 'end_date',
'searchable' => true,
'sortable' => true,
'switchable' => true,
'title' => trans('general.end_date'),
'visible' => false,
'formatter' => 'dateDisplayFormatter',
],
[
'field' => 'last_login',
'searchable' => false,
+4
View File
@@ -159,6 +159,10 @@ class AuthServiceProvider extends ServiceProvider
return $user->hasAccess('self.checkout_assets');
});
Gate::define('self.view_purchase_cost', function ($user) {
return $user->hasAccess('self.view_purchase_cost');
});
// This is largely used to determine whether to display the gear icon sidenav
// in the left-side navigation
Gate::define('backend.interact', function ($user) {
Generated
+8 -8
View File
@@ -78,18 +78,18 @@
"source": {
"type": "git",
"url": "https://github.com/grokability/laravel-scim-server.git",
"reference": "d0e3d7c0b5da2ec76283b8a2fa2e672a91596509"
"reference": "2c7ecc450eee59234e059ec2e7724b2d8f3a8369"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/grokability/laravel-scim-server/zipball/d0e3d7c0b5da2ec76283b8a2fa2e672a91596509",
"reference": "d0e3d7c0b5da2ec76283b8a2fa2e672a91596509",
"url": "https://api.github.com/repos/grokability/laravel-scim-server/zipball/2c7ecc450eee59234e059ec2e7724b2d8f3a8369",
"reference": "2c7ecc450eee59234e059ec2e7724b2d8f3a8369",
"shasum": ""
},
"require": {
"illuminate/console": "^6.0|^7.0|^8.0",
"illuminate/database": "^6.0|^7.0|^8.0",
"illuminate/support": "^6.0|^7.0|^8.0",
"illuminate/console": "^6.0|^7.0|^8.0|^9.0",
"illuminate/database": "^6.0|^7.0|^8.0|^9.0",
"illuminate/support": "^6.0|^7.0|^8.0|^9.0",
"php": "^7.0|^8.0",
"tmilos/scim-filter-parser": "^1.3",
"tmilos/scim-schema": "^0.1.0"
@@ -133,7 +133,7 @@
"support": {
"source": "https://github.com/grokability/laravel-scim-server/tree/master"
},
"time": "2022-07-18T22:15:42+00:00"
"time": "2022-11-22T20:26:54+00:00"
},
{
"name": "asm89/stack-cors",
@@ -13530,5 +13530,5 @@
"ext-pdo": "*"
},
"platform-dev": [],
"plugin-api-version": "2.0.0"
"plugin-api-version": "2.3.0"
}
+5
View File
@@ -100,6 +100,11 @@ return [
'emergency' => [
'path' => storage_path('logs/laravel.log'),
],
'scimtrace' => [
'driver' => 'single',
'path' => storage_path('logs/scim.log')
]
],
];
+26
View File
@@ -145,6 +145,13 @@ return [
'note' => '',
'display' => true,
],
[
'permission' => 'accessories.files',
'label' => 'View and Modify Accessory Files',
'note' => '',
'display' => true,
],
],
'Consumables' => [
@@ -178,6 +185,12 @@ return [
'note' => '',
'display' => true,
],
[
'permission' => 'consumables.files',
'label' => 'View and Modify Consumable Files',
'note' => '',
'display' => true,
],
],
@@ -264,6 +277,12 @@ return [
'note' => '',
'display' => true,
],
[
'permission' => 'components.files',
'label' => 'View and Modify Component Files',
'note' => '',
'display' => true,
],
],
@@ -626,6 +645,13 @@ return [
'display' => true,
],
[
'permission' => 'self.view_purchase_cost',
'label' => 'View Purchase-Cost Column',
'note' => 'This user can see the purchase cost column of items assigned to them.',
'display' => true,
],
],
];
+4 -1
View File
@@ -1,5 +1,8 @@
<?php
return [
"publish_routes" => false
"trace" => env("SCIM_TRACE",false),
// below, if we ever get 'sure' that we can change this default to 'true' we should
"omit_main_schema_in_return" => env('SCIM_STANDARDS_COMPLIANCE', false),
"publish_routes" => false,
];
+6 -6
View File
@@ -1,10 +1,10 @@
<?php
return array (
'app_version' => 'v6.0.11',
'full_app_version' => 'v6.0.11 - build 8758-g61fa0bda4',
'build_version' => '8758',
'app_version' => 'v6.0.14',
'full_app_version' => 'v6.0.14 - build 9038-g163b3f6c0',
'build_version' => '9038',
'prerelease_version' => '',
'hash_version' => 'g61fa0bda4',
'full_hash' => 'v6.0.11-145-g61fa0bda4',
'branch' => 'master',
'hash_version' => 'g163b3f6c0',
'full_hash' => 'v6.0.14-113-g163b3f6c0',
'branch' => 'develop',
);
@@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddsLdapDefaultGroupToSettingsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('settings', function (Blueprint $table) {
$table->integer('ldap_default_group')
->after('ldap_basedn')->default(null);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('settings', function (Blueprint $table) {
$table->dropColumn('ldap_default_group');
});
}
}
@@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddStartTerminationDateToUsers extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->date('start_date')->nullable()->default(null);
$table->date('end_date')->nullable()->default(null);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('start_date');
$table->dropColumn('end_date');
});
}
}
@@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddExternalidToUsers extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->string('scim_externalid')->nullable()->default(null);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('scim_externalid');
});
}
}
@@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddDisplayToUserInCustomFields extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('custom_fields', function (Blueprint $table) {
$table->boolean('display_in_user_view')->nullable()->default(0);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('custom_fields', function (Blueprint $table) {
$table->dropColumn('display_in_user_view');
});
}
}
@@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class FixNullableMigrationForSettings extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('settings', function (Blueprint $table) {
$table->string('ldap_default_group')->nullable()->default(null)->change();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
// nothing to do here - this is a hotfix
}
}
+1 -1
View File
@@ -24,7 +24,7 @@
"vue-template-compiler": "2.4.4"
},
"dependencies": {
"@fortawesome/fontawesome-free": "^6.2.0",
"@fortawesome/fontawesome-free": "^6.2.1",
"acorn": "^8.8.0",
"acorn-import-assertions": "^1.8.0",
"admin-lte": "^2.4.18",
+15
View File
@@ -953,4 +953,19 @@ th.css-accessory > .th-inner::before {
.bs-checkbox input {
zoom: 1.5;
}
@media screen and (max-width: 511px) {
.sidebar-menu {
margin-top: 64px;
}
}
@media screen and (max-width: 771px) and (min-width: 512px) {
.sidebar-menu {
margin-top: 14px;
}
}
@media screen and (max-width: 1098px) and (min-width: 772px) {
.sidebar-menu {
margin-top: 51px;
}
}
+15
View File
@@ -586,4 +586,19 @@ th.css-accessory > .th-inner::before {
.bs-checkbox input {
zoom: 1.5;
}
@media screen and (max-width: 511px) {
.sidebar-menu {
margin-top: 64px;
}
}
@media screen and (max-width: 771px) and (min-width: 512px) {
.sidebar-menu {
margin-top: 14px;
}
}
@media screen and (max-width: 1098px) and (min-width: 772px) {
.sidebar-menu {
margin-top: 51px;
}
}
+30
View File
@@ -23815,6 +23815,21 @@ th.css-accessory > .th-inner::before {
.bs-checkbox input {
zoom: 1.5;
}
@media screen and (max-width: 511px) {
.sidebar-menu {
margin-top: 64px;
}
}
@media screen and (max-width: 771px) and (min-width: 512px) {
.sidebar-menu {
margin-top: 14px;
}
}
@media screen and (max-width: 1098px) and (min-width: 772px) {
.sidebar-menu {
margin-top: 51px;
}
}
.select2-container {
@@ -24887,4 +24902,19 @@ th.css-accessory > .th-inner::before {
.bs-checkbox input {
zoom: 1.5;
}
@media screen and (max-width: 511px) {
.sidebar-menu {
margin-top: 64px;
}
}
@media screen and (max-width: 771px) and (min-width: 512px) {
.sidebar-menu {
margin-top: 14px;
}
}
@media screen and (max-width: 1098px) and (min-width: 772px) {
.sidebar-menu {
margin-top: 51px;
}
}
+3
View File
@@ -217,6 +217,9 @@ a:visited {
.navbar-nav > li > a:link {
color: var(--nav-link);
}
.far fa-life-ring {
color: var(--link);
}
.modal-content {
background-color: var(--back-main);
color: var(--text-main);
+3
View File
@@ -217,6 +217,9 @@ a:visited {
.navbar-nav > li > a:link {
color: var(--nav-link);
}
.far fa-life-ring {
color: var(--link);
}
.modal-content {
background-color: var(--back-main);
color: var(--text-main);
+3
View File
@@ -199,6 +199,9 @@ a.btn-danger:visited {
.btn-danger.btn-sm.disabled {
color: #FFF;
}
.far fa-life-ring {
color: var(--link);
}
.sidebar-toggle-mobile {
color: #FFF !important;
}
+3
View File
@@ -199,6 +199,9 @@ a.btn-danger:visited {
.btn-danger.btn-sm.disabled {
color: #FFF;
}
.far fa-life-ring {
color: var(--link);
}
.sidebar-toggle-mobile {
color: #FFF !important;
}
+3
View File
@@ -212,6 +212,9 @@ a:visited {
.navbar-nav > li > a:link {
color: var(--nav-link);
}
.far fa-life-ring {
color: var(--link);
}
.modal-content {
background-color: var(--back-main);
color: var(--text-main);
+3
View File
@@ -212,6 +212,9 @@ a:visited {
.navbar-nav > li > a:link {
color: var(--nav-link);
}
.far fa-life-ring {
color: var(--link);
}
.modal-content {
background-color: var(--back-main);
color: var(--text-main);
+4 -1
View File
@@ -123,7 +123,7 @@
border-bottom-left-radius: 0;
}
.skin-blue.layout-top-nav .main-header > .logo .logo-variant {
background-color: none;
background-color: unset;
}
.btn.btn-primary,
btn-sm.btn-primary,
@@ -218,6 +218,9 @@ a:hover {
.text-primary {
color: #23536f;
}
.far fa-life-ring {
color: var(--link);
}
.fixed-table-container tbody .selected td {
background-color: #fff8af;
}
+4 -1
View File
@@ -123,7 +123,7 @@
border-bottom-left-radius: 0;
}
.skin-blue.layout-top-nav .main-header > .logo .logo-variant {
background-color: none;
background-color: unset;
}
.btn.btn-primary,
btn-sm.btn-primary,
@@ -218,6 +218,9 @@ a:hover {
.text-primary {
color: #23536f;
}
.far fa-life-ring {
color: var(--link);
}
.fixed-table-container tbody .selected td {
background-color: #fff8af;
}
+3
View File
@@ -205,6 +205,9 @@ a:visited {
.bootstrap-table .fixed-table-container .table thead th .sortable {
color: var(--nav-link);
}
.far fa-life-ring {
color: var(--link);
}
.thead,
.navbar-nav > li > a:link {
color: var(--nav-link);
+3
View File
@@ -205,6 +205,9 @@ a:visited {
.bootstrap-table .fixed-table-container .table thead th .sortable {
color: var(--nav-link);
}
.far fa-life-ring {
color: var(--link);
}
.thead,
.navbar-nav > li > a:link {
color: var(--nav-link);
+3
View File
@@ -195,6 +195,9 @@ a:visited {
.text-primary {
color: #004023;
}
.far fa-life-ring {
color: var(--link);
}
.fixed-table-container tbody .selected td {
background-color: #fff8af;
}
+3
View File
@@ -195,6 +195,9 @@ a:visited {
.text-primary {
color: #004023;
}
.far fa-life-ring {
color: var(--link);
}
.fixed-table-container tbody .selected td {
background-color: #fff8af;
}
+3
View File
@@ -196,6 +196,9 @@ li.dropdown-item-marker {
background: linear-gradient(to bottom, var(--header) 0%, var(--header) 100%);
border-color: var(--header);
}
.far fa-life-ring {
color: var(--link);
}
.bootstrap-table .fixed-table-container .table thead th .sortable {
color: var(--nav-link);
}
+3
View File
@@ -196,6 +196,9 @@ li.dropdown-item-marker {
background: linear-gradient(to bottom, var(--header) 0%, var(--header) 100%);
border-color: var(--header);
}
.far fa-life-ring {
color: var(--link);
}
.bootstrap-table .fixed-table-container .table thead th .sortable {
color: var(--nav-link);
}
+3
View File
@@ -190,6 +190,9 @@ a.btn-warning:visited,
a.btn-danger:visited {
color: #FFF;
}
.far fa-life-ring {
color: var(--link);
}
.fixed-table-container tbody .selected td {
background-color: #fff8af;
}
+3
View File
@@ -190,6 +190,9 @@ a.btn-warning:visited,
a.btn-danger:visited {
color: #FFF;
}
.far fa-life-ring {
color: var(--link);
}
.fixed-table-container tbody .selected td {
background-color: #fff8af;
}
+3
View File
@@ -223,6 +223,9 @@ a:visited {
a:link {
color: var(--link);
}
.far fa-life-ring {
color: var(--link);
}
.btn-primary.hover {
color: var(--nav-link);
}
+3
View File
@@ -223,6 +223,9 @@ a:visited {
a:link {
color: var(--link);
}
.far fa-life-ring {
color: var(--link);
}
.btn-primary.hover {
color: var(--nav-link);
}
+3
View File
@@ -196,6 +196,9 @@ a.btn-danger:visited {
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background-color: #605ca8;
}
.far fa-life-ring {
color: var(--link);
}
.search-highlight,
.search-highlight:hover {
background-color: #e9d15b;
+3
View File
@@ -196,6 +196,9 @@ a.btn-danger:visited {
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background-color: #605ca8;
}
.far fa-life-ring {
color: var(--link);
}
.search-highlight,
.search-highlight:hover {
background-color: #e9d15b;
+3
View File
@@ -226,6 +226,9 @@ a:visited {
a:hover {
color: var(--hover-link);
}
.far fa-life-ring {
color: var(--link);
}
.btn-primary.hover {
color: var(--nav-link);
}
+3
View File
@@ -226,6 +226,9 @@ a:visited {
a:hover {
color: var(--hover-link);
}
.far fa-life-ring {
color: var(--link);
}
.btn-primary.hover {
color: var(--nav-link);
}
+3
View File
@@ -207,4 +207,7 @@ a.btn-danger:visited {
.search-highlight:hover {
background-color: #e9d15b;
}
.far fa-life-ring {
color: var(--link);
}
+3
View File
@@ -207,4 +207,7 @@ a.btn-danger:visited {
.search-highlight:hover {
background-color: #e9d15b;
}
.far fa-life-ring {
color: var(--link);
}
+3
View File
@@ -217,6 +217,9 @@ a:link.btn-default {
text-decoration: none;
color: var(--nav-link) !important;
}
.far fa-life-ring {
color: var(--link);
}
#accessoriesTable > tbody > tr > td > nobr > a > i.fa {
color: var(--text-main);
}
+3
View File
@@ -217,6 +217,9 @@ a:link.btn-default {
text-decoration: none;
color: var(--nav-link) !important;
}
.far fa-life-ring {
color: var(--link);
}
#accessoriesTable > tbody > tr > td > nobr > a > i.fa {
color: var(--text-main);
}
+3
View File
@@ -214,4 +214,7 @@ a:visited {
.skin-yellow .main-header .navbar .nav > li > a {
color: #413F42;
}
.far fa-life-ring {
color: var(--link);
}

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