Compare commits

..

863 Commits

Author SHA1 Message Date
snipe d2daaf30eb Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2023-03-28 03:32:04 -07:00
snipe 6800098469 Bumped version for 6.1.0-pre
Signed-off-by: snipe <snipe@snipe.net>
2023-03-28 03:31:02 -07:00
snipe 468805bab5 Merge pull request #12732 from svpernova09/preflight-translation-string-fixes
User preflight fix translation strings w/ bad path
2023-03-27 10:43:13 -07:00
Joe Ferguson cd49f65c0b User preflight fix translation strings w/ bad path 2023-03-24 15:27:08 -05:00
snipe dcbd216e2c Merge remote-tracking branch 'origin/develop' 2023-03-24 08:29:22 -07:00
snipe 008ba83128 Merge pull request #12729 from snipe/fixes/file_importer_string
Fixed translation string for importer
2023-03-24 08:28:51 -07:00
snipe 697cb4fe6d Fixed translation string for importer
Signed-off-by: snipe <snipe@snipe.net>
2023-03-24 08:27:53 -07:00
snipe 8a395d63a1 Merge remote-tracking branch 'origin/develop' 2023-03-24 07:23:06 -07:00
snipe 4d1e28ad03 Merge pull request #12727 from snipe/fixes/add_json_to_mimes
Fixed #12641 - added JSON to mimes
2023-03-24 07:22:30 -07:00
snipe 47eccb665e Merge pull request #12728 from snipe/fixes/fixes_typo_in_category_list
Use single “accessory” translation
2023-03-24 07:19:59 -07:00
snipe 150a2b572e Use single “accessory” translation
Signed-off-by: snipe <snipe@snipe.net>
2023-03-24 07:14:02 -07:00
snipe 6bc0df73e8 Merge pull request #12661 from Godmartinz/gh12655_missing_translations
Adds translations for category types to index and edit of categories
2023-03-24 07:09:40 -07:00
snipe 16dcc2d3ed Fixed #12641 - add JSON to mimes
Signed-off-by: snipe <snipe@snipe.net>
2023-03-24 06:57:43 -07:00
snipe 43c286c61f Merge remote-tracking branch 'origin/develop' 2023-03-24 06:18:10 -07:00
snipe aa4bdd4eb3 Merge pull request #12726 from snipe/fixes/12724_custom_fields
Fixed #12724 - fieldset not saving on model
2023-03-24 06:17:42 -07:00
snipe e869b1fd53 Fixed #12724 - fieldset not saving on model
Signed-off-by: snipe <snipe@snipe.net>
2023-03-24 06:11:24 -07:00
snipe 13ad69ee75 Merge pull request #12713 from inietov/fixes/trying_access_array_offset_null
Fixed Trying to access array offset on value of type null [sc-20528]
2023-03-24 04:52:56 -07:00
snipe 642d1e9f36 Merge pull request #12720 from inietov/fixes/undefined_array_key_266
Fixed Undefined array key 266 rollbar 17086
2023-03-24 04:50:47 -07:00
snipe 3792d3fdd2 Merge pull request #12721 from marcusmoore/fixes/allow-migrating-sqlite
Fixes the migration of sqlite databases
2023-03-24 04:50:15 -07:00
Marcus Moore 317335e79f Allow the migration of sqlite databases 2023-03-23 17:40:03 -07:00
Ivan Nieto Vivanco fbb3684022 Add a condition to 'restart' the color index for the status pie chart 2023-03-23 12:43:02 -06:00
snipe b91e914a61 Merge remote-tracking branch 'origin/develop' 2023-03-23 10:55:58 -07:00
snipe fc3672c119 Merge pull request #12717 from marcusmoore/fixes/update-slack-property-names
Fixes calls to changed webhook properties names
2023-03-23 10:55:02 -07:00
Marcus Moore 9d2c4a4dee Update webhook message 2023-03-23 10:38:35 -07:00
Marcus Moore fe6295a5e4 Update slack_* properties to webhook_* 2023-03-22 14:43:00 -07:00
Ivan Nieto Vivanco aa8dfcf89f Added a ternary to avoid null offset in array 2023-03-22 13:48:23 -06:00
snipe e8e1ada776 Merge pull request #12669 from akemidx/feature/sc-20178
#20178: Added Dell and Lenovo to warranty link function
2023-03-22 00:54:40 -07:00
snipe 58ea1592bb Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/js/build/app.js
#	public/js/dist/all.js
#	public/mix-manifest.json
#	resources/views/livewire/slack-settings-form.blade.php
2023-03-22 00:26:15 -07:00
snipe f3785acf4d Merge pull request #12710 from snipe/localization/fixing_a_few_more_hardcoded_strings
Handled a few more hard-coded strings
2023-03-22 00:22:06 -07:00
snipe 545d023a18 Handled a few more hard-coded strings
Signed-off-by: snipe <snipe@snipe.net>
2023-03-21 23:56:07 -07:00
snipe 473211397f Merge pull request #12708 from uberbrady/livewire_importer_no_subcomponent
Livewire importer without subcomponent
2023-03-21 23:07:04 -07:00
snipe e28d4fa588 Merge pull request #12709 from snipe/fixes/null_location_in_bulk_users
Ability to remove user location from users
2023-03-21 23:04:31 -07:00
snipe e08327be95 Ability to remove user location from users
Rework of #9677 - sorry @godmartinez - I suck :(

Signed-off-by: snipe <snipe@snipe.net>
2023-03-21 23:03:57 -07:00
snipe 418ce75a9f Merge pull request #11431 from ntbutler-nbcs/develop
[Fix / Minor Change] Asset checkinbytag now consistent with existingAPI
2023-03-21 22:40:21 -07:00
Brady Wetherington 6fe520a55d Hooked various the contents of the components together 2023-03-21 22:26:32 -07:00
snipe 0418d390f0 Corrected width to 100%
I should not be allowed to touch computers

Signed-off-by: snipe <snipe@snipe.net>
2023-03-21 22:25:15 -07:00
snipe b3d5bb75a3 Apply master patch to develop because I am an idiot on the wrong branch
Signed-off-by: snipe <snipe@snipe.net>
2023-03-21 22:23:09 -07:00
snipe 5346ebba94 Make select2 list in slack settings not searchable
Signed-off-by: snipe <snipe@snipe.net>
2023-03-21 22:21:21 -07:00
snipe 6c2c36469a Merge remote-tracking branch 'origin/develop' 2023-03-21 22:18:53 -07:00
snipe 1fa9f80c03 Correctly disable the select2 in demo mode
Signed-off-by: snipe <snipe@snipe.net>
2023-03-21 22:18:42 -07:00
snipe 4efac7827b Trying other save method, I guess?
Signed-off-by: snipe <snipe@snipe.net>
2023-03-21 22:10:30 -07:00
snipe b45dc09f57 Merge pull request #12707 from snipe/fixes/fixed_migration_for_demo
Fixes back-in-time Slack v slack migration
2023-03-21 22:01:17 -07:00
snipe 76425ca2a5 Fixes back-in-time Slack v slack migration
Signed-off-by: snipe <snipe@snipe.net>
2023-03-21 21:59:17 -07:00
snipe e609130291 Merge pull request #12706 from snipe/fixes/static_helper
Forgot the static method declaration - derp
2023-03-21 21:21:56 -07:00
snipe 41eb2464e2 Forgot the static method declaration - derp
Signed-off-by: snipe <snipe@snipe.net>
2023-03-21 21:21:01 -07:00
snipe 8aec28fad6 Merge remote-tracking branch 'origin/develop' 2023-03-21 21:14:06 -07:00
snipe e55fc4d047 Merge pull request #12705 from snipe/fixes/webhook_ui
Slack webhook UI tweaks, added select2
2023-03-21 21:11:14 -07:00
snipe e40762cf7f Small anal-retentive spacing/indenting tweaks
Signed-off-by: snipe <snipe@snipe.net>
2023-03-21 21:00:43 -07:00
snipe 2d3ddd1c7a Fixed default value for webhook_selected
Signed-off-by: snipe <snipe@snipe.net>
2023-03-21 20:56:08 -07:00
snipe 637438ccf6 Added select2 to slack settings
Signed-off-by: snipe <snipe@snipe.net>
2023-03-21 20:00:11 -07:00
snipe 647f47cdfe Check for demo mode in the clear method for the controller
Signed-off-by: snipe <snipe@snipe.net>
2023-03-21 19:27:05 -07:00
snipe a14d1b981d Switched singleton to static helper method
Signed-off-by: snipe <snipe@snipe.net>
2023-03-21 19:22:18 -07:00
snipe 5217141dfb Yuck, but added helper function to return the demo mode form warning
Signed-off-by: snipe <snipe@snipe.net>
2023-03-21 18:59:34 -07:00
snipe b28a25f544 Normalize the flash session to the way we do it elsewhere
Signed-off-by: snipe <snipe@snipe.net>
2023-03-21 18:59:18 -07:00
snipe d55ae44638 Helper method to make it easier (shorter) to determine if the app is in demo mode
Signed-off-by: snipe <snipe@snipe.net>
2023-03-21 18:59:03 -07:00
snipe f29e813332 Translated “Clear & Save”
Signed-off-by: snipe <snipe@snipe.net>
2023-03-21 18:58:35 -07:00
snipe d883084830 Fixed some funky HTML tags
Signed-off-by: snipe <snipe@snipe.net>
2023-03-21 18:58:26 -07:00
snipe 658252125e Added new partial for the form inline “demo mode”
Signed-off-by: snipe <snipe@snipe.net>
2023-03-21 18:57:27 -07:00
snipe 35bef6625a Merge pull request #12703 from Godmartinz/webhook_clean_up
adds clear and save button, save button updates accordingly
2023-03-21 17:02:33 -07:00
snipe 342b399191 Merge pull request #12700 from marcusmoore/fixes/purify-factories
Purifies model factories
2023-03-21 16:52:30 -07:00
Godfrey M 2754277068 adds csrf token and missing divs 2023-03-21 16:12:46 -07:00
snipe 4cc29b76f0 Merge remote-tracking branch 'origin/develop' 2023-03-21 16:07:03 -07:00
snipe 7059a57be1 Merge pull request #12704 from snipe/features/next_audit_date
Added next audit date override in bulk asset edit
2023-03-21 16:02:37 -07:00
snipe c229d69cec Added next audit date override in bulk asset edit
Signed-off-by: snipe <snipe@snipe.net>
2023-03-21 16:01:41 -07:00
Godfrey M 3c28242a2e save button updates accordingly 2023-03-21 15:53:09 -07:00
snipe c41aa8ac7f Merge pull request #12701 from snipe/features/add_default_location_to_maintenance_report
Fixed #12682 - add default location to maintenance report
2023-03-21 13:55:09 -07:00
snipe ecb11c3a12 Fixed #12682 - add default location to maintenance report
Signed-off-by: snipe <snipe@snipe.net>
2023-03-21 13:52:21 -07:00
snipe 4f8542b71b Merge pull request #12680 from akemidx/clone_accessories
Clone accessories
2023-03-21 13:37:04 -07:00
akemidx bb7b655fd2 translating screen reader lines 2023-03-21 16:02:34 -04:00
akemidx 3134279a95 small edits 2023-03-21 15:48:53 -04:00
Marcus Moore 751abe1438 Re-add asset factory states 2023-03-21 09:54:55 -07:00
Marcus Moore d214bd0b06 Remove temporary command 2023-03-20 16:41:33 -07:00
Marcus Moore 3b16a65988 Merge branch 'develop' into fixes/purify-factories 2023-03-20 16:24:35 -07:00
Marcus Moore 918239961a Add simple test case for assets 2023-03-20 15:47:57 -07:00
Marcus Moore 272cc1adac Skip creating user when creating a setting since it isn't needed 2023-03-20 15:33:40 -07:00
Marcus Moore 16e3416225 Update test case 2023-03-20 14:27:45 -07:00
snipe 8012c966b0 Merge pull request #12696 from snipe/dependabot/github_actions/docker/build-push-action-4
Bump docker/build-push-action from 3 to 4
2023-03-20 14:19:44 -07:00
Marcus Moore a0e547c7fb Remove some unused imports 2023-03-20 14:18:59 -07:00
Marcus Moore 44a91f0a2b Seed license checkouts 2023-03-20 14:18:54 -07:00
dependabot[bot] 4537ab3d54 Bump docker/build-push-action from 3 to 4
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 3 to 4.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-20 21:18:50 +00:00
snipe 05b4170116 Merge pull request #12694 from uberbrady/config_cachable_if_no_rollbar
Fixed #12671: Re-enable config:cache when there's no Rollbar
2023-03-20 14:17:53 -07:00
Marcus Moore 92e0c59f89 Fix typo in Keyboard accessory name 2023-03-20 12:01:39 -07:00
Marcus Moore 1bad8e1fc2 Remove outdated comments 2023-03-20 11:42:15 -07:00
Marcus Moore 1fd574779b Remove unneeded or outdated comments and update imports 2023-03-20 11:39:27 -07:00
Marcus Moore a37d69fcf1 Replace remaining user_ids in factories 2023-03-20 11:19:34 -07:00
Brady Wetherington 3a4ca5acad Re-enable config:cache *only* if there's no Rollbar 2023-03-18 21:07:00 -07:00
Brady Wetherington 704a2ad858 WIP: trying to merge two LW components into one, not working yet 2023-03-18 20:31:56 -07:00
snipe 3a30f04b51 Merge remote-tracking branch 'origin/develop' 2023-03-18 12:00:42 -07:00
snipe f2a3c2a349 Merge pull request #12693 from snipe/fixes/use_statements
Updates the Gate “use” statement to be more specific
2023-03-18 12:00:23 -07:00
snipe f9e190eb32 Updates the Gate “use” statement to be more specific
Signed-off-by: snipe <snipe@snipe.net>
2023-03-18 11:58:09 -07:00
snipe de6b663833 Merge pull request #12692 from snipe/fixes/small_group_api_fixes
Corrected gates, added fillable
2023-03-18 11:56:15 -07:00
snipe 8dd3ae8a37 Corrected gates, added fillable
Signed-off-by: snipe <snipe@snipe.net>
2023-03-18 11:53:20 -07:00
snipe 03b4a87a65 Merge remote-tracking branch 'origin/develop' 2023-03-18 00:16:34 -07:00
snipe c7f4a93c17 Merge pull request #12691 from snipe/fixes/small_cleanup_for_bulk_delete_checkin
Small cleanup for bulk delete checkin
2023-03-18 00:16:15 -07:00
snipe 071a642509 Changed phrasing in translatons
Signed-off-by: snipe <snipe@snipe.net>
2023-03-18 00:15:28 -07:00
snipe e39a75f2cc Fixed min width on select2 bulk menus
Signed-off-by: snipe <snipe@snipe.net>
2023-03-18 00:14:57 -07:00
snipe ea4a37d8ef Fixed cancel button alignment
Signed-off-by: snipe <snipe@snipe.net>
2023-03-18 00:14:09 -07:00
snipe d7363a41c8 Merge remote-tracking branch 'origin/develop' 2023-03-17 17:30:32 -07:00
snipe 789c4b4df8 Merge pull request #12690 from snipe/features/more_merge_user_olish
More merge-user polishing
2023-03-17 17:29:12 -07:00
snipe 12a2d8ad49 Fixed admin ID
Signed-off-by: snipe <snipe@snipe.net>
2023-03-17 17:03:10 -07:00
snipe e47fc9527b Updated language
Signed-off-by: snipe <snipe@snipe.net>
2023-03-17 16:50:02 -07:00
snipe 820ae09a6f Reworked the layout of the confirm merge form a little
Signed-off-by: snipe <snipe@snipe.net>
2023-03-17 16:42:41 -07:00
snipe fb54a21e12 Added strings
Signed-off-by: snipe <snipe@snipe.net>
2023-03-17 16:42:22 -07:00
snipe b39fa1d987 Added merge icon
Signed-off-by: snipe <snipe@snipe.net>
2023-03-17 16:42:17 -07:00
snipe 28cc8f9d69 Nicer user history display
Signed-off-by: snipe <snipe@snipe.net>
2023-03-17 16:41:43 -07:00
snipe a54e50961e Added event and listener
Signed-off-by: snipe <snipe@snipe.net>
2023-03-17 16:41:33 -07:00
snipe 82dc57aa18 Renamed some variables, invoked the event listener
Signed-off-by: snipe <snipe@snipe.net>
2023-03-17 16:24:58 -07:00
snipe 9ac4efb912 Better commenting
Signed-off-by: snipe <snipe@snipe.net>
2023-03-17 16:24:38 -07:00
snipe a4e6b3c022 Merge remote-tracking branch 'origin/develop' 2023-03-17 02:48:51 -07:00
snipe c752e3bb86 Fixed divs
Signed-off-by: snipe <snipe@snipe.net>
2023-03-17 02:48:41 -07:00
snipe 934f43e104 Merge remote-tracking branch 'origin/develop' 2023-03-17 02:45:04 -07:00
snipe 1a8622dc3b Merge pull request #12689 from snipe/features/add_password_lock_and_use_new_strings
Features/add password lock and use new strings
2023-03-17 02:44:37 -07:00
snipe e557f03cc2 Disable submit if app is locked
Signed-off-by: snipe <snipe@snipe.net>
2023-03-17 02:43:33 -07:00
snipe 30cf7eb750 Disallow action in demo mode
Signed-off-by: snipe <snipe@snipe.net>
2023-03-17 02:42:50 -07:00
snipe ccdd6ef5e0 Merge remote-tracking branch 'origin/develop' 2023-03-16 23:14:47 -07:00
snipe 13a02ff241 Merge pull request #12687 from snipe/features/nicer_ui_for_merge
Made the table wider, used icons to compact space
2023-03-16 23:14:25 -07:00
snipe c93096b767 Made the table wider, used icons to compact space
Signed-off-by: snipe <snipe@snipe.net>
2023-03-16 23:13:05 -07:00
snipe 94a275f239 Merge remote-tracking branch 'origin/develop' 2023-03-16 22:50:11 -07:00
snipe d8d7ed4465 Merge pull request #12686 from snipe/features/added_email_and_username_to_merge_confirm
Added email and username to merge user confirmation screen
2023-03-16 22:49:54 -07:00
snipe 736777e1e6 Added email and username to merge user confirmation screen
Signed-off-by: snipe <snipe@snipe.net>
2023-03-16 22:48:20 -07:00
Marcus Moore 3849bb838d Make a few more factories a bit more pure 2023-03-16 18:29:51 -07:00
snipe 0ef8aba36f Merge remote-tracking branch 'origin/develop' 2023-03-16 18:20:57 -07:00
snipe f566a71658 Merge pull request #12685 from snipe/features/merge_users
Added user merge
2023-03-16 18:20:24 -07:00
snipe 0dd11575c5 Added merge controller
Signed-off-by: snipe <snipe@snipe.net>
2023-03-16 18:19:16 -07:00
snipe d3d26cb988 Added translations
Signed-off-by: snipe <snipe@snipe.net>
2023-03-16 18:19:03 -07:00
snipe 07fbbf5f7f Added merge to user menu
Signed-off-by: snipe <snipe@snipe.net>
2023-03-16 18:18:54 -07:00
snipe 0dfb51f642 User merge blade
Signed-off-by: snipe <snipe@snipe.net>
2023-03-16 18:18:32 -07:00
snipe 853e809ff8 Added route
Signed-off-by: snipe <snipe@snipe.net>
2023-03-16 18:18:26 -07:00
Marcus Moore 605f214597 Add properties necessary for factories to be called in isolation 2023-03-16 17:08:18 -07:00
Marcus Moore d9c1a548f1 Update deprecated faker calls 2023-03-16 17:07:46 -07:00
Marcus Moore 582c3b987b Update some faker calls 2023-03-16 16:38:21 -07:00
snipe ffd9bbd7c6 Merge remote-tracking branch 'origin/develop' 2023-03-16 16:27:41 -07:00
snipe ffb87a0a87 Merge pull request #12684 from snipe/features/added_console_command_to_normalize_names
Added console command to normalize capitalization on names
2023-03-16 16:24:33 -07:00
snipe 8f04342fc2 Added console command to normalize capitalization on names
Signed-off-by: snipe <snipe@snipe.net>
2023-03-16 16:23:52 -07:00
snipe d6434fa55a Merge pull request #12683 from snipe/fixes/additional_sort
Fixes/additional sort
2023-03-16 16:08:51 -07:00
snipe b374834999 Added extra order by switch for first_name and last_name
Signed-off-by: snipe <snipe@snipe.net>
2023-03-16 16:07:51 -07:00
snipe 5e4455f042 Deleted duplicate statement
Signed-off-by: snipe <snipe@snipe.net>
2023-03-16 16:07:36 -07:00
Marcus Moore f47a28f790 Actually remove unused methods 2023-03-16 15:40:16 -07:00
Marcus Moore ca677038b0 Remove unused methods 2023-03-16 15:39:02 -07:00
Marcus Moore a50ddb4a5d Improve actionlog factory and seeder 2023-03-16 15:25:23 -07:00
Marcus Moore daf6e9fa4b Seed assets with randomized locations 2023-03-16 14:23:40 -07:00
Marcus Moore 31630e3677 Seed licenses with categories 2023-03-16 13:47:02 -07:00
Marcus Moore 2f0f9586b1 Remove default category relationship from license factory 2023-03-16 13:46:30 -07:00
Marcus Moore a98cc01766 Seed users with departments 2023-03-16 13:25:35 -07:00
Marcus Moore 345946d6d4 Remove default department relationship from user factory 2023-03-16 13:25:02 -07:00
Marcus Moore 76861c0c30 Remove hard-coded manager_id in factory 2023-03-16 12:46:47 -07:00
Marcus Moore 7062b0acaa Remove hard-coded supplier_id in factories 2023-03-16 12:41:34 -07:00
Marcus Moore 0ec885bf18 Remove hard-coded fieldset_id in factories 2023-03-15 18:49:21 -07:00
Marcus Moore dfd6cf0d29 Improve factories for location relationships 2023-03-15 18:31:08 -07:00
snipe b64d7e38f2 Merge pull request #12679 from snipe/bug/sc-20451
Handle already-deleted license files more gracefully
2023-03-15 16:26:15 -07:00
Godfrey M 371e142bae removes unnecessary function 2023-03-15 15:57:45 -07:00
Marcus Moore b944945377 Remove hard-coded company_id in factories and update seeders 2023-03-15 14:12:34 -07:00
akemidx a8e2f72e25 accessory cloning, WITHOUT copying over the image. 2023-03-15 16:55:24 -04:00
snipe e9601bcf13 Handle already-deleted license files more gracefully
Signed-off-by: snipe <snipe@snipe.net>
2023-03-15 13:05:51 -07:00
snipe b89dcfbb8e Merge remote-tracking branch 'origin/develop' 2023-03-15 12:55:55 -07:00
akemidx 0909d94c8f actually added the icons haha 2023-03-15 15:07:07 -04:00
akemidx 68094b23b9 moved dell and levono icons to local machine 2023-03-15 15:02:33 -04:00
snipe fdacd5d5b5 Merge pull request #12636 from akemidx/feature/sc-20330/date-on-all-assigned-pdf
Datestamp on "Print All Assigned" generated form
2023-03-15 11:31:52 -07:00
akemidx f38f6f57ae fixed localization and formatting. simplified code to remove php snippet 2023-03-15 14:00:29 -04:00
akemidx a3353b8496 committing 2023-03-15 13:48:22 -04:00
snipe f463c02783 Merge remote-tracking branch 'origin/develop' 2023-03-14 19:56:26 -07:00
snipe 08e09a3215 Merge pull request #12675 from snipe/security/webpack_upgrade
Updated webpack
2023-03-14 19:55:42 -07:00
snipe 039a5dde7d Updated webpack
Signed-off-by: snipe <snipe@snipe.net>
2023-03-14 19:54:58 -07:00
snipe 3b3bdb6535 Merge remote-tracking branch 'origin/develop' 2023-03-14 19:03:59 -07:00
snipe 1968aebf78 Merge pull request #12674 from snipe/fixes/translation_variable_for_slack
Fixed missing variable in Slack hook test
2023-03-14 19:03:42 -07:00
snipe a0617edaf0 Fixed missing variable in Slack hook test
Signed-off-by: snipe <snipe@snipe.net>
2023-03-14 19:02:38 -07:00
snipe 723e4ebd15 Merge remote-tracking branch 'origin/develop' 2023-03-14 18:55:07 -07:00
Marcus Moore fb789eb048 Remove hard-coded depreciation_id in factories 2023-03-14 17:51:20 -07:00
snipe 4c66267f3b Merge pull request #12668 from inietov/fixes/undefined_array_key_0
Fixed ErrorException: Undefined array key 0 [sc-20424]
2023-03-14 17:10:04 -07:00
Marcus Moore f7577bff52 Merge branch 'develop' into fixes/purify-factories 2023-03-14 17:09:30 -07:00
snipe 322fd76353 Merge pull request #12664 from Godmartinz/The_final_lowercase
The final lowercase in webhooks
2023-03-14 17:09:20 -07:00
snipe c12d261fc8 Merge pull request #12673 from marcusmoore/fixes/fix-component-factory
Fixed Component factory
2023-03-14 17:05:38 -07:00
snipe a991bdd136 Merge pull request #12672 from inietov/fixes/consumable_factory_seeder
Fixed Consumable Factory Seeder
2023-03-14 17:04:33 -07:00
Marcus Moore 9cd8460e1e Add proper date format to purchase date in the component factory 2023-03-14 17:02:45 -07:00
Marcus Moore 72a61783a3 Inline two relationships in asset maintenance factory 2023-03-14 14:59:34 -07:00
snipe f0d05a7461 Merge branch 'develop' of https://github.com/snipe/snipe-it into develop 2023-03-14 14:34:11 -07:00
snipe 88624ff2c0 Add @marcusmoore as a contributor 2023-03-14 14:34:03 -07:00
snipe f71ee699f4 Add @spencerrlongg as a contributor 2023-03-14 14:33:31 -07:00
snipe ce83d3aec1 Merge pull request #12670 from spencerrlongg/bug/sc-20437
Catch Duplicate Headers in Asset History Import
2023-03-14 14:32:34 -07:00
slong753 60b70a4074 catch and redirect back with error 2023-03-14 16:07:09 -05:00
Marcus Moore 1ff094dd47 Remove hard-coded model_id in asset factory 2023-03-14 13:56:25 -07:00
Marcus Moore ef8007a890 Remove hard-coded status_id in asset factory 2023-03-14 13:24:50 -07:00
akemidx d50a5d1880 dell and lenovo icons/links added 2023-03-14 16:04:03 -04:00
Marcus Moore a2efe3fa67 Remove hard-coded category_id in factories 2023-03-14 12:50:02 -07:00
akemidx a9782b7e00 testing links 2023-03-14 15:26:44 -04:00
Marcus Moore 4c4101fe64 Fix key name 2023-03-14 12:04:31 -07:00
akemidx 9c5ee060d3 WIP string/int error 2023-03-14 15:01:56 -04:00
Marcus Moore 7cf424b914 Remove hard-coded manufacturer_id in factories 2023-03-14 12:01:23 -07:00
Marcus Moore e8ff7cc09c Remove hard-coded user_id in factories 2023-03-14 11:34:58 -07:00
snipe dfd9fcc5e0 Merge pull request #12599 from inietov/fixes/unknown_column_0_in_field_list
Fixed Column not found: 1054 Unknown column '0' in 'field list' [sc-20004]
2023-03-14 09:51:42 -07:00
snipe b83980299a Merge pull request #12667 from snipe/fixes/small_livewire_ui_fixed
Small UI tweaks
2023-03-14 09:47:45 -07:00
snipe 5a709a83e7 Small UI tweaks
Signed-off-by: snipe <snipe@snipe.net>
2023-03-14 09:38:30 -07:00
Ivan Nieto Vivanco 66bb897ac4 Fix format to purchase date 2023-03-14 02:55:20 -06:00
Ivan Nieto Vivanco 67471a3a77 Evaluate if the collection is empty before access the array index 2023-03-13 21:44:06 -06:00
Marcus Moore adba450b40 Remove some hard-coded ids in factories 2023-03-13 17:27:06 -07:00
snipe 7acf449ed3 Merge pull request #12665 from snipe/fixes/fixed_migration_for_smaller_chunking
Removed loading and reduced chunking to 10
2023-03-13 17:23:19 -07:00
Godfrey M 955d8313b2 the final lowercase 2023-03-13 17:14:02 -07:00
snipe 1b9c3c93ad Removed loading and reduced chunking to 10
Signed-off-by: snipe <snipe@snipe.net>
2023-03-13 17:12:51 -07:00
snipe a2667a7520 Merge pull request #12663 from Godmartinz/webhook_tweaks
fixes webhook variables to lowercase
2023-03-13 16:55:32 -07:00
Marcus Moore 099ec3f550 Remove creation of category within category factory state 2023-03-13 16:45:43 -07:00
Marcus Moore 6e6a021928 Add temporary command to display model counts 2023-03-13 16:44:47 -07:00
Godfrey M 1bd37b49e9 adds translations for webhook names 2023-03-13 16:13:02 -07:00
Ivan Nieto Vivanco d224f3177e Delete a rule that was breaking validation 2023-03-13 16:43:10 -06:00
Godfrey M 6474249ea8 uppercased names 2023-03-13 15:29:53 -07:00
Godfrey M 7612c5d852 lowercases variables 2023-03-13 15:26:51 -07:00
Ivan Nieto Vivanco e7b3daa80c Adjust validator to only receive valid groups id's 2023-03-13 16:10:08 -06:00
snipe 477bd27cba Merge pull request #12570 from Godmartinz/generalize_webhooks
Adds General option to the webhooks settings
2023-03-13 14:54:51 -07:00
Ivan Nieto Vivanco e4204a6dd1 Adds validator to PATCH request in the API UsersController 2023-03-13 15:49:05 -06:00
Godfrey M 11bf3f5285 aligned inputs 2023-03-13 14:06:05 -07:00
Godfrey M 576b8f8c48 adds translations to edit and index of categories 2023-03-13 13:33:03 -07:00
snipe cacb000693 Merge pull request #12660 from snipe/upgrades/bump_codacy
Bumped codacy workflow
2023-03-13 11:13:46 -07:00
snipe 4f772468e6 Bumped codacy workflow
Relates to #12657 but for develop

Signed-off-by: snipe <snipe@snipe.net>
2023-03-13 11:10:41 -07:00
Godfrey M 542332ea0c removes discord from rules 2023-03-13 10:54:18 -07:00
Godfrey M b6d105c4f4 removes help text from general integrations 2023-03-13 10:49:41 -07:00
Godfrey M 27a2ed5c79 Merge branch 'develop' into generalize_webhooks 2023-03-13 10:41:08 -07:00
snipe 8a977c66f0 Merge pull request #12659 from Godmartinz/update_notification_name
fixes alerts to notifications in notification settings
2023-03-13 09:57:43 -07:00
Godfrey M 82504c9764 updates alerts to notifications in notification settings 2023-03-13 09:51:25 -07:00
snipe 1e6a3b8c45 Add @floschoepfer as a contributor 2023-03-10 14:24:56 -08:00
snipe 785ba3b5ed Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
#	public/js/build/app.js
#	public/js/dist/all.js
#	public/mix-manifest.json
2023-03-10 14:23:45 -08:00
snipe d1d89f872a Merge pull request #12638 from snipe/fixes/dashboard_category_count_with_show_archived
Fixed #12635 - dashboard category should not show archived
2023-03-10 14:19:40 -08:00
snipe 58d2e658d2 Merge pull request #12648 from floschoepfer/patch-1
Fixed #12647: fix translation and adds icon on property reassignable
2023-03-10 14:13:48 -08:00
Florian 86205bc996 fix translation and adds icon on property reassignable
Fixing #12647
2023-03-10 10:36:42 +01:00
akemidx 4533982345 added time of day 2023-03-09 15:11:07 -05:00
snipe 65c2f27644 Merge pull request #12640 from marcusmoore/fix/test-suite
Fixes unit and feature test suite
2023-03-09 11:57:39 -08:00
snipe 88eb73d160 Use Carbon’s diffForHumans() method instead of our own home-grown stuff
Signed-off-by: snipe <snipe@snipe.net>
2023-03-08 16:47:54 -08:00
snipe f4bd307421 Added comments, removed gthe AgeFormat() helper method
Signed-off-by: snipe <snipe@snipe.net>
2023-03-08 16:47:27 -08:00
snipe 059ead5af5 Added comments (not related to this, sorry)
Signed-off-by: snipe <snipe@snipe.net>
2023-03-08 16:47:08 -08:00
snipe 02dd0669dc Added comments
Signed-off-by: snipe <snipe@snipe.net>
2023-03-08 16:36:08 -08:00
snipe b3b9efbaff New helper method to return icon type
Signed-off-by: snipe <snipe@snipe.net>
2023-03-08 16:34:04 -08:00
snipe a6f4e53e2b Added translation strings
Signed-off-by: snipe <snipe@snipe.net>
2023-03-08 16:33:49 -08:00
snipe fe470b32fc Added icon and import type to header, more translations
Signed-off-by: snipe <snipe@snipe.net>
2023-03-08 16:33:40 -08:00
snipe 474e32ea2a Added translations and formatting
Signed-off-by: snipe <snipe@snipe.net>
2023-03-08 16:33:02 -08:00
snipe b9e4b2a0ba Added some translations, date formatting, and filesize human reporting
Signed-off-by: snipe <snipe@snipe.net>
2023-03-08 16:32:45 -08:00
Brady Wetherington 087fe19ae7 Merge branch 'livewire_importer_2_squashed_and_rebased' of github.com:uberbrady/snipe-it into livewire_importer_2_squashed_and_rebased 2023-03-08 13:57:21 -08:00
Brady Wetherington 22d7d2a04e Aliases could get selected when they weren't for an import_type 2023-03-08 13:56:29 -08:00
snipe b8887bd3e3 Translated strings
Signed-off-by: snipe <snipe@snipe.net>
2023-03-08 13:47:56 -08:00
snipe 65c2d75c04 Added aliases
Signed-off-by: snipe <snipe@snipe.net>
2023-03-08 13:47:38 -08:00
snipe dccd6fd4b1 Duplicate withCount
Signed-off-by: snipe <snipe@snipe.net>
2023-03-08 13:06:14 -08:00
snipe 7f8bdbd252 Added showableAssets() relationship to Category model
Signed-off-by: snipe <snipe@snipe.net>
2023-03-08 13:01:38 -08:00
snipe 00896a8615 Updated comment
Signed-off-by: snipe <snipe@snipe.net>
2023-03-08 12:51:53 -08:00
Marcus Moore 44b48a954a Remove unneed section of testing docs 2023-03-08 12:15:37 -08:00
Marcus Moore 0be882dc35 Merge branch 'develop' into fix/test-suite 2023-03-08 12:13:53 -08:00
akemidx 2a4d30a748 forgot to add datestamp to title of page 2023-03-08 15:09:33 -05:00
Marcus Moore 5fb18af245 Update testing documentation 2023-03-08 11:58:36 -08:00
Marcus Moore 697824007a Move DB_CONNECTION back to .env.testing.example 2023-03-08 11:58:29 -08:00
akemidx cd9f2f7fb7 datestamp for print all assigned form generation 2023-03-08 14:56:14 -05:00
Godfrey M 15c19a7ab7 silenced Discord option and validation, more translations 2023-03-08 10:35:45 -08:00
snipe ac0b22d696 Updated dev assets
Signed-off-by: snipe <snipe@snipe.net>
2023-03-08 00:33:04 -08:00
snipe 1ed7cd27b4 Lots of HTML/CSS tweaks for better UI
Signed-off-by: snipe <snipe@snipe.net>
2023-03-08 00:32:30 -08:00
snipe e143e0c5ee Make the <tr> reflect that it’s active
Signed-off-by: snipe <snipe@snipe.net>
2023-03-08 00:32:16 -08:00
snipe 42601fecbf Merge branch 'livewire_importer_2_squashed_and_rebased' of https://github.com/uberbrady/snipe-it into uberbrady-livewire_importer_2_squashed_and_rebased 2023-03-07 21:42:32 -08:00
Brady Wetherington 7c09de3ea8 Re-introduce the 'placeholder' option for our form-helper 2023-03-07 21:38:55 -08:00
snipe 094859cfe8 Merge branch 'livewire_importer_2_squashed_and_rebased' of https://github.com/uberbrady/snipe-it into uberbrady-livewire_importer_2_squashed_and_rebased 2023-03-07 21:38:04 -08:00
Brady Wetherington 037489a6c0 If fields were already mapped, they would cause a 500 on re-mapping on import 2023-03-07 21:33:20 -08:00
snipe 5defd5ec0a Merge develop into master
Signed-off-by: snipe <snipe@snipe.net>
2023-03-07 19:59:17 -08:00
snipe e66b19aca0 Bumped hash
Signed-off-by: snipe <snipe@snipe.net>
2023-03-07 19:44:06 -08:00
snipe fd96ff0160 Add @kenchan0130 as a contributor 2023-03-07 19:42:52 -08:00
snipe 1ccedf6426 Merge pull request #12617 from kenchan0130/patch-12249
Fixed #12249: fix csv importer for serial_number field
2023-03-07 19:42:23 -08:00
snipe 8adeee41e6 Merge pull request #12633 from snipe/bug/sc-20332
Fixed 500 when admin erroneously tries to upload a tiff as logo, cleaned up logo upload layout
2023-03-07 19:41:10 -08:00
snipe 19d19a4c42 Updated language string
Signed-off-by: snipe <snipe@snipe.net>
2023-03-07 19:18:32 -08:00
snipe 383b5b43bb Added a few more jquery options for prevoew flexibility
Signed-off-by: snipe <snipe@snipe.net>
2023-03-07 18:54:38 -08:00
snipe 379c5f6790 Reworked the layout for logo upoloads
Signed-off-by: snipe <snipe@snipe.net>
2023-03-07 18:54:09 -08:00
snipe e55d02fd59 Added new string
Signed-off-by: snipe <snipe@snipe.net>
2023-03-07 18:53:53 -08:00
Brady Wetherington 942bedaf06 Re-add VIP and BYOD to importer, but in Livewire 2023-03-07 18:53:32 -08:00
Brady Wetherington 09c1298e03 Merge branch 'develop' into livewire_importer_2_squashed_and_rebased
I'll be taking in the changes to the importer front-end elsewhere
2023-03-07 18:51:05 -08:00
Brady Wetherington fe699737eb Add improved field-guessing logic; make sure 'do not map' fields work 2023-03-07 18:26:59 -08:00
Marcus Moore dd9c00195b Remove old $tester variable and usused imports 2023-03-07 17:04:46 -08:00
snipe e60fa15414 Nicer layout, but it kinda dosn’t work :(
Signed-off-by: snipe <snipe@snipe.net>
2023-03-07 17:02:52 -08:00
Marcus Moore 43ff7261b2 Remove redundant base test case 2023-03-07 16:57:55 -08:00
Marcus Moore 8c13a4c5c9 Use LazilyRefreshDatabase instead of RefreshDatabase 2023-03-07 16:43:18 -08:00
Godfrey M 69944853f9 more translations 2023-03-07 15:57:58 -08:00
snipe 45b5a8b6ab Catch exception if the file can’t be handled via Intervention
Signed-off-by: snipe <snipe@snipe.net>
2023-03-07 15:56:36 -08:00
Godfrey M 35dd0d8def adds generalized webhooks, updates settings page, translations, validation 2023-03-07 15:48:21 -08:00
snipe 8b70a7f216 Merge remote-tracking branch 'origin/develop' 2023-03-07 14:00:37 -08:00
snipe 182a5ea5fc Merge pull request #12631 from snipe/bug/sc-20297/expected-checkin-email-report-link-back-error
Dynamically determine target route for expected checkin emails
2023-03-07 13:57:26 -08:00
snipe ea54f540de Dynamically determine target route for expected checkin emails
Signed-off-by: snipe <snipe@snipe.net>
2023-03-07 13:42:51 -08:00
akemidx ec5836dab4 cloning accessories first bit 2023-03-07 16:41:48 -05:00
snipe e399015427 Merge pull request #12628 from marcusmoore/fixes/keep-asset-name-on-import
Maintain asset name during import with checkout
2023-03-07 11:22:53 -08:00
Marcus Moore c80595e05c Ensure asset name is maintained when importing assets that are checked out 2023-03-07 11:09:25 -08:00
Marcus Moore 8fad377114 Remove helper methods by inlining where needed 2023-03-07 10:28:33 -08:00
Tadayuki Onishi f4675927a0 fix csv importer for serial_number filed
Signed-off-by: Tadayuki Onishi <tt.tanishi100@gmail.com>
2023-03-07 22:53:02 +09:00
Marcus Moore a3c8c3757a Remove unused method 2023-03-06 17:50:44 -08:00
Marcus Moore ddcb8d8dd9 Remove commited .env.testing file 2023-03-06 17:37:08 -08:00
Marcus Moore 245f0aff72 Ignore the correct env file 2023-03-06 17:35:49 -08:00
Marcus Moore ba92501670 Add .env.testing.example file 2023-03-06 17:34:43 -08:00
Marcus Moore 9aad981895 Update phpunit schema location and remove unneeded environment variable 2023-03-06 17:25:03 -08:00
Marcus Moore a24d734ee9 Alphabetize keys in phpunit.xml 2023-03-06 17:24:09 -08:00
snipe c7fb542dc3 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/js/build/app.js
#	public/js/dist/all.js
#	public/mix-manifest.json
2023-03-06 17:13:29 -08:00
snipe 1ebbc767f1 Merge pull request #12624 from snipe/features/added_vip_and_byod_to_importer
Added `vip` and `byod` to importer
2023-03-06 17:11:28 -08:00
snipe a34cb8b862 Check for boolean on requestable
Signed-off-by: snipe <snipe@snipe.net>
2023-03-06 17:11:08 -08:00
snipe d36b4c1bd3 Merge remote-tracking branch 'origin/develop' 2023-03-06 17:04:15 -08:00
Marcus Moore d27fe7d4b9 Merge branch 'develop' into fix/test-suite 2023-03-06 17:04:00 -08:00
snipe d55393a3d9 Merge pull request #12626 from marcusmoore/fixes/checkouts-in-seeders
Fix seeder so assets are checked out to users
2023-03-06 17:01:47 -08:00
Marcus Moore ef27c35d1d Update array keys to set asset location properly 2023-03-06 16:33:40 -08:00
snipe 0d3388b3ae Merge pull request #12623 from snipe/bug/sc-20254/errorexception-filesize-stat-failed-for-snipe
Check that the file exists before trying to stat it for filesize
2023-03-06 15:43:17 -08:00
snipe fffe5da2e0 Merge pull request #12625 from uberbrady/quiet_down_scim_exceptions
Suppress SCIMExceptions from cluttering up Rollbar
2023-03-06 15:42:58 -08:00
Brady Wetherington dd3c3a1428 Suppress SCIMExceptions from cluttering up Rollbar 2023-03-06 15:24:16 -08:00
snipe 16bd2cde0f Updated string for file not found
Signed-off-by: snipe <snipe@snipe.net>
2023-03-06 15:09:45 -08:00
snipe e1069ac234 Return a file not found error if it doesn’t appear on disk
Signed-off-by: snipe <snipe@snipe.net>
2023-03-06 15:09:37 -08:00
snipe 8b6e8898c1 Fixed hardcoded string
Signed-off-by: snipe <snipe@snipe.net>
2023-03-06 15:09:12 -08:00
snipe 2cb06165c4 Added missing vip field to transformer and request
Signed-off-by: snipe <snipe@snipe.net>
2023-03-06 15:00:04 -08:00
snipe b46c455e0a Updated mappings.md with byod and vip fields
Signed-off-by: snipe <snipe@snipe.net>
2023-03-06 14:28:34 -08:00
snipe 304ccaa30e Added byod to asset importer
Signed-off-by: snipe <snipe@snipe.net>
2023-03-06 14:28:24 -08:00
snipe f672bdd3b7 Added vip to user importer
Signed-off-by: snipe <snipe@snipe.net>
2023-03-06 14:28:14 -08:00
snipe eec5163e7f Updated vue assets
Signed-off-by: snipe <snipe@snipe.net>
2023-03-06 14:28:04 -08:00
snipe f460d881da Updated vue
Signed-off-by: snipe <snipe@snipe.net>
2023-03-06 14:27:53 -08:00
snipe 27a495223d Updated sample CSVs
Signed-off-by: snipe <snipe@snipe.net>
2023-03-06 14:27:45 -08:00
Marcus Moore bc54144284 Fix test by passing proper user 2023-03-06 12:40:47 -08:00
snipe cc7325074e Check that the file exists before trying to stat it for filesize
Signed-off-by: snipe <snipe@snipe.net>
2023-03-06 10:47:28 -08:00
snipe 04ff472428 Merge remote-tracking branch 'origin/develop' 2023-03-06 10:29:07 -08:00
snipe 3a1cf26e98 Merge pull request #12621 from Godmartinz/bug/sc-20259/divisionbyzeroerror-division-by-zero-in-snipe
Fixes depreciation model rule for months
2023-03-06 10:28:39 -08:00
Godfrey M e5deb4b413 doesn't allow months to be zero 2023-03-06 09:41:14 -08:00
snipe f54d83ed59 Merge pull request #12612 from manuteleco/add_path_in_preflight_url_message
Fixed #11800: Include path in the expected URL during Pre-Flight
2023-03-06 09:36:15 -08:00
snipe 39193a71b7 Merge pull request #12611 from manuteleco/add_reverse_proxy_support_in_preflight
Fixed #10779: Add Reverse Proxy support to Pre-Flight URL check
2023-03-06 09:35:34 -08:00
snipe 83b906b153 Merge remote-tracking branch 'origin/develop' 2023-03-06 09:27:43 -08:00
snipe 191f955333 Merge pull request #12610 from veenone/feat/sortable_group_id
enable sortable for ID column
2023-03-06 09:26:52 -08:00
Manuel Rodríguez Guimeráns 548ae7ad22 Add Reverse Proxy support to Pre-Flight URL check
Before this change, the Pre-Flight URL check would inevitably fail
whenever Snipe-IT was running behind a reverse proxy or load balancer.

The URL check tries to ensure that the configured application URL
matches the URL that is actually used to reach the application. However,
when running behind an HTTP intermediary (like a reverse proxy or a load
balancer) the HTTP connection that Snipe-IT receives is not the _real_
connection from the user anymore, but a connection from the HTTP
intermediary. The scheme, host and port that Snipe-IT would obtain from
that incoming intermediary connection wouldn't match what is configured
as application URL and, therefore, the URL check would fail.

This commit solves the situation by making Snipe-IT's Pre-Flight URL
check aware of the `X-Forwarded-Proto` and `X-Forwarded-Host` HTTP
headers. These headers represent the _de-facto_ standard used by reverse
proxies and other HTTP intermediary components to convey information
about the incoming HTTP connection to the upstream application. Being
the upstream application, Snipe-IT can then make use of this information
to correctly evaluate the validity of the configured application URL.
2023-03-05 18:15:16 +01:00
Manuel Rodríguez Guimeráns 1d4f4b92de Include path in the expected URL during Pre-Flight
So that the message displayed to the user when the URL Pre-Flight check
fails is:

> Snipe-IT thinks your URL is SCHEME://DOMAIN, but your real
  URL is SCHEME://DOMAIN/setup

instead of:

> Snipe-IT thinks your URL is SCHEME://DOMAIN/setup, but your real
  URL is SCHEME://DOMAIN/setup

Having a missing "/setup" in the expected URL might confuse the user
into thinking that it is an additional configuration problem they need
to fix.

With this change, the comparison between the expected and actual URL
will not contain any accidental difference anymore. Only those that the
user really needs to be aware of and fix in their setup.
2023-03-05 17:52:45 +01:00
Achmad Fienan Rahardianto 0b3becee7a enable sortable for ID column 2023-03-04 11:27:00 +07:00
Ivan Nieto Vivanco 95f568b934 Remove unnecessary try/catch 2023-03-02 19:50:47 -06:00
snipe 95bd58487a Merge pull request #12602 from inietov/fixes/error_checkin_license_seat
Fixed #12601 Error checkin license seats
2023-03-02 17:48:22 -08:00
Ivan Nieto Vivanco 8a5d426ccd Use correct LicenseSeat property 2023-03-02 19:33:32 -06:00
Marcus Moore e8da6d8bac Set purchase date in correct format 2023-03-02 13:47:58 -08:00
Marcus Moore ad9eef6393 Update deprecated faker calls in Asset and Supplier factories 2023-03-02 13:41:52 -08:00
Marcus Moore c3cc20fe0c Merge branch 'develop' into fix/test-suite 2023-03-02 13:23:00 -08:00
snipe f817027fc2 Merge pull request #12593 from snipe/features/add_clone_to_locations
Added ability to clone location
2023-03-02 13:15:38 -08:00
Marcus Moore 45d7e9b134 Switch to using LazilyRefreshDatabase in unit test suite 2023-03-02 13:13:30 -08:00
Marcus Moore 75fc624ec6 Globally disable SecurityHeaders in tests 2023-03-02 13:12:25 -08:00
Ivan Nieto Vivanco e0b2dc043a Adds try/catch to users API 2023-03-02 11:13:56 -06:00
Brady Wetherington 7edec26e73 Fixes to layout, improvements to import types, better icons for processing. 2023-03-01 17:18:36 -08:00
Godfrey M aae178a606 gets select working, placeholders update dynamically 2023-03-01 17:10:10 -08:00
snipe 778787db3c Rip out jquery for location parent
Signed-off-by: snipe <snipe@snipe.net>
2023-03-01 15:36:01 -08:00
snipe b8231f420b Remove name from blanking paroperties
Signed-off-by: snipe <snipe@snipe.net>
2023-03-01 14:12:33 -08:00
snipe 9b522006f3 Usew route group for locations
Signed-off-by: snipe <snipe@snipe.net>
2023-03-01 14:05:53 -08:00
snipe 84a14918bb Updated comments
Signed-off-by: snipe <snipe@snipe.net>
2023-03-01 14:03:33 -08:00
snipe 473553c464 Moved gate
Signed-off-by: snipe <snipe@snipe.net>
2023-03-01 14:01:40 -08:00
snipe dac877f184 Added location clone
Signed-off-by: snipe <snipe@snipe.net>
2023-03-01 13:51:35 -08:00
Godfrey M 354f04534e add multi array, migration, still having issues 2023-03-01 12:30:32 -08:00
snipe ca2619ca12 Merge remote-tracking branch 'origin/develop' 2023-03-01 12:28:34 -08:00
snipe 78b36c7886 Merge pull request #12592 from uberbrady/fix_accessories_report
The 'download activity report' displayed the wrong value for 'admin' (fixes FD-33368)
2023-03-01 12:28:03 -08:00
Brady Wetherington ca849db316 The 'download activity report' displayed the wrong value for 'admin' 2023-03-01 12:23:13 -08:00
snipe 816d2f99cc Merge remote-tracking branch 'origin/develop' 2023-03-01 11:52:29 -08:00
snipe c1b57064d4 Merge pull request #12591 from uberbrady/accessories_report_companies
Actually display name of company in Accessories Report
2023-03-01 11:52:10 -08:00
Brady Wetherington 9b80e86306 Actually display name of company in Accessories Report 2023-03-01 11:34:30 -08:00
snipe d954c841e6 Merge pull request #12590 from snipe/fixes/check_for_array_in_linux_setup
Fixes/check for array in linux setup
2023-03-01 11:06:31 -08:00
snipe 562546a853 Updated comment
Signed-off-by: snipe <snipe@snipe.net>
2023-02-28 23:37:30 -08:00
snipe 4860440306 Check that it’s an array (versus checking that it’s not a bool)
Signed-off-by: snipe <snipe@snipe.net>
2023-02-28 23:32:10 -08:00
snipe b72a9cc6fd Check if the $owner is boolean
Signed-off-by: snipe <snipe@snipe.net>
2023-02-28 23:31:26 -08:00
snipe 823203641d Updated assets with new font awesome
Signed-off-by: snipe <snipe@snipe.net>
2023-02-28 23:18:58 -08:00
snipe b2fe3c36e9 Merge pull request #12589 from snipe/security/update_font_awesome_to_6_3_0
Updated font-awesome to ^6.3.0
2023-02-28 23:16:54 -08:00
snipe 1911480d3a Updated font-awesome to ^6.3.0
Signed-off-by: snipe <snipe@snipe.net>
2023-02-28 23:15:50 -08:00
Brady Wetherington c48e19d236 Whoops, went a little overboard there. Whoopsie! 2023-02-28 22:51:48 -08:00
Brady Wetherington 863b30a07a Remove extraneous change to composer.json 2023-02-28 22:49:48 -08:00
Brady Wetherington f3c500014c Another file I didn't really need to commit 2023-02-28 22:37:16 -08:00
Brady Wetherington 4f8710db63 Whoops, mis-committed something here that doesn't belong 2023-02-28 22:36:26 -08:00
Brady Wetherington 54cb38603b Cleaned up the last of the FIXME's (or downgraded them to TODO's) 2023-02-28 22:34:44 -08:00
Brady Wetherington 5cf66851f7 Finalizing the Livewire Importer! Just going to do some testing now 2023-02-28 21:58:02 -08:00
snipe a6816c5e15 Merge remote-tracking branch 'origin/develop' 2023-02-28 20:53:32 -08:00
snipe 463ef02fae Merge pull request #12578 from inietov/fixes/undefined_variable_total
Fixed Undefined variable `$total`
2023-02-28 20:50:00 -08:00
snipe b29276579f Updated prod assets
Signed-off-by: snipe <snipe@snipe.net>
2023-02-28 20:34:31 -08:00
snipe dbe0a3352b Updated prod assets
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/css/build/app.css
#	public/css/build/overrides.css
#	public/css/dist/all.css
#	public/mix-manifest.json
2023-02-28 20:34:20 -08:00
snipe 6fec3f4303 Merge pull request #12586 from snipe/assets/compiled_dev_assets
Compiled dev assets
2023-02-28 20:32:41 -08:00
snipe f9b5a67dc2 Compiled dev assets
Signed-off-by: snipe <snipe@snipe.net>
2023-02-28 20:32:08 -08:00
snipe 2189a74d6a Bumped hash
Signed-off-by: snipe <snipe@snipe.net>
2023-02-28 20:32:00 -08:00
snipe 44e2796645 Merge pull request #12579 from Godmartinz/gh12571_sidebar_adjustment
Fixes the sidebar margin top
2023-02-28 20:30:07 -08:00
snipe 70d0347fe9 Merge pull request #12580 from marcusmoore/feature/crowdin-source-upload
Add GitHub Action to push translation sources to Crowdin
2023-02-28 20:28:04 -08:00
Brady Wetherington 2f94bf96ff Everything's all wired up; just need to clean up all the FIXME's and stuff 2023-02-28 18:36:52 -08:00
snipe 417a1e624a Merge remote-tracking branch 'origin/develop' 2023-02-28 18:22:24 -08:00
snipe 34f13eaa8a Merge pull request #12393 from snipe/features/make_eol_sortable
Added EOL as de-normed and sortable on assets
2023-02-28 18:22:00 -08:00
snipe 1f7ae08d76 Merge branch 'develop' into features/make_eol_sortable 2023-02-28 18:05:09 -08:00
snipe 3a4e20ae82 Merge remote-tracking branch 'origin/develop' 2023-02-28 16:57:59 -08:00
snipe 2ab0abc8a1 Merge pull request #12575 from inietov/fixes/typeError_get_class_argument_must_be_object_null_given
Fixed: TypeError: get_class(): Argument #1 ($object) must be of type object, null given
2023-02-28 16:45:53 -08:00
snipe 373aeb26da Merge remote-tracking branch 'origin/develop' 2023-02-28 16:14:42 -08:00
snipe d838662f48 Merge pull request #12585 from marcusmoore/fixes/fix-license-seeder
Fix license seeder
2023-02-28 16:03:15 -08:00
snipe ff122bd07c Merge remote-tracking branch 'origin/develop' 2023-02-28 15:56:35 -08:00
snipe 5e626e75ad Merge pull request #12584 from snipe/fixes/error_on_datepicker
Convert string to date object for formatting
2023-02-28 15:55:59 -08:00
Marcus Moore a7a26bb154 Fix License Factory 2023-02-28 15:55:28 -08:00
snipe af9f9d2523 Convert string to date object for formatting
Signed-off-by: snipe <snipe@snipe.net>
2023-02-28 15:48:45 -08:00
snipe d13e1b32e7 Merge pull request #12583 from inietov/fixes/user_start_and_end_date_error
Fixed User start and end date throws error [sc-20228]
2023-02-28 15:30:46 -08:00
Ivan Nieto Vivanco ad598425ef Adds format to the dates cast 2023-02-28 17:24:14 -06:00
snipe ec2ce1dff8 Merge remote-tracking branch 'origin/develop' 2023-02-28 15:13:22 -08:00
snipe 5194711a6a Merge pull request #12582 from akemidx/bug/sc-20065/license-export-does-not-show-info-of-boolean 2023-02-28 15:13:04 -08:00
Marcus Moore 4197e613b2 Fix License Factory 2023-02-28 14:50:48 -08:00
akemidx 25f3e4d41a Adding ability to see boolean values when using normal export 2023-02-28 16:01:23 -05:00
Marcus Moore 589a5d0d8b Merge branch 'develop' into fix/test-suite 2023-02-28 09:48:48 -08:00
Godfrey M e8fbb0608f adjusts the sidebar margin top 2023-02-28 09:30:02 -08:00
Marcus Moore d707f2d391 Add GitHub Action to push translation sources to Crowdin 2023-02-28 09:07:34 -08:00
Ivan Nieto Vivanco 1be0a8d911 Declare variable as an empty array 2023-02-28 10:22:49 -06:00
Ivan Nieto Vivanco 0d860c0b72 Check if target is not null to retrieve the proper data 2023-02-27 19:01:37 -06:00
Ivan Nieto Vivanco 9d94bd6567 Validate if the license seat is not checked out, it can't be checked in 2023-02-27 18:57:38 -06:00
snipe ae35af55d1 Merge remote-tracking branch 'origin/develop' 2023-02-27 15:55:58 -08:00
snipe 23fe11c71e Merge pull request #12574 from inietov/fixes/address_in_mailbox_not_comply_rfc
Fixed Address in mailbox given does not comply with RFC 2822, 3.6.2. [sc-202022]
2023-02-27 15:55:31 -08:00
Ivan Nieto Vivanco b4e578c95e Convert the alert_email setting from string to array 2023-02-27 17:34:29 -06:00
Brady Wetherington 53db266b69 WIP: cleaning up extraneous gunk and trying to standardize on one single Livewire Select2 implementation 2023-02-27 14:29:02 -08:00
Brady Wetherington fb201e61f3 More wiring up Livewire to the back-end. 2023-02-27 14:29:02 -08:00
Brady Wetherington e1c8f155bb Wiring up more bits to Livewire 2023-02-27 14:29:02 -08:00
Brady Wetherington 5c97e45d00 WIP - trying to get select2 wired up for importer 2023-02-27 14:29:02 -08:00
Brady Wetherington 8009ee79db I think I have, now, full parity on the base Importer level
Meaning that you can upload new files, delete old files, have error
messages, have status updates - and all of them seem to work.
2023-02-27 14:29:02 -08:00
Brady Wetherington 0a085af0a0 Getting the basic wiring of the importer over into Livewire
WIP: Wiring up more and more of the actions on the importer

Files now upload okay, a little glitchy on the display-side though

add to readmes so i dont forget
2023-02-27 14:28:59 -08:00
snipe c2cdf5dae1 Merge remote-tracking branch 'origin/develop' 2023-02-27 13:34:16 -08:00
snipe 23ca124e94 Merge pull request #12573 from snipe/fixes/ambiguous_model_clause
Added table aliases to fix ambiguous SQL clause
2023-02-27 13:33:52 -08:00
snipe c7106a1df2 Added table aliases to fix ambiguous SQL clause
Signed-off-by: snipe <snipe@snipe.net>
2023-02-27 13:24:09 -08:00
snipe 3f4a4e72a7 Merge remote-tracking branch 'origin/develop' 2023-02-27 12:17:33 -08:00
snipe b78aba787f Merge pull request #12572 from snipe/fixes/add_max_results_limit_to_acitivity_report
Added max results limit to report index
2023-02-27 12:16:57 -08:00
snipe 96c851468c Added max results limit to report index
Signed-off-by: snipe <snipe@snipe.net>
2023-02-27 12:04:46 -08:00
Godfrey M e8fc895e51 "adds variables, but still not working" 2023-02-27 09:19:59 -08:00
snipe a5ccef5e96 Merge pull request #12564 from uberbrady/upgrade_acorn
Upgrade Acorn
2023-02-26 12:12:21 -08:00
Brady Wetherington 059190f002 Upgrade Acorn 2023-02-26 11:29:10 -08:00
snipe 6428cc259f Merge remote-tracking branch 'origin/develop' 2023-02-24 10:02:43 -08:00
snipe cb0b234b80 Merge pull request #12561 from inietov/fixes/unable_to_import_purchase_date
Fixed #12559 Unable to import Purchase Date field
2023-02-24 10:02:25 -08:00
snipe 8caf29975f Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2023-02-24 09:58:19 -08:00
snipe 95501bf57c Bumped hash
Signed-off-by: snipe <snipe@snipe.net>
2023-02-24 09:57:25 -08:00
snipe 75a73d095f Merge pull request #12560 from snipe/fixes/bulk_checkout_nulles_asset_name
Pass the existing asset name to the bulk checkout form
2023-02-24 09:56:13 -08:00
snipe 3e47d9e689 Pass the existing asset name to the bulk checkout form
Signed-off-by: snipe <snipe@snipe.net>
2023-02-24 09:54:46 -08:00
Ivan Nieto Vivanco 51efd9b413 Adjust the date format for purchase_date field 2023-02-24 10:59:31 -06:00
snipe bd0b00e361 Merge pull request #12558 from inietov/fixes/non_numeric_value_in_license_seat
Fixed ErrorException: A non-numeric value encountered in app/Models/License [sc-20187]
2023-02-24 00:29:26 -08:00
Ivan Nieto Vivanco 6bd72125bd Deletes problematic cast 2023-02-23 22:31:41 -06:00
snipe 1415c8c6e2 Merge remote-tracking branch 'origin/develop' 2023-02-23 15:00:03 -08:00
snipe 41253b2680 Merge pull request #12556 from marcusmoore/fixes/asset-seeder
Fix purchase date field in asset seeder
2023-02-23 14:05:45 -08:00
Marcus Moore bdac0f16ce Set purchase date field to the correct format in asset factory 2023-02-23 13:39:05 -08:00
snipe dde2b946da Merge pull request #12555 from snipe/security/upgrade_dompdf
Update dompdf
2023-02-23 13:00:46 -08:00
snipe 0b408218b0 Update dompdf
Signed-off-by: snipe <snipe@snipe.net>
2023-02-23 12:59:04 -08:00
snipe 5e6ebb9a65 Merge pull request #12410 from uberbrady/paginate_accessories_report
Paginate accessories report
2023-02-23 12:26:17 -08:00
snipe 8e72da42e8 Merge pull request #12406 from akemidx/vip_tag
Added a checkbox to notate VIP status
2023-02-23 12:23:29 -08:00
snipe 309c0ff66f Merge remote-tracking branch 'origin/develop' 2023-02-23 11:41:36 -08:00
snipe eb6357636a Merge pull request #12467 from marcusmoore/fix/scope-people-with-full-multiple-companies
Fix full company scoping in user selects
2023-02-23 10:36:33 -08:00
snipe adb166fb8d Merge remote-tracking branch 'origin/develop' 2023-02-22 18:01:06 -08:00
snipe 4a9ced192b Merge pull request #12550 from marcusmoore/fixes/closing-tag-in-mail-template
Properly close tag in mail template
2023-02-22 17:59:20 -08:00
Marcus Moore 6c8de181cf Properly close tag in mail template 2023-02-22 17:52:47 -08:00
snipe 5a1e5f740d Merge pull request #12537 from inietov/fixes/expected_checkin_date_validation
Fixed #12531 Expected Checkin Date on Asset Checkout throws an error
2023-02-22 16:03:51 -08:00
akemidx 690970b4aa fixing ff error 2023-02-22 18:18:20 -05:00
Marcus Moore f63710fb5c Remove unused import 2023-02-22 12:34:56 -08:00
Marcus Moore 7667b0a216 Remove extra line 2023-02-22 12:34:35 -08:00
Marcus Moore 931ca98c02 Remove middleware bypass 2023-02-22 12:33:55 -08:00
snipe 225b6ef310 Merge remote-tracking branch 'origin/develop' 2023-02-22 12:24:52 -08:00
snipe 13ed2a05a3 Add @AndrewSav as a contributor 2023-02-22 12:24:13 -08:00
Marcus Moore aae2106658 Use existing language translation string 2023-02-22 12:02:14 -08:00
snipe 81cb29db5e Merge pull request #12509 from inietov/fixes/add_images_to_user_inventory_mail_report
Added images to emailed user inventory report [sc-19801]
2023-02-22 10:38:07 -08:00
snipe 05f6d0bd5e Merge pull request #11984 from nh314/Correct-assignedusers-relation
Correct assignedusers relation setting
2023-02-21 20:15:20 -08:00
snipe 4bf1566d2a Merge pull request #12124 from Godmartinz/feature/sc-16946/add-checkbox-to-allow-skipping-a-user-during
Adds Boolean to Users Table for Auto Assigning Licenses
2023-02-21 20:10:46 -08:00
snipe 0c3115553e Merge branch 'develop' into vip_tag 2023-02-21 20:03:49 -08:00
snipe 942fee4d43 Merge pull request #12447 from akemidx/user_setup_translation
FIXED: Translations on the User Creation setup page
2023-02-21 19:53:00 -08:00
snipe ba461d0114 Merge pull request #12538 from AndrewSav/develop
Added #12532: add version endpoint
2023-02-21 19:50:07 -08:00
snipe 3ae783a9c7 Merge pull request #12525 from uberbrady/add_sodium_php_shim
Add libsodium shim, and mark the sodium extension as 'optional'
2023-02-21 19:38:14 -08:00
Ivan Nieto Vivanco d494afcf01 Add order by clause, to ensure assets and accessories are in order in the report 2023-02-21 21:24:19 -06:00
snipe 57065b8936 Merge remote-tracking branch 'origin/develop' 2023-02-21 09:20:59 -08:00
snipe 40a38486b9 Merge pull request #12545 from snipe/localizations/more_new_translations
Two more translations
2023-02-21 09:20:38 -08:00
snipe 29158dece5 Two more translations
Signed-off-by: snipe <snipe@snipe.net>
2023-02-21 09:19:34 -08:00
snipe f6e4e17e5c Merge remote-tracking branch 'origin/develop' 2023-02-21 09:05:50 -08:00
snipe 8185f264a4 Merge pull request #12544 from snipe/localizations/updated_general
Updated the general translation file with new strings
2023-02-21 09:05:24 -08:00
snipe 04d3938f0c Updated the general translation file with new strings
Signed-off-by: snipe <snipe@snipe.net>
2023-02-21 09:04:13 -08:00
snipe f109218e16 Re-added dropped translations from CrowdIn
Signed-off-by: snipe <snipe@snipe.net>
2023-02-21 09:00:10 -08:00
snipe 049213c3da Merge remote-tracking branch 'origin/develop' 2023-02-21 04:02:08 -08:00
snipe 9c1a71e04a Merge pull request #12541 from snipe/localizations/new_strings
Updated translations with new strings and new translations
2023-02-21 03:58:25 -08:00
snipe a0b05bac8d Updated translations with new strings and new translations
Signed-off-by: snipe <snipe@snipe.net>
2023-02-21 03:54:55 -08:00
Andrew Savinykh d2ede75de8 fixes #12532 adds version endpoint 2023-02-20 22:19:18 +13:00
Ivan Nieto Vivanco 6e994c209f Adds setter to model Asset class for expected checkin 2023-02-19 12:31:10 -06:00
akemidx f33b6a3e26 Update user.blade.php 2023-02-17 12:52:54 -05:00
akemidx dfc2aa35f4 Update general.php 2023-02-17 12:51:58 -05:00
snipe f71d8b2f07 Merge remote-tracking branch 'origin/develop' 2023-02-16 17:05:48 -08:00
snipe 248eb0885c Merge pull request #12533 from snipe/fixes/expected_checkin_wtf
FML - this is a hotfix and I don’t know why this is causing problems
2023-02-16 17:01:54 -08:00
snipe 754842f620 FML - this is a hotfix and I don’t know why this is causing problems
Signed-off-by: snipe <snipe@snipe.net>
2023-02-16 16:58:00 -08:00
snipe 43eacff265 Merge remote-tracking branch 'origin/develop' 2023-02-16 12:11:26 -08:00
snipe fdffe76b9f Merge pull request #12529 from Godmartinz/bug/sc-20046/allow-user-to-submit-the-slack-livewire-form
allows users to clear their slack settings
2023-02-16 11:47:58 -08:00
Godfrey M 58801dbb0b allows users to clear their slack settings 2023-02-16 08:43:12 -08:00
snipe e9ab90eafc Merge pull request #12422 from marcusmoore/fix/adhere-to-email-alerts-setting
Have acceptance result notifications adhere to alerts enabled setting
2023-02-15 18:46:08 -08:00
snipe 495d7e057d Merge remote-tracking branch 'origin/develop' 2023-02-15 18:37:39 -08:00
snipe 9f8ea9a243 Merge pull request #12524 from snipe/fixes/small_UI_tweaks
Cleanup some small UI bugaboos (padding, etc)
2023-02-15 18:20:08 -08:00
Brady Wetherington 3a2b54fd47 Add libsodium shim, and mark the sodium extension as 'optional'
Trying to handle some composer.lock conflicts, as savely as possible.
2023-02-15 18:16:39 -08:00
snipe 71334b5eae More tweaking for top button alignment
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 18:13:38 -08:00
snipe f124249e1c More padding twiddles
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 18:08:11 -08:00
snipe e451ca1a5c Stray semicolon
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 17:37:53 -08:00
snipe 3e111fca6e Cleanup some small UI bugaboos (padding, etc)
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 17:13:40 -08:00
snipe df64e0e291 Merge pull request #12523 from Godmartinz/bug/sc-20041/slack-ui-livewire-tweaks
Fixes slack settings submit button availability
2023-02-15 16:28:57 -08:00
snipe 51c9a7d4f8 Merge pull request #12521 from akemidx/weird_checkout_text
Fixed awkward checkout text in checkedout side panel
2023-02-15 16:28:05 -08:00
akemidx d8d713426d indent? 2023-02-15 19:24:20 -05:00
akemidx 7dd789d5c0 translate no assets at checkout 2023-02-15 19:22:13 -05:00
Godfrey M 2d8c8e8f48 removes lazy loading 2023-02-15 16:16:14 -08:00
Godfrey M 7b510d5f2b greys out submit button conditionally 2023-02-15 15:46:05 -08:00
snipe 221f5f5ca7 Merge pull request #12522 from snipe/fixes/slack_livewire_translations
Fixes slack livewire translations, UI
2023-02-15 14:45:46 -08:00
snipe d4634e83c9 Nicer padding, removed unused ids
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 14:45:18 -08:00
snipe 6c3ffa7918 Removed unused CSS
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 14:39:24 -08:00
snipe 27e5832a28 Use existing slack translations
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 14:06:52 -08:00
snipe 2d0bd2b292 Make spinner actually spin
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 14:06:40 -08:00
akemidx b96f2f738d fixed weird phrasing in asset checkout screen 2023-02-15 16:47:48 -05:00
snipe ff895739f4 Merge pull request #12446 from Godmartinz/livewire_slack_inputs
Adds Livewire slack inputs
2023-02-15 13:27:07 -08:00
snipe de4f7bd274 Merge pull request #12408 from snipe/fixes/stricter_date_rectrictions_on_validation
Enforce Y-m-d as date format for date fields
2023-02-15 12:54:22 -08:00
snipe 25461caa2c Removed date validation rule
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 12:53:55 -08:00
snipe bfac0fc811 Merge pull request #12470 from inietov/fixes/rollbar_16883_attempt_assign_on_null
Fixed Rollbar 16883 Error: Attempt to assign property "assigned_to" on null
2023-02-15 12:33:32 -08:00
snipe 057f0be20a Merge pull request #12473 from inietov/fixes/rollbar_attempt_to_read_property_on_null
Fixed ErrorException:  Attempt to read property "id" on null [sc-19855]
2023-02-15 12:32:53 -08:00
snipe 7980e2ab2e Merge pull request #12517 from uberbrady/silence_ldap_exceptions
Silence E_WARNING "exceptions"
2023-02-15 11:56:37 -08:00
Marcus Moore f99f6d32fa Make phpstan configuration more flexible 2023-02-15 11:33:08 -08:00
Marcus Moore d088b39fb2 Remove ignore errors section covered by larastan config 2023-02-15 11:33:08 -08:00
Marcus Moore 6bfd2fd5ad Sort paths 2023-02-15 11:33:08 -08:00
Marcus Moore 6778cf79a0 Include Larastan configuration file 2023-02-15 11:33:08 -08:00
snipe ac4103281c Still throwing errors, but trying to fix the docblock
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 11:33:08 -08:00
snipe 03af417e89 We shouldn’t need this because aliases??
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 11:33:08 -08:00
snipe 77362b3b41 Added larastan and psalm to composer dev
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 11:33:08 -08:00
snipe db8c29b901 Psalm and phpstan configs
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 11:33:08 -08:00
snipe 3d219f578e The sea, Brady.
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 11:33:08 -08:00
snipe 8c3511a00b Fixed wonky switch statement indenting
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 11:33:08 -08:00
snipe c1ae406049 Fixed visibility for constants and methods
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 11:33:08 -08:00
snipe 1ef3112628 FIxed yoda operator
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 11:33:08 -08:00
snipe 0325cbad64 Removed unused else condition
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 11:33:08 -08:00
snipe 6dc89fc2b0 Use null coalescing operator
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 11:33:08 -08:00
snipe b25676c96b Fixed Implicit array creation is disallowed.
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 11:33:08 -08:00
snipe 14e95c47e1 Made constant DATA_SESSION_KEY public
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 11:33:08 -08:00
snipe dc43c4f68a Removed unneeded concat
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 11:33:08 -08:00
snipe 0e7ac5c95e Added phpinsights
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 11:33:08 -08:00
snipe c7f90f304d Added insights config
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 11:33:08 -08:00
snipe 78a0b06a61 Fixed array bracket indenting
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 11:33:08 -08:00
snipe 40f487beae Added parens
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 11:33:08 -08:00
snipe 2992ca1fa2 Fixed yoda operator
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 11:33:08 -08:00
snipe 15f9c6af67 Removed unused variable
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 11:33:08 -08:00
snipe 7a19da4f64 Removed unused variable
Signed-off-by: snipe <snipe@snipe.net>
2023-02-15 11:33:08 -08:00
Ivan Nieto Vivanco 07f501408f Add migration to fix already escaped formats in the database 2023-02-15 11:33:08 -08:00
Ivan Nieto Vivanco 53e449899b Remove e() function from customfield format input 2023-02-15 11:33:08 -08:00
Godfrey M b2f1ca95df missing things like mr magoo 2023-02-15 11:33:08 -08:00
Godfrey M f3ab384e70 simplified to an else instead of elseif 2023-02-15 11:33:08 -08:00
Godfrey M 61bf1e91e7 adds the red x icon to a false deployable status 2023-02-15 11:33:08 -08:00
Godfrey M 1c54feea5b adds a red icon next to broken- not fixable status label 2023-02-15 11:33:08 -08:00
Marcus Moore 7423570e6b Add comment 2023-02-15 11:33:08 -08:00
Marcus Moore b946a6066d Use name if provided by asset checkout request 2023-02-15 11:33:07 -08:00
Marcus Moore 9c25dd4eb6 Improve error message wording 2023-02-15 11:33:07 -08:00
Marcus Moore e69fcf10b7 Use translation strings for importer exceptions 2023-02-15 11:33:07 -08:00
akemidx 937e2813e9 fixing external if statement 2023-02-15 11:33:07 -08:00
akemidx a84081068d functionality to Apple Warranty link 2023-02-15 11:33:07 -08:00
akemidx d9857d955b translations for the layout setup 2023-02-15 11:33:07 -08:00
akemidx 66251bfd8a sweedish chef fixes up your typos 2023-02-15 11:33:07 -08:00
akemidx 677f7a446e manufacturer marker removal 2023-02-15 11:33:07 -08:00
Marcus Moore fdce6f98ff Return 422 instead of 500 when import is invalid 2023-02-15 11:33:07 -08:00
Marcus Moore 5a00685c81 Fix return type 2023-02-15 11:33:07 -08:00
Marcus Moore 18f0b1cc3d Formatting 2023-02-15 11:33:07 -08:00
Marcus Moore 6da43bc940 Catch json encoding exceptions and display them to the user 2023-02-15 11:33:07 -08:00
Ivan Nieto Vivanco 98187773f7 Adds translation strings to theinventory report sent to users 2023-02-15 11:33:07 -08:00
Brady Wetherington 3757c7e353 Make early-boot errors (syntax, others) be more easy-to-read 2023-02-15 11:31:13 -08:00
snipe 3800cdd0da Merge pull request #12466 from snipe/fixes/style_fixes
Style fixes
2023-02-15 11:07:59 -08:00
snipe 1ed57d30e0 Merge pull request #12516 from inietov/fixes/quotes_in_custom_field_custom_regex
Fixed #12252 Quotes in Custom Field regex are being HTML-escaped
2023-02-14 20:10:43 -08:00
Brady Wetherington a1b0eaf128 Got working E_WARNING-in-production going. YAY! 2023-02-14 20:00:06 -08:00
snipe f7df2ae403 Merge pull request #12513 from Godmartinz/gh12493
adds a red icon next to the  undeployable status
2023-02-14 14:37:06 -08:00
Godfrey M 793cf4823b missing things like mr magoo 2023-02-14 14:35:54 -08:00
Godfrey M c0d8ff1676 simplified to an else instead of elseif 2023-02-14 14:21:24 -08:00
snipe b0b1c96ab5 Merge pull request #12514 from marcusmoore/fixes/preserve-asset-name-during-api-checkout
Fix asset names being removed during API checkout requests
2023-02-14 12:22:03 -08:00
Marcus Moore 8e00191b69 Add comment 2023-02-14 12:19:16 -08:00
Marcus Moore a94f19a68e Use name if provided by asset checkout request 2023-02-14 12:08:20 -08:00
Godfrey M 0cd558593d adds the red x icon to a false deployable status 2023-02-14 10:34:36 -08:00
Godfrey M d03e042eda adds a red icon next to broken- not fixable status label 2023-02-14 09:55:48 -08:00
Marcus Moore 8b183490ba Use "testing" environment for tests 2023-02-13 18:56:22 -08:00
Marcus Moore 228c59e6ed Bring phpunit.xml closer to default 2023-02-13 18:55:50 -08:00
snipe 2dd7690d2d Merge pull request #12464 from snipe/dependabot/github_actions/docker/build-push-action-4
Bump docker/build-push-action from 3 to 4
2023-02-13 14:45:21 -08:00
snipe 1520c9c6a7 Merge pull request #12506 from marcusmoore/fix/use-translation-strings-for-importer-errors
Use translation strings for importer exceptions
2023-02-13 14:17:47 -08:00
Marcus Moore 4bdb1cf552 Improve error message wording 2023-02-13 13:34:20 -08:00
Marcus Moore 2349f54013 Use translation strings for importer exceptions 2023-02-13 13:30:36 -08:00
snipe 2bbbc8158b Merge pull request #12477 from akemidx/apple_warranty_link
Added functionality to Apple Warranty link
2023-02-13 13:02:33 -08:00
snipe 2f5b4c8e1b Merge pull request #12498 from akemidx/layout_trans
Translations for the layout setup
2023-02-13 13:01:58 -08:00
Ivan Nieto Vivanco 99122ccb50 Add migration to fix already escaped formats in the database 2023-02-12 17:40:04 -06:00
Ivan Nieto Vivanco 6936efd387 Remove e() function from customfield format input 2023-02-12 16:27:37 -06:00
Ivan Nieto Vivanco f0bf16d784 Fix more uneven tags 2023-02-12 12:01:40 -06:00
Ivan Nieto Vivanco 9a68a747a0 Fix uneven tags 2023-02-12 11:59:56 -06:00
Ivan Nieto Vivanco 81cc9f3700 Adds images to emailed user inventory report 2023-02-12 08:23:50 -06:00
akemidx 5714824aa7 translations for the layout setup 2023-02-09 17:24:34 -05:00
snipe e79818967d Merge pull request #12490 from akemidx/manufacturer_marker
Removed "required" marker for manufacturer on asset models (since it is not actually required)
2023-02-09 12:43:14 -08:00
akemidx 32ed70259e sweedish chef fixes up your typos 2023-02-09 15:39:10 -05:00
snipe 35ab4a4cce Merge pull request #12489 from marcusmoore/fix/encoding-errors-in-importer
Improve error messaging around invalid characters in import
2023-02-08 15:08:23 -08:00
akemidx 1a651b33fc manufacturer marker removal 2023-02-08 17:31:39 -05:00
Marcus Moore 73f355f3a8 Return 422 instead of 500 when import is invalid 2023-02-08 12:39:42 -08:00
Marcus Moore b3881a43a7 Fix return type 2023-02-08 12:34:25 -08:00
Marcus Moore c2c666aef0 Formatting 2023-02-08 12:32:57 -08:00
Marcus Moore 5962f1b627 Catch json encoding exceptions and display them to the user 2023-02-08 12:21:51 -08:00
snipe a4a3c03a7c Merge pull request #12478 from inietov/fixes/added_translation_strings_inventory_report
Fixed #12064 Mail-Template missing translation strings
2023-02-08 10:02:19 -08:00
snipe 201728989f Merge pull request #12486 from svpernova09/patch-1
Don't auto assign feature requests to Snipe
2023-02-08 07:59:58 -08:00
Joe Ferguson dea175bd40 Don't auto assign feature requests to Snipe 2023-02-08 09:57:54 -06:00
snipe 23b1e8da27 Merge remote-tracking branch 'origin/develop' 2023-02-07 18:46:30 -08:00
snipe e883a61a48 Merge pull request #12480 from snipe/fixes/ui_fix_for_user_files
Fixed UI bug where download button was missing for non-images
2023-02-07 18:46:07 -08:00
snipe 16fcc6dc44 Fixed UI bug where download button was missing for non-images
Signed-off-by: snipe <snipe@snipe.net>
2023-02-07 18:40:00 -08:00
Marcus Moore 4f9ebf6cde Fix array key 2023-02-07 16:40:27 -08:00
Ivan Nieto Vivanco 49b6a1cc53 Adds translation strings to theinventory report sent to users 2023-02-07 18:29:19 -06:00
Marcus Moore 787f619a6b Standardize test method syntax 2023-02-07 16:28:40 -08:00
Marcus Moore 505ca48da2 Remove test method without assertions 2023-02-07 16:17:36 -08:00
Marcus Moore 6b8c0f9e88 Make BaseTest abstract 2023-02-07 16:17:16 -08:00
Marcus Moore 3fdf4dea1b Use factories for relationships in asset factory 2023-02-07 16:17:05 -08:00
Marcus Moore 6dbcec2310 Exclude Dusk tests from phpunit test suite 2023-02-07 16:16:39 -08:00
akemidx 75f3cb3079 fixing external if statement 2023-02-07 19:02:12 -05:00
akemidx c0074baa26 functionality to Apple Warranty link 2023-02-07 17:27:39 -05:00
snipe 4f9587da57 Merge remote-tracking branch 'origin/develop' 2023-02-07 13:34:57 -08:00
snipe 4b2d35e05d Merge pull request #12474 from snipe/fixes/destroy_method_for_fieldsets
Fixed mismatched field/fieldset
2023-02-07 13:33:38 -08:00
Marcus Moore 321a34a9d3 Make phpstan configuration more flexible 2023-02-07 13:32:32 -08:00
snipe c1d484b5df Fixed mismatched field/fieldset
Signed-off-by: snipe <snipe@snipe.net>
2023-02-07 13:31:50 -08:00
Marcus Moore fd524c5f14 Remove ignore errors section covered by larastan config 2023-02-07 12:48:41 -08:00
Marcus Moore e4cf59c034 Sort paths 2023-02-07 12:46:13 -08:00
Marcus Moore efac2259db Include Larastan configuration file 2023-02-07 12:25:13 -08:00
snipe ea644f8d47 Still throwing errors, but trying to fix the docblock
Signed-off-by: snipe <snipe@snipe.net>
2023-02-07 11:02:20 -08:00
snipe dd5f256450 We shouldn’t need this because aliases??
Signed-off-by: snipe <snipe@snipe.net>
2023-02-07 11:02:02 -08:00
snipe f4617d8d5b Added larastan and psalm to composer dev
Signed-off-by: snipe <snipe@snipe.net>
2023-02-07 11:01:21 -08:00
snipe 32be88d796 Psalm and phpstan configs
Signed-off-by: snipe <snipe@snipe.net>
2023-02-07 11:00:59 -08:00
snipe 219d92dcfb The sea, Brady.
Signed-off-by: snipe <snipe@snipe.net>
2023-02-07 11:00:30 -08:00
Ivan Nieto Vivanco d4c838a979 Add condition in activity report to only access assigned item id if it exist 2023-02-07 11:26:49 -06:00
Ivan Nieto Vivanco ddabe7cc9f Added Guard Clause to License Importer to return if no empty seat is found 2023-02-07 01:36:55 -06:00
Marcus Moore c03079944a Be more explicit in test case 2023-02-06 16:06:13 -08:00
snipe cd5546e4a1 Fixed wonky switch statement indenting
Signed-off-by: snipe <snipe@snipe.net>
2023-02-06 12:44:17 -08:00
snipe d52d32fed9 Fixed visibility for constants and methods
Signed-off-by: snipe <snipe@snipe.net>
2023-02-06 12:44:02 -08:00
snipe 7363d4e223 FIxed yoda operator
Signed-off-by: snipe <snipe@snipe.net>
2023-02-06 12:43:35 -08:00
snipe c8c5dddcc1 Removed unused else condition
Signed-off-by: snipe <snipe@snipe.net>
2023-02-06 12:43:19 -08:00
snipe 1651dbb68d Use null coalescing operator
Signed-off-by: snipe <snipe@snipe.net>
2023-02-06 12:43:00 -08:00
snipe d95adcae37 Fixed Implicit array creation is disallowed.
Signed-off-by: snipe <snipe@snipe.net>
2023-02-06 12:41:54 -08:00
snipe 8a8575bf2d Made constant DATA_SESSION_KEY public
Signed-off-by: snipe <snipe@snipe.net>
2023-02-06 12:40:32 -08:00
snipe 590cb6a15b Removed unneeded concat
Signed-off-by: snipe <snipe@snipe.net>
2023-02-06 12:40:09 -08:00
snipe aeb8dfb07d Added phpinsights
Signed-off-by: snipe <snipe@snipe.net>
2023-02-06 12:39:55 -08:00
snipe a60510c063 Added insights config
Signed-off-by: snipe <snipe@snipe.net>
2023-02-06 12:39:48 -08:00
snipe 8841f04333 Fixed array bracket indenting
Signed-off-by: snipe <snipe@snipe.net>
2023-02-06 12:39:38 -08:00
snipe ab6ca0e066 Added parens
Signed-off-by: snipe <snipe@snipe.net>
2023-02-06 12:39:22 -08:00
snipe ec2afee57d Fixed yoda operator
Signed-off-by: snipe <snipe@snipe.net>
2023-02-06 12:39:12 -08:00
snipe b10ea0c25c Removed unused variable
Signed-off-by: snipe <snipe@snipe.net>
2023-02-06 12:38:56 -08:00
snipe 686d1aaae7 Removed unused variable
Signed-off-by: snipe <snipe@snipe.net>
2023-02-06 12:38:29 -08:00
Marcus Moore 0e57e4836e Add translation for Company 2023-02-06 12:21:23 -08:00
Marcus Moore 45e8e9bbed Move company name to better location 2023-02-06 12:21:09 -08:00
Marcus Moore 38cdcdf064 Eager load company 2023-02-06 10:59:51 -08:00
Marcus Moore 78343ddb7c Add asset's company name to checkout page 2023-02-06 10:58:10 -08:00
Godfrey M 74c64c1fc5 adds validation to the update hook, removes typos and deadlines 2023-02-06 09:40:57 -08:00
dependabot[bot] ea0f505db7 Bump docker/build-push-action from 3 to 4
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 3 to 4.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-06 08:07:13 +00:00
snipe b37c4553ef Merge remote-tracking branch 'origin/develop' 2023-02-02 23:41:05 -08:00
snipe b0f4015bb4 Merge pull request #12459 from snipe/fixes/broken_route_in_deleted_models
Updated model restore route
2023-02-02 23:40:39 -08:00
snipe dc414d3552 Updated model restore route
Signed-off-by: snipe <snipe@snipe.net>
2023-02-02 23:38:59 -08:00
Marcus Moore 0cefc7de15 Skip security headers middleware when testing 2023-02-02 18:37:35 -08:00
Marcus Moore 9a0c66bd30 Clear some extra lines 2023-02-02 18:30:18 -08:00
Marcus Moore d8e92d29c0 Improve readability 2023-02-02 18:25:54 -08:00
Marcus Moore 93a62c87c2 Implement test for searching users 2023-02-02 17:57:24 -08:00
Marcus Moore 89eff23e44 Continue implementing tests 2023-02-02 17:41:32 -08:00
snipe 41b0756286 Merge remote-tracking branch 'origin/develop' 2023-02-02 15:35:41 -08:00
snipe f9ef49f886 Merge pull request #12457 from snipe/fixed/regression_on_field_associations
Fixed regression in fieldset -> field association
2023-02-02 15:35:22 -08:00
snipe 51f3857a31 Fixed something I think I broke
Signed-off-by: snipe <snipe@snipe.net>
2023-02-02 15:32:45 -08:00
Marcus Moore a2e47d19fc Scaffold tests for user select list api and begin to implemenet 2023-02-02 13:47:00 -08:00
snipe bbf6e5e69e Merge pull request #12421 from akemidx/hardware_blades_translations
Fixed: translations added for the hardware blades
2023-02-02 13:02:46 -08:00
akemidx b8951e2b54 fixing name from vipuser to vip 2023-02-02 15:58:05 -05:00
akemidx 37ce68af5b once again fixing an apostrophe 2023-02-02 15:54:05 -05:00
akemidx 29851c626f Merge branch 'develop' into user_setup_translation 2023-02-02 14:34:09 -05:00
snipe 1f60afa8e3 Merge remote-tracking branch 'origin/develop' 2023-02-02 11:28:41 -08:00
snipe 64aea8d374 Merge pull request #12456 from snipe/features/add_notes_to_user_history
Fixed #12449 - Added checkout/checkin  note to user history
2023-02-02 11:28:08 -08:00
snipe 7344bbdd7f Added checkout/checkin note to user history
Signed-off-by: snipe <snipe@snipe.net>
2023-02-02 11:26:33 -08:00
snipe 782abe1cf3 Merge remote-tracking branch 'origin/develop' 2023-02-02 11:09:18 -08:00
snipe 2d3318feb6 Merge pull request #12454 from snipe/fixes/fixed_500_when_userfile_does_not_exisy
Handle missing userfiles more gracefully
2023-02-02 11:08:54 -08:00
snipe 78dca7fd32 Handle missing userfiles more gracefully
Signed-off-by: snipe <snipe@snipe.net>
2023-02-02 10:49:36 -08:00
snipe 2a8851bbd7 Merge pull request #12342 from marcusmoore/fix/dusk-test-suite
Fixed Dusk Test Suite
2023-02-02 09:50:34 -08:00
akemidx 69c38bf686 translations on the User Creation page 2023-02-01 20:32:16 -05:00
Brady Wetherington 039d159cbd WIP: working on better Rollbar filtering in prod 2023-02-01 17:15:22 -08:00
Godfrey M 17f1772143 removes postslack from settings controller 2023-02-01 16:58:08 -08:00
Godfrey M 3a86547ef5 fixes messages for integration test, removes slack request file, rehouses ajax method 2023-02-01 16:51:05 -08:00
snipe 4bc804e876 Merge remote-tracking branch 'origin/develop' 2023-02-01 16:50:19 -08:00
snipe 2997de2a66 Merge pull request #12445 from snipe/fixes/exit_out_ldap
Added an exit for the LDAP disabled sync short-circuit
2023-02-01 16:48:00 -08:00
snipe 0cfeab8c50 Added an exit for the LDAP disabled sync short-circuit
Signed-off-by: snipe <snipe@snipe.net>
2023-02-01 16:46:58 -08:00
snipe c706759b5c Merge remote-tracking branch 'origin/develop' 2023-02-01 16:42:11 -08:00
snipe 1432403c9f Merge pull request #12444 from snipe/fixes/only_fire_ldap_sync_in_console_if_enabled
Fixed: Short-circuit the LDAP sync is LDAP is disabled
2023-02-01 16:40:32 -08:00
snipe 67e6089805 Short circuit the LDAP sync is LDAP is disabled
Signed-off-by: snipe <snipe@snipe.net>
2023-02-01 16:36:30 -08:00
snipe d9cdb92014 Merge branch 'develop' into vip_tag 2023-02-01 16:03:23 -08:00
snipe ea4d5e69bc Merge pull request #12407 from akemidx/slack_message
Fixed: translation for slack message notification
2023-02-01 13:44:12 -08:00
snipe 2da4578aa5 Merge branch 'develop' into slack_message 2023-02-01 13:43:09 -08:00
snipe 1a8fb5bcfe Merge pull request #12423 from snipe/features/edit_fieldset_name
Fixed #12418 - added ability to edit custom field names via GUI
2023-02-01 13:39:39 -08:00
snipe 0d4ca218c5 Merge pull request #12437 from uberbrady/ldap_allow_undelegatable_users_to_login
Fixed: Active Directory "not-delegated+dont-expire-password+normal-accounts" can now login
2023-02-01 13:38:59 -08:00
snipe 4a6250a08c Merge pull request #12409 from akemidx/component_checkin_limit
Fixed: Checkin limit string translation for components
2023-02-01 13:37:56 -08:00
akemidx 0ffd40a217 fixing syntax 2023-02-01 16:30:07 -05:00
akemidx 33d819fd41 fixing pr 2023-02-01 16:13:53 -05:00
akemidx 90c1bfe03d fixing pr 2023-02-01 16:12:39 -05:00
akemidx 3702dd87ce fixing pr 2023-02-01 16:10:30 -05:00
akemidx 4d9d73483f fixing pr 2023-02-01 16:09:19 -05:00
akemidx 4e5b8fa213 fixing pr 2023-02-01 16:05:50 -05:00
akemidx a8643e5d35 cleaning up/adding variable 2023-02-01 15:55:16 -05:00
Godfrey M f95a904d90 adds integration button, working on its functionality 2023-02-01 12:08:13 -08:00
Marcus Moore a45ce468cc Update return type for routing mail notifications 2023-02-01 11:44:56 -08:00
Marcus Moore 3580bdae86 Use object accessor instead of array accessor 2023-02-01 11:44:35 -08:00
snipe 38f3843c23 Merge pull request #12386 from snipe/features/fixed_12382_added_checked_out_count_to_accessories
Fixed #12382 - added checked out count to accessories
2023-01-31 19:57:12 -08:00
snipe f7ae5db4f3 Merge branch 'develop' into features/fixed_12382_added_checked_out_count_to_accessories 2023-01-31 19:56:43 -08:00
snipe 6fbd20a11b Merge remote-tracking branch 'origin/develop' 2023-01-31 19:50:18 -08:00
snipe de1141491a Replaced help text
Signed-off-by: snipe <snipe@snipe.net>
2023-01-31 19:41:42 -08:00
snipe 2d45ebe103 Merge pull request #12433 from inietov/fixes/asset_declined_date_issues
Fixed Invalid date value on assets acceptance mail notification
2023-01-31 19:14:51 -08:00
snipe 656344b1c7 Merge pull request #12429 from svpernova09/benperiton/patch-1
Cherry-picked Feature: Add DB_PORT to pgsql connection
2023-01-31 19:10:17 -08:00
snipe 7a23398c0c Merge pull request #12439 from uberbrady/fix_bootstrap_username_doubling
Fixed: username doubles on 'checked-out-to' column if display is resized [sc-19869], [fd-33242]
2023-01-31 18:10:02 -08:00
Brady Wetherington 02ca5248b1 Don't append username to the user's name if it's already there 2023-01-31 17:44:09 -08:00
snipe b1179c7b1e Merge pull request #12438 from inietov/fixes/replace_ios_homescreen_logo
Fixed #9694 Replace iOS "Add to homescreen icon"
2023-01-31 17:02:05 -08:00
Brady Wetherington a4173e3881 Permit not-delegated+dont-expire-password+normal-accounts to login 2023-01-31 16:49:41 -08:00
snipe a2a078015f Merge pull request #12435 from lukasfehling/bugfix/fixed-endpoint-for-user-notification
Fixed the endpoint for user notification with all their assigned assets
2023-01-31 12:41:47 -08:00
Godfrey M 1e0c58c3cf saves data correctly now 2023-01-31 11:32:05 -08:00
lukasfehling cddae4869f fixed the endpoint for user notification with all their assigned assets 2023-01-31 18:27:25 +01:00
Ivan Nieto Vivanco a7a578bf51 Added head only logo to be used as default in apple-touch-icon 2023-01-31 00:13:44 -06:00
Godfrey M fc044528b8 validation is working, success message appears, database is not updating 2023-01-30 16:10:02 -08:00
akemidx 214a1af61a apostrophe updates 2023-01-30 16:54:23 -05:00
Ivan Nieto Vivanco ccc7b78f62 Store the acceptance dates with format YYY-mm-dd 2023-01-30 15:11:41 -06:00
Ben Periton c2854f1bcb Update database.php
Although Postgres is not officially supported, it does seem to work ok, but to help a little bit with the Docker image, this is non-breaking change but allows the env file to specify the pgsql connection port
2023-01-29 19:28:04 -06:00
snipe 22b0b9b090 Fixed gates on fieldsets
Signed-off-by: snipe <snipe@snipe.net>
2023-01-26 17:05:41 -08:00
snipe 583a0412fe Added edit fieldsets translations
Signed-off-by: snipe <snipe@snipe.net>
2023-01-26 17:03:23 -08:00
snipe a16604285c Normalize the fieldset form
Signed-off-by: snipe <snipe@snipe.net>
2023-01-26 17:03:07 -08:00
snipe 37f5cfa8ce Added edit button for fieldsets
Signed-off-by: snipe <snipe@snipe.net>
2023-01-26 17:02:53 -08:00
Godfrey M a63ea560ae adds submit button, getting setAttribute error 2023-01-26 15:17:08 -08:00
akemidx 79d9cff22a translations added for the hardware blades 2023-01-26 16:26:31 -05:00
Marcus Moore 39289dd18e Use user provided alert email for checkout acceptances 2023-01-26 13:18:18 -08:00
snipe 8b94b208e3 Merge remote-tracking branch 'origin/develop' 2023-01-26 13:17:28 -08:00
Marcus Moore 6fc8982478 Have acceptance result notifications adhere to alerts enabled setting 2023-01-26 12:59:33 -08:00
snipe cc370084d1 Merge pull request #12341 from uberbrady/redo_scim_config
Redo SCIM config; use latest laravel-scim-server from our fork
2023-01-26 12:57:29 -08:00
Brady Wetherington cd573c484d Change the SCIM_STANDARDS_COMPLIANCE config to default to 'true' 2023-01-26 12:48:41 -08:00
akemidx df31a76906 fixed apostraphe 2023-01-26 15:02:39 -05:00
Brady Wetherington 4a54586690 Add to Accessories#index an additional gate-check against reports.view 2023-01-26 11:56:06 -08:00
Godfrey M 62b4c79150 adds a couple error messages 2023-01-25 16:38:08 -08:00
Godfrey M a69cb6204a adds rest of inputs, and corrects Data binding 2023-01-25 16:22:34 -08:00
Brady Wetherington c5d3b3ab81 Change out the SCIM config for a fixed one; update our fork of the SCIM-server 2023-01-25 15:59:46 -08:00
Brady Wetherington cfe9c687f9 Mark a bunch of SCIM config as nullable 2023-01-25 15:54:57 -08:00
Brady Wetherington 91cf683f3d Re-do the entire SCIM config so it no longer inherits 2023-01-25 15:53:46 -08:00
Godfrey M 2e22eeade5 adds one input 2023-01-25 14:29:20 -08:00
akemidx 53d8008a5f Merge branch 'vip_tag' of github.com:akemidx/snipe-it into vip_tag 2023-01-25 17:14:29 -05:00
akemidx b363524305 vipuser label updated to vip 2023-01-25 15:58:44 -05:00
snipe 4c3354b778 Merge branch 'develop' into vip_tag 2023-01-24 20:29:43 -08:00
snipe e7917d1f93 Rebuild prod assets
Signed-off-by: snipe <snipe@snipe.net>
2023-01-24 19:16:03 -08:00
snipe 6b729502c6 Rebuilt dev assets
Signed-off-by: snipe <snipe@snipe.net>
2023-01-24 19:13:40 -08:00
snipe be6f367565 Merge remote-tracking branch 'origin/develop' 2023-01-24 19:12:50 -08:00
snipe f0b14513db Merge pull request #12411 from uberbrady/fix_rb_16746
Resolved Rollbar error 16746 - missing array key 'extension'
2023-01-24 18:24:18 -08:00
Brady Wetherington ab12ad1140 Resolves Rollbar error 16746 - missing array key 'extension' 2023-01-24 18:19:26 -08:00
snipe 9c79fc19cb Tightened up and removed some validation that wasn’t needed
Signed-off-by: snipe <snipe@snipe.net>
2023-01-24 17:37:15 -08:00
snipe fd2a057d38 Make audit dates fillable
Signed-off-by: snipe <snipe@snipe.net>
2023-01-24 17:36:58 -08:00
Brady Wetherington b00333c9f5 Merge remote-tracking branch 'upstream/develop' into develop 2023-01-24 17:36:39 -08:00
Brady Wetherington c9f0f5fe8b Change Accessories report to use server-side pagination from URL 2023-01-24 17:35:44 -08:00
snipe a61ccbb965 Added very clunky but better error messages on that validation for date_format
Signed-off-by: snipe <snipe@snipe.net>
2023-01-24 17:33:49 -08:00
snipe 91394f7262 Removed duplicate comment section
Signed-off-by: snipe <snipe@snipe.net>
2023-01-24 17:23:06 -08:00
akemidx 3ba79600fb checkin limit for the components checkin 2023-01-24 18:17:49 -05:00
snipe 935f5018cc Merge pull request #12405 from Godmartinz/high_contrast_color_adjustments
Fixed buttons colors in high contrast theme
2023-01-24 15:17:03 -08:00
snipe 3c4f254583 Enforce Y-m-d as date format for date fields
Signed-off-by: snipe <snipe@snipe.net>
2023-01-24 13:38:53 -08:00
akemidx cafe8f3074 notification for slack message 2023-01-24 16:20:20 -05:00
akemidx 19cf170dd9 Add VIP Checkbox 2023-01-24 15:30:21 -05:00
akemidx 596846a94a Add VIP Checkbox 2023-01-24 15:29:27 -05:00
Marcus Moore b92d1d3ec7 Logically group query when searching users to scope to company 2023-01-24 11:54:56 -08:00
Godfrey M 4b51424723 fixes a couple buttons color choices in high contrast 2023-01-24 09:42:03 -08:00
Godfrey M 0f8ee22053 Creates Slack Setting Form 2023-01-24 09:25:05 -08:00
snipe 86812b024d Merge remote-tracking branch 'origin/develop' 2023-01-23 22:03:12 -08:00
snipe dc155846ca Hoist the autorization higher in the stack so we’re not doing logic or math when the user isn’t authorized to touch this
Signed-off-by: snipe <snipe@snipe.net>
2023-01-23 21:49:17 -08:00
snipe 7a9ea91be0 Merge pull request #12387 from snipe/fixes/inconsistent_UI_for_image_delete
Updated - Refactored ImageHandler request to be more re-usable, and checkboxes with missing `minimal` class for iCheck
2023-01-23 21:39:55 -08:00
snipe 02dcb0fbd7 Shorten the additiona form request invocation to just ImageUploadRequest
We already have the `use App\Http\Requests\ImageUploadRequest` clause at the top of this file.

Signed-off-by: snipe <snipe@snipe.net>
2023-01-23 21:37:35 -08:00
snipe 690bfbe16a Merge pull request #12398 from akemidx/acceptance_translations
Fixed: translations for EULA Acceptance Summary
2023-01-23 21:28:59 -08:00
Marcus Moore cd582be851 Drop tables that may exist in down methods 2023-01-23 15:42:45 -08:00
Marcus Moore 760844de6f Add conditionals 2023-01-23 15:42:33 -08:00
Marcus Moore e6dc61d2cf Revert column names to legacy versions in down method 2023-01-23 15:42:05 -08:00
snipe 4c7b731acc Merge remote-tracking branch 'origin/develop' 2023-01-23 15:36:05 -08:00
snipe 35dfaddd79 Merge pull request #12400 from snipe/jerm/fix-import-backup-checkbox
Fixed "Backup before importing?" checkbox on import page
2023-01-23 15:35:18 -08:00
Jeremy Price d3bcc48ae5 [imports] fix "Backup before importing?" checkbox on import page
We were always taking backups before import, no matter the status of
this box.

Turns out we were testing for the presence of the property defined by
the checkbox, rather than the value of the property, and as such were
always doing a backup.

We're now checking the status, and it behaves as expected
2023-01-23 15:08:59 -08:00
akemidx 25996cbe03 translating the quick info printed out on accept x eula blades 2023-01-23 16:18:21 -05:00
snipe 4b01909806 Merge pull request #12389 from snipe/fixes/livewire_ui
Fixed #12388 - Add CSS to the div to correct the weird indenting
2023-01-23 11:42:26 -08:00
snipe 41537a2449 Added field to the API controller endpoints
Signed-off-by: snipe <snipe@snipe.net>
2023-01-22 00:56:44 -08:00
snipe 5f9af7d509 Updated API response
Signed-off-by: snipe <snipe@snipe.net>
2023-01-22 00:56:28 -08:00
snipe febfcd4803 Updated model with new field
Signed-off-by: snipe <snipe@snipe.net>
2023-01-22 00:56:19 -08:00
snipe cad76f671a Added asset_eol_date to blade
Signed-off-by: snipe <snipe@snipe.net>
2023-01-22 00:55:42 -08:00
snipe 4104d7260f Include new eol date picker blade
Signed-off-by: snipe <snipe@snipe.net>
2023-01-22 00:55:31 -08:00
snipe 3587017591 Updated EOL date in view blade
Signed-off-by: snipe <snipe@snipe.net>
2023-01-22 00:55:19 -08:00
snipe 8040d08e8c Removed formatter from EOL date
Signed-off-by: snipe <snipe@snipe.net>
2023-01-22 00:54:37 -08:00
snipe 2f7ca37666 Migration to normalize eol date for assets
Signed-off-by: snipe <snipe@snipe.net>
2023-01-22 00:54:24 -08:00
snipe abad579306 Added eol date picker
Signed-off-by: snipe <snipe@snipe.net>
2023-01-22 00:45:33 -08:00
snipe 72295c093a Add CSS to the div to correct the weird indenting - fixes #12388
Signed-off-by: snipe <snipe@snipe.net>
2023-01-21 18:24:23 -08:00
snipe cd8cb445ba Corrected fieldname for user fieldname for avatar in Controller
Signed-off-by: snipe <snipe@snipe.net>
2023-01-21 18:20:53 -08:00
snipe 2dc1182582 Don’t offer the delete option if there is no avatar currently
Signed-off-by: snipe <snipe@snipe.net>
2023-01-21 18:20:26 -08:00
snipe 93ad0d02b9 Use fieldname for aria labels too
Signed-off-by: snipe <snipe@snipe.net>
2023-01-21 18:20:02 -08:00
snipe 48c85966d7 Added gravatar and avatar as fillable
Signed-off-by: snipe <snipe@snipe.net>
2023-01-21 18:07:17 -08:00
snipe a0aed19f95 Refactor image handler
Signed-off-by: snipe <snipe@snipe.net>
2023-01-21 18:05:55 -08:00
snipe f77d871dff Use the imageHandler for profile avatar changes
Signed-off-by: snipe <snipe@snipe.net>
2023-01-21 18:05:20 -08:00
snipe 3674f46ce0 Added arial labels
Signed-off-by: snipe <snipe@snipe.net>
2023-01-21 16:42:44 -08:00
snipe cfa342c81a Updated HTML for “standard” image edit/delete
Signed-off-by: snipe <snipe@snipe.net>
2023-01-21 16:23:04 -08:00
snipe 563a252d18 Updated checkboxed with missing minimal class for iCheck
Signed-off-by: snipe <snipe@snipe.net>
2023-01-21 14:57:52 -08:00
snipe 2bdf3d3f44 Missed a few strong HTML tags
Signed-off-by: snipe <snipe@snipe.net>
2023-01-21 14:44:10 -08:00
snipe 60eab08735 Added ->with(‘users as users_count’) in Accessory query
Signed-off-by: snipe <snipe@snipe.net>
2023-01-21 14:41:07 -08:00
snipe 90c1631820 Added users_count to transformer for API
Signed-off-by: snipe <snipe@snipe.net>
2023-01-21 14:40:35 -08:00
snipe dceb77d4d4 Refactored numRemaining, removed unnecessary numCheckout
Signed-off-by: snipe <snipe@snipe.net>
2023-01-21 14:40:20 -08:00
snipe 46e3e8a3dd Added new users_count field to API
Signed-off-by: snipe <snipe@snipe.net>
2023-01-21 14:39:53 -08:00
snipe 56090bc645 Re-ordered notes to be more consistent, fixed missing iCheck class
Signed-off-by: snipe <snipe@snipe.net>
2023-01-21 14:38:35 -08:00
snipe fd73bee850 Fixed hardcoded string and added new checkout count to accessory view
Signed-off-by: snipe <snipe@snipe.net>
2023-01-21 14:38:05 -08:00
snipe 2564da648b Merge remote-tracking branch 'origin/develop' 2023-01-19 16:22:09 -08:00
snipe b59dcc7b30 Merge pull request #12379 from marcusmoore/fix/row-divider-overflow
Fix minor visual bug on asset show page
2023-01-19 16:21:31 -08:00
snipe d020ab455d Bumped hash
Signed-off-by: snipe <snipe@snipe.net>
2023-01-19 15:56:53 -08:00
snipe 05a3f20d51 Updated production assets
Signed-off-by: snipe <snipe@snipe.net>
2023-01-19 15:55:59 -08:00
snipe 69ab42b3f9 Merge pull request #12380 from snipe/maintenance/asset_updates
Updated dev assets
2023-01-19 15:53:55 -08:00
snipe 0080ac92e7 Updated dev assets
Signed-off-by: snipe <snipe@snipe.net>
2023-01-19 15:52:06 -08:00
snipe 9508a97852 Merge pull request #12378 from marcusmoore/fix/allow-removing-asset-name-during-checkout
Allow users to set a blank asset name during checkout
2023-01-19 14:50:58 -08:00
Marcus Moore 0fa956403c Fix row divider overflow 2023-01-19 14:16:28 -08:00
Marcus Moore 181f96ad33 Allow users to set a blank asset name during checkout 2023-01-19 12:35:44 -08:00
snipe 04e28c2d34 Merge pull request #12377 from inietov/fixes/visual_glitch_deleting_importing_files
Fixed #12340  Deleting imported files visually drops first element in table.
2023-01-19 11:59:40 -08:00
Ivan Nieto Vivanco f045008237 Add index to deleteFile() call, so it knows what element delete 2023-01-19 13:04:49 -06:00
snipe fa9116b184 Merge pull request #12369 from snipe/features/add_byod_to_assets
Added BYOD to assets
2023-01-18 16:09:45 -08:00
snipe 155977de2d Merge pull request #12370 from marcusmoore/fix/file-upload-tab-permissions
Fixed file uploads for accessories, components, and consumables
2023-01-18 16:08:53 -08:00
snipe 378dc968b7 Derp. Copypasta
Signed-off-by: snipe <snipe@snipe.net>
2023-01-18 15:44:28 -08:00
Marcus Moore c089f6eff2 Reference the accessory instance instead of the model 2023-01-18 13:48:01 -08:00
Marcus Moore e506ed7950 Remove extra quote 2023-01-18 13:42:09 -08:00
Marcus Moore 07744ca7bd Reference the consumable instance instead of the model 2023-01-18 13:41:58 -08:00
snipe 0c39c7a53d Updated blades to add byod as a “status”
Signed-off-by: snipe <snipe@snipe.net>
2023-01-18 13:25:46 -08:00
snipe fce620b54f Added byod to blades
Signed-off-by: snipe <snipe@snipe.net>
2023-01-18 13:11:02 -08:00
snipe 33fe2b57f7 Added new byod strings
Signed-off-by: snipe <snipe@snipe.net>
2023-01-18 13:10:48 -08:00
snipe 45019c65f1 BYOD migration
Signed-off-by: snipe <snipe@snipe.net>
2023-01-18 13:10:39 -08:00
snipe acd182e3d2 Added byod to presenter with boolean formatter
Signed-off-by: snipe <snipe@snipe.net>
2023-01-18 13:10:30 -08:00
snipe 48b8cfcef9 Added byod to model, removed duplicate validation rule
Signed-off-by: snipe <snipe@snipe.net>
2023-01-18 13:04:36 -08:00
snipe f626413502 Added byod to API transformer
Signed-off-by: snipe <snipe@snipe.net>
2023-01-18 13:04:02 -08:00
snipe b80d52a9c3 Added byod to asset controller for create and update methods
Signed-off-by: snipe <snipe@snipe.net>
2023-01-18 13:03:51 -08:00
snipe ee4b8f4694 Added byod to API controller
Signed-off-by: snipe <snipe@snipe.net>
2023-01-18 13:03:31 -08:00
Marcus Moore ca1198ceb2 Constrain the bottom bar to the content window 2023-01-18 12:55:20 -08:00
Marcus Moore b31e000165 Have Info and History tables in accessory show page span entire width of row 2023-01-18 12:54:52 -08:00
Godfrey M 7ce230fadc missed a few renames 2023-01-18 08:57:59 -08:00
Godfrey M 6fbb484dfd renames db column for auto_assign boolean, rewords trans string, default value of 1 now 2023-01-18 08:43:03 -08:00
snipe 956bd384b0 Merge pull request #12364 from snipe/features/make_2fa_sortable
BREAKING: Partial fix for #12356: Make 2FA sortable in user list
2023-01-17 20:24:05 -08:00
snipe 7e22663326 Merge pull request #12363 from corydlamb/Ampersand-Patch
Fixed #12362: Bug With Passwords Including Ampersands?
2023-01-17 19:17:50 -08:00
snipe c3e4d9d773 Make column name consistent with field name (BREAKING)
Signed-off-by: snipe <snipe@snipe.net>
2023-01-17 18:27:47 -08:00
snipe f08babfa8a Just moved some stuff around - no actual meaningful code changes
Signed-off-by: snipe <snipe@snipe.net>
2023-01-17 17:22:03 -08:00
snipe 4ef0005e7c BREAKING: changed API fieldname result for 2FA
Signed-off-by: snipe <snipe@snipe.net>
2023-01-17 17:21:40 -08:00
snipe dbda288a44 Formatting changes only for readability
Signed-off-by: snipe <snipe@snipe.net>
2023-01-17 17:21:20 -08:00
snipe eaf9332096 Added filterability to 2FA fields
Signed-off-by: snipe <snipe@snipe.net>
2023-01-17 17:21:03 -08:00
Marcus Moore 5282ca47b3 Allow users with consumables.files ability to upload files for consumables 2023-01-17 17:16:50 -08:00
Marcus Moore 23a1b2d60a Register the consumables.files ability 2023-01-17 17:15:23 -08:00
Marcus Moore 1f12137245 Close divs in correct location 2023-01-17 17:09:55 -08:00
Marcus Moore 6c89f08193 Register the accessories.files ability and allow users with the ability to upload files for accessories 2023-01-17 16:59:50 -08:00
corydlamb 295f0dd1f5 Update WelcomeNotification.php
Used htmlspecialchars_decode to fix the issue I had involving Ampersands in the password field (and I'm assuming the other fields) of the welcome notification email. Changes are all in lines 22-26. Sorry if I'm not doing this very well as this is my first pull request.
2023-01-17 19:33:25 -05:00
Marcus Moore 1fef992fa8 Allow users with components.files ability to upload files for components 2023-01-17 15:58:11 -08:00
Marcus Moore e23ee7540d Register the components.files ability 2023-01-17 15:45:40 -08:00
snipe dd8c6e92db Merge pull request #12355 from snipe/features/make_category_visable_on_models_page_by_default
Added catergories to default visiable set on asset models
2023-01-15 17:09:00 -08:00
snipe f4630d67be Added catergories to default visiable set
Signed-off-by: snipe <snipe@snipe.net>
2023-01-15 17:07:50 -08:00
snipe 6f6f99f64e Merge pull request #12354 from uberbrady/fix_npm_dependencies
Backed out less-loader version requirement so that builds still work
2023-01-14 10:57:35 -08:00
Brady Wetherington 6f89e8b0d8 Backed out less-loader version requirement so that builds still work 2023-01-14 10:53:36 -08:00
snipe 6815a16a5f Merge pull request #12353 from snipe/fixes/rollbar_logging
Only add rollbar to the logging array if the app is in production
2023-01-13 13:53:30 -08:00
snipe 0c3d03a4ce Only add rollbar to the logging array if the app is in production
Signed-off-by: snipe <snipe@snipe.net>
2023-01-13 13:50:16 -08:00
snipe 8048d06853 Merge pull request #12352 from snipe/fixes/added_south_sudan_to_country_list
Added South Sudan to country list
2023-01-13 13:24:54 -08:00
snipe 50cc69c427 Added South Sudan to country list
Signed-off-by: snipe <snipe@snipe.net>
2023-01-13 13:23:57 -08:00
snipe 021e54adaa Merge pull request #12351 from snipe/fixes/check_filename_has_value_before_delete
Check that the `$use_db_field` has a value before attempting a delete
2023-01-13 11:29:31 -08:00
snipe 9d0a15990e Check that the $use_db_field has a value before attempting a delete
Signed-off-by: snipe <snipe@snipe.net>
2023-01-13 11:26:11 -08:00
Marcus Moore 51da747809 Add note about database requirements when running Dusk tests 2023-01-11 18:05:07 -08:00
Marcus Moore 0dd7cc9967 Add note about installing ChromeDriver to testing readme 2023-01-11 13:54:28 -08:00
Marcus Moore 49f2573f36 Update testing readme 2023-01-11 13:51:01 -08:00
Marcus Moore bc80f672ee Keep the example dusk environment file 2023-01-11 13:00:34 -08:00
Marcus Moore 49383ddbe0 Delete old dusk local configuration 2023-01-11 12:58:57 -08:00
Marcus Moore 9a3a796e17 Add dusk environment files to gitignore 2023-01-11 12:57:05 -08:00
Marcus Moore e8c2b84d24 Add example dusk environment file 2023-01-11 12:51:15 -08:00
snipe 4f8951f6f1 Merge pull request #12335 from uberbrady/windows_snipeit_restore
Fixed #12004: Snipe-IT restore didn't work on Windows
2023-01-11 11:03:44 -08:00
snipe 85b712e915 Merge pull request #12337 from snipe/docs/added_jamf_rename
Added jamf-snipe-rename script to third party list
2023-01-10 18:10:47 -08:00
snipe ca244911ed Added jamf-snipe-rename script to third party list
Signed-off-by: snipe <snipe@snipe.net>
2023-01-10 18:10:13 -08:00
snipe 942681bee5 Merge pull request #12336 from snipe/features/category_query_optimization
Refactor category API for fewer queries
2023-01-10 17:54:45 -08:00
snipe 459c95064e Fixed default
Signed-off-by: snipe <snipe@snipe.net>
2023-01-10 17:54:04 -08:00
Marcus Moore b5ea8b8a4f Conditionally drop table 2023-01-10 17:29:38 -08:00
Marcus Moore aec64fa64a Comment out migration's down method to match its up method 2023-01-10 17:25:25 -08:00
Marcus Moore 03938d0f32 Conditionally drop table 2023-01-10 17:24:38 -08:00
Marcus Moore 296c9a723d Reverse column rename in migration's down method 2023-01-10 17:22:29 -08:00
snipe 2eac03db4a Merge pull request #12329 from snipe/fixes/rollbar_integration
Fixed rollbar integration if ROLLBAR_TOKEN is provided
2023-01-10 17:21:52 -08:00
Marcus Moore c5b09ed955 Fix column name typo 2023-01-10 17:21:46 -08:00
Marcus Moore 4ee3cbf60e Comment out migration's down method to match its up method 2023-01-10 17:20:20 -08:00
Marcus Moore 39ab545cf5 Update alter statement to use correct suffix for column
This is brittle...
2023-01-10 17:08:28 -08:00
Marcus Moore e5cb68cc5e Move drop column command to correct migration 2023-01-10 17:06:16 -08:00
Marcus Moore b8b2543b0d Reference the correct table in migration down method 2023-01-10 17:04:21 -08:00
Marcus Moore bc0f666906 Create Setting in test to avoid being redirected to the setup screen 2023-01-10 17:03:09 -08:00
Marcus Moore 581655f756 Run database migrations for all Dusk tests 2023-01-10 17:02:11 -08:00
Marcus Moore 2aa50859b3 Bump Dusk version to fix broken macOS chrome driver link 2023-01-10 17:01:03 -08:00
snipe 0b0fdd8aa5 Small formatting fixes, fixed typo in comment
Signed-off-by: snipe <snipe@snipe.net>
2023-01-10 16:32:18 -08:00
snipe 8f3a237ea0 More comments
Signed-off-by: snipe <snipe@snipe.net>
2023-01-10 16:29:51 -08:00
snipe 151719a91c Added comments
Signed-off-by: snipe <snipe@snipe.net>
2023-01-10 16:24:46 -08:00
snipe 825df2cf75 Load up the item counts with the individual API methods for accurate numbers without n+1
Signed-off-by: snipe <snipe@snipe.net>
2023-01-10 16:17:03 -08:00
snipe b66cd313b9 Refactored itemCount() to use existing blah_count fields if they exist
Signed-off-by: snipe <snipe@snipe.net>
2023-01-10 16:16:25 -08:00
snipe d508374c57 Disallowed category type change string
Signed-off-by: snipe <snipe@snipe.net>
2023-01-10 16:15:51 -08:00
snipe f50b622eb8 Disallow editing of category type once created, added help text
Signed-off-by: snipe <snipe@snipe.net>
2023-01-10 16:15:40 -08:00
snipe bef4224e14 Added notes to itemCount()
Signed-off-by: snipe <snipe@snipe.net>
2023-01-10 13:50:24 -08:00
snipe 249b188654 Refactor category API and transformer for query optimization
Signed-off-by: snipe <snipe@snipe.net>
2023-01-10 13:30:01 -08:00
Brady Wetherington 2170343958 Fixed #12004: Snipe-IT restore didn't work on Windows 2023-01-10 13:06:47 -08:00
snipe 1cf7784bb8 Logging override if ROLLBAR_TOKEN is provided
Signed-off-by: snipe <snipe@snipe.net>
2023-01-10 00:20:56 -08:00
Godfrey M 8a0517fb5d removes data dump 2022-11-15 15:59:47 -08:00
Godfrey M 90828e3a87 fixes variable name 2022-11-15 15:51:52 -08:00
Godfrey M 45636b8114 adds should_autoassign boolean to users table 2022-11-15 15:42:57 -08:00
Phan Nguyen e457b2e98d Correct assignedusers relation setting 2022-10-17 13:10:09 +07:00
Nathan Butler 0617480f73 Asset checkinbytag now consistent with existingAPI
This is a non-breaking change to the checkinbytag endpoint to bring it
inline with the usage/formatting of the other bytag endpoints that
currently exist - using the URL path to define the asset_tag instead of
passing it through as a url query.

Both methods will work, but the URL Path method will take precidence if
it is used (the query will be ignored if included)
2022-06-30 09:23:52 +10:00
1249 changed files with 14394 additions and 7423 deletions
+45
View File
@@ -2837,6 +2837,51 @@
"contributions": [
"code"
]
},
{
"login": "AndrewSav",
"name": "Andrew Savinykh",
"avatar_url": "https://avatars.githubusercontent.com/u/658865?v=4",
"profile": "https://github.com/AndrewSav",
"contributions": [
"code"
]
},
{
"login": "kenchan0130",
"name": "Tadayuki Onishi",
"avatar_url": "https://avatars.githubusercontent.com/u/1155067?v=4",
"profile": "https://kenchan0130.github.io",
"contributions": [
"code"
]
},
{
"login": "floschoepfer",
"name": "Florian",
"avatar_url": "https://avatars.githubusercontent.com/u/112496896?v=4",
"profile": "https://github.com/floschoepfer",
"contributions": [
"code"
]
},
{
"login": "spencerrlongg",
"name": "Spencer Long",
"avatar_url": "https://avatars.githubusercontent.com/u/7305753?v=4",
"profile": "http://spencerlong.com",
"contributions": [
"code"
]
},
{
"login": "marcusmoore",
"name": "Marcus Moore",
"avatar_url": "https://avatars.githubusercontent.com/u/1141514?v=4",
"profile": "https://github.com/marcusmoore",
"contributions": [
"code"
]
}
]
}
+5 -5
View File
@@ -20,13 +20,13 @@ PUBLIC_FILESYSTEM_DISK=local_public
# REQUIRED: DATABASE SETTINGS
# --------------------------------------------
DB_CONNECTION=mysql
DB_HOST=localhost
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=snipeit-local
DB_USERNAME=snipeit-local
DB_PASSWORD=snipeit-local
DB_DATABASE=null
DB_USERNAME=null
DB_PASSWORD=null
DB_PREFIX=null
DB_DUMP_PATH='/Applications/MAMP/Library/bin'
#DB_DUMP_PATH=
# --------------------------------------------
# OPTIONAL: SSL DATABASE SETTINGS
-75
View File
@@ -1,75 +0,0 @@
# --------------------------------------------
# REQUIRED: BASIC APP SETTINGS
# --------------------------------------------
APP_ENV=testing
APP_DEBUG=true
APP_KEY=base64:glJpcM7BYwWiBggp3SQ/+NlRkqsBQMaGEOjemXqJzOU=
APP_URL=http://localhost:8000
APP_TIMEZONE='US/Pacific'
APP_LOCALE=en
FILESYSTEM_DISK=local
# --------------------------------------------
# REQUIRED: DATABASE SETTINGS
# --------------------------------------------
DB_CONNECTION=sqlite_testing
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=testing.sqlite
DB_USERNAME=null
DB_PASSWORD=null
# --------------------------------------------
# REQUIRED: OUTGOING MAIL SERVER SETTINGS
# --------------------------------------------
MAIL_DRIVER=log
MAIL_HOST=email-smtp.us-west-2.amazonaws.com
MAIL_PORT=587
MAIL_USERNAME=YOURUSERNAME
MAIL_PASSWORD=YOURPASSWORD
MAIL_ENCRYPTION=null
MAIL_FROM_ADDR=you@example.com
MAIL_FROM_NAME=Snipe-IT
# --------------------------------------------
# REQUIRED: IMAGE LIBRARY
# This should be gd or imagick
# --------------------------------------------
IMAGE_LIB=gd
# --------------------------------------------
# OPTIONAL: AWS SETTINGS
# --------------------------------------------
AWS_SECRET_ACCESS_KEY=null
AWS_ACCESS_KEY_ID=null
AWS_DEFAULT_REGION=null
AWS_BUCKET=null
AWS_BUCKET_ROOT=null
AWS_URL=null
# --------------------------------------------
# OPTIONAL: CACHE SETTINGS
# --------------------------------------------
CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync
# --------------------------------------------
# OPTIONAL: SESSION SETTINGS
# --------------------------------------------
SESSION_LIFETIME=12000
EXPIRE_ON_CLOSE=false
ENCRYPT=false
COOKIE_NAME=snipeittest_session
COOKIE_DOMAIN=null
SECURE_COOKIES=false
# --------------------------------------------
# OPTIONAL: APP LOG FORMAT
# --------------------------------------------
LOG_CHANNEL=single
LOG_LEVEL=debug
+19
View File
@@ -0,0 +1,19 @@
# --------------------------------------------
# REQUIRED: BASIC APP SETTINGS
# --------------------------------------------
APP_ENV=testing
APP_DEBUG=true
APP_KEY=base64:glJpcM7BYwWiBggp3SQ/+NlRkqsBQMaGEOjemXqJzOU=
APP_URL=http://localhost:8000
APP_TIMEZONE='UTC'
APP_LOCALE=en
# --------------------------------------------
# REQUIRED: DATABASE SETTINGS
# --------------------------------------------
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=null
DB_USERNAME=null
DB_PASSWORD=null
@@ -2,8 +2,6 @@ name: Feature Request
description: Suggest an idea for this project
title: "[Feature Request]: "
labels: ["feature request"]
assignees:
- snipe
body:
- type: textarea
attributes:
+1 -1
View File
@@ -36,7 +36,7 @@ jobs:
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
- name: Run Codacy Analysis CLI
uses: codacy/codacy-analysis-cli-action@v4.2.0
uses: codacy/codacy-analysis-cli-action@v4.3.0
with:
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
# You can also omit the token and run the tools that support default configurations
+21
View File
@@ -0,0 +1,21 @@
name: Crowdin Action
on:
push:
branches: [ develop ]
jobs:
upload-sources-to-crowdin:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Crowdin push
uses: crowdin/github-action@v1
with:
upload_sources: true
upload_translations: false
download_translations: false
project_id: ${{ secrets.CROWDIN_PROJECT_ID }}
token: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
+1 -1
View File
@@ -72,7 +72,7 @@ jobs:
# https://github.com/docker/build-push-action
- name: Build and push 'snipe-it' image
id: docker_build
uses: docker/build-push-action@v3
uses: docker/build-push-action@v4
with:
context: .
file: ./Dockerfile.alpine
+1 -1
View File
@@ -72,7 +72,7 @@ jobs:
# https://github.com/docker/build-push-action
- name: Build and push 'snipe-it' image
id: docker_build
uses: docker/build-push-action@v3
uses: docker/build-push-action@v4
with:
context: .
file: ./Dockerfile
+4
View File
@@ -1,6 +1,10 @@
.couscous
.DS_Store
.env
.env.dusk.*
!.env.dusk.example
.env.testing
phpstan.neon
.idea
/bin/
/bootstrap/compiled.php
+4 -2
View File
@@ -1,5 +1,5 @@
![Build Status](https://app.chipperci.com/projects/0e5f8979-31eb-4ee6-9abf-050b76ab0383/status/master) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/snipe-it/localized.svg)](https://crowdin.com/project/snipe-it) [![Docker Pulls](https://img.shields.io/docker/pulls/snipe/snipe-it.svg)](https://hub.docker.com/r/snipe/snipe-it/) [![Twitter Follow](https://img.shields.io/twitter/follow/snipeitapp.svg?style=social)](https://twitter.com/snipeitapp) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/553ce52037fc43ea99149785afcfe641)](https://www.codacy.com/app/snipe/snipe-it?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=snipe/snipe-it&amp;utm_campaign=Badge_Grade)
[![All Contributors](https://img.shields.io/badge/all_contributors-312-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-317-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
@@ -60,6 +60,7 @@ Since the release of the JSON REST API, several third-party developers have been
- [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/grokability/jamf2snipe) - Python script to sync assets between a JAMFPro instance and a Snipe-IT instance
- [jamf-snipe-rename](https://macblog.org/jamf-snipe-rename/) - Python script to rename computers in Jamf from Snipe-IT
- [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.
@@ -139,7 +140,8 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
| [<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/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") | [<img src="https://avatars.githubusercontent.com/u/5957345?v=4" width="110px;"/><br /><sub>subdriven</sub>](https://github.com/subdriven)<br />[💻](https://github.com/snipe/snipe-it/commits?author=subdriven "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") | [<img src="https://avatars.githubusercontent.com/u/5957345?v=4" width="110px;"/><br /><sub>subdriven</sub>](https://github.com/subdriven)<br />[💻](https://github.com/snipe/snipe-it/commits?author=subdriven "Code") | [<img src="https://avatars.githubusercontent.com/u/658865?v=4" width="110px;"/><br /><sub>Andrew Savinykh</sub>](https://github.com/AndrewSav)<br />[💻](https://github.com/snipe/snipe-it/commits?author=AndrewSav "Code") | [<img src="https://avatars.githubusercontent.com/u/1155067?v=4" width="110px;"/><br /><sub>Tadayuki Onishi</sub>](https://kenchan0130.github.io)<br />[💻](https://github.com/snipe/snipe-it/commits?author=kenchan0130 "Code") | [<img src="https://avatars.githubusercontent.com/u/112496896?v=4" width="110px;"/><br /><sub>Florian</sub>](https://github.com/floschoepfer)<br />[💻](https://github.com/snipe/snipe-it/commits?author=floschoepfer "Code") |
| [<img src="https://avatars.githubusercontent.com/u/7305753?v=4" width="110px;"/><br /><sub>Spencer Long</sub>](http://spencerlong.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=spencerrlongg "Code") | [<img src="https://avatars.githubusercontent.com/u/1141514?v=4" width="110px;"/><br /><sub>Marcus Moore</sub>](https://github.com/marcusmoore)<br />[💻](https://github.com/snipe/snipe-it/commits?author=marcusmoore "Code") |
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
+29 -43
View File
@@ -1,65 +1,51 @@
# Using the Test Suite
# Running the Test Suite
This document is targeted at developers looking to make modifications to
this application's code base and want to run the existing test suite.
This document is targeted at developers looking to make modifications to this application's code base and want to run the existing test suite.
Before starting, follow the [instructions](README.md#installation) for installing the application locally and ensure you can load it in a browser properly.
## Setup
## Unit and Feature Tests
Follow the instructions for installing the application locally,
making sure to have also run the [database migrations](link to db migrations).
Before attempting to run the test suite copy the example environment file for tests and update the values to match your environment:
`cp .env.testing.example .env.testing`
> Since the data in the database is flushed after each test it is recommended you create a separate mysql database for specifically for tests
## Unit Tests
Now you are ready to run the entire test suite from your terminal:
The application will use values in the `.env.testing` file located
in the root directory to override the
default settings and/or other values that exist in your `.env` files.
`php artisan test`
Make sure to modify the section in `.env.testing` that has the
database settings. In the example below, it is connecting to the
[MariaDB](link-to-maria-db) server that is used if you install the
application using [Docker](https://docker.com).
To run individual test files, you can pass the path to the test that you want to run:
```dotenv
# --------------------------------------------
# REQUIRED: DATABASE SETTINGS
# --------------------------------------------
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_DATABASE=snipeit
DB_USERNAME=root
DB_PASSWORD=changeme1234
```
To run the entire unit test suite, use the following command from your terminal:
`php artisan test --env=testing`
To run individual test files, you can pass the path to the test that
you want to run.
`php artisan test --env=testing tests/Unit/AccessoryTest.php`
`php artisan test tests/Unit/AccessoryTest.php`
## Browser Tests
The browser tests use [Dusk](https://laravel.com/docs/8.x/dusk) to run them.
When troubleshooting any problems, make sure that your `.env` file is configured
correctly to run the existing application.
Browser tests are run via [Laravel Dusk](https://laravel.com/docs/8.x/dusk) and require Google Chrome to be installed.
### Test Setup
Before attempting to run Dusk tests copy the example environment file for Dusk and update the values to match your environment:
Your application needs to be configued and up and running in order for the browser
tests to actually run. When running the tests locally, you can start the application
using the following command:
`cp .env.dusk.example .env.dusk.local`
> `local` refers to the value of `APP_ENV` in your `.env` so if you have it set to `dev` then the file should be named `.env.dusk.dev`.
**Important**: Dusk tests cannot be run using an in-memory SQLite database. Additionally, the Dusk test suite uses the `DatabaseMigrations` trait which will leave the database in a fresh state after running. Therefore, it is recommended that you create a test database and point `DB_DATABASE` in `.env.dusk.local` to it.
### Running Browser Tests
Your application needs to be configured and up and running in order for the browser tests to actually run. When running the tests locally, you can start the application using the following command:
`php artisan serve`
To run the test suite use the following command from another terminal tab or window:
Now you are ready to run the test suite. Use the following command from another terminal tab or window:
`php artisan dusk`
To run individual test files, you can pass the path to the test that you want to run.
To run individual test files, you can pass the path to the test that you want to run:
`php artisan dusk tests/Browser/LoginTest.php`
If you get an error when attempting to run Dusk tests that says `Couldn't connect to server` run:
`php artisan dusk:chrome-driver --detect`
This command will install the specific ChromeDriver Dusk needs for your operating system and Chrome version.
@@ -56,7 +56,7 @@ class CheckoutLicenseToAllUsers extends Command
return false;
}
$users = User::whereNull('deleted_at')->with('licenses')->get();
$users = User::whereNull('deleted_at')->where('autoassign_licenses', '==', 1)->with('licenses')->get();
if ($users->count() > $license->getAvailSeatsCountAttribute()) {
$this->info('You do not have enough free seats to complete this task, so we will check out as many as we can. ');
+20 -9
View File
@@ -3,14 +3,29 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use \App\Models\User;
class CreateAdmin extends Command
{
/** @mixin User **/
/**
* The name and signature of the console command.
*
* @var string
* App\Console\CreateAdmin
* @property mixed $first_name
* @property string $last_name
* @property string $username
* @property string $email
* @property string $permissions
* @property string $password
* @property boolean $activated
* @property boolean $show_in_list
* @property \Illuminate\Support\Carbon|null $created_at
* @property mixed $created_by
*/
protected $signature = 'snipeit:create-admin {--first_name=} {--last_name=} {--email=} {--username=} {--password=} {show_in_list?}';
/**
@@ -30,11 +45,7 @@ class CreateAdmin extends Command
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$first_name = $this->option('first_name');
@@ -47,7 +58,7 @@ class CreateAdmin extends Command
if (($first_name == '') || ($last_name == '') || ($username == '') || ($email == '') || ($password == '')) {
$this->info('ERROR: All fields are required.');
} else {
$user = new \App\Models\User;
$user = new User;
$user->first_name = $first_name;
$user->last_name = $last_name;
$user->username = $username;
+39 -32
View File
@@ -44,12 +44,18 @@ class LdapSync extends Command
*/
public function handle()
{
// If LDAP enabled isn't set to 1 (ldap_enabled!=1) then we should cut this short immediately without going any further
if (Setting::getSettings()->ldap_enabled!='1') {
$this->error('LDAP is not enabled. Aborting. See Settings > LDAP to enable it.');
exit();
}
ini_set('max_execution_time', env('LDAP_TIME_LIM', 600)); //600 seconds = 10 minutes
ini_set('memory_limit', env('LDAP_MEM_LIM', '500M'));
$ldap_result_username = Setting::getSettings()->ldap_username_field;
$ldap_result_last_name = Setting::getSettings()->ldap_lname_field;
$ldap_result_first_name = Setting::getSettings()->ldap_fname_field;
$ldap_result_active_flag = Setting::getSettings()->ldap_active_flag;
$ldap_result_emp_num = Setting::getSettings()->ldap_emp_num;
$ldap_result_email = Setting::getSettings()->ldap_email;
@@ -68,7 +74,7 @@ class LdapSync extends Command
$json_summary = ['error' => true, 'error_message' => $e->getMessage(), 'summary' => []];
$this->info(json_encode($json_summary));
}
LOG::info($e);
Log::info($e);
return [];
}
@@ -78,7 +84,7 @@ class LdapSync extends Command
try {
if ($this->option('base_dn') != '') {
$search_base = $this->option('base_dn');
LOG::debug('Importing users from specified base DN: \"'.$search_base.'\".');
Log::debug('Importing users from specified base DN: \"'.$search_base.'\".');
} else {
$search_base = null;
}
@@ -92,7 +98,7 @@ class LdapSync extends Command
$json_summary = ['error' => true, 'error_message' => $e->getMessage(), 'summary' => []];
$this->info(json_encode($json_summary));
}
LOG::info($e);
Log::info($e);
return [];
}
@@ -102,16 +108,16 @@ class LdapSync extends Command
if ($this->option('location') != '') {
$location = Location::where('name', '=', $this->option('location'))->first();
LOG::debug('Location name '.$this->option('location').' passed');
LOG::debug('Importing to '.$location->name.' ('.$location->id.')');
Log::debug('Location name '.$this->option('location').' passed');
Log::debug('Importing to '.$location->name.' ('.$location->id.')');
} elseif ($this->option('location_id') != '') {
$location = Location::where('id', '=', $this->option('location_id'))->first();
LOG::debug('Location ID '.$this->option('location_id').' passed');
LOG::debug('Importing to '.$location->name.' ('.$location->id.')');
Log::debug('Location ID '.$this->option('location_id').' passed');
Log::debug('Importing to '.$location->name.' ('.$location->id.')');
}
if (! isset($location)) {
LOG::debug('That location is invalid or a location was not provided, so no location will be assigned by default.');
Log::debug('That location is invalid or a location was not provided, so no location will be assigned by default.');
}
/* Process locations with explicitly defined OUs, if doing a full import. */
@@ -127,7 +133,7 @@ class LdapSync extends Command
array_multisort($ldap_ou_lengths, SORT_ASC, $ldap_ou_locations);
if (count($ldap_ou_locations) > 0) {
LOG::debug('Some locations have special OUs set. Locations will be automatically set for users in those OUs.');
Log::debug('Some locations have special OUs set. Locations will be automatically set for users in those OUs.');
}
// Inject location information fields
@@ -145,7 +151,7 @@ class LdapSync extends Command
$json_summary = ['error' => true, 'error_message' => trans('admin/users/message.error.ldap_could_not_search').' Location: '.$ldap_loc['name'].' (ID: '.$ldap_loc['id'].') cannot connect to "'.$ldap_loc['ldap_ou'].'" - '.$e->getMessage(), 'summary' => []];
$this->info(json_encode($json_summary));
}
LOG::info($e);
Log::info($e);
return [];
}
@@ -191,18 +197,18 @@ class LdapSync extends Command
for ($i = 0; $i < $results['count']; $i++) {
$item = [];
$item['username'] = isset($results[$i][$ldap_result_username][0]) ? $results[$i][$ldap_result_username][0] : '';
$item['employee_number'] = isset($results[$i][$ldap_result_emp_num][0]) ? $results[$i][$ldap_result_emp_num][0] : '';
$item['lastname'] = isset($results[$i][$ldap_result_last_name][0]) ? $results[$i][$ldap_result_last_name][0] : '';
$item['firstname'] = isset($results[$i][$ldap_result_first_name][0]) ? $results[$i][$ldap_result_first_name][0] : '';
$item['email'] = isset($results[$i][$ldap_result_email][0]) ? $results[$i][$ldap_result_email][0] : '';
$item['ldap_location_override'] = isset($results[$i]['ldap_location_override']) ? $results[$i]['ldap_location_override'] : '';
$item['location_id'] = isset($results[$i]['location_id']) ? $results[$i]['location_id'] : '';
$item['telephone'] = isset($results[$i][$ldap_result_phone][0]) ? $results[$i][$ldap_result_phone][0] : '';
$item['jobtitle'] = isset($results[$i][$ldap_result_jobtitle][0]) ? $results[$i][$ldap_result_jobtitle][0] : '';
$item['country'] = isset($results[$i][$ldap_result_country][0]) ? $results[$i][$ldap_result_country][0] : '';
$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] : '';
$item['username'] = $results[$i][$ldap_result_username][0] ?? '';
$item['employee_number'] = $results[$i][$ldap_result_emp_num][0] ?? '';
$item['lastname'] = $results[$i][$ldap_result_last_name][0] ?? '';
$item['firstname'] = $results[$i][$ldap_result_first_name][0] ?? '';
$item['email'] = $results[$i][$ldap_result_email][0] ?? '';
$item['ldap_location_override'] = $results[$i]['ldap_location_override'] ?? '';
$item['location_id'] = $results[$i]['location_id'] ?? '';
$item['telephone'] = $results[$i][$ldap_result_phone][0] ?? '';
$item['jobtitle'] = $results[$i][$ldap_result_jobtitle][0] ?? '';
$item['country'] = $results[$i][$ldap_result_country][0] ?? '';
$item['department'] = $results[$i][$ldap_result_dept][0] ?? '';
$item['manager'] = $results[$i][$ldap_result_manager][0] ?? '';
$department = Department::firstOrCreate([
@@ -303,17 +309,18 @@ class LdapSync extends Command
$user->activated = 0;
} */
$enabled_accounts = [
'512', // 0x200 NORMAL_ACCOUNT
'544', // 0x220 NORMAL_ACCOUNT, PASSWD_NOTREQD
'66048', // 0x10200 NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD
'66080', // 0x10220 NORMAL_ACCOUNT, PASSWD_NOTREQD, DONT_EXPIRE_PASSWORD
'262656', // 0x40200 NORMAL_ACCOUNT, SMARTCARD_REQUIRED
'262688', // 0x40220 NORMAL_ACCOUNT, PASSWD_NOTREQD, SMARTCARD_REQUIRED
'328192', // 0x50200 NORMAL_ACCOUNT, SMARTCARD_REQUIRED, DONT_EXPIRE_PASSWORD
'328224', // 0x50220 NORMAL_ACCOUNT, PASSWD_NOT_REQD, SMARTCARD_REQUIRED, DONT_EXPIRE_PASSWORD
'4194816',// 0x400200 NORMAL_ACCOUNT, DONT_REQ_PREAUTH
'512', // 0x200 NORMAL_ACCOUNT
'544', // 0x220 NORMAL_ACCOUNT, PASSWD_NOTREQD
'66048', // 0x10200 NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD
'66080', // 0x10220 NORMAL_ACCOUNT, PASSWD_NOTREQD, DONT_EXPIRE_PASSWORD
'262656', // 0x40200 NORMAL_ACCOUNT, SMARTCARD_REQUIRED
'262688', // 0x40220 NORMAL_ACCOUNT, PASSWD_NOTREQD, SMARTCARD_REQUIRED
'328192', // 0x50200 NORMAL_ACCOUNT, SMARTCARD_REQUIRED, DONT_EXPIRE_PASSWORD
'328224', // 0x50220 NORMAL_ACCOUNT, PASSWD_NOT_REQD, SMARTCARD_REQUIRED, DONT_EXPIRE_PASSWORD
'4194816',// 0x400200 NORMAL_ACCOUNT, DONT_REQ_PREAUTH
'4260352', // 0x410200 NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD, DONT_REQ_PREAUTH
'1049088', // 0x100200 NORMAL_ACCOUNT, NOT_DELEGATED
'1114624', // 0x110200 NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD, NOT_DELEGATED,
];
$user->activated = (in_array($results[$i]['useraccountcontrol'][0], $enabled_accounts)) ? 1 : 0;
@@ -0,0 +1,52 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\User;
class NormalizeUserNames extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'snipeit:normalize-names';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Normalizes weirdly formatted names as first-letter upercased';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$users = User::get();
$this->info($users->count() . ' users');
foreach ($users as $user) {
$user->first_name = ucwords(strtolower($user->first_name));
$user->last_name = ucwords(strtolower($user->last_name));
$user->email = strtolower($user->email);
$user->save();
}
}
}
+2 -2
View File
@@ -149,7 +149,7 @@ class RestoreFromBackup extends Command
$boring_files[] = $raw_path;
continue;
}
if (@pathinfo($raw_path)['extension'] == 'sql') {
if (@pathinfo($raw_path, PATHINFO_EXTENSION) == 'sql') {
\Log::debug("Found a sql file!");
$sqlfiles[] = $raw_path;
$sqlfile_indices[] = $i;
@@ -214,7 +214,7 @@ class RestoreFromBackup extends Command
$env_vars['MYSQL_PWD'] = config('database.connections.mysql.password');
// TODO notes: we are stealing the dump_binary_path (which *probably* also has your copy of the mysql binary in it. But it might not, so we might need to extend this)
// we unilaterally prepend a slash to the `mysql` command. This might mean your path could look like /blah/blah/blah//mysql - which should be fine. But maybe in some environments it isn't?
$mysql_binary = config('database.connections.mysql.dump.dump_binary_path').'/mysql';
$mysql_binary = config('database.connections.mysql.dump.dump_binary_path').\DIRECTORY_SEPARATOR.'mysql'.(\DIRECTORY_SEPARATOR == '\\' ? ".exe" : "");
if( ! file_exists($mysql_binary) ) {
return $this->error("mysql tool at: '$mysql_binary' does not exist, cannot restore. Please edit DB_DUMP_PATH in your .env to point to a directory that contains the mysqldump and mysql binary");
}
+24
View File
@@ -0,0 +1,24 @@
<?php
namespace App\Events;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use App\Models\User;
class UserMerged
{
use Dispatchable, SerializesModels;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(User $from_user, User $to_user, User $admin)
{
$this->merged_from = $from_user;
$this->merged_to = $to_user;
$this->admin = $admin;
}
}
+11 -4
View File
@@ -6,6 +6,7 @@ use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use App\Helpers\Helper;
use Illuminate\Validation\ValidationException;
use Illuminate\Auth\AuthenticationException;
use ArieTimmerman\Laravel\SCIMServer\Exceptions\SCIMException;
use Log;
use Throwable;
use JsonException;
@@ -28,6 +29,7 @@ class Handler extends ExceptionHandler
\Intervention\Image\Exception\NotSupportedException::class,
\League\OAuth2\Server\Exception\OAuthServerException::class,
JsonException::class,
SCIMException::class, //these generally don't need to be reported
];
/**
@@ -41,7 +43,9 @@ class Handler extends ExceptionHandler
public function report(Throwable $exception)
{
if ($this->shouldReport($exception)) {
\Log::error($exception);
if (class_exists(\Log::class)) {
\Log::error($exception);
}
return parent::report($exception);
}
}
@@ -51,7 +55,7 @@ class Handler extends ExceptionHandler
*
* @param \Illuminate\Http\Request $request
* @param \Exception $e
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse|\Illuminate\Http\Response
*/
public function render($request, Throwable $e)
{
@@ -68,6 +72,9 @@ class Handler extends ExceptionHandler
return response()->json(Helper::formatStandardApiResponse('error', null, 'invalid JSON'), 422);
}
if ($e instanceof SCIMException) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'invalid SCIM Request'), 400);
}
// Handle Ajax requests that fail because the model doesn't exist
if ($request->ajax() || $request->wantsJson()) {
@@ -111,8 +118,8 @@ class Handler extends ExceptionHandler
*
* @param \Illuminate\Http\Request $request
* @param \Illuminate\Auth\AuthenticationException $exception
* @return \Illuminate\Http\Response
*/
* @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
*/
protected function unauthenticated($request, AuthenticationException $exception)
{
if ($request->expectsJson()) {
+102 -25
View File
@@ -334,7 +334,11 @@ class Helper
'#92896B',
];
$total_colors = count($colors);
if ($index >= $total_colors) {
$index = $index - $total_colors;
}
return $colors[$index];
}
@@ -528,20 +532,23 @@ class Helper
* @since [v2.5]
* @return array
*/
public static function categoryTypeList()
public static function categoryTypeList($selection=null)
{
$category_types = [
'' => '',
'accessory' => 'Accessory',
'asset' => 'Asset',
'consumable' => 'Consumable',
'component' => 'Component',
'license' => 'License',
'accessory' => trans('general.accessory'),
'asset' => trans('general.asset'),
'consumable' => trans('general.consumable'),
'component' => trans('general.component'),
'license' => trans('general.license'),
];
if($selection != null){
return $category_types[$selection];
}
else
return $category_types;
}
/**
* Get the list of custom fields in an array to make a dropdown menu
*
@@ -1092,6 +1099,15 @@ class Helper
return $file_name;
}
/**
* Universal helper to show file size in human-readable formats
*
* @author A. Gianotto <snipe@snipe.net>
* @since 5.0
*
* @return string[]
*/
public static function formatFilesizeUnits($bytes)
{
if ($bytes >= 1073741824)
@@ -1121,30 +1137,91 @@ class Helper
return $bytes;
}
/**
* This is weird but used by the side nav to determine which URL to point the user to
*
* @author A. Gianotto <snipe@snipe.net>
* @since 5.0
*
* @return string[]
*/
public static function SettingUrls(){
$settings=['#','fields.index', 'statuslabels.index', 'models.index', 'categories.index', 'manufacturers.index', 'suppliers.index', 'departments.index', 'locations.index', 'companies.index', 'depreciations.index'];
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;
/**
* Generic helper (largely used by livewire right now) that returns the font-awesome icon
* for the object type.
*
* @author A. Gianotto <snipe@snipe.net>
* @since 6.1.0
*
* @return string
*/
public static function iconTypeByItem($item) {
switch ($item) {
case 'asset':
return 'fas fa-barcode';
break;
case 'accessory':
return 'fas fa-keyboard';
break;
case 'component':
return 'fas fa-hdd';
break;
case 'consumable':
return 'fas fa-tint';
break;
case 'license':
return 'far fa-save';
break;
case 'location':
return 'fas fa-map-marker-alt';
break;
case 'user':
return 'fas fa-user';
break;
}
}
/*
* This is a shorter way to see if the app is in demo mode.
*
* This makes it cleanly available in blades and in controllers, e.g.
*
* Blade:
* {{ Helper::isDemoMode() ? ' disabled' : ''}} for form blades where we need to disable a form
*
* Controller:
* if (Helper::isDemoMode()) {
* // don't allow the thing
* }
* @todo - use this everywhere else in the app where we have very long if/else config('app.lock_passwords') stuff
*/
public static function isDemoMode() {
if (config('app.lock_passwords') === true) {
return true;
\Log::debug('app locked!');
}
return false;
}
/*
* I know it's gauche to return a shitty HTML string, but this is just a helper and since it will be the same every single time,
* it seemed pretty safe to do here. Don't you judge me.
*/
public static function showDemoModeFieldWarning() {
if (Helper::isDemoMode()) {
return "<p class=\"text-warning\"><i class=\"fas fa-lock\"></i>" . trans('general.feature_disabled') . "</p>";
}
}
}
@@ -63,6 +63,7 @@ class AccessoriesController extends Controller
public function store(ImageUploadRequest $request)
{
$this->authorize(Accessory::class);
// create a new model instance
$accessory = new Accessory();
@@ -82,7 +83,6 @@ class AccessoriesController extends Controller
$accessory->supplier_id = request('supplier_id');
$accessory->notes = request('notes');
$accessory = $request->handleImages($accessory);
// Was the accessory created?
@@ -115,6 +115,33 @@ class AccessoriesController extends Controller
}
/**
* Returns a view that presents a form to clone an accessory.
*
* @author [J. Vinsmoke]
* @param int $accessoryId
* @since [v6.0]
* @return View
*/
public function getClone($accessoryId = null)
{
$this->authorize('create', Accesory::class);
// Check if the asset exists
if (is_null($accessory_to_clone = Accessory::find($accessoryId))) {
// Redirect to the asset management page
return redirect()->route('accessory.index')->with('error', trans('admin/accessories/message.does_not_exist'));
}
$accessory = clone $accessory_to_clone;
$accessory->id = null;
$accessory->location_id = null;
return view('accessories/edit')
->with('item', $accessory);
}
/**
* Save edited Accessory from form post
@@ -127,45 +154,47 @@ class AccessoriesController extends Controller
*/
public function update(ImageUploadRequest $request, $accessoryId = null)
{
if (is_null($accessory = Accessory::find($accessoryId))) {
if ($accessory = Accessory::withCount('users as users_count')->find($accessoryId)) {
$this->authorize($accessory);
$validator = Validator::make($request->all(), [
"qty" => "required|numeric|min:$accessory->users_count"
]);
if ($validator->fails()) {
return redirect()->back()
->withErrors($validator)
->withInput();
}
// Update the accessory data
$accessory->name = request('name');
$accessory->location_id = request('location_id');
$accessory->min_amt = request('min_amt');
$accessory->category_id = request('category_id');
$accessory->company_id = Company::getIdForCurrentUser(request('company_id'));
$accessory->manufacturer_id = request('manufacturer_id');
$accessory->order_number = request('order_number');
$accessory->model_number = request('model_number');
$accessory->purchase_date = request('purchase_date');
$accessory->purchase_cost = Helper::ParseCurrency(request('purchase_cost'));
$accessory->qty = request('qty');
$accessory->supplier_id = request('supplier_id');
$accessory->notes = request('notes');
$accessory = $request->handleImages($accessory);
// Was the accessory updated?
if ($accessory->save()) {
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.update.success'));
}
} else {
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
}
$min = $accessory->numCheckedOut();
$validator = Validator::make($request->all(), [
"qty" => "required|numeric|min:$min"
]);
if ($validator->fails()) {
return redirect()->back()
->withErrors($validator)
->withInput();
}
$this->authorize($accessory);
// Update the accessory data
$accessory->name = request('name');
$accessory->location_id = request('location_id');
$accessory->min_amt = request('min_amt');
$accessory->category_id = request('category_id');
$accessory->company_id = Company::getIdForCurrentUser(request('company_id'));
$accessory->manufacturer_id = request('manufacturer_id');
$accessory->order_number = request('order_number');
$accessory->model_number = request('model_number');
$accessory->purchase_date = request('purchase_date');
$accessory->purchase_cost = Helper::ParseCurrency(request('purchase_cost'));
$accessory->qty = request('qty');
$accessory->supplier_id = request('supplier_id');
$accessory->notes = request('notes');
$accessory = $request->handleImages($accessory);
// Was the accessory updated?
if ($accessory->save()) {
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.update.success'));
}
return redirect()->back()->withInput()->withErrors($accessory->getErrors());
}
@@ -217,7 +246,7 @@ class AccessoriesController extends Controller
*/
public function show($accessoryID = null)
{
$accessory = Accessory::find($accessoryID);
$accessory = Accessory::withCount('users as users_count')->find($accessoryID);
$this->authorize('view', $accessory);
if (isset($accessory->id)) {
return view('accessories/view', compact('accessory'));
@@ -222,8 +222,8 @@ class AcceptanceController extends Controller
'item_model' => $display_model,
'item_serial' => $item->serial,
'eula' => $item->getEula(),
'check_out_date' => Carbon::parse($acceptance->created_at)->format($branding_settings->date_display_format),
'accepted_date' => Carbon::parse($acceptance->accepted_at)->format($branding_settings->date_display_format),
'check_out_date' => Carbon::parse($acceptance->created_at)->format('Y-m-d'),
'accepted_date' => Carbon::parse($acceptance->accepted_at)->format('Y-m-d'),
'assigned_to' => $assigned_to,
'company_name' => $branding_settings->site_name,
'signature' => ($sig_filename) ? storage_path() . '/private_uploads/signatures/' . $sig_filename : null,
@@ -273,7 +273,7 @@ class AcceptanceController extends Controller
'item_tag' => $item->asset_tag,
'item_model' => $display_model,
'item_serial' => $item->serial,
'declined_date' => Carbon::parse($acceptance->accepted_at)->format($branding_settings->date_display_format),
'declined_date' => Carbon::parse($acceptance->declined_at)->format('Y-m-d'),
'assigned_to' => $assigned_to,
'company_name' => $branding_settings->site_name,
'date_settings' => $branding_settings->date_display_format,
@@ -26,7 +26,10 @@ class AccessoriesController extends Controller
*/
public function index(Request $request)
{
$this->authorize('view', Accessory::class);
if ($request->user()->cannot('reports.view')) {
$this->authorize('view', Accessory::class);
}
// This array is what determines which fields should be allowed to be sorted on ON the table itself, no relations
// Relations will be handled in query scopes a little further down.
@@ -41,10 +44,13 @@ class AccessoriesController extends Controller
'min_amt',
'company_id',
'notes',
'users_count',
'qty',
];
$accessories = Accessory::select('accessories.*')->with('category', 'company', 'manufacturer', 'users', 'location', 'supplier');
$accessories = Accessory::select('accessories.*')->with('category', 'company', 'manufacturer', 'users', 'location', 'supplier')
->withCount('users as users_count');
if ($request->filled('search')) {
$accessories = $accessories->TextSearch($request->input('search'));
+24 -7
View File
@@ -100,6 +100,8 @@ class AssetsController extends Controller
'checkout_counter',
'checkin_counter',
'requests_counter',
'byod',
'asset_eol_date',
];
$filter = [];
@@ -127,7 +129,6 @@ class AssetsController extends Controller
// They are also used by the individual searches on detail pages like
// locations, etc.
// Search custom fields by column name
foreach ($all_custom_fields as $field) {
if ($request->filled($field->db_column_name())) {
@@ -135,7 +136,6 @@ class AssetsController extends Controller
}
}
if ($request->filled('status_id')) {
$assets->where('assets.status_id', '=', $request->input('status_id'));
}
@@ -172,6 +172,10 @@ class AssetsController extends Controller
$assets->where('assets.supplier_id', '=', $request->input('supplier_id'));
}
if ($request->filled('asset_eol_date')) {
$assets->where('assets.asset_eol_date', '=', $request->input('asset_eol_date'));
}
if (($request->filled('assigned_to')) && ($request->filled('assigned_type'))) {
$assets->where('assets.assigned_to', '=', $request->input('assigned_to'))
->where('assets.assigned_type', '=', $request->input('assigned_type'));
@@ -189,6 +193,10 @@ class AssetsController extends Controller
$assets->ByDepreciationId($request->input('depreciation_id'));
}
if ($request->filled('byod')) {
$assets->where('assets.byod', '=', $request->input('byod'));
}
$request->filled('order_number') ? $assets = $assets->where('assets.order_number', '=', e($request->get('order_number'))) : '';
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
@@ -266,6 +274,11 @@ class AssetsController extends Controller
// more sad, horrible workarounds for laravel bugs when doing full text searches
$assets->where('assets.assigned_to', '>', '0');
break;
case 'byod':
// This is kind of redundant, since we already check for byod=1 above, but this keeps the
// sidebar nav links a little less chaotic
$assets->where('assets.byod', '=', '1');
break;
default:
if ((! $request->filled('status_id')) && ($settings->show_archived_in_list != '1')) {
@@ -847,7 +860,8 @@ class AssetsController extends Controller
$checkout_at = request('checkout_at', date('Y-m-d H:i:s'));
$expected_checkin = request('expected_checkin', null);
$note = request('note', null);
$asset_name = request('name', null);
// Using `->has` preserves the asset name if the name parameter was not included in request.
$asset_name = request()->has('name') ? request('name') : $asset->name;
// Set the location ID to the RTD location id if there is one
// Wait, why are we doing this? This overrides the stuff we set further up, which makes no sense.
@@ -927,18 +941,21 @@ class AssetsController extends Controller
* @since [v6.0]
* @return JsonResponse
*/
public function checkinByTag(Request $request)
public function checkinByTag(Request $request, $tag = null)
{
$this->authorize('checkin', Asset::class);
$asset = Asset::where('asset_tag', $request->input('asset_tag'))->first();
if(null == $tag && null !== ($request->input('asset_tag'))) {
$tag = $request->input('asset_tag');
}
$asset = Asset::where('asset_tag', $tag)->first();
if ($asset) {
return $this->checkin($request, $asset->id);
}
return response()->json(Helper::formatStandardApiResponse('error', [
'asset'=> e($request->input('asset_tag'))
], 'Asset with tag '.e($request->input('asset_tag')).' not found'));
'asset'=> e($tag)
], 'Asset with tag '.e($tag).' not found'));
}
@@ -10,6 +10,7 @@ use App\Models\Category;
use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
class CategoriesController extends Controller
{
@@ -23,10 +24,50 @@ class CategoriesController extends Controller
public function index(Request $request)
{
$this->authorize('view', Category::class);
$allowed_columns = ['id', 'name', 'category_type', 'category_type', 'use_default_eula', 'eula_text', 'require_acceptance', 'checkin_email', 'assets_count', 'accessories_count', 'consumables_count', 'components_count', 'licenses_count', 'image'];
$allowed_columns = [
'id',
'name',
'category_type',
'category_type',
'use_default_eula',
'eula_text',
'require_acceptance',
'checkin_email',
'assets_count',
'accessories_count',
'consumables_count',
'components_count',
'licenses_count',
'image',
];
$categories = Category::select([
'id',
'created_at',
'updated_at',
'name', 'category_type',
'use_default_eula',
'eula_text',
'require_acceptance',
'checkin_email',
'image'
])->withCount('accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'licenses as licenses_count');
/*
* This checks to see if we should override the Admin Setting to show archived assets in list.
* We don't currently use it within the Snipe-IT GUI, but will be useful for API integrations where they
* may actually need to fetch assets that are archived.
*
* @see \App\Models\Category::showableAssets()
*/
if ($request->input('archived')=='true') {
$categories = $categories->withCount('assets as assets_count');
} else {
$categories = $categories->withCount('showableAssets as assets_count');
}
$categories = Category::select(['id', 'created_at', 'updated_at', 'name', 'category_type', 'use_default_eula', 'eula_text', 'require_acceptance', 'checkin_email', 'image'])
->withCount('assets as assets_count', 'accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'licenses as licenses_count');
if ($request->filled('search')) {
$categories = $categories->TextSearch($request->input('search'));
@@ -107,7 +148,7 @@ class CategoriesController extends Controller
public function show($id)
{
$this->authorize('view', Category::class);
$category = Category::findOrFail($id);
$category = Category::withCount('assets as assets_count', 'accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'licenses as licenses_count')->findOrFail($id);
return (new CategoriesTransformer)->transformCategory($category);
}
@@ -126,8 +167,14 @@ class CategoriesController extends Controller
{
$this->authorize('update', Category::class);
$category = Category::findOrFail($id);
// Don't allow the user to change the category_type once it's been created
if (($request->filled('category_type')) && ($category->category_type != $request->input('category_type'))) {
return response()->json(
Helper::formatStandardApiResponse('error', null, trans('admin/categories/message.update.cannot_change_category_type'))
);
}
$category->fill($request->all());
$category->category_type = strtolower($request->input('category_type'));
$category = $request->handleImages($category);
if ($category->save()) {
@@ -148,7 +195,7 @@ class CategoriesController extends Controller
public function destroy($id)
{
$this->authorize('delete', Category::class);
$category = Category::findOrFail($id);
$category = Category::withCount('assets as assets_count', 'accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'licenses as licenses_count')->findOrFail($id);
if (! $category->isDeletable()) {
return response()->json(
@@ -33,7 +33,7 @@ class CustomFieldsetsController extends Controller
*/
public function index()
{
$this->authorize('index', CustomFieldset::class);
$this->authorize('index', CustomField::class);
$fieldsets = CustomFieldset::withCount('fields as fields_count', 'models as models_count')->get();
return (new CustomFieldsetsTransformer)->transformCustomFieldsets($fieldsets, $fieldsets->count());
@@ -49,7 +49,7 @@ class CustomFieldsetsController extends Controller
*/
public function show($id)
{
$this->authorize('view', CustomFieldset::class);
$this->authorize('view', CustomField::class);
if ($fieldset = CustomFieldset::find($id)) {
return (new CustomFieldsetsTransformer)->transformCustomFieldset($fieldset);
}
@@ -68,7 +68,7 @@ class CustomFieldsetsController extends Controller
*/
public function update(Request $request, $id)
{
$this->authorize('update', CustomFieldset::class);
$this->authorize('update', CustomField::class);
$fieldset = CustomFieldset::findOrFail($id);
$fieldset->fill($request->all());
@@ -89,7 +89,7 @@ class CustomFieldsetsController extends Controller
*/
public function store(Request $request)
{
$this->authorize('create', CustomFieldset::class);
$this->authorize('create', CustomField::class);
$fieldset = new CustomFieldset;
$fieldset->fill($request->all());
@@ -109,7 +109,7 @@ class CustomFieldsetsController extends Controller
*/
public function destroy($id)
{
$this->authorize('delete', CustomFieldset::class);
$this->authorize('delete', CustomField::class);
$fieldset = CustomFieldset::findOrFail($id);
$modelsCount = $fieldset->models->count();
@@ -136,7 +136,7 @@ class CustomFieldsetsController extends Controller
*/
public function fields($id)
{
$this->authorize('view', CustomFieldset::class);
$this->authorize('view', CustomField::class);
$set = CustomFieldset::findOrFail($id);
$fields = $set->fields;
@@ -153,7 +153,7 @@ class CustomFieldsetsController extends Controller
*/
public function fieldsWithDefaultValues($fieldsetId, $modelId)
{
$this->authorize('view', CustomFieldset::class);
$this->authorize('view', CustomField::class);
$set = CustomFieldset::findOrFail($fieldsetId);
+13 -7
View File
@@ -8,6 +8,7 @@ use App\Http\Transformers\GroupsTransformer;
use App\Models\Group;
use Illuminate\Http\Request;
class GroupsController extends Controller
{
/**
@@ -19,6 +20,8 @@ class GroupsController extends Controller
*/
public function index(Request $request)
{
$this->authorize('superadmin');
$this->authorize('view', Group::class);
$allowed_columns = ['id', 'name', 'created_at', 'users_count'];
@@ -59,9 +62,11 @@ class GroupsController extends Controller
*/
public function store(Request $request)
{
$this->authorize('create', Group::class);
$this->authorize('superadmin');
$group = new Group;
$group->fill($request->all());
$group->name = $request->input('name');
$group->permissions = $request->input('permissions'); // Todo - some JSON validation stuff here
if ($group->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $group, trans('admin/groups/message.create.success')));
@@ -80,7 +85,7 @@ class GroupsController extends Controller
*/
public function show($id)
{
$this->authorize('view', Group::class);
$this->authorize('superadmin');
$group = Group::findOrFail($id);
return (new GroupsTransformer)->transformGroup($group);
@@ -97,9 +102,11 @@ class GroupsController extends Controller
*/
public function update(Request $request, $id)
{
$this->authorize('update', Group::class);
$this->authorize('superadmin');
$group = Group::findOrFail($id);
$group->fill($request->all());
$group->name = $request->input('name');
$group->permissions = $request->input('permissions'); // Todo - some JSON validation stuff here
if ($group->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $group, trans('admin/groups/message.update.success')));
@@ -118,9 +125,8 @@ class GroupsController extends Controller
*/
public function destroy($id)
{
$this->authorize('delete', Group::class);
$this->authorize('superadmin');
$group = Group::findOrFail($id);
$this->authorize('delete', $group);
$group->delete();
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/groups/message.delete.success')));
+41 -10
View File
@@ -10,6 +10,7 @@ use App\Models\Asset;
use App\Models\Company;
use App\Models\Import;
use Artisan;
use Illuminate\Database\Eloquent\JsonEncodingException;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Storage;
@@ -35,7 +36,7 @@ class ImportController extends Controller
* Process and store a CSV upload file.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\JsonResponse
*/
public function store()
{
@@ -56,7 +57,7 @@ class ImportController extends Controller
'text/tsv', ])) {
$results['error'] = 'File type must be CSV. Uploaded file is '.$file->getMimeType();
return response()->json(Helper::formatStandardApiResponse('error', null, $results['error']), 500);
return response()->json(Helper::formatStandardApiResponse('error', null, $results['error']), 422);
}
//TODO: is there a lighter way to do this?
@@ -64,7 +65,19 @@ class ImportController extends Controller
ini_set('auto_detect_line_endings', '1');
}
$reader = Reader::createFromFileObject($file->openFile('r')); //file pointer leak?
$import->header_row = $reader->fetchOne(0);
try {
$import->header_row = $reader->fetchOne(0);
} catch (JsonEncodingException $e) {
return response()->json(
Helper::formatStandardApiResponse(
'error',
null,
trans('admin/hardware/message.import.header_row_has_malformed_characters')
),
422
);
}
//duplicate headers check
$duplicate_headers = [];
@@ -82,11 +95,22 @@ class ImportController extends Controller
}
}
if (count($duplicate_headers) > 0) {
return response()->json(Helper::formatStandardApiResponse('error', null, implode('; ', $duplicate_headers)), 500); //should this be '4xx'?
return response()->json(Helper::formatStandardApiResponse('error', null, implode('; ', $duplicate_headers)),422);
}
// Grab the first row to display via ajax as the user picks fields
$import->first_row = $reader->fetchOne(1);
try {
// Grab the first row to display via ajax as the user picks fields
$import->first_row = $reader->fetchOne(1);
} catch (JsonEncodingException $e) {
return response()->json(
Helper::formatStandardApiResponse(
'error',
null,
trans('admin/hardware/message.import.content_row_has_malformed_characters')
),
422
);
}
$date = date('Y-m-d-his');
$fixed_filename = str_slug($file->getClientOriginalName());
@@ -102,18 +126,25 @@ class ImportController extends Controller
}
$file_name = date('Y-m-d-his').'-'.$fixed_filename;
$import->file_path = $file_name;
$import->filesize = null;
if (!file_exists($path.'/'.$file_name)) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.file_not_found')), 500);
}
$import->filesize = filesize($path.'/'.$file_name);
$import->save();
$results[] = $import;
}
$results = (new ImportsTransformer)->transformImports($results);
return [
return response()->json([
'files' => $results,
];
]);
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.feature_disabled')), 500);
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.feature_disabled')), 422);
}
/**
@@ -127,7 +158,7 @@ class ImportController extends Controller
$this->authorize('import');
// Run a backup immediately before processing
if ($request->has('run-backup')) {
if ($request->get('run-backup')) {
\Log::debug('Backup manually requested via importer');
Artisan::call('backup:run');
} else {
@@ -10,7 +10,7 @@ use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
use Laravel\Passport\TokenRepository;
use Illuminate\Contracts\Validation\Factory as ValidationFactory;
use Gate;
use Illuminate\Support\Facades\Gate;
use DB;
class ProfileController extends Controller
@@ -57,8 +57,12 @@ class ReportsController extends Controller
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
$order = ($request->input('order') == 'asc') ? 'asc' : 'desc';
$offset = request('offset', 0);
$limit = request('limit', 50);
$total = $actionlogs->count();
// Check to make sure the limit is not higher than the max allowed
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
$actionlogs = $actionlogs->orderBy($sort, $order)->skip($offset)->take($limit)->get();
return response()->json((new ActionlogsTransformer)->transformActionlogs($actionlogs, $total), 200, ['Content-Type' => 'application/json;charset=utf8'], JSON_UNESCAPED_UNICODE);
@@ -143,47 +143,6 @@ class SettingsController extends Controller
}
public function slacktest(SlackSettingsRequest $request)
{
$validator = Validator::make($request->all(), [
'slack_endpoint' => 'url|required_with:slack_channel|starts_with:https://hooks.slack.com/|nullable',
'slack_channel' => 'required_with:slack_endpoint|starts_with:#|nullable',
]);
if ($validator->fails()) {
return response()->json(['message' => 'Validation failed', 'errors' => $validator->errors()], 422);
}
// If validation passes, continue to the curl request
$slack = new Client([
'base_url' => e($request->input('slack_endpoint')),
'defaults' => [
'exceptions' => false,
],
]);
$payload = json_encode(
[
'channel' => e($request->input('slack_channel')),
'text' => trans('general.slack_test_msg'),
'username' => e($request->input('slack_botname')),
'icon_emoji' => ':heart:',
]);
try {
$slack->post($request->input('slack_endpoint'), ['body' => $payload]);
return response()->json(['message' => 'Success'], 200);
} catch (\Exception $e) {
return response()->json(['message' => 'Please check the channel name and webhook endpoint URL ('.e($request->input('slack_endpoint')).'). Slack responded with: '.$e->getMessage()], 400);
}
//}
return response()->json(['message' => 'Something went wrong :( '], 400);
}
/**
* Test the email configuration
*
@@ -312,7 +271,7 @@ class SettingsController extends Controller
$headers = ['ContentType' => 'application/zip'];
return Storage::download($path.'/'.$file, $file, $headers);
} else {
return response()->json(Helper::formatStandardApiResponse('error', null, 'File not found'));
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.file_not_found')));
}
}
@@ -196,6 +196,7 @@ class StatuslabelsController extends Controller
{
$this->authorize('view', Statuslabel::class);
$statuslabels = Statuslabel::withCount('assets')->get();
$total = Array();
foreach ($statuslabels as $statuslabel) {
+71 -12
View File
@@ -20,6 +20,7 @@ use Auth;
use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
class UsersController extends Controller
{
@@ -69,6 +70,7 @@ class UsersController extends Controller
'users.ldap_import',
'users.start_date',
'users.end_date',
'users.vip',
])->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');
@@ -149,6 +151,18 @@ class UsersController extends Controller
$users = $users->where('remote', '=', $request->input('remote'));
}
if ($request->filled('vip')) {
$users = $users->where('vip', '=', $request->input('vip'));
}
if ($request->filled('two_factor_enrolled')) {
$users = $users->where('two_factor_enrolled', '=', $request->input('two_factor_enrolled'));
}
if ($request->filled('two_factor_optin')) {
$users = $users->where('two_factor_optin', '=', $request->input('two_factor_optin'));
}
if ($request->filled('start_date')) {
$users = $users->where('users.start_date', '=', $request->input('start_date'));
}
@@ -157,7 +171,6 @@ class UsersController extends Controller
$users = $users->where('users.end_date', '=', $request->input('end_date'));
}
if ($request->filled('assets_count')) {
$users->has('assets', '=', $request->input('assets_count'));
}
@@ -179,7 +192,6 @@ class UsersController extends Controller
}
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$offset = (($users) && (request('offset') > $users->count())) ? 0 : request('offset', 0);
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
@@ -205,14 +217,51 @@ class UsersController extends Controller
case 'company':
$users = $users->OrderCompany($order);
break;
case 'first_name':
$users->orderBy('first_name', $order);
$users->orderBy('last_name', $order);
break;
case 'last_name':
$users->orderBy('last_name', $order);
$users->orderBy('first_name', $order);
break;
default:
$allowed_columns =
[
'last_name', 'first_name', 'email', 'jobtitle', 'username', 'employee_num',
'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', 'start_date', 'end_date',
'last_name',
'first_name',
'email',
'jobtitle',
'username',
'employee_num',
'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',
'two_factor_optin',
'two_factor_enrolled',
'remote',
'vip',
'start_date',
'end_date',
];
$sort = in_array($request->get('sort'), $allowed_columns) ? $request->get('sort') : 'first_name';
@@ -251,9 +300,11 @@ class UsersController extends Controller
$users = Company::scopeCompanyables($users);
if ($request->filled('search')) {
$users = $users->SimpleNameSearch($request->get('search'))
->orWhere('username', 'LIKE', '%'.$request->get('search').'%')
->orWhere('employee_num', 'LIKE', '%'.$request->get('search').'%');
$users = $users->where(function ($query) use ($request) {
$query->SimpleNameSearch($request->get('search'))
->orWhere('username', 'LIKE', '%'.$request->get('search').'%')
->orWhere('employee_num', 'LIKE', '%'.$request->get('search').'%');
});
}
$users = $users->orderBy('last_name', 'asc')->orderBy('first_name', 'asc');
@@ -414,6 +465,13 @@ class UsersController extends Controller
// Check if the request has groups passed and has a value
if ($request->filled('groups')) {
$validator = Validator::make($request->all(), [
'groups.*' => 'integer|exists:permission_groups,id',
]);
if ($validator->fails()){
return response()->json(Helper::formatStandardApiResponse('error', null, $user->getErrors()));
}
$user->groups()->sync($request->input('groups'));
// The groups field has been passed but it is null, so we should blank it out
} elseif ($request->has('groups')) {
@@ -507,9 +565,10 @@ class UsersController extends Controller
if (empty($user->email)) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.inventorynotification.error')));
}
$user->notify((new CurrentInventory($user)));
return response()->Helper::formatStandardApiResponse('success', null, trans('admin/users/message.inventorynotification.success'));
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.inventorynotification.success')));
}
/**
@@ -82,8 +82,8 @@ class AssetModelsController extends Controller
$model->user_id = Auth::id();
$model->requestable = Request::has('requestable');
if ($request->input('custom_fieldset') != '') {
$model->fieldset_id = e($request->input('custom_fieldset'));
if ($request->input('fieldset_id') != '') {
$model->fieldset_id = e($request->input('fieldset_id'));
}
$model = $request->handleImages($model);
@@ -160,10 +160,10 @@ class AssetModelsController extends Controller
$this->removeCustomFieldsDefaultValues($model);
if ($request->input('custom_fieldset') == '') {
if ($request->input('fieldset_id') == '') {
$model->fieldset_id = null;
} else {
$model->fieldset_id = $request->input('custom_fieldset');
$model->fieldset_id = $request->input('fieldset_id');
if ($this->shouldAddDefaultValues($request->input())) {
if (!$this->assignCustomFieldsDefaultValues($model, $request->input('default_values'))){
@@ -444,7 +444,7 @@ class AssetModelsController extends Controller
{
return ! empty($input['add_default_values'])
&& ! empty($input['default_values'])
&& ! empty($input['custom_fieldset']);
&& ! empty($input['fieldset_id']);
}
/**
@@ -27,7 +27,7 @@ class AssetCheckoutController extends Controller
public function create($assetId)
{
// Check if the asset exists
if (is_null($asset = Asset::find(e($assetId)))) {
if (is_null($asset = Asset::with('company')->find(e($assetId)))) {
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
}
@@ -16,7 +16,7 @@ use App\Models\User;
use Auth;
use Carbon\Carbon;
use DB;
use Gate;
use Illuminate\Support\Facades\Gate;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Storage;
@@ -142,10 +142,12 @@ class AssetsController extends Controller
$asset->warranty_months = request('warranty_months', null);
$asset->purchase_cost = Helper::ParseCurrency($request->get('purchase_cost'));
$asset->purchase_date = request('purchase_date', null);
$asset->asset_eol_date = request('asset_eol_date', null);
$asset->assigned_to = request('assigned_to', null);
$asset->supplier_id = request('supplier_id', null);
$asset->requestable = request('requestable', 0);
$asset->rtd_location_id = request('rtd_location_id', null);
$asset->byod = request('byod', 0);
if (! empty($settings->audit_interval)) {
$asset->next_audit_date = Carbon::now()->addMonths($settings->audit_interval)->toDateString();
@@ -311,6 +313,8 @@ class AssetsController extends Controller
$asset->status_id = $request->input('status_id', null);
$asset->warranty_months = $request->input('warranty_months', null);
$asset->purchase_cost = Helper::ParseCurrency($request->input('purchase_cost', null));
$asset->asset_eol_date = request('asset_eol_date', null);
$asset->purchase_date = $request->input('purchase_date', null);
$asset->supplier_id = $request->input('supplier_id', null);
$asset->expected_checkin = $request->input('expected_checkin', null);
@@ -318,6 +322,7 @@ class AssetsController extends Controller
// If the box isn't checked, it's not in the request at all.
$asset->requestable = $request->filled('requestable');
$asset->rtd_location_id = $request->input('rtd_location_id', null);
$asset->byod = $request->input('byod', 0);
if ($asset->assigned_to == '') {
$asset->location_id = $request->input('rtd_location_id', null);
@@ -622,7 +627,11 @@ class AssetsController extends Controller
$csv->setHeaderOffset(0);
$header = $csv->getHeader();
$isCheckinHeaderExplicit = in_array('checkin date', (array_map('strtolower', $header)));
$results = $csv->getRecords();
try {
$results = $csv->getRecords();
} catch (\Exception $e) {
return back()->with('error', trans('general.error_in_import_file', ['error' => $e->getMessage()]));
}
$item = [];
$status = [];
$status['error'] = [];
@@ -102,8 +102,11 @@ class BulkAssetsController extends Controller
|| ($request->filled('company_id'))
|| ($request->filled('status_id'))
|| ($request->filled('model_id'))
|| ($request->filled('next_audit_date'))
|| ($request->filled('null_purchase_date'))
|| ($request->filled('null_expected_checkin_date'))
|| ($request->filled('null_next_audit_date'))
) {
foreach ($assets as $assetId) {
@@ -116,7 +119,8 @@ class BulkAssetsController extends Controller
->conditionallyAddItem('requestable')
->conditionallyAddItem('status_id')
->conditionallyAddItem('supplier_id')
->conditionallyAddItem('warranty_months');
->conditionallyAddItem('warranty_months')
->conditionallyAddItem('next_audit_date');
if ($request->input('null_purchase_date')=='1') {
$this->update_array['purchase_date'] = null;
@@ -126,6 +130,10 @@ class BulkAssetsController extends Controller
$this->update_array['expected_checkin'] = null;
}
if ($request->input('null_next_audit_date')=='1') {
$this->update_array['next_audit_date'] = null;
}
if ($request->filled('purchase_cost')) {
$this->update_array['purchase_cost'] = Helper::ParseCurrency($request->input('purchase_cost'));
}
@@ -288,7 +296,8 @@ class BulkAssetsController extends Controller
foreach ($asset_ids as $asset_id) {
$asset = Asset::findOrFail($asset_id);
$this->authorize('checkout', $asset);
$error = $asset->checkOut($target, $admin, $checkout_at, $expected_checkin, e($request->get('note')), null);
$error = $asset->checkOut($target, $admin, $checkout_at, $expected_checkin, e($request->get('note')), $asset->name, null);
if ($target->location_id != '') {
$asset->location_id = $target->location_id;
@@ -109,9 +109,9 @@ class CustomFieldsController extends Controller
if ($request->filled('custom_format')) {
$field->format = e($request->get('custom_format'));
$field->format = $request->get('custom_format');
} else {
$field->format = e($request->get('format'));
$field->format = $request->get('format');
}
if ($field->save()) {
@@ -75,9 +75,9 @@ class CustomFieldsetsController extends Controller
*/
public function create()
{
$this->authorize('create', CustomFieldset::class);
$this->authorize('create', CustomField::class);
return view('custom_fields.fieldsets.edit');
return view('custom_fields.fieldsets.edit')->with('item', new CustomFieldset());
}
/**
@@ -91,7 +91,7 @@ class CustomFieldsetsController extends Controller
*/
public function store(Request $request)
{
$this->authorize('create', CustomFieldset::class);
$this->authorize('create', CustomField::class);
$cfset = new CustomFieldset([
'name' => e($request->get('name')),
@@ -110,31 +110,52 @@ class CustomFieldsetsController extends Controller
}
/**
* What the actual fuck, Brady?
* Presents edit form for fieldset
*
* @todo Uhh, build this?
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $id
* @since [v1.8]
* @return Fuckall
* @since [v6.0.14]
* @return Redirect
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function edit($id)
{
//
$this->authorize('create', CustomField::class);
if ($fieldset = CustomFieldset::find($id)) {
return view('custom_fields.fieldsets.edit')->with('item', $fieldset);
}
return redirect()->route('fields.index')->with('error', trans('admin/custom_fields/general.fieldset_does_not_exist', ['id' => $id]));
}
/**
* GET IN THE SEA BRADY.
* Saves updated fieldset data
*
* @todo Uhh, build this too?
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $id
* @since [v1.8]
* @return Fuckall
* @since [v6.0.14]
* @return Redirect
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function update($id)
public function update(Request $request, $id)
{
//
$this->authorize('create', CustomField::class);
if ($fieldset = CustomFieldset::find($id)) {
$fieldset->name = $request->input('name');
if ($fieldset->save()) {
return redirect()->route('fields.index')->with('success', trans('admin/custom_fields/general.fieldset_updated'));
}
return redirect()->back()->withInput()->withErrors($fieldset->getErrors());
}
return redirect()->route('fields.index')->with('error', trans('admin/custom_fields/general.fieldset_does_not_exist', ['id' => $id]));
}
/**
@@ -202,7 +223,7 @@ class CustomFieldsetsController extends Controller
*/
public function makeFieldRequired($fieldset_id, $field_id)
{
$this->authorize('update', CustomFieldset::class);
$this->authorize('update', CustomField::class);
$field = CustomField::findOrFail($field_id);
$fieldset = CustomFieldset::findOrFail($fieldset_id);
$fields[$field->id] = ['required' => 1];
@@ -220,7 +241,7 @@ class CustomFieldsetsController extends Controller
*/
public function makeFieldOptional($fieldset_id, $field_id)
{
$this->authorize('update', CustomFieldset::class);
$this->authorize('update', CustomField::class);
$field = CustomField::findOrFail($field_id);
$fieldset = CustomFieldset::findOrFail($fieldset_id);
$fields[$field->id] = ['required' => 0];
@@ -1,22 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Http\Transformers\ImportsTransformer;
use App\Models\Asset;
use App\Models\Import;
class ImportsController extends Controller
{
/**
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function index()
{
$this->authorize('import');
$imports = (new ImportsTransformer)->transformImports(Import::latest()->get());
return view('importer/import')->with('imports', $imports);
}
}
@@ -59,6 +59,12 @@ class LicenseCheckinController extends Controller
}
$license = License::find($licenseSeat->license_id);
// LicenseSeat is not assigned, it can't be checked in
if (is_null($licenseSeat->assigned_to) && is_null($licenseSeat->asset_id)) {
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.checkin.error'));
}
$this->authorize('checkout', $license);
if (! $license->reassignable) {
@@ -91,29 +91,30 @@ class LicenseFilesController extends Controller
*/
public function destroy($licenseId = null, $fileId = null)
{
$license = License::find($licenseId);
if ($license = License::find($licenseId)) {
// the asset is valid
if (isset($license->id)) {
$this->authorize('update', $license);
$log = Actionlog::find($fileId);
// Remove the file if one exists
if (Storage::exists('licenses/'.$log->filename)) {
try {
Storage::delete('licenses/'.$log->filename);
} catch (\Exception $e) {
\Log::debug($e);
if ($log = Actionlog::find($fileId)) {
// Remove the file if one exists
if (Storage::exists('licenses/'.$log->filename)) {
try {
Storage::delete('licenses/'.$log->filename);
} catch (\Exception $e) {
\Log::debug($e);
}
}
$log->delete();
return redirect()->back()
->with('success', trans('admin/hardware/message.deletefile.success'));
}
$log->delete();
return redirect()->back()
->with('success', trans('admin/hardware/message.deletefile.success'));
return redirect()->route('licenses.index')->with('error', trans('general.log_does_not_exist'));
}
// Redirect to the licence management page
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist'));
}
@@ -129,7 +130,6 @@ class LicenseFilesController extends Controller
*/
public function show($licenseId = null, $fileId = null, $download = true)
{
\Log::info('Private filesystem is: '.config('filesystems.default'));
$license = License::find($licenseId);
// the license is valid
@@ -227,6 +227,36 @@ class LocationsController extends Controller
}
/**
* Returns a view that presents a form to clone a location.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $locationId
* @since [v6.0.14]
* @return View
*/
public function getClone($locationId = null)
{
$this->authorize('create', Location::class);
// Check if the asset exists
if (is_null($location_to_clone = Location::find($locationId))) {
// Redirect to the asset management page
return redirect()->route('licenses.index')->with('error', trans('admin/locations/message.does_not_exist'));
}
$location = clone $location_to_clone;
// unset these values
$location->id = null;
$location->image = null;
return view('locations/edit')
->with('item', $location);
}
public function print_all_assigned($id)
{
if ($location = Location::where('id', $id)->first()) {
+1 -1
View File
@@ -17,7 +17,7 @@ class ModalController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net]
* @return View
*/
function show ($type, $itemId = null) {
public function show ($type, $itemId = null) {
// These values should correspond to a file in resources/views/modals/
$allowed_types = [
+3 -31
View File
@@ -8,7 +8,7 @@ use App\Models\Setting;
use App\Models\User;
use App\Notifications\CurrentInventory;
use Illuminate\Support\Facades\Auth;
use Gate;
use Illuminate\Support\Facades\Gate;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
@@ -67,37 +67,9 @@ class ProfileController extends Controller
$user->location_id = $request->input('location_id');
}
// Handle the avatar upload and/or delete if necessary
app('\App\Http\Requests\ImageUploadRequest')->handleImages($user, 600, 'avatar', 'avatars', 'avatar');
if ($request->input('avatar_delete') == 1) {
$user->avatar = null;
}
if ($request->hasFile('avatar')) {
$path = 'avatars';
if (! Storage::disk('public')->exists($path)) {
Storage::disk('public')->makeDirectory($path, 775);
}
$upload = $image = $request->file('avatar');
$ext = $image->getClientOriginalExtension();
$file_name = 'avatar-'.str_random(18).'.'.$ext;
if ($image->getClientOriginalExtension() != 'svg') {
$upload = Image::make($image->getRealPath())->resize(84, 84);
}
// This requires a string instead of an object, so we use ($string)
Storage::disk('public')->put($path.'/'.$file_name, (string) $upload->encode());
// Remove Current image if exists
if (($user->avatar) && (Storage::disk('public')->exists($path.'/'.$user->avatar))) {
Storage::disk('public')->delete($path.'/'.$user->avatar);
}
$user->avatar = $file_name;
}
if ($user->save()) {
return redirect()->route('profile')->with('success', 'Account successfully updated');
+7 -6
View File
@@ -51,9 +51,8 @@ class ReportsController extends Controller
public function getAccessoryReport()
{
$this->authorize('reports.view');
$accessories = Accessory::orderBy('created_at', 'DESC')->with('company')->get();
return view('reports/accessories', compact('accessories'));
return view('reports/accessories');
}
/**
@@ -285,7 +284,7 @@ class ReportsController extends Controller
$row = [
$actionlog->created_at,
($actionlog->user) ? e($actionlog->user->getFullNameAttribute()) : '',
($actionlog->admin) ? e($actionlog->admin->getFullNameAttribute()) : '',
$actionlog->present()->actionType(),
e($actionlog->itemType()),
($actionlog->itemType() == 'user') ? $actionlog->filename : $item_name,
@@ -1025,7 +1024,11 @@ class ReportsController extends Controller
if (is_null($acceptance->created_at)){
return redirect()->route('reports/unaccepted_assets')->with('error', trans('general.bad_data'));
} else {
$logItem = $assetItem->checkouts()->where('created_at', '=', $acceptance->created_at)->get()[0];
$logItem_res = $assetItem->checkouts()->where('created_at', '=', $acceptance->created_at)->get();
if ($logItem_res->isEmpty()){
return redirect()->route('reports/unaccepted_assets')->with('error', trans('general.bad_data'));
}
$logItem = $logItem_res[0];
}
if(!$assetItem->assignedTo->locale){
@@ -1120,8 +1123,6 @@ class ReportsController extends Controller
$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?
}
}
+25 -43
View File
@@ -65,18 +65,27 @@ class SettingsController extends Controller
$start_settings['db_error'] = $e->getMessage();
}
$protocol = array_key_exists('HTTPS', $_SERVER) && ('on' == $_SERVER['HTTPS']) ? 'https://' : 'http://';
if (array_key_exists("HTTP_X_FORWARDED_PROTO", $_SERVER)) {
$protocol = $_SERVER["HTTP_X_FORWARDED_PROTO"] . "://";
} elseif (array_key_exists('HTTPS', $_SERVER) && ('on' == $_SERVER['HTTPS'])) {
$protocol = "https://";
} else {
$protocol = "http://";
}
$host = array_key_exists('SERVER_NAME', $_SERVER) ? $_SERVER['SERVER_NAME'] : null;
$port = array_key_exists('SERVER_PORT', $_SERVER) ? $_SERVER['SERVER_PORT'] : null;
if (('http://' === $protocol && '80' != $port) || ('https://' === $protocol && '443' != $port)) {
$host .= ':'.$port;
if (array_key_exists("HTTP_X_FORWARDED_HOST", $_SERVER)) {
$host = $_SERVER["HTTP_X_FORWARDED_HOST"];
} else {
$host = array_key_exists('SERVER_NAME', $_SERVER) ? $_SERVER['SERVER_NAME'] : null;
$port = array_key_exists('SERVER_PORT', $_SERVER) ? $_SERVER['SERVER_PORT'] : null;
if (('http://' === $protocol && '80' != $port) || ('https://' === $protocol && '443' != $port)) {
$host .= ':'.$port;
}
}
$pageURL = $protocol.$host.$_SERVER['REQUEST_URI'];
$start_settings['url_valid'] = (url('/').'/setup' === $pageURL);
$start_settings['url_config'] = url('/');
$start_settings['url_config'] = url('/').'/setup';
$start_settings['url_valid'] = ($start_settings['url_config'] === $pageURL);
$start_settings['real_url'] = $pageURL;
$start_settings['php_version_min'] = true;
@@ -111,17 +120,17 @@ class SettingsController extends Controller
$start_settings['prod'] = true;
}
$start_settings['owner'] = '';
if (function_exists('posix_getpwuid')) { // Probably Linux
$owner = posix_getpwuid(fileowner($_SERVER['SCRIPT_FILENAME']));
$start_settings['owner'] = $owner['name'];
} else { // Windows
// TODO: Is there a way of knowing if a windows user has elevated permissions
// This just gets the user name, which likely isn't 'root'
// $start_settings['owner'] = getenv('USERNAME');
$start_settings['owner'] = '';
// This *should* be an array, but we've seen this return a bool in some chrooted environments
if (is_array($owner)) {
$start_settings['owner'] = $owner['name'];
}
}
if (('root' === $start_settings['owner']) || ('0' === $start_settings['owner'])) {
if (($start_settings['owner'] === 'root') || ($start_settings['owner'] === '0')) {
$start_settings['owner_is_admin'] = true;
} else {
$start_settings['owner_is_admin'] = false;
@@ -679,33 +688,6 @@ class SettingsController extends Controller
return view('settings.slack', compact('setting'));
}
/**
* Return a form to allow a super admin to update settings.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
*
* @since [v1.0]
*
* @return View
*/
public function postSlack(SlackSettingsRequest $request)
{
if (is_null($setting = Setting::getSettings())) {
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
}
$setting->slack_endpoint = $request->input('slack_endpoint');
$setting->slack_channel = $request->input('slack_channel');
$setting->slack_botname = $request->input('slack_botname');
if ($setting->save()) {
return redirect()->route('settings.index')
->with('success', trans('admin/settings/message.update.success'));
}
return redirect()->back()->withInput()->withErrors($setting->getErrors());
}
/**
* Return a form to allow a super admin to update settings.
*
@@ -807,7 +789,7 @@ class SettingsController extends Controller
*/
public function getPhpInfo()
{
if (true === config('app.debug')) {
if (config('app.debug') === true) {
return view('settings.phpinfo');
}
@@ -2,6 +2,7 @@
namespace App\Http\Controllers\Users;
use App\Events\UserMerged;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Models\Accessory;
@@ -13,6 +14,7 @@ use App\Models\LicenseSeat;
use App\Models\ConsumableAssignment;
use App\Models\Consumable;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
@@ -21,7 +23,7 @@ use Illuminate\Support\Facades\Password;
class BulkUsersController extends Controller
{
/**
* Returns a view that confirms the user's a bulk delete will be applied to.
* Returns a view that confirms the user's a bulk action will be applied to.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.7]
@@ -35,16 +37,32 @@ class BulkUsersController extends Controller
// Make sure there were users selected
if (($request->filled('ids')) && (count($request->input('ids')) > 0)) {
// Get the list of affected users
$user_raw_array = request('ids');
$users = User::whereIn('id', $user_raw_array)
->with('groups', 'assets', 'licenses', 'accessories')->get();
// bulk edit, display the bulk edit form
if ($request->input('bulk_actions') == 'edit') {
return view('users/bulk-edit', compact('users'))
->with('groups', Group::pluck('name', 'id'));
// bulk delete, display the bulk delete confirmation form
} elseif ($request->input('bulk_actions') == 'delete') {
return view('users/confirm-bulk-delete')->with('users', $users)->with('statuslabel_list', Helper::statusLabelList());
// merge, confirm they have at least 2 users selected and display the merge screen
} elseif ($request->input('bulk_actions') == 'merge') {
if (($request->filled('ids')) && (count($request->input('ids')) > 1)) {
return view('users/confirm-merge')->with('users', $users);
// Not enough users selected, send them back
} else {
return redirect()->back()->with('error', trans('general.not_enough_users_selected', ['count' => 2]));
}
// bulk password reset, just do the thing
} elseif ($request->input('bulk_actions') == 'bulkpasswordreset') {
foreach ($users as $user) {
if (($user->activated == '1') && ($user->email != '')) {
@@ -59,7 +77,7 @@ class BulkUsersController extends Controller
}
}
return redirect()->back()->with('error', 'No users selected');
return redirect()->back()->with('error', trans('general.no_users_selected'));
}
/**
@@ -76,7 +94,7 @@ class BulkUsersController extends Controller
$this->authorize('update', User::class);
if ((! $request->filled('ids')) || $request->input('ids') <= 0) {
return redirect()->back()->with('error', 'No users selected');
return redirect()->back()->with('error', trans('general.no_users_selected'));
}
$user_raw_array = $request->input('ids');
@@ -105,6 +123,11 @@ class BulkUsersController extends Controller
'warning' => trans('admin/users/message.bulk_manager_warn'),
];
}
if ($request->input('null_location_id')=='1') {
$this->update_array['location_id'] = null;
}
if (! $manager_conflict) {
$this->conditionallyAddItem('manager_id');
}
@@ -163,11 +186,11 @@ class BulkUsersController extends Controller
$this->authorize('update', User::class);
if ((! $request->filled('ids')) || (count($request->input('ids')) == 0)) {
return redirect()->back()->with('error', 'No users selected');
return redirect()->back()->with('error', trans('general.no_users_selected'));
}
if (config('app.lock_passwords')) {
return redirect()->route('users.index')->with('error', 'Bulk delete is not enabled in this installation');
return redirect()->route('users.index')->with('error', trans('general.feature_disabled'));
}
$user_raw_array = request('ids');
@@ -249,4 +272,80 @@ class BulkUsersController extends Controller
$logAction->logaction('checkin from');
}
}
/**
* Save bulk-edited users
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @param Request $request
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function merge(Request $request)
{
$this->authorize('update', User::class);
if (config('app.lock_passwords')) {
return redirect()->route('users.index')->with('error', trans('general.feature_disabled'));
}
$user_ids_to_merge = $request->input('ids_to_merge');
$user_ids_to_merge = array_diff($user_ids_to_merge, array($request->input('merge_into_id')));
if ((!$request->filled('merge_into_id')) || (count($user_ids_to_merge) < 1)) {
return redirect()->back()->with('error', trans('general.no_users_selected'));
}
// Get the users
$merge_into_user = User::find($request->input('merge_into_id'));
$users_to_merge = User::whereIn('id', $user_ids_to_merge)->with('assets', 'licenses', 'consumables','accessories')->get();
$admin = User::find(Auth::user()->id);
// Walk users
foreach ($users_to_merge as $user_to_merge) {
foreach ($user_to_merge->assets as $asset) {
\Log::debug('Updating asset: '.$asset->asset_tag . ' to '.$merge_into_user->id);
$asset->assigned_to = $request->input('merge_into_id');
$asset->save();
}
foreach ($user_to_merge->licenses as $license) {
\Log::debug('Updating license pivot: '.$license->id . ' to '.$merge_into_user->id);
$user_to_merge->licenses()->updateExistingPivot($license->id, ['assigned_to' => $merge_into_user->id]);
}
foreach ($user_to_merge->consumables as $consumable) {
\Log::debug('Updating consumable pivot: '.$consumable->id . ' to '.$merge_into_user->id);
$user_to_merge->consumables()->updateExistingPivot($consumable->id, ['assigned_to' => $merge_into_user->id]);
}
foreach ($user_to_merge->accessories as $accessory) {
$user_to_merge->accessories()->updateExistingPivot($accessory->id, ['assigned_to' => $merge_into_user->id]);
}
foreach ($user_to_merge->userlog as $log) {
$log->target_id = $user_to_merge->id;
$log->save();
}
User::where('manager_id', '=', $user_to_merge->id)->update(['manager_id' => $merge_into_user->id]);
foreach ($user_to_merge->managedLocations as $managedLocation) {
$managedLocation->manager_id = $merge_into_user->id;
$managedLocation->save();
}
$user_to_merge->delete();
//$user_to_merge->save();
event(new UserMerged($user_to_merge, $merge_into_user, $admin));
}
return redirect()->route('users.index')->with('success', trans('general.merge_success', ['count' => $users_to_merge->count(), 'into_username' => $merge_into_user->username]));
}
}
@@ -121,6 +121,7 @@ class UsersController extends Controller
$user->created_by = Auth::user()->id;
$user->start_date = $request->input('start_date', null);
$user->end_date = $request->input('end_date', null);
$user->autoassign_licenses= $request->input('autoassign_licenses', 1);
// Strip out the superuser permission if the user isn't a superadmin
$permissions_array = $request->input('permission');
@@ -131,7 +132,7 @@ class UsersController extends Controller
$user->permissions = json_encode($permissions_array);
// we have to invoke the
app(\App\Http\Requests\ImageUploadRequest::class)->handleImages($user, 600, 'image', 'avatars', 'avatar');
app(ImageUploadRequest::class)->handleImages($user, 600, 'avatar', 'avatars', 'avatar');
if ($user->save()) {
if ($request->filled('groups')) {
@@ -271,9 +272,11 @@ class UsersController extends Controller
$user->activated = $request->input('activated', 0);
$user->zip = $request->input('zip', null);
$user->remote = $request->input('remote', 0);
$user->vip = $request->input('vip', 0);
$user->website = $request->input('website', null);
$user->start_date = $request->input('start_date', null);
$user->end_date = $request->input('end_date', null);
$user->autoassign_licenses = $request->input('autoassign_licenses', 1);
// Update the location of any assets checked out to this user
Asset::where('assigned_type', User::class)
@@ -296,7 +299,7 @@ class UsersController extends Controller
$user->permissions = json_encode($permissions_array);
// Handle uploaded avatar
app(\App\Http\Requests\ImageUploadRequest::class)->handleImages($user, 600, 'avatar', 'avatars', 'avatar');
app(ImageUploadRequest::class)->handleImages($user, 600, 'avatar', 'avatars', 'avatar');
//\Log::debug(print_r($user, true));
+322
View File
@@ -0,0 +1,322 @@
<?php
namespace App\Http\Livewire;
use App\Models\CustomField;
use Livewire\Component;
use App\Models\Import;
use Storage;
use Log;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
class Importer extends Component
{
use AuthorizesRequests;
public $files;
public $progress; //upload progress - '-1' means don't show
public $progress_message;
public $progress_bar_class;
public $message; //status/error message?
public $message_type; //success/error?
//originally from ImporterFile
public $import_errors; //
public ?Import $activeFile = null;
public $importTypes;
public $columnOptions;
public $statusType;
public $statusText;
public $update;
public $send_welcome;
public $run_backup;
public $field_map; // we need a separate variable for the field-mapping, because the keys in the normal array are too complicated for Livewire to understand
public $file_id; // TODO: I can't figure out *why* we need this, but it really seems like we do. I can't seem to pull the id from the activeFile for some reason?
protected $rules = [
'files.*.file_path' => 'required|string',
'files.*.created_at' => 'required|string',
'files.*.filesize' => 'required|integer',
'activeFile' => 'Import',
'activeFile.import_type' => 'string',
'activeFile.field_map' => 'array',
'activeFile.header_row' => 'array',
'field_map' => 'array'
];
public function generate_field_map()
{
\Log::debug("header row is: ".print_r($this->activeFile->header_row,true));
\Log::debug("Field map is: ".print_r($this->field_map,true));
$tmp = array_combine($this->activeFile->header_row, $this->field_map);
return json_encode(array_filter($tmp));
}
// all of these 'statics', alas, may have to change to something else to handle translations?
// I'm not sure. Maybe I use them to 'populate' the translations? TBH, I don't know yet.
static $general = [
'category' => 'Category',
'company' => 'Company',
'email' => 'Email',
'item_name' => 'Item Name',
'location' => 'Location',
'maintained' => 'Maintained',
'manufacturer' => 'Manufacturer',
'notes' => 'Notes',
'order_number' => 'Order Number',
'purchase_cost' => 'Purchase Cost',
'purchase_date' => 'Purchase Date',
'quantity' => 'Quantity',
'requestable' => 'Requestable',
'serial' => 'Serial Number',
'supplier' => 'Supplier',
'username' => 'Username',
'department' => 'Department',
];
static $accessories = [
'model_number' => 'Model Number',
];
static $assets = [
'asset_tag' => 'Asset Tag',
'asset_model' => 'Model Name',
'byod' => 'BYOD',
'checkout_class' => 'Checkout Type',
'checkout_location' => 'Checkout Location',
'image' => 'Image Filename',
'model_number' => 'Model Number',
'full_name' => 'Full Name',
'status' => 'Status',
'warranty_months' => 'Warranty Months',
];
static $consumables = [
'item_no' => "Item Number",
'model_number' => "Model Number",
'min_amt' => "Minimum Quantity",
];
static $licenses = [
'asset_tag' => 'Assigned To Asset',
'expiration_date' => 'Expiration Date',
'full_name' => 'Full Name',
'license_email' => 'Licensed To Email',
'license_name' => 'Licensed To Name',
'purchase_order' => 'Purchase Order',
'reassignable' => 'Reassignable',
'seats' => 'Seats',
];
static $users = [
'employee_num' => 'Employee Number',
'first_name' => 'First Name',
'jobtitle' => 'Job Title',
'last_name' => 'Last Name',
'phone_number' => 'Phone Number',
'manager_first_name' => 'Manager First Name',
'manager_last_name' => 'Manager Last Name',
'activated' => 'Activated',
'address' => 'Address',
'city' => 'City',
'state' => 'State',
'country' => 'Country',
'vip' => 'VIP'
];
//array of "real fieldnames" to a list of aliases for that field
static $aliases = [
'model_number' =>
[
'model',
'model no',
'model no.',
'model number',
'model num',
'model num.'
],
'warranty_months' =>
[
'Warranty',
'Warranty Months'
],
'qty' =>
[
'QTY',
'Quantity'
],
'min_amt' =>
[
'Min Amount',
'Min QTY'
],
'next_audit_date' =>
[
'Next Audit',
],
];
private function getColumns($type)
{
switch ($type) {
case 'asset':
$results = self::$general + self::$assets;
break;
case 'accessory':
$results = self::$general + self::$accessories;
break;
case 'consumable':
$results = self::$general + self::$consumables;
break;
case 'license':
$results = self::$general + self::$licenses;
break;
case 'user':
$results = self::$general + self::$users;
break;
default:
$results = self::$general;
}
asort($results, SORT_FLAG_CASE | SORT_STRING);
if ($type == "asset") {
// add Custom Fields after a horizontal line
$results['-'] = "———" . trans('admin/custom_fields/general.custom_fields') . "———’";
foreach (CustomField::orderBy('name')->get() as $field) {
$results[$field->db_column_name()] = $field->name;
}
}
return $results;
}
public function updating($name, $new_import_type)
{
if ($name == "activeFile.import_type") {
\Log::info("WE ARE CHANGING THE import_type!!!!! TO: " . $new_import_type);
\Log::info("so, what's \$this->>field_map at?: " . print_r($this->field_map, true));
// go through each header, find a matching field to try and map it to.
foreach ($this->activeFile->header_row as $i => $header) {
// do we have something mapped already?
if (array_key_exists($i, $this->field_map)) {
// yes, we do. Is it valid for this type of import?
// (e.g. the import type might have been changed...?)
if (array_key_exists($this->field_map[$i], $this->columnOptions[$new_import_type])) {
//yes, this key *is* valid. Continue on to the next field.
continue;
} else {
//no, this key is *INVALID* for this import type. Better set it to null
// and we'll hope that the aliases or something else picks it up.
$this->field_map[$i] = null; // fingers crossed! But it's not likely, tbh.
} // TODO - strictly speaking, this isn't necessary here I don't think.
}
// first, check for exact matches
foreach ($this->columnOptions[$new_import_type] as $value => $text) {
if (strcasecmp($text, $header) === 0) { // case-INSENSITIVe on purpose!
$this->field_map[$i] = $value;
continue 2; //don't bother with the alias check, go to the next header
}
}
// if you got here, we didn't find a match. Try the aliases
foreach (self::$aliases as $key => $alias_values) {
foreach ($alias_values as $alias_value) {
if (strcasecmp($alias_value, $header) === 0) { // aLsO CaSe-INSENSitiVE!
// Make *absolutely* sure that this key actually _exists_ in this import type -
// you can trigger this by importing accessories with a 'Warranty' column (which don't exist
// in "Accessories"!)
if (array_key_exists($key, $this->columnOptions[$new_import_type])) {
$this->field_map[$i] = $key;
continue 3; // bust out of both of these loops; as well as the surrounding one - e.g. move on to the next header
}
}
}
}
// and if you got here, we got nothing. Let's recommend 'null'
$this->field_map[$i] = null; // Booooo :(
}
}
}
public function boot() { // FIXME - delete or undelete.
///////$this->activeFile = null; // I do *not* understand why I have to do this, but, well, whatever.
}
public function mount()
{
$this->authorize('import');
$this->progress = -1; // '-1' means 'don't show the progressbar'
$this->progress_bar_class = 'progress-bar-warning';
\Log::info("Hey, we are calling MOUNT (in the importer-file) !!!!!!!!"); //fcuk
$this->importTypes = [
'asset' => trans('general.assets'),
'accessory' => trans('general.accessories'),
'consumable' => trans('general.consumables'),
'component' => trans('general.components'),
'license' => trans('general.licenses'),
'user' => trans('general.users'),
];
$this->columnOptions[''] = $this->getColumns(''); //blank mode? I don't know what this is supposed to mean
foreach($this->importTypes AS $type => $name) {
$this->columnOptions[$type] = $this->getColumns($type);
}
if ($this->activeFile) {
$this->field_map = $this->activeFile->field_map ? array_values($this->activeFile->field_map) : [];
}
}
public function selectFile($id)
{
\Log::info("TOGGLE EVENT FIRED!");
\Log::error("The ID we are trying to find is AS FOLLOWS: ".$id);
$this->activeFile = Import::find($id);
$this->field_map = null;
foreach($this->activeFile->header_row as $element) {
if(isset($this->activeFile->field_map[$element])) {
$this->field_map[] = $this->activeFile->field_map[$element];
} else {
$this->field_map[] = null; // re-inject the 'nulls' if a file was imported with some 'Do Not Import' settings
}
}
//$this->field_map = $this->activeFile->field_map ? array_values($this->activeFile->field_map) : []; // this is wrong
$this->file_id = $id;
$this->import_errors = null;
$this->statusText = null;
\Log::error("The import type we are about to try and load up is gonna be this: ".$this->activeFile->import_type);
}
public function destroy($id)
{
// TODO: why don't we just do File::find($id)? This seems dumb.
foreach($this->files as $file) {
\Log::debug("File id is: ".$file->id);
if($id == $file->id) {
if(Storage::delete('private_uploads/imports/'.$file->file_path)) {
$file->delete();
$this->message = trans('admin/hardware/message.import.file_delete_success');
$this->message_type = 'success';
return;
} else {
$this->message = trans('admin/hardware/message.import.file_delete_error');
$this->message_type = 'danger';
}
}
}
}
public function render()
{
$this->files = Import::orderBy('id','desc')->get(); //HACK - slows down renders.
return view('livewire.importer')
->extends('layouts.default')
->section('content');
}
}
+177
View File
@@ -0,0 +1,177 @@
<?php
namespace App\Http\Livewire;
use GuzzleHttp\Client;
use Livewire\Component;
use App\Models\Setting;
use App\Helpers\Helper;
class SlackSettingsForm extends Component
{
public $webhook_endpoint;
public $webhook_channel;
public $webhook_botname;
public $isDisabled ='' ;
public $webhook_name;
public $webhook_link;
public $webhook_placeholder;
public $webhook_icon;
public $webhook_selected;
public array $webhook_text;
public Setting $setting;
protected $rules = [
'webhook_endpoint' => 'url|required_with:webhook_channel|starts_with:https://hooks.slack.com/services|nullable',
'webhook_channel' => 'required_with:webhook_endpoint|starts_with:#|nullable',
'webhook_botname' => 'string|nullable',
];
public function mount() {
$this->webhook_text= [
"slack" => array(
"name" => trans('admin/settings/general.slack') ,
"icon" => 'fab fa-slack',
"placeholder" => "https://hooks.slack.com/services/XXXXXXXXXXXXXXXXXXXXX",
"link" => 'https://api.slack.com/messaging/webhooks',
),
"general"=> array(
"name" => trans('admin/settings/general.general_webhook'),
"icon" => "fab fa-hashtag",
"placeholder" => "",
"link" => "",
),
];
$this->setting = Setting::getSettings();
$this->save_button = trans('general.save');
$this->webhook_selected = $this->setting->webhook_selected;
$this->webhook_placeholder = $this->webhook_text[$this->setting->webhook_selected]["placeholder"];
$this->webhook_name = $this->webhook_text[$this->setting->webhook_selected]["name"];
$this->webhook_icon = $this->webhook_text[$this->setting->webhook_selected]["icon"];
$this->webhook_endpoint = $this->setting->webhook_endpoint;
$this->webhook_channel = $this->setting->webhook_channel;
$this->webhook_botname = $this->setting->webhook_botname;
$this->webhook_options = $this->setting->webhook_selected;
if($this->setting->webhook_selected == 'general'){
$this->isDisabled='';
}
if($this->setting->webhook_endpoint != null && $this->setting->webhook_channel != null){
$this->isDisabled= '';
}
}
public function updated($field) {
if($this->webhook_selected != 'general') {
$this->validateOnly($field, $this->rules);
}
}
public function updatedWebhookSelected() {
$this->webhook_name = $this->webhook_text[$this->webhook_selected]['name'];
$this->webhook_icon = $this->webhook_text[$this->webhook_selected]["icon"]; ;
$this->webhook_placeholder = $this->webhook_text[$this->webhook_selected]["placeholder"];
$this->webhook_link = $this->webhook_text[$this->webhook_selected]["link"];
if($this->webhook_selected != 'slack'){
$this->isDisabled= '';
$this->save_button = trans('general.save');
}
}
private function isButtonDisabled() {
if($this->webhook_selected == 'slack') {
if (empty($this->webhook_endpoint)) {
$this->isDisabled = 'disabled';
$this->save_button = trans('admin/settings/general.webhook_presave');
}
if (empty($this->webhook_channel)) {
$this->isDisabled = 'disabled';
$this->save_button = trans('admin/settings/general.webhook_presave');
}
}
}
public function render()
{
$this->isButtonDisabled();
return view('livewire.slack-settings-form');
}
public function testWebhook(){
$webhook = new Client([
'base_url' => e($this->webhook_endpoint),
'defaults' => [
'exceptions' => false,
],
]);
$payload = json_encode(
[
'channel' => e($this->webhook_channel),
'text' => trans('general.webhook_test_msg', ['app' => $this->webhook_name]),
'username' => e($this->webhook_botname),
'icon_emoji' => ':heart:',
]);
try {
$webhook->post($this->webhook_endpoint, ['body' => $payload]);
$this->isDisabled='';
$this->save_button = trans('general.save');
return session()->flash('success' , 'Your '.$this->webhook_name.' Integration works!');
} catch (\Exception $e) {
$this->isDisabled= 'disabled';
return session()->flash('error' , trans('admin/settings/message.webhook.error', ['error_message' => $e->getMessage(), 'app' => $this->webhook_name]));
}
return session()->flash('error' , trans('admin/settings/message.webhook.error_misc'));
}
public function clearSettings(){
if (Helper::isDemoMode()) {
session()->flash('error',trans('general.feature_disabled'));
} else {
$this->webhook_endpoint = '';
$this->webhook_channel = '';
$this->webhook_botname = '';
$this->setting->webhook_endpoint = '';
$this->setting->webhook_channel = '';
$this->setting->webhook_botname = '';
$this->setting->save();
session()->flash('success', trans('admin/settings/message.update.success'));
}
}
public function submit()
{
if (Helper::isDemoMode()) {
session()->flash('error',trans('general.feature_disabled'));
} else {
if ($this->webhook_selected != 'general') {
$this->validate($this->rules);
}
$this->setting->webhook_selected = $this->webhook_selected;
$this->setting->webhook_endpoint = $this->webhook_endpoint;
$this->setting->webhook_channel = $this->webhook_channel;
$this->setting->webhook_botname = $this->webhook_botname;
$this->setting->save();
session()->flash('success',trans('admin/settings/message.update.success'));
}
}
}
@@ -52,6 +52,13 @@ class AssetCountForSidebar
\Log::debug($e);
}
try {
$total_byod_sidebar = Asset::where('byod', '=', '1')->count();
view()->share('total_byod_sidebar', $total_byod_sidebar);
} catch (\Exception $e) {
\Log::debug($e);
}
return $next($request);
}
}
+1 -1
View File
@@ -11,7 +11,7 @@ class CheckForTwoFactor
/**
* Routes to ignore for Two Factor Auth
*/
const IGNORE_ROUTES = ['two-factor', 'two-factor-enroll', 'setup', 'logout'];
public const IGNORE_ROUTES = ['two-factor', 'two-factor-enroll', 'setup', 'logout'];
/**
* Handle an incoming request.
+1 -1
View File
@@ -3,7 +3,7 @@
namespace App\Http\Middleware;
use Closure;
use Gate;
use Illuminate\Support\Facades\Gate;
class CheckPermissions
{
+1 -1
View File
@@ -24,7 +24,7 @@ class AssetFileRequest extends Request
$max_file_size = \App\Helpers\Helper::file_upload_max_size();
return [
'file.*' => 'required|mimes:png,gif,jpg,svg,jpeg,doc,docx,pdf,txt,zip,rar,xls,xlsx,lic,xml,rtf,webp|max:'.$max_file_size,
'file.*' => 'required|mimes:png,gif,jpg,svg,jpeg,doc,docx,pdf,txt,zip,rar,xls,xlsx,lic,xml,rtf,json,webp|max:'.$max_file_size,
];
}
}
+40 -38
View File
@@ -7,7 +7,9 @@ use enshrined\svgSanitize\Sanitizer;
use Intervention\Image\Facades\Image;
use App\Http\Traits\ConvertsBase64ToFiles;
use Illuminate\Http\UploadedFile;
use Storage;
use Illuminate\Support\Facades\Storage;
use Intervention\Image\Exception\NotReadableException;
class ImageUploadRequest extends Request
{
@@ -63,11 +65,13 @@ class ImageUploadRequest extends Request
* @param string $path location for uploaded images, defaults to uploads/plural of item type.
* @return SnipeModel Target asset is being checked out to.
*/
public function handleImages($item, $w = 600, $form_fieldname = null, $path = null, $db_fieldname = 'image')
public function handleImages($item, $w = 600, $form_fieldname = 'image', $path = null, $db_fieldname = 'image')
{
$type = strtolower(class_basename(get_class($item)));
if (is_null($path)) {
$path = str_plural($type);
if ($type == 'assetmodel') {
@@ -79,49 +83,47 @@ class ImageUploadRequest extends Request
}
}
if (is_null($form_fieldname)) {
$form_fieldname = 'image';
}
// This is dumb, but we need it for overriding field names for exceptions like avatars and logo uploads
if (is_null($db_fieldname)) {
$use_db_field = $form_fieldname;
} else {
$use_db_field = $db_fieldname;
}
// ConvertBase64ToFiles just changes object type,
// as it cannot currently insert files to $this->files
if ($this->offsetGet($form_fieldname) instanceof UploadedFile) {
$image=$this->offsetGet($form_fieldname);
$image = $this->offsetGet($form_fieldname);
\Log::debug('Image is an instance of UploadedFile');
} elseif ($this->hasFile($form_fieldname)) {
$image = $this->file($form_fieldname);
\Log::debug('Just use regular upload for '.$form_fieldname);
} else {
if ($this->hasFile($form_fieldname)) {
$image = $this->file($form_fieldname);
}
\Log::debug('No image found for form fieldname: '.$form_fieldname);
}
if (isset($image)) {
\Log::debug($image);
if (!config('app.lock_passwords')) {
$ext = $image->getClientOriginalExtension();
$file_name = $type.'-'.$form_fieldname.'-'.str_random(10).'.'.$ext;
$file_name = $type.'-'.$form_fieldname.'-'.$item->id.'-'.str_random(10).'.'.$ext;
\Log::info('File name will be: '.$file_name);
\Log::debug('File extension is: '.$ext);
if (($image->getClientOriginalExtension() !== 'webp') && ($image->getClientOriginalExtension() !== 'svg')) {
\Log::debug('Not an SVG or webp - resize');
\Log::debug('Trying to upload to: '.$path.'/'.$file_name);
$upload = Image::make($image->getRealPath())->resize(null, $w, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
});
try {
$upload = Image::make($image->getRealPath())->resize(null, $w, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
});
} catch(NotReadableException $e) {
\Log::debug($e);
$validator = \Validator::make([], []);
$validator->errors()->add($form_fieldname, trans('general.unaccepted_image_type', ['mimetype' => $image->getClientMimeType()]));
throw new \Illuminate\Validation\ValidationException($validator);
}
// This requires a string instead of an object, so we use ($string)
Storage::disk('public')->put($path.'/'.$file_name, (string) $upload->encode());
} else {
// If the file is a webp, we need to just move it since webp support
// needs to be compiled into gd for resizing to be available
@@ -146,30 +148,30 @@ class ImageUploadRequest extends Request
}
// Remove Current image if exists
if (Storage::disk('public')->exists($path.'/'.$item->{$use_db_field})) {
if (($item->{$form_fieldname}!='') && (Storage::disk('public')->exists($path.'/'.$item->{$db_fieldname}))) {
\Log::debug('A file already exists that we are replacing - we should delete the old one.');
try {
Storage::disk('public')->delete($path.'/'.$item->{$use_db_field});
Storage::disk('public')->delete($path.'/'.$item->{$form_fieldname});
\Log::debug('Old file '.$path.'/'.$file_name.' has been deleted.');
} catch (\Exception $e) {
\Log::debug('Could not delete old file. '.$path.'/'.$file_name.' does not exist?');
}
}
$item->{$use_db_field} = $file_name;
$item->{$db_fieldname} = $file_name;
}
// If the user isn't uploading anything new but wants to delete their old image, do so
} else {
if ($this->input('image_delete') == '1') {
\Log::debug('Deleting image');
try {
Storage::disk('public')->delete($path.'/'.$item->{$use_db_field});
$item->{$use_db_field} = null;
} catch (\Exception $e) {
\Log::debug($e);
}
} elseif ($this->input('image_delete') == '1') {
\Log::debug('Deleting image');
try {
Storage::disk('public')->delete($path.'/'.$item->{$db_fieldname});
$item->{$db_fieldname} = null;
} catch (\Exception $e) {
\Log::debug($e);
}
}
return $item;
+2 -5
View File
@@ -39,14 +39,12 @@ class SaveUserRequest extends FormRequest
// Brand new user
case 'POST':
{
$rules['first_name'] = 'required|string|min:1';
$rules['username'] = 'required_unless:ldap_import,1|string|min:1';
if ($this->request->get('ldap_import') == false) {
$rules['password'] = Setting::passwordComplexityRulesSaving('store').'|confirmed';
}
break;
}
// Save all fields
case 'PUT':
@@ -57,12 +55,11 @@ class SaveUserRequest extends FormRequest
// Save only what's passed
case 'PATCH':
{
$rules['password'] = Setting::passwordComplexityRulesSaving('update');
break;
}
default:break;
default:
break;
}
return $rules;
@@ -1,33 +0,0 @@
<?php
namespace App\Http\Requests;
class SlackSettingsRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'slack_endpoint' => 'url|required_with:slack_channel|starts_with:"https://hooks.slack.com"|nullable',
'slack_channel' => 'required_with:slack_endpoint|starts_with:#|nullable',
'slack_botname' => 'string|nullable',
];
}
}
@@ -4,7 +4,7 @@ namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\Accessory;
use Gate;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Storage;
@@ -38,7 +38,8 @@ class AccessoriesTransformer
'purchase_cost' => Helper::formatCurrencyOutput($accessory->purchase_cost),
'order_number' => ($accessory->order_number) ? e($accessory->order_number) : null,
'min_qty' => ($accessory->min_amt) ? (int) $accessory->min_amt : null,
'remaining_qty' => $accessory->numRemaining(),
'remaining_qty' => (int) $accessory->numRemaining(),
'users_count' => $accessory->users_count,
'created_at' => Helper::getFormattedDateObject($accessory->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($accessory->updated_at, 'datetime'),
@@ -50,6 +51,8 @@ class AccessoriesTransformer
'checkin' => false,
'update' => Gate::allows('update', Accessory::class),
'delete' => Gate::allows('delete', Accessory::class),
'clone' => Gate::allows('create', Accessory::class),
];
$permissions_array['user_can_checkout'] = false;
@@ -60,12 +60,14 @@ class ActionlogsTransformer
if ($actionlog->action_type == 'accepted') {
$file_url = route('log.storedeula.download', ['filename' => $actionlog->filename]);
} else {
if ($actionlog->itemType() == 'asset') {
$file_url = route('show/assetfile', ['assetId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
} elseif ($actionlog->itemType() == 'license') {
$file_url = route('show.licensefile', ['licenseId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
} elseif ($actionlog->itemType() == 'user') {
$file_url = route('show/userfile', ['userId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
if ($actionlog->item) {
if ($actionlog->itemType() == 'asset') {
$file_url = route('show/assetfile', ['assetId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
} elseif ($actionlog->itemType() == 'license') {
$file_url = route('show.licensefile', ['licenseId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
} elseif ($actionlog->itemType() == 'user') {
$file_url = route('show/userfile', ['userId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
}
}
}
}
@@ -5,7 +5,7 @@ namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\Asset;
use App\Models\AssetMaintenance;
use Gate;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
class AssetMaintenancesTransformer
@@ -45,6 +45,10 @@ class AssetMaintenancesTransformer
'name'=> e($assetmaintenance->asset->location->name),
] : null,
'rtd_location' => ($assetmaintenance->asset->defaultLoc) ? [
'id' => (int) $assetmaintenance->asset->defaultLoc->id,
'name'=> e($assetmaintenance->asset->defaultLoc->name),
] : null,
'notes' => ($assetmaintenance->notes) ? e($assetmaintenance->notes) : null,
'supplier' => ($assetmaintenance->supplier) ? ['id' => $assetmaintenance->supplier->id, 'name'=> e($assetmaintenance->supplier->name)] : null,
'cost' => Helper::formatCurrencyOutput($assetmaintenance->cost),
@@ -4,7 +4,7 @@ namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\AssetModel;
use Gate;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Storage;
+6 -5
View File
@@ -5,7 +5,7 @@ namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\Asset;
use App\Models\Setting;
use Gate;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
@@ -35,8 +35,11 @@ class AssetsTransformer
'id' => (int) $asset->model->id,
'name'=> e($asset->model->name),
] : null,
'byod' => ($asset->byod ? true : false),
'model_number' => (($asset->model) && ($asset->model->model_number)) ? e($asset->model->model_number) : null,
'eol' => ($asset->purchase_date != '') ? Helper::getFormattedDateObject($asset->present()->eol_date(), 'date') : null,
'eol' => ($asset->model->eol != '') ? $asset->model->eol : null,
'asset_eol_date' => ($asset->asset_eol_date != '') ? Helper::getFormattedDateObject($asset->asset_eol_date, 'date') : null,
'status_label' => ($asset->assetstatus) ? [
'id' => (int) $asset->assetstatus->id,
'name'=> e($asset->assetstatus->name),
@@ -81,7 +84,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) : '',
'age' => $asset->purchase_date ? $asset->purchase_date->diffForHumans() : '',
'last_checkout' => Helper::getFormattedDateObject($asset->last_checkout, 'datetime'),
'expected_checkin' => Helper::getFormattedDateObject($asset->expected_checkin, 'date'),
'purchase_cost' => Helper::formatCurrencyOutput($asset->purchase_cost),
@@ -190,8 +193,6 @@ class AssetsTransformer
'email'=> ($asset->assigned->email) ? e($asset->assigned->email) : null,
'employee_number' => ($asset->assigned->employee_num) ? e($asset->assigned->employee_num) : null,
'type' => 'user',
'eula_pdf' => e($asset->acceptanceLog->last()->filename),
'signature_file' => e($asset->acceptanceLog->last()->accept_signature),
] : null;
}
@@ -4,7 +4,7 @@ namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\Category;
use Gate;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Storage;
@@ -22,18 +22,38 @@ class CategoriesTransformer
public function transformCategory(Category $category = null)
{
// We only ever use item_count for categories in this transformer, so it makes sense to keep it
// simple and do this switch here.
switch ($category->category_type) {
case 'asset':
$category->item_count = $category->assets_count;
break;
case 'accessory':
$category->item_count = $category->accessories_count;
break;
case 'consumable':
$category->item_count = $category->consumables_count;
break;
case 'component':
$category->item_count = $category->components_count;
break;
default:
$category->item_count = 0;
}
if ($category) {
$array = [
'id' => (int) $category->id,
'name' => e($category->name),
'image' => ($category->image) ? Storage::disk('public')->url('categories/'.e($category->image)) : null,
'category_type' => ucwords(e($category->category_type)),
'category_type' => Helper::categoryTypeList($category->category_type),
'has_eula' => ($category->getEula() ? true : false),
'use_default_eula' => ($category->use_default_eula=='1' ? true : false),
'eula' => ($category->getEula()),
'checkin_email' => ($category->checkin_email == '1'),
'require_acceptance' => ($category->require_acceptance == '1'),
'item_count' => (int) $category->itemCount(),
'item_count' => (int) $category->item_count,
'assets_count' => (int) $category->assets_count,
'accessories_count' => (int) $category->accessories_count,
'consumables_count' => (int) $category->consumables_count,
@@ -4,7 +4,7 @@ namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\Company;
use Gate;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Storage;
@@ -3,7 +3,7 @@
namespace App\Http\Transformers;
use App\Models\Asset;
use Gate;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
class ComponentsAssetsTransformer
@@ -4,7 +4,7 @@ namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\Component;
use Gate;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Storage;
@@ -4,7 +4,7 @@ namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\Consumable;
use Gate;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Storage;
@@ -4,7 +4,7 @@ namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\Department;
use Gate;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Storage;
@@ -5,7 +5,7 @@ namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\Depreciable;
use App\Models\Depreciation;
use Gate;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
class DepreciationsTransformer
+1 -1
View File
@@ -4,7 +4,7 @@ namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\Group;
use Gate;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
class GroupsTransformer
@@ -4,7 +4,7 @@ namespace App\Http\Transformers;
use App\Models\License;
use App\Models\LicenseSeat;
use Gate;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
class LicenseSeatsTransformer
@@ -4,7 +4,7 @@ namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\License;
use Gate;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
class LicensesTransformer
@@ -4,7 +4,7 @@ namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\Location;
use Gate;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Storage;
@@ -63,6 +63,7 @@ class LocationsTransformer
$permissions_array['available_actions'] = [
'update' => Gate::allows('update', Location::class) ? true : false,
'delete' => $location->isDeletable(),
'clone' => (Gate::allows('create', Location::class) && ($location->deleted_at == '')),
];
$array += $permissions_array;
@@ -4,7 +4,7 @@ namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\Manufacturer;
use Gate;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Storage;
@@ -4,7 +4,7 @@ namespace App\Http\Transformers;
use App\Models\PredefinedKit;
use App\Models\SnipeModel;
use Gate;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
/**
@@ -4,7 +4,7 @@ namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\Statuslabel;
use Gate;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
class StatuslabelsTransformer
@@ -4,7 +4,7 @@ namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\Supplier;
use Gate;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Storage;
+3 -2
View File
@@ -4,7 +4,7 @@ namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\User;
use Gate;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
class UsersTransformer
@@ -36,6 +36,7 @@ class UsersTransformer
'name'=> e($user->manager->first_name).' '.e($user->manager->last_name),
] : null,
'jobtitle' => ($user->jobtitle) ? e($user->jobtitle) : null,
'vip' => ($user->vip == '1') ? true : false,
'phone' => ($user->phone) ? e($user->phone) : null,
'website' => ($user->website) ? e($user->website) : null,
'address' => ($user->address) ? e($user->address) : null,
@@ -56,8 +57,8 @@ class UsersTransformer
'permissions' => $user->decodePermissions(),
'activated' => ($user->activated == '1') ? true : false,
'ldap_import' => ($user->ldap_import == '1') ? true : false,
'two_factor_activated' => ($user->two_factor_active()) ? true : false,
'two_factor_enrolled' => ($user->two_factor_active_and_enrolled()) ? true : false,
'two_factor_optin' => ($user->two_factor_active()) ? true : false,
'assets_count' => (int) $user->assets_count,
'licenses_count' => (int) $user->licenses_count,
'accessories_count' => (int) $user->accessories_count,
+5 -3
View File
@@ -76,10 +76,12 @@ class AssetImporter extends ItemImporter
}
$this->item['notes'] = $this->findCsvMatch($row, 'asset_notes');
$this->item['image'] = $this->findCsvMatch($row, 'image');
$this->item['requestable'] = $this->fetchHumanBoolean($this->findCsvMatch($row, 'requestable'));
$asset->requestable = $this->fetchHumanBoolean($this->findCsvMatch($row, 'requestable'));
$this->item['requestable'] = ($this->fetchHumanBoolean($this->findCsvMatch($row, 'requestable')) == 1) ? '1' : 0;
$asset->requestable = $this->item['requestable'];
$this->item['warranty_months'] = intval($this->findCsvMatch($row, 'warranty_months'));
$this->item['model_id'] = $this->createOrFetchAssetModel($row);
$this->item['byod'] = ($this->fetchHumanBoolean($this->findCsvMatch($row, 'byod')) == 1) ? '1' : 0;
// If no status ID is found
if (! array_key_exists('status_id', $this->item) && ! $editingAsset) {
@@ -135,7 +137,7 @@ class AssetImporter extends ItemImporter
//-- user_id is a property of the abstract class Importer, which this class inherits from and it's setted by
//-- the class that needs to use it (command importer or GUI importer inside the project).
if (isset($target)) {
$asset->fresh()->checkOut($target, $this->user_id, date('Y-m-d H:i:s'));
$asset->fresh()->checkOut($target, $this->user_id, date('Y-m-d H:i:s'), null, $asset->notes, $asset->name);
}
return;
+4 -4
View File
@@ -74,7 +74,7 @@ class ItemImporter extends Importer
$this->item['purchase_date'] = null;
if ($this->findCsvMatch($row, 'purchase_date') != '') {
$this->item['purchase_date'] = date('Y-m-d 00:00:01', strtotime($this->findCsvMatch($row, 'purchase_date')));
$this->item['purchase_date'] = date('Y-m-d', strtotime($this->findCsvMatch($row, 'purchase_date')));
}
$this->item['last_audit_date'] = null;
@@ -90,7 +90,7 @@ class ItemImporter extends Importer
$this->item['qty'] = $this->findCsvMatch($row, 'quantity');
$this->item['requestable'] = $this->findCsvMatch($row, 'requestable');
$this->item['user_id'] = $this->user_id;
$this->item['serial'] = $this->findCsvMatch($row, 'serial number');
$this->item['serial'] = $this->findCsvMatch($row, 'serial');
// NO need to call this method if we're running the user import.
// TODO: Merge these methods.
$this->item['checkout_class'] = $this->findCsvMatch($row, 'checkout_class');
@@ -222,11 +222,11 @@ class ItemImporter extends Importer
$item = $this->sanitizeItemForStoring($asset_model, $editingModel);
$item['name'] = $asset_model_name;
$item['notes'] = $this->findCsvMatch($row, 'model_notes');
if(!empty($asset_modelNumber)){
$item['model_number'] = $asset_modelNumber;
}
$asset_model->update($item);
$asset_model->save();
$this->log('Asset Model Updated');
+5
View File
@@ -80,6 +80,11 @@ class LicenseImporter extends ItemImporter
$checkout_target = $this->item['checkout_target'];
$asset = Asset::where('asset_tag', $asset_tag)->first();
$targetLicense = $license->freeSeat();
if (is_null($targetLicense)){
return;
}
if ($checkout_target) {
$targetLicense->assigned_to = $checkout_target->id;
$targetLicense->user_id = Auth::id();
+2
View File
@@ -58,6 +58,8 @@ class UserImporter extends ItemImporter
$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;
$this->item['vip'] =($this->fetchHumanBoolean($this->findCsvMatch($row, 'vip')) ==1 ) ? '1' : 0;
$user_department = $this->findCsvMatch($row, 'department');
if ($this->shouldUpdateField($user_department)) {
+6 -4
View File
@@ -36,8 +36,10 @@
| name | | |
| email | | |
| username | | |
| address | address | User |
| city | city | User |
| state | state | User |
| country | country | User |
| address | address | User |
| city | city | User |
| state | state | User |
| country | country | User |
| vip | vip | User |
| byod | byod | Asset |
+42
View File
@@ -18,7 +18,9 @@ use App\Events\ItemDeclined;
use App\Events\LicenseCheckedIn;
use App\Events\LicenseCheckedOut;
use App\Models\Actionlog;
use App\Models\User;
use App\Models\LicenseSeat;
use App\Events\UserMerged;
class LogListener
{
@@ -87,6 +89,43 @@ class LogListener
$logaction->save();
}
public function onUserMerged(UserMerged $event)
{
$to_from_array = [
'to_id' => $event->merged_to->id,
'to_username' => $event->merged_to->username,
'from_id' => $event->merged_from->id,
'from_username' => $event->merged_from->username,
];
// Add a record to the users being merged FROM
\Log::debug('Users merged: '.$event->merged_from->id .' ('.$event->merged_from->username.') merged into '. $event->merged_to->id. ' ('.$event->merged_to->username.')');
$logaction = new Actionlog();
$logaction->item_id = $event->merged_from->id;
$logaction->item_type = User::class;
$logaction->target_id = $event->merged_to->id;
$logaction->target_type = User::class;
$logaction->action_type = 'merged';
$logaction->note = trans('general.merged_log_this_user_from', $to_from_array);
$logaction->user_id = $event->admin->id;
$logaction->save();
// Add a record to the users being merged TO
$logaction = new Actionlog();
$logaction->target_id = $event->merged_from->id;
$logaction->target_type = User::class;
$logaction->item_id = $event->merged_to->id;
$logaction->item_type = User::class;
$logaction->action_type = 'merged';
$logaction->note = trans('general.merged_log_this_user_into', $to_from_array);
$logaction->user_id = $event->admin->id;
$logaction->save();
}
/**
* Register the listeners for the subscriber.
*
@@ -99,6 +138,7 @@ class LogListener
'CheckoutableCheckedOut',
'CheckoutAccepted',
'CheckoutDeclined',
'UserMerged',
];
foreach ($list as $event) {
@@ -108,4 +148,6 @@ class LogListener
);
}
}
}
+3 -16
View File
@@ -63,6 +63,7 @@ class Accessory extends SnipeModel
'company_id' => 'integer|nullable',
'min_amt' => 'integer|min:0|nullable',
'purchase_cost' => 'numeric|nullable|gte:0',
'purchase_date' => 'date_format:Y-m-d|nullable',
];
@@ -327,20 +328,6 @@ class Accessory extends SnipeModel
return null;
}
/**
* Check how many items within an accessory are checked out
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v5.0]
* @return int
*/
public function numCheckedOut()
{
$checkedout = 0;
$checkedout = $this->users->count();
return $checkedout;
}
/**
* Check how many items of an accessory remain
@@ -351,11 +338,11 @@ class Accessory extends SnipeModel
*/
public function numRemaining()
{
$checkedout = $this->users->count();
$checkedout = $this->users_count;
$total = $this->qty;
$remaining = $total - $checkedout;
return $remaining;
return (int) $remaining;
}
/**
+51 -38
View File
@@ -34,9 +34,9 @@ class Asset extends Depreciable
use CompanyableTrait;
use HasFactory, Loggable, Requestable, Presentable, SoftDeletes, ValidatingTrait, UniqueUndeletedTrait, UniqueSerialTrait;
const LOCATION = 'location';
const ASSET = 'asset';
const USER = 'user';
public const LOCATION = 'location';
public const ASSET = 'asset';
public const USER = 'user';
use Acceptable;
@@ -84,17 +84,18 @@ class Asset extends Depreciable
protected $casts = [
'purchase_date' => 'datetime',
'purchase_date' => 'date',
'last_checkout' => 'datetime',
'expected_checkin' => 'datetime',
'expected_checkin' => 'date',
'last_audit_date' => 'datetime',
'next_audit_date' => 'datetime',
'next_audit_date' => 'date',
'model_id' => 'integer',
'status_id' => 'integer',
'company_id' => 'integer',
'location_id' => 'integer',
'rtd_company_id' => 'integer',
'supplier_id' => 'integer',
'byod' => 'boolean',
];
protected $rules = [
@@ -104,17 +105,16 @@ class Asset extends Depreciable
'company_id' => 'integer|nullable',
'warranty_months' => 'numeric|nullable|digits_between:0,240',
'physical' => 'numeric|max:1|nullable',
'checkout_date' => 'date|max:10|min:10|nullable',
'checkin_date' => 'date|max:10|min:10|nullable',
'last_checkout' => 'date_format:Y-m-d H:i:s|nullable',
'expected_checkin' => 'date|nullable',
'location_id' => 'exists:locations,id|nullable',
'rtd_location_id' => 'exists:locations,id|nullable',
'asset_tag' => 'required|min:1|max:255|unique_undeleted',
'status' => 'integer',
'purchase_date' => 'date|date_format:Y-m-d|nullable',
'serial' => 'unique_serial|nullable',
'purchase_cost' => 'numeric|nullable|gte:0',
'next_audit_date' => 'date|nullable',
'last_audit_date' => 'date|nullable',
'supplier_id' => 'exists:suppliers,id|nullable',
'asset_eol_date' => 'date|max:10|min:10|nullable',
];
/**
@@ -143,6 +143,10 @@ class Asset extends Depreciable
'requestable',
'last_checkout',
'expected_checkin',
'byod',
'asset_eol_date',
'last_audit_date',
'next_audit_date',
];
use Searchable;
@@ -165,6 +169,7 @@ class Asset extends Depreciable
'expected_checkin',
'next_audit_date',
'last_audit_date',
'asset_eol_date',
];
/**
@@ -178,11 +183,19 @@ class Asset extends Depreciable
'company' => ['name'],
'defaultLoc' => ['name'],
'location' => ['name'],
'model' => ['name', 'model_number'],
'model' => ['name', 'model_number', 'eol'],
'model.category' => ['name'],
'model.manufacturer' => ['name'],
];
// To properly set the expected checkin as Y-m-d
public function setExpectedCheckinAttribute($value)
{
if ($value == '') {
$value = null;
}
$this->attributes['expected_checkin'] = $value;
}
/**
* This handles the custom field validation for assets
@@ -314,14 +327,10 @@ class Asset extends Depreciable
}
$this->last_checkout = $checkout_at;
$this->name = $name;
$this->assignedTo()->associate($target);
if ($name != null) {
$this->name = $name;
}
if ($location != null) {
$this->location_id = $location;
} else {
@@ -538,6 +547,28 @@ class Asset extends Depreciable
return strtolower(class_basename($this->assigned_type));
}
/**
* This is annoying, but because we don't say "assets" in our route names, we have to make an exception here
* @todo - normalize the route names - API endpoint URLS can stay the same
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v6.1.0]
* @return string
*/
public function targetShowRoute()
{
$route = str_plural($this->assignedType());
if ($route=='assets') {
return 'hardware';
}
return $route;
}
/**
* Get the asset's location based on default RTD location
*
@@ -587,24 +618,6 @@ class Asset extends Depreciable
->withTrashed();
}
/**
* Get the log info for acceptances on this asset.
* To use this as a single record, invoke it using ->last(), for
* example, $asset->lastAcceptedLog->last().
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v6.0.14]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function acceptanceLog()
{
return $this->hasMany(\App\Models\Actionlog::class, 'item_id')
->where('item_type', '=', self::class)
->where('action_type', '=', 'accepted')
->orderBy('created_at', 'desc')
->withTrashed();
}
/**
* Get the list of checkouts for this asset
*
@@ -1652,9 +1665,9 @@ class Asset extends Depreciable
*/
public function scopeOrderManufacturer($query, $order)
{
return $query->join('models', 'assets.model_id', '=', 'models.id')
->join('manufacturers', 'models.manufacturer_id', '=', 'manufacturers.id')
->orderBy('manufacturers.name', $order);
return $query->join('models as order_asset_model', 'assets.model_id', '=', 'order_asset_model.id')
->join('manufacturers as manufacturer_order', 'order_asset_model.manufacturer_id', '=', 'manufacturer_order.id')
->orderBy('manufacturer_order.name', $order);
}
/**
+32 -3
View File
@@ -10,6 +10,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Gate;
use Watson\Validating\ValidatingTrait;
use App\Helpers\Helper;
use Illuminate\Support\Str;
/**
* Model for Categories. Categories are a higher-level group
@@ -97,6 +98,7 @@ class Category extends SnipeModel
*/
public function isDeletable()
{
return Gate::allows('delete', $this)
&& ($this->itemCount() == 0);
}
@@ -150,7 +152,10 @@ class Category extends SnipeModel
}
/**
* Get the number of items in the category
* Get the number of items in the category. This should NEVER be used in
* a collection of categories, as you'll end up with an n+1 query problem.
*
* It should only be used in a single category context.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
@@ -158,6 +163,11 @@ class Category extends SnipeModel
*/
public function itemCount()
{
if (isset($this->{Str::plural($this->category_type).'_count'})) {
return $this->{Str::plural($this->category_type).'_count'};
}
switch ($this->category_type) {
case 'asset':
return $this->assets()->count();
@@ -169,9 +179,10 @@ class Category extends SnipeModel
return $this->consumables()->count();
case 'license':
return $this->licenses()->count();
default:
return 0;
}
return '0';
}
/**
@@ -183,7 +194,25 @@ class Category extends SnipeModel
*/
public function assets()
{
return $this->hasManyThrough(\App\Models\Asset::class, \App\Models\AssetModel::class, 'category_id', 'model_id');
return $this->hasManyThrough(Asset::class, \App\Models\AssetModel::class, 'category_id', 'model_id');
}
/**
* Establishes the category -> assets relationship but also takes into consideration
* the setting to show archived in lists.
*
* We could have complicated the assets() method above, but keeping this separate
* should give us more flexibility if we need to return actually archived assets
* by their category.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v6.1.0]
* @see \App\Models\Asset::scopeAssetsForShow()
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function showableAssets()
{
return $this->hasManyThrough(Asset::class, \App\Models\AssetModel::class, 'category_id', 'model_id')->AssetsForShow();
}
/**
+10 -3
View File
@@ -16,12 +16,19 @@ class CheckoutAcceptance extends Model
'declined_at' => 'datetime',
];
// Get the mail recipient from the config
public function routeNotificationForMail(): string
/**
* Get the mail recipient from the config
*
* @return mixed|string|null
*/
public function routeNotificationForMail()
{
// 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')) ? config('mail.reply_to.address') : '' ;
$recipients_string = explode(',', Setting::getSettings()->alert_email);
$recipients = array_map('trim', $recipients_string);
return array_filter($recipients);
}
/**
+1 -1
View File
@@ -35,7 +35,7 @@ class Component extends SnipeModel
'category_id' => 'required|integer|exists:categories,id',
'company_id' => 'integer|nullable',
'min_amt' => 'integer|min:0|nullable',
'purchase_date' => 'date|nullable',
'purchase_date' => 'date_format:Y-m-d|nullable',
'purchase_cost' => 'numeric|nullable|gte:0',
];
+1
View File
@@ -41,6 +41,7 @@ class Consumable extends SnipeModel
'company_id' => 'integer|nullable',
'min_amt' => 'integer|min:0|nullable',
'purchase_cost' => 'numeric|nullable|gte:0',
'purchase_date' => 'date_format:Y-m-d|nullable',
];
/**
+2 -2
View File
@@ -21,7 +21,7 @@ class CustomField extends Model
*
* @var array
*/
const PREDEFINED_FORMATS = [
public const PREDEFINED_FORMATS = [
'ANY' => '',
'CUSTOM REGEX' => '',
'ALPHA' => 'alpha',
@@ -238,7 +238,7 @@ class CustomField extends Model
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
* @return string
*/
public function db_column_name()
{
+1 -1
View File
@@ -16,7 +16,7 @@ class Depreciation extends SnipeModel
// Declare the rules for the form validation
protected $rules = [
'name' => 'required|min:3|max:255|unique:depreciations,name',
'months' => 'required|max:3600|integer',
'months' => 'required|max:3600|integer|gt:0',
];
/**
+5
View File
@@ -16,6 +16,11 @@ class Group extends SnipeModel
'name' => 'required|min:2|max:255',
];
protected $fillable = [
'name',
'permissions'
];
/**
* Whether the model should inject it's identifier to the unique
* validation rules before attempting validation. If this property
+10 -10
View File
@@ -217,16 +217,16 @@ class Ldap extends Model
$ldap_result_manager = Setting::getSettings()->ldap_manager;
// Get LDAP user data
$item = [];
$item['username'] = isset($ldapattributes[$ldap_result_username][0]) ? $ldapattributes[$ldap_result_username][0] : '';
$item['employee_number'] = isset($ldapattributes[$ldap_result_emp_num][0]) ? $ldapattributes[$ldap_result_emp_num][0] : '';
$item['lastname'] = isset($ldapattributes[$ldap_result_last_name][0]) ? $ldapattributes[$ldap_result_last_name][0] : '';
$item['firstname'] = isset($ldapattributes[$ldap_result_first_name][0]) ? $ldapattributes[$ldap_result_first_name][0] : '';
$item['email'] = isset($ldapattributes[$ldap_result_email][0]) ? $ldapattributes[$ldap_result_email][0] : '';
$item['telephone'] = isset($ldapattributes[$ldap_result_phone][0]) ? $ldapattributes[$ldap_result_phone][0] : '';
$item['jobtitle'] = isset($ldapattributes[$ldap_result_jobtitle][0]) ? $ldapattributes[$ldap_result_jobtitle][0] : '';
$item['country'] = isset($ldapattributes[$ldap_result_country][0]) ? $ldapattributes[$ldap_result_country][0] : '';
$item['department'] = isset($ldapattributes[$ldap_result_dept][0]) ? $ldapattributes[$ldap_result_dept][0] : '';
$item['manager'] = isset($ldapattributes[$ldap_result_manager][0]) ? $ldapattributes[$ldap_result_manager][0] : '';
$item['username'] = $ldapattributes[$ldap_result_username][0] ?? '';
$item['employee_number'] = $ldapattributes[$ldap_result_emp_num][0] ?? '';
$item['lastname'] = $ldapattributes[$ldap_result_last_name][0] ?? '';
$item['firstname'] = $ldapattributes[$ldap_result_first_name][0] ?? '';
$item['email'] = $ldapattributes[$ldap_result_email][0] ?? '';
$item['telephone'] = $ldapattributes[$ldap_result_phone][0] ?? '';
$item['jobtitle'] = $ldapattributes[$ldap_result_jobtitle][0] ?? '';
$item['country'] = $ldapattributes[$ldap_result_country][0] ?? '';
$item['department'] = $ldapattributes[$ldap_result_dept][0] ?? '';
$item['manager'] = $ldapattributes[$ldap_result_manager][0] ?? '';
return $item;
}
+4 -2
View File
@@ -36,7 +36,6 @@ class License extends Depreciable
'purchase_date' => 'datetime',
'expiration_date' => 'datetime',
'termination_date' => 'datetime',
'seats' => 'integer',
'category_id' => 'integer',
'company_id' => 'integer',
];
@@ -50,6 +49,9 @@ class License extends Depreciable
'category_id' => 'required|exists:categories,id',
'company_id' => 'integer|nullable',
'purchase_cost'=> 'numeric|nullable|gte:0',
'purchase_date' => 'date_format:Y-m-d|nullable',
'expiration_date' => 'date_format:Y-m-d|nullable',
'termination_date' => 'date_format:Y-m-d|nullable',
];
/**
@@ -365,7 +367,7 @@ class License extends Depreciable
*/
public function assignedusers()
{
return $this->belongsToMany(\App\Models\User::class, 'license_seats', 'assigned_to', 'license_id');
return $this->belongsToMany(\App\Models\User::class, 'license_seats', 'license_id', 'assigned_to');
}
/**
+6 -2
View File
@@ -93,8 +93,12 @@ trait Loggable
{
$settings = Setting::getSettings();
$log = new Actionlog;
$log->target_type = get_class($target);
$log->target_id = $target->id;
if($target != null){
$log->target_type = get_class($target);
$log->target_id = $target->id;
}
if (static::class == LicenseSeat::class) {
$log->item_type = License::class;
+5 -2
View File
@@ -31,7 +31,7 @@ class Setting extends Model
*
* @var string
*/
const SETUP_CHECK_KEY = 'snipeit_setup_check';
public const SETUP_CHECK_KEY = 'snipeit_setup_check';
/**
* Whether the model should inject it's identifier to the unique
@@ -83,6 +83,9 @@ class Setting extends Model
'email_domain',
'email_format',
'username_format',
'webhook_endpoint',
'webhook_channel',
'webhook_botname',
];
/**
@@ -262,7 +265,7 @@ class Setting 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 self::getSettings()->slack_endpoint;
return self::getSettings()->webhook_endpoint;
}
/**
+195 -133
View File
@@ -12,94 +12,9 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig
{
public function getUserConfig()
{
$config = parent::getUserConfig();
// Much of this is copied verbatim from the library, then adjusted for our needs
$config['class'] = SCIMUser::class;
unset($config['mapping']['example:name:space']);
$config['map_unmapped'] = false; // anything we don't explicitly map will _not_ show up.
$core_namespace = 'urn:ietf:params:scim:schemas:core:2.0:User';
$core = $core_namespace.':';
$mappings =& $config['mapping'][$core_namespace]; //grab this entire key, we don't want to be repeating ourselves
//username - *REQUIRED*
$config['validations'][$core.'userName'] = 'required';
$mappings['userName'] = AttributeMapping::eloquent('username');
//human name - *FIRST NAME REQUIRED*
$config['validations'][$core.'name.givenName'] = 'required';
$config['validations'][$core.'name.familyName'] = 'string'; //not required
$mappings['name']['familyName'] = AttributeMapping::eloquent("last_name");
$mappings['name']['givenName'] = AttributeMapping::eloquent("first_name");
$mappings['name']['formatted'] = (new AttributeMapping())->ignoreWrite()->setRead(
function (&$object) {
return $object->getFullNameAttribute();
}
);
// 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)
$mappings['emails'] = [[
"value" => AttributeMapping::eloquent("email"),
"display" => null,
"type" => AttributeMapping::constant("work")->ignoreWrite(),
"primary" => AttributeMapping::constant(true)->ignoreWrite()
]];
//active
$config['validations'][$core.'active'] = 'boolean';
$mappings['active'] = AttributeMapping::eloquent('activated');
//phone
$config['validations'][$core.'phoneNumbers'] = 'nullable|array';
$config['validations'][$core.'phoneNumbers.*.value'] = 'string'; // another one where want to say 'we don't _need_ a phone number, but if you have one it better have a value.
$mappings['phoneNumbers'] = [[
"value" => AttributeMapping::eloquent("phone"),
"display" => null,
"type" => AttributeMapping::constant("work")->ignoreWrite(),
"primary" => AttributeMapping::constant(true)->ignoreWrite()
]];
//address
$config['validations'][$core.'addresses'] = 'nullable|array';
$config['validations'][$core.'addresses.*.streetAddress'] = 'string';
$config['validations'][$core.'addresses.*.locality'] = 'string';
$config['validations'][$core.'addresses.*.region'] = 'nullable|string';
$config['validations'][$core.'addresses.*.postalCode'] = 'nullable|string';
$config['validations'][$core.'addresses.*.country'] = 'string';
$mappings['addresses'] = [[
'type' => AttributeMapping::constant("work")->ignoreWrite(),
'formatted' => AttributeMapping::constant("n/a")->ignoreWrite(), // TODO - is this right? This doesn't look right.
'streetAddress' => AttributeMapping::eloquent("address"),
'locality' => AttributeMapping::eloquent("city"),
'region' => AttributeMapping::eloquent("state"),
'postalCode' => AttributeMapping::eloquent("zip"),
'country' => AttributeMapping::eloquent("country"),
'primary' => AttributeMapping::constant(true)->ignoreWrite() //this isn't in the example?
]];
//title
$config['validations'][$core.'title'] = 'string';
$mappings['title'] = AttributeMapping::eloquent('jobtitle');
//Preferred Language
$config['validations'][$core.'preferredLanguage'] = 'string';
$mappings['preferredLanguage'] = AttributeMapping::eloquent('locale');
/*
/*
more snipe-it attributes I'd like to check out (to map to 'enterprise' maybe?):
- website
- notes?
@@ -108,66 +23,213 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig
- company_id to "organization?"
*/
$enterprise_namespace = 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User';
$ent = $enterprise_namespace.':';
// we remove the 'example' namespace and add the Enterprise one
$config['mapping']['schemas'] = AttributeMapping::constant( [$core_namespace, $enterprise_namespace] )->ignoreWrite();
$user_prefix = 'urn:ietf:params:scim:schemas:core:2.0:User:';
$enterprise_prefix = 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:';
$config['validations'][$ent.'employeeNumber'] = 'string';
$config['validations'][$ent.'department'] = 'string';
$config['validations'][$ent.'manager'] = 'nullable';
$config['validations'][$ent.'manager.value'] = 'string';
return [
$config['mapping'][$enterprise_namespace] = [
'employeeNumber' => AttributeMapping::eloquent('employee_num'),
'department' =>(new AttributeMapping())->setAdd( // FIXME parent?
function ($value, &$object) {
$department = Department::where("name", $value)->first();
if ($department) {
$object->department_id = $department->id;
}
}
)->setReplace(
function ($value, &$object) {
$department = Department::where("name", $value)->first();
if ($department) {
$object->department_id = $department->id;
// Set to 'null' to make use of auth.providers.users.model (App\User::class)
'class' => SCIMUser::class,
'validations' => [
$user_prefix . 'userName' => 'required',
$user_prefix . 'name.givenName' => 'required',
$user_prefix . 'name.familyName' => 'nullable|string',
$user_prefix . 'externalId' => 'nullable|string',
$user_prefix . 'emails' => 'nullable|array',
$user_prefix . 'emails.*.value' => 'nullable|email',
$user_prefix . 'active' => 'boolean',
$user_prefix . 'phoneNumbers' => 'nullable|array',
$user_prefix . 'phoneNumbers.*.value' => 'nullable|string',
$user_prefix . 'addresses' => 'nullable|array',
$user_prefix . 'addresses.*.streetAddress' => 'nullable|string',
$user_prefix . 'addresses.*.locality' => 'nullable|string',
$user_prefix . 'addresses.*.region' => 'nullable|string',
$user_prefix . 'addresses.*.postalCode' => 'nullable|string',
$user_prefix . 'addresses.*.country' => 'nullable|string',
$user_prefix . 'title' => 'nullable|string',
$user_prefix . 'preferredLanguage' => 'nullable|string',
// Enterprise validations:
$enterprise_prefix . 'employeeNumber' => 'nullable|string',
$enterprise_prefix . 'department' => 'nullable|string',
$enterprise_prefix . 'manager' => 'nullable',
$enterprise_prefix . 'manager.value' => 'nullable|string'
],
'singular' => 'User',
'schema' => [Schema::SCHEMA_USER],
//eager loading
'withRelations' => [],
'map_unmapped' => false,
// 'unmapped_namespace' => 'urn:ietf:params:scim:schemas:laravel:unmapped',
'description' => 'User Account',
// Map a SCIM attribute to an attribute of the object.
'mapping' => [
'id' => AttributeMapping::eloquent("id")->disableWrite(),
'externalId' => AttributeMapping::eloquent('scim_externalid'), // FIXME - I have a PR that changes a lot of this.
'meta' => [
'created' => AttributeMapping::eloquent("created_at")->disableWrite(),
'lastModified' => AttributeMapping::eloquent("updated_at")->disableWrite(),
'location' => (new AttributeMapping())->setRead(
function ($object) {
return route(
'scim.resource',
[
'resourceType' => 'Users',
'resourceObject' => $object->id
]
);
}
}
)->setRead(
function (&$object) {
return $object->department ? $object->department->name : null;
}
),
'manager' => [
// FIXME - manager writes are disabled. This kinda works but it leaks errors all over the place. Not cool.
// '$ref' => (new AttributeMapping())->ignoreWrite()->ignoreRead(),
// 'displayName' => (new AttributeMapping())->ignoreWrite()->ignoreRead(),
// NOTE: you could probably do a 'plain' Eloquent mapping here, but we don't for future-proofing
'value' => (new AttributeMapping())->setAdd(
function ($value, &$object) {
$manager = User::find($value);
if ($manager) {
$object->manager_id = $manager->id;
)->disableWrite(),
'resourceType' => AttributeMapping::constant("User")
],
'schemas' => AttributeMapping::constant(
[
'urn:ietf:params:scim:schemas:core:2.0:User',
'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User'
]
)->ignoreWrite(),
'urn:ietf:params:scim:schemas:core:2.0:User' => [
'userName' => AttributeMapping::eloquent("username"),
'name' => [
'formatted' => (new AttributeMapping())->ignoreWrite()->setRead(
function (&$object) {
return $object->getFullNameAttribute();
}
),
'familyName' => AttributeMapping::eloquent("last_name"),
'givenName' => AttributeMapping::eloquent("first_name"),
'middleName' => null,
'honorificPrefix' => null,
'honorificSuffix' => null
],
'displayName' => null,
'nickName' => null,
'profileUrl' => null,
'title' => AttributeMapping::eloquent('jobtitle'),
'userType' => null,
'preferredLanguage' => AttributeMapping::eloquent('locale'), // Section 5.3.5 of [RFC7231]
'locale' => null, // see RFC5646
'timezone' => null, // see RFC6557
'active' => AttributeMapping::eloquent('activated'),
'password' => AttributeMapping::eloquent('password')->disableRead(),
// Multi-Valued Attributes
'emails' => [[
"value" => AttributeMapping::eloquent("email"),
"display" => null,
"type" => AttributeMapping::constant("work")->ignoreWrite(),
"primary" => AttributeMapping::constant(true)->ignoreWrite()
]],
'phoneNumbers' => [[
"value" => AttributeMapping::eloquent("phone"),
"display" => null,
"type" => AttributeMapping::constant("work")->ignoreWrite(),
"primary" => AttributeMapping::constant(true)->ignoreWrite()
]],
'ims' => [[
"value" => null,
"display" => null,
"type" => null,
"primary" => null
]], // Instant messaging addresses for the User
'photos' => [[
"value" => null,
"display" => null,
"type" => null,
"primary" => null
]],
'addresses' => [[
'type' => AttributeMapping::constant("work")->ignoreWrite(),
'formatted' => AttributeMapping::constant("n/a")->ignoreWrite(), // TODO - is this right? This doesn't look right.
'streetAddress' => AttributeMapping::eloquent("address"),
'locality' => AttributeMapping::eloquent("city"),
'region' => AttributeMapping::eloquent("state"),
'postalCode' => AttributeMapping::eloquent("zip"),
'country' => AttributeMapping::eloquent("country"),
'primary' => AttributeMapping::constant(true)->ignoreWrite() //this isn't in the example?
]],
'groups' => [[
'value' => null,
'$ref' => null,
'display' => null,
'type' => null,
'type' => null
]],
'entitlements' => null,
'roles' => null,
'x509Certificates' => null
],
'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User' => [
'employeeNumber' => AttributeMapping::eloquent('employee_num'),
'department' => (new AttributeMapping())->setAdd( // FIXME parent?
function ($value, &$object) {
$department = Department::where("name", $value)->first();
if ($department) {
$object->department_id = $department->id;
}
}
}
)->setReplace(
function ($value, &$object) {
$manager = User::find($value);
if ($manager) {
$object->manager_id = $manager->id;
$department = Department::where("name", $value)->first();
if ($department) {
$object->department_id = $department->id;
}
}
)->setRead(
function (&$object) {
return $object->manager_id;
}
return $object->department ? $object->department->name : null;
}
),
'manager' => [
// FIXME - manager writes are disabled. This kinda works but it leaks errors all over the place. Not cool.
// '$ref' => (new AttributeMapping())->ignoreWrite()->ignoreRead(),
// 'displayName' => (new AttributeMapping())->ignoreWrite()->ignoreRead(),
// NOTE: you could probably do a 'plain' Eloquent mapping here, but we don't for future-proofing
'value' => (new AttributeMapping())->setAdd(
function ($value, &$object) {
$manager = User::find($value);
if ($manager) {
$object->manager_id = $manager->id;
}
}
)->setReplace(
function ($value, &$object) {
$manager = User::find($value);
if ($manager) {
$object->manager_id = $manager->id;
}
}
)->setRead(
function (&$object) {
return $object->manager_id;
}
),
]
]
]
];
return $config;
}
}
+3 -3
View File
@@ -164,7 +164,7 @@ trait Searchable
}
// I put this here because I only want to add the concat one time in the end of the user relation search
if($relation == 'user') {
$query->orWhereRaw('CONCAT (users.first_name, " ", users.last_name) LIKE ?', ["%$term%"]);
$query->orWhereRaw('CONCAT (users.first_name, " ", users.last_name) LIKE ?', ["%{$term}%"]);
}
});
}
@@ -195,7 +195,7 @@ trait Searchable
*/
private function getSearchableAttributes()
{
return isset($this->searchableAttributes) ? $this->searchableAttributes : [];
return $this->searchableAttributes ?? [];
}
/**
@@ -205,7 +205,7 @@ trait Searchable
*/
private function getSearchableRelations()
{
return isset($this->searchableRelations) ? $this->searchableRelations : [];
return $this->searchableRelations ?? [];
}
/**

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