Compare commits

...

604 Commits

Author SHA1 Message Date
snipe 8052447de6 Ugh
Signed-off-by: snipe <snipe@snipe.net>
2024-10-03 14:34:29 +01:00
snipe b4f9284d41 Added migration
Signed-off-by: snipe <snipe@snipe.net>
2024-10-02 21:34:31 +01:00
snipe aac876eaa8 First stab
Signed-off-by: snipe <snipe@snipe.net>
2024-10-02 21:30:08 +01:00
snipe 54fbd0540d Merge branch 'develop' of https://github.com/snipe/snipe-it into develop 2024-10-02 12:40:49 +01:00
snipe b483bb1633 Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2024-10-02 12:40:45 +01:00
snipe 4db7358086 Merge pull request #15593 from Godmartinz/Fixed-divide-by-zero-bug
Fixed divide by zero bug in depreciation transformer
2024-10-02 12:38:46 +01:00
snipe 0dd6f41f66 Simplified 2fa if/else
Signed-off-by: snipe <snipe@snipe.net>
2024-10-02 11:04:55 +01:00
snipe 684c20ae39 Fixed parenthasis
Signed-off-by: snipe <snipe@snipe.net>
2024-10-02 11:00:49 +01:00
snipe c32f4e34b4 Minor formatting fix
Signed-off-by: snipe <snipe@snipe.net>
2024-10-01 20:35:49 +01:00
snipe ca1886cebc Merge pull request #15594 from snipe/localizations/update-2024-10-01
Updated strings
2024-10-01 20:31:38 +01:00
snipe a79dfea40a Updated strings
Signed-off-by: snipe <snipe@snipe.net>
2024-10-01 20:30:58 +01:00
snipe 45ab49eeab Merge pull request #15592 from spencerrlongg/bug/catch_request_notify_errors
Catch Errors Around Request Notifications
2024-10-01 20:26:42 +01:00
spencerrlongg 8232618a9f change the other one too 2024-10-01 14:26:32 -05:00
spencerrlongg 9a651b567d change error to warning 2024-10-01 14:24:03 -05:00
snipe 97d00e5aa8 Fixed erroneous form tag on anchor
Signed-off-by: snipe <snipe@snipe.net>
2024-10-01 20:08:54 +01:00
Godfrey M b9cfdf2e54 reworked monthly depreciation variable value 2024-10-01 11:41:59 -07:00
spencerrlongg 1139acd9f3 catch errors around request notifications 2024-10-01 13:36:47 -05:00
Godfrey M b7ad80bd31 fix monthly depreciation value 2024-10-01 11:24:24 -07:00
Godfrey M 5ffd1b8daa fixes if statement in transformer 2024-10-01 11:02:39 -07:00
snipe 9a2117466e Removed placeholder
Signed-off-by: snipe <snipe@snipe.net>
2024-10-01 18:23:40 +01:00
snipe 7e3a062984 Use <th> for table header in bulk interstitial
Signed-off-by: snipe <snipe@snipe.net>
2024-10-01 18:23:07 +01:00
snipe d274fb6963 Merge pull request #15589 from snipe/adds_checkin_action_on_asset_delete
Adds checkin action on asset delete via View UI
2024-10-01 14:32:48 +01:00
snipe 27ba641aa5 Added checkin on delete to API
Signed-off-by: snipe <snipe@snipe.net>
2024-10-01 14:30:34 +01:00
snipe 5823197e6f Added checkin action on delete for checked out assets
Signed-off-by: snipe <snipe@snipe.net>
2024-10-01 14:29:02 +01:00
snipe cfc04a1d12 Merge pull request #15588 from snipe/added_more_maxlengths
Added maxlengths to additional fields
2024-10-01 14:08:58 +01:00
snipe cae8aa7840 Added maxlengths to additional fields
Signed-off-by: snipe <snipe@snipe.net>
2024-10-01 14:02:54 +01:00
snipe 12da43303f Fixed #15584 - regression with required css change
Signed-off-by: snipe <snipe@snipe.net>
2024-10-01 01:44:05 +01:00
snipe b04afbbc85 Merge pull request #15564 from uberbrady/improve_autoclose
Get us better debugging output for new Github Stale Action
2024-09-30 19:26:08 +01:00
snipe b964ce1025 Merge pull request #15583 from Godmartinz/remove-sortable-from-depreciations
Removed sortablity for current value column in depreciations report
2024-09-30 19:25:05 +01:00
snipe 6217cba201 Merge pull request #15524 from Godmartinz/double-notif-bug
Fixed double webhook notifications // Separated email and webhook notifications.
2024-09-30 19:24:19 +01:00
Godfrey M 68e3f375fc removes sortablity from current value column 2024-09-30 11:15:49 -07:00
snipe 5689e940b8 Fixed #15581 - missing bracker
Signed-off-by: snipe <snipe@snipe.net>
2024-09-30 18:23:12 +01:00
snipe 001348c638 Unset required on checkout select :(
Related to the discussion at #15552

Signed-off-by: snipe <snipe@snipe.net>
2024-09-29 14:33:42 +01:00
snipe 1b041af862 Merge remote-tracking branch 'origin/master' into develop
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
2024-09-29 11:25:01 +01:00
snipe 260b153689 Merge pull request #15573 from snipe/fixed_requiredness_indicator
Fixes for requiredness indicator in UI
2024-09-28 16:09:51 +01:00
snipe 05d74f7a92 Covered setup pages too
Signed-off-by: snipe <snipe@snipe.net>
2024-09-28 15:42:03 +01:00
snipe dc85588d7f Don’t show password as required if editing
Signed-off-by: snipe <snipe@snipe.net>
2024-09-28 15:31:44 +01:00
snipe 585f998cae Fixes for requiredness display
Signed-off-by: snipe <snipe@snipe.net>
2024-09-28 15:28:06 +01:00
snipe d120585f94 Check for valid eula for license, consumable
Signed-off-by: snipe <snipe@snipe.net>
2024-09-27 14:07:30 +01:00
snipe 166a700342 Merge remote-tracking branch 'origin/develop' 2024-09-27 13:37:28 +01:00
snipe 36b27fcda3 Check for valid category before getting the eula
Signed-off-by: snipe <snipe@snipe.net>
2024-09-27 13:37:14 +01:00
snipe a44490e448 Nowrap on files column
Signed-off-by: snipe <snipe@snipe.net>
2024-09-27 13:07:24 +01:00
snipe 9aada2ec70 Merge pull request #15498 from Godmartinz/Modal_fix
Refactoring modals with partials and fixing misalignments
2024-09-26 09:09:35 +01:00
Godfrey M ef82f954e5 fixed required css, and user input lengths 2024-09-25 15:47:57 -07:00
Brady Wetherington 3f311ba2fb Get us better debugging output for new Github Stale Action 2024-09-25 21:27:45 +01:00
Godfrey Martinez 96953aa2ed Merge pull request #23 from Godmartinz/Modal_fix_p3
replace duplicate code with partials
2024-09-25 12:50:01 -07:00
Godfrey M b797c37acb replace duplicate code with partials 2024-09-25 12:48:05 -07:00
snipe 6c85ba3495 Merge remote-tracking branch 'origin/develop' 2024-09-25 20:45:02 +01:00
snipe ac6411743b Merge pull request #15563 from snipe/refined_gates_on_user_bulk
Update for #15534 - Refined gates on user bulk
2024-09-25 20:35:58 +01:00
snipe 3f0245f88f Make controller gate match dropdown gate
Signed-off-by: snipe <snipe@snipe.net>
2024-09-25 20:33:00 +01:00
snipe c02647a0fa Moved merge into delete gate, since they do technically delete
Signed-off-by: snipe <snipe@snipe.net>
2024-09-25 20:32:03 +01:00
snipe edca3f432c Removed gate for delete
Signed-off-by: snipe <snipe@snipe.net>
2024-09-25 20:30:58 +01:00
snipe 2218c94aa3 Gates the dropdown based on user permissions
Signed-off-by: snipe <snipe@snipe.net>
2024-09-25 20:29:23 +01:00
Godfrey Martinez e609b39760 Merge pull request #22 from Godmartinz/Modal_fix_p2
Modal fix p2
2024-09-25 12:09:26 -07:00
Godfrey M 12522a3791 fix spacing issues 2024-09-25 12:07:15 -07:00
snipe f6d7ea19e4 Set view as base permission, drill down for more intrusive actions
Signed-off-by: snipe <snipe@snipe.net>
2024-09-25 19:44:39 +01:00
Godfrey M 18ddffe8f9 fix partial variable intialization, fix width of input fields 2024-09-25 11:42:16 -07:00
snipe 9b03f46490 Merge pull request #15534 from marcusmoore/bulk-print-users
Added the ability to bulk print users
2024-09-25 19:32:01 +01:00
Godfrey M 926a319552 Merge branch 'develop' into Modal_fix_p2 2024-09-25 11:10:24 -07:00
snipe 9f8473e254 Merge remote-tracking branch 'origin/develop' 2024-09-25 18:36:40 +01:00
snipe cb6e5042d9 Merge pull request #15547 from snipe/disallow_checkout_with_nondeployable_status
Fixed #13396 - do not allow checkout to undeployable status types
2024-09-25 18:32:59 +01:00
snipe c1a887b48b Merge pull request #15561 from snipe/fixes/adds_action_date_to_sorting
Changed `action_date` to `created_at` in activity report
2024-09-25 18:32:21 +01:00
snipe 658c94ad8b Changed action_date to created_at
Signed-off-by: snipe <snipe@snipe.net>
2024-09-25 17:25:15 +01:00
snipe 0e61d0b195 Merge remote-tracking branch 'origin/develop' 2024-09-25 15:51:38 +01:00
snipe ba12204842 Merge pull request #15555 from snipe/fixes/user_file_upload
Fixed case on `$logAction` for user file upload
2024-09-25 15:51:14 +01:00
snipe 1c3babacaf Fixed case on logAction for usewr file upload
Signed-off-by: snipe <snipe@snipe.net>
2024-09-25 15:46:57 +01:00
snipe abdddbec44 Merge remote-tracking branch 'origin/develop'
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
2024-09-25 11:58:25 +01:00
snipe eeabc8dc9d Dev assets
Signed-off-by: snipe <snipe@snipe.net>
2024-09-25 11:33:45 +01:00
snipe 21f8ac8e52 Merge pull request #15552 from Godmartinz/ragged-form-inputs
Fixed input field misalignments
2024-09-25 11:31:23 +01:00
snipe a425c2b765 Merge remote-tracking branch 'origin/develop' 2024-09-25 10:52:19 +01:00
Godfrey M 2a2666be0b makes required a pseudo field 2024-09-24 13:24:50 -07:00
snipe c38222e956 Merge pull request #15549 from snipe/fixes/#15548_unify_audit_api_endpoints
Fixes #15548 - unify audit api endpoints
2024-09-24 18:10:53 +01:00
snipe 0ce5832b6c Removed debugging
Signed-off-by: snipe <snipe@snipe.net>
2024-09-24 17:29:40 +01:00
snipe 5fb43dd159 Handle audit *and* audits for urls
Signed-off-by: snipe <snipe@snipe.net>
2024-09-24 16:55:56 +01:00
snipe de57d71bf1 Fixed #15548 - unify audit due/overdue APIs
Signed-off-by: snipe <snipe@snipe.net>
2024-09-24 16:30:24 +01:00
snipe ba69259f2d Fixed #13396 - do not allow checkout to undeployable status types
Signed-off-by: snipe <snipe@snipe.net>
2024-09-24 15:35:00 +01:00
snipe 8cf1e4dceb Merge pull request #15544 from snipe/bug/sc-26855
Fixed app settings view on mobile
2024-09-24 11:10:20 +01:00
snipe 66249a37ed Tweaked styles
Signed-off-by: snipe <snipe@snipe.net>
2024-09-24 11:08:31 +01:00
snipe 96712cb398 Fixed app settings view on mobile
Signed-off-by: snipe <snipe@snipe.net>
2024-09-24 10:55:26 +01:00
Marcus Moore fac4833b58 Remove unused import 2024-09-23 17:15:16 -07:00
Marcus Moore a12c9d053f Hide label when printing 2024-09-23 16:44:25 -07:00
Marcus Moore 8b3b68b308 Show or hide all eulas at once when printing multiple users 2024-09-23 16:43:14 -07:00
Marcus Moore 4b02db5031 Add authorization check in bulk users controller 2024-09-23 16:26:22 -07:00
Marcus Moore ab90c0cf05 Add missing eager load in bulk users controller 2024-09-23 16:10:40 -07:00
Marcus Moore cef7ddc719 Add eager loads to userscontroller 2024-09-23 16:10:21 -07:00
Marcus Moore 3870095a28 Fix Cannot read properties of undefined error by removing snipe-table class from eula table 2024-09-23 15:50:24 -07:00
Marcus Moore a02e250b22 Add page breaks for each user 2024-09-23 15:26:15 -07:00
Marcus Moore 8ac5c0e471 Re-combine layout and view 2024-09-23 14:05:47 -07:00
Marcus Moore a2d4dcf6e8 Use bulk actions menu 2024-09-23 12:49:36 -07:00
Marcus Moore 54044bfa5e Add eager loads 2024-09-23 10:57:57 -07:00
Marcus Moore e493cc964d Remove AssetCountForSidebar middleware from print view 2024-09-23 10:48:07 -07:00
Marcus Moore 29af210f4f Merge branch 'develop' into bulk-print-users 2024-09-23 10:26:20 -07:00
snipe 34eb10ff73 Merge remote-tracking branch 'origin/develop' 2024-09-20 19:45:20 +01:00
snipe ab0c009c0d Fixed seeder
Signed-off-by: snipe <snipe@snipe.net>
2024-09-20 19:45:10 +01:00
snipe 7d7d58769c Merge remote-tracking branch 'origin/develop' 2024-09-20 19:13:00 +01:00
snipe b68805cf83 Small fix for notifications checkout
Signed-off-by: snipe <snipe@snipe.net>
2024-09-20 19:11:52 +01:00
snipe 245d5dc469 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2024-09-20 17:28:15 +01:00
snipe 7d858129d9 Bumped hash
Signed-off-by: snipe <snipe@snipe.net>
2024-09-20 14:44:19 +01:00
snipe 65ce63bc9b Merge pull request #15537 from snipe/snyk/updated_jspdf_autotable
Updated jspdf autotable
2024-09-20 14:42:07 +01:00
snipe 54fba2f547 Update jspdf autotable
Signed-off-by: snipe <snipe@snipe.net>
2024-09-20 14:40:41 +01:00
snipe 5eea9d1950 Corrected text warning translation
Signed-off-by: snipe <snipe@snipe.net>
2024-09-20 14:33:56 +01:00
snipe b84a634ec7 Corrected comment
Signed-off-by: snipe <snipe@snipe.net>
2024-09-20 14:33:35 +01:00
snipe 2fc88a0e08 Eager load adminuser
Signed-off-by: snipe <snipe@snipe.net>
2024-09-20 14:33:26 +01:00
snipe bc540b6564 Requestable status not saving with manual [sc-26848]
Signed-off-by: snipe <snipe@snipe.net>
2024-09-20 14:02:28 +01:00
snipe f53b852dff Make created_by equal one in the seeder
Signed-off-by: snipe <snipe@snipe.net>
2024-09-20 13:53:52 +01:00
snipe b83d1a043f Merge pull request #15519 from snipe/features/add_created_at_created_by
Change `user_id` to `created_by`
2024-09-20 13:47:31 +01:00
snipe 4ab478bb97 Merge remote-tracking branch 'origin/develop' 2024-09-20 13:44:45 +01:00
snipe b21c303e56 Merge remote-tracking branch 'origin/develop' into features/add_created_at_created_by 2024-09-20 13:43:50 +01:00
Marcus Moore 5128fd49e6 Allow printing all users 2024-09-19 17:27:25 -07:00
Marcus Moore 2d2d5bdc7e Pass user in array 2024-09-19 17:23:47 -07:00
Marcus Moore 8364d26c9b Extract parent layout 2024-09-19 17:18:26 -07:00
Marcus Moore efd6d7625f Remove bad closing tag 2024-09-19 17:16:05 -07:00
Marcus Moore bdf5708bfc Remove accidental line 2024-09-19 17:10:43 -07:00
Marcus Moore e95703cb18 Use eager load 2024-09-19 17:10:07 -07:00
Marcus Moore 7ad4a29970 Add eager loading 2024-09-19 16:54:39 -07:00
snipe cdb7ccb8f3 Merge pull request #15532 from spencerrlongg/bug/15253
Catch Exceptions on Checkout Notification
2024-09-19 21:54:03 +01:00
snipe 8270947ed2 Merge pull request #13291 from akemidx/eol_date_range_for_reports
Added date range for EOL in custom reports
2024-09-19 21:49:27 +01:00
snipe 4f7c8e0c3d Merge pull request #14671 from Robert-Azelis/patch-6
[FIX] Update EOL date when used bulk update of purchase date
2024-09-19 21:36:09 +01:00
snipe b88f2054dd Refactor isDeletable on companies
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 20:38:34 +01:00
snipe d7914e238d Added created by to company on save
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 20:34:54 +01:00
snipe d7bde37842 Merge pull request #15507 from setpill/setpill/feat/use_explicit_attributes_in_ldap_sync
Added #15506: Explicitly request used LDAP attributes
2024-09-19 20:33:10 +01:00
snipe 454796e52a Merge pull request #15518 from snipe/sort_by_numeric_custom_fields
Fixed #11634 - Sort by numeric columns for numeric custom fields
2024-09-19 20:32:03 +01:00
snipe eef487d61b Merge pull request #15531 from Godmartinz/status-doesnt-update-in-email
Fixed mail notification field `status label` not updating
2024-09-19 20:31:02 +01:00
Godfrey M 71dbc7abb0 refreshed the assetstatus relationship 2024-09-19 12:23:07 -07:00
snipe 74088ea581 Optimize isDeletable counts
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 20:13:38 +01:00
spencerrlongg d446773fdd catch exceptions on notification 2024-09-19 14:05:48 -05:00
snipe f283b5fbe8 Eager load adminuser
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 19:56:39 +01:00
snipe eb6f05faf7 Eager load adminuser
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 19:41:46 +01:00
snipe 118183ff58 Removed footer
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 19:41:39 +01:00
snipe ebf6ce6980 Refactor for fewer queries
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 19:27:10 +01:00
snipe 5ebf0ed2b2 Updated variable
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 19:19:14 +01:00
snipe 836893cba5 Added id to report
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 18:35:00 +01:00
snipe cd98b3817d Removed duplicate line
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 18:26:08 +01:00
snipe 727806372c Added created_by to status label
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 18:22:11 +01:00
snipe 5e1c736d49 Added created_by for manufacturers
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 18:04:50 +01:00
snipe 6579fa72da Added scoping for categories and companies
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 17:56:05 +01:00
snipe 82d6e1510f Order by created_by for depreciations
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 17:41:05 +01:00
snipe 822ea96dfd Use auth()->id() instead of Auth::id()
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 17:31:46 +01:00
snipe b247fc33b9 Added legacy comment
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 17:28:01 +01:00
snipe 2dcae780c0 Reapply deleted code
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 17:26:21 +01:00
snipe 5c3180ffa0 Removed duplicate code
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 17:25:09 +01:00
snipe 65eba30038 Fixed markdown in acceptance reminder
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 17:23:34 +01:00
snipe bbce7b40ca Additional consistencies
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 17:20:56 +01:00
snipe 02a29c71ef Added created_by
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 17:01:48 +01:00
snipe 6699995972 Added created_by to components
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 17:01:36 +01:00
snipe 951f03094a Added created_by to kits
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 17:01:17 +01:00
snipe 354b00ef15 Made method name consistent
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 16:45:51 +01:00
snipe c93229179b Added order by created_by to accessories
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 16:45:39 +01:00
snipe a77a7065d7 Added order by admin to assets
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 16:34:10 +01:00
snipe 4363e8b34c Updated importer
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 16:20:42 +01:00
snipe 9adb2c24f3 Squashed commit of the following:
commit dddbf27d78
Author: snipe <snipe@snipe.net>
Date:   Wed Sep 18 14:18:52 2024 +0100

    Updated language strings

    Signed-off-by: snipe <snipe@snipe.net>

commit fcefcc8184
Merge: 04bb3eec8 3519a82dd
Author: snipe <snipe@snipe.net>
Date:   Wed Sep 18 13:44:44 2024 +0100

    Merge pull request #15512 from marcusmoore/testing/fmcs

    Added tests for delete methods in api

commit 04bb3eec83
Merge: 154d5d8d9 f963b9a19
Author: snipe <snipe@snipe.net>
Date:   Wed Sep 18 13:41:37 2024 +0100

    Merge pull request #15521 from uberbrady/improve_country_selector

    Fix selected-index of Countries drop-down [fd-44144]

commit f963b9a19f
Author: Brady Wetherington <bwetherington@grokability.com>
Date:   Wed Sep 18 13:24:26 2024 +0100

    Fix selected-index of Countries drop-down

commit 154d5d8d91
Merge: 6c996b775 9e5f6d656
Author: snipe <snipe@snipe.net>
Date:   Tue Sep 17 23:40:25 2024 +0100

    Merge pull request #15491 from uberbrady/numeric_prefixes_add_multiple_assets

    [Fixes fd-43940] Improve multi-asset create when using numeric prefixes to asset_tags

commit 3519a82ddd
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Mon Sep 16 16:55:20 2024 -0700

    Fix name: TestsFullMultipleCompaniesSupport

commit a629df07bf
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Mon Sep 16 14:49:08 2024 -0700

    Implement interfaces on existing test classes

commit 9a13fcab23
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Mon Sep 16 14:38:38 2024 -0700

    Pluralize

commit f5705a1dde
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Mon Sep 16 14:34:55 2024 -0700

    More unification

commit f325c4afdb
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Mon Sep 16 14:32:38 2024 -0700

    Unify assertion method

commit 1fddacd7d0
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Mon Sep 16 14:25:11 2024 -0700

    Re-order test methods

commit 4af893df61
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Mon Sep 16 14:20:24 2024 -0700

    Improve assertions

commit b8b3f91ce4
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Mon Sep 16 13:55:18 2024 -0700

    Formatting

commit 7f40f55343
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Mon Sep 16 13:52:02 2024 -0700

    Add tests for delete supplier endpoint

commit b06e8d442d
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Mon Sep 16 13:37:08 2024 -0700

    Add tests for delete status label endpoint

commit c269184c60
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Mon Sep 16 13:29:41 2024 -0700

    Add tests for delete predefined kit endpoint

commit 53c673dee2
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Mon Sep 16 13:13:12 2024 -0700

    Add tests for delete manufacturer endpoint

commit 50730fc4fb
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Mon Sep 16 12:37:18 2024 -0700

    Add tests for delete location endpoint

commit 60a54cee79
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Mon Sep 16 12:33:30 2024 -0700

    Add tests for delete license endpoint

commit 446e962a50
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Mon Sep 16 10:38:51 2024 -0700

    Add tests for delete group endpoint

commit 79a4bb7316
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Mon Sep 16 10:35:44 2024 -0700

    Add tests for delete depreciation endpoint

commit 2f76c1bc5b
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Mon Sep 16 10:33:21 2024 -0700

    Add assertion

commit 38b9f4a438
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Mon Sep 16 10:29:20 2024 -0700

    Add tests for delete departments endpoint

commit 3105f53aff
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Thu Sep 12 16:54:29 2024 -0700

    Add tests for delete custom fieldsets endpoint

commit 2047cfed09
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Thu Sep 12 16:20:32 2024 -0700

    Add tests for delete custom fields endpoint

commit e3268d32df
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Thu Sep 12 16:00:02 2024 -0700

    Add tests for delete consumable endpoint

commit 6df8b0ac0e
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Thu Sep 12 15:52:07 2024 -0700

    Add tests for delete component endpoint

commit 910f13c1f7
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Thu Sep 12 15:38:30 2024 -0700

    Add tests for delete companies endpoint

commit 8ce2512f55
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Thu Sep 12 13:54:44 2024 -0700

    Add tests for delete category endpoint

commit 0ec415d4d0
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Thu Sep 12 13:46:22 2024 -0700

    Clean up

commit 2044570e95
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Thu Sep 12 13:39:36 2024 -0700

    Add tests for delete asset model endpoint

commit b336c6273d
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Thu Sep 12 13:32:42 2024 -0700

    Pluralize test classes

commit 5299b3e9f0
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Thu Sep 12 13:29:44 2024 -0700

    Remove code handled by CompanyableChildTrait

commit 872b76b45f
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Thu Sep 12 13:29:10 2024 -0700

    Add tests for delete asset maintenance endpoint

commit 275cf4630e
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Thu Sep 12 13:16:37 2024 -0700

    Add tests for delete asset endpoint

commit 5c2660bd34
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Thu Sep 12 13:02:32 2024 -0700

    Introduce interface

commit c7ae9d9dfa
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Thu Sep 12 12:58:47 2024 -0700

    Add tests for delete accessory endpoint

commit 9e5f6d656a
Author: Brady Wetherington <bwetherington@grokability.com>
Date:   Wed Sep 11 15:45:01 2024 +0100

    Improve multi-asset create when using numeric prefixes to asset_tags

Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 16:06:36 +01:00
snipe 634a4afa75 Fixed 1001 query on license
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 16:04:54 +01:00
snipe 7650628d30 Removed free seat count from fillable
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 16:00:59 +01:00
snipe 7f690a6238 Fixed variable name
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 15:58:32 +01:00
Godfrey M b32ab6a06c import User model 2024-09-18 16:36:24 -07:00
Godfrey M 4ff5fc1ff9 clean up variables 2024-09-18 16:19:35 -07:00
Godfrey M c40209f500 seperates emails and webhook notifications 2024-09-18 15:23:44 -07:00
snipe 655abe8be5 Fixed requestable user_id
Signed-off-by: snipe <snipe@snipe.net>
2024-09-18 14:32:59 +01:00
snipe d96c5e1ba4 Merge remote-tracking branch 'origin/develop' 2024-09-18 14:20:55 +01:00
snipe dddbf27d78 Updated language strings
Signed-off-by: snipe <snipe@snipe.net>
2024-09-18 14:18:52 +01:00
snipe bae9982833 Updated request methods
Signed-off-by: snipe <snipe@snipe.net>
2024-09-18 14:18:14 +01:00
snipe a807646d39 Merge remote-tracking branch 'origin/develop' 2024-09-18 13:48:09 +01:00
snipe abe79df6dc Added translation
Signed-off-by: snipe <snipe@snipe.net>
2024-09-18 13:47:30 +01:00
snipe fcefcc8184 Merge pull request #15512 from marcusmoore/testing/fmcs
Added tests for delete methods in api
2024-09-18 13:44:44 +01:00
snipe 04bb3eec83 Merge pull request #15521 from uberbrady/improve_country_selector
Fix selected-index of Countries drop-down [fd-44144]
2024-09-18 13:41:37 +01:00
Brady Wetherington f963b9a19f Fix selected-index of Countries drop-down 2024-09-18 13:24:26 +01:00
snipe 154d5d8d91 Merge pull request #15491 from uberbrady/numeric_prefixes_add_multiple_assets
[Fixes fd-43940] Improve multi-asset create when using numeric prefixes to asset_tags
2024-09-17 23:40:25 +01:00
snipe 1582d81e5b Change user_id to created_by
Signed-off-by: snipe <snipe@snipe.net>
2024-09-17 22:16:41 +01:00
snipe 7c85ad54eb Sort by numeric columns for numeric custom fields
Signed-off-by: snipe <snipe@snipe.net>
2024-09-17 19:44:03 +01:00
snipe 83b4bf9cf8 Merge remote-tracking branch 'origin/develop' 2024-09-17 15:54:53 +01:00
snipe 6c996b7759 Merge pull request #15516 from snipe/fixes/fmcs_edit_user
Fixed check for outside assets on user update validation
2024-09-17 15:54:11 +01:00
snipe 9e957baeb5 Fixed check for outside assets on user update validation
Signed-off-by: snipe <snipe@snipe.net>
2024-09-17 15:46:45 +01:00
Marcus Moore 3519a82ddd Fix name: TestsFullMultipleCompaniesSupport 2024-09-16 16:55:20 -07:00
Marcus Moore a629df07bf Implement interfaces on existing test classes 2024-09-16 14:49:08 -07:00
Marcus Moore 9a13fcab23 Pluralize 2024-09-16 14:38:38 -07:00
Marcus Moore f5705a1dde More unification 2024-09-16 14:34:55 -07:00
Marcus Moore f325c4afdb Unify assertion method 2024-09-16 14:32:38 -07:00
Marcus Moore 1fddacd7d0 Re-order test methods 2024-09-16 14:25:11 -07:00
Marcus Moore 4af893df61 Improve assertions 2024-09-16 14:20:24 -07:00
Marcus Moore b8b3f91ce4 Formatting 2024-09-16 13:55:18 -07:00
Marcus Moore 7f40f55343 Add tests for delete supplier endpoint 2024-09-16 13:52:02 -07:00
Marcus Moore b06e8d442d Add tests for delete status label endpoint 2024-09-16 13:37:08 -07:00
Marcus Moore c269184c60 Add tests for delete predefined kit endpoint 2024-09-16 13:29:41 -07:00
Marcus Moore 53c673dee2 Add tests for delete manufacturer endpoint 2024-09-16 13:13:12 -07:00
Marcus Moore 50730fc4fb Add tests for delete location endpoint 2024-09-16 12:37:18 -07:00
Marcus Moore 60a54cee79 Add tests for delete license endpoint 2024-09-16 12:33:30 -07:00
Marcus Moore 446e962a50 Add tests for delete group endpoint 2024-09-16 10:38:51 -07:00
Marcus Moore 79a4bb7316 Add tests for delete depreciation endpoint 2024-09-16 10:35:44 -07:00
Marcus Moore 2f76c1bc5b Add assertion 2024-09-16 10:33:21 -07:00
Marcus Moore 38b9f4a438 Add tests for delete departments endpoint 2024-09-16 10:29:20 -07:00
snipe fe5fc6e0ce Merge pull request #15471 from Godmartinz/Edit_side-panel
Fixes margin for the sidebar menus while using rtl languages
2024-09-16 15:56:31 +01:00
snipe 62747a0090 Merge pull request #15493 from Godmartinz/fix_consumables_media_sizing
Fixed misalignment of consumables with smaller media
2024-09-16 15:02:55 +01:00
snipe 9ff2111055 Merge remote-tracking branch 'origin/develop' 2024-09-16 14:52:48 +01:00
snipe b465cc98d8 Merge pull request #15510 from snipe/bulk_users_locale_fix
Fixed #15504 - allow nulling/not changing locale in user bulk edit
2024-09-16 14:45:06 +01:00
snipe 4debaaea39 Fixed #15504 - allow nulling/not changing locale in user bulk edit
Signed-off-by: snipe <snipe@snipe.net>
2024-09-16 14:31:10 +01:00
snipe 1328366a48 Merge remote-tracking branch 'origin/develop' 2024-09-16 12:38:56 +01:00
setpill 4facc4007e feat: Explicitly request LDAP attributes during sync 2024-09-13 17:05:48 +02:00
setpill 31da47e046 refactor: Put LDAP attribute mapping in array 2024-09-13 17:05:28 +02:00
Marcus Moore 3105f53aff Add tests for delete custom fieldsets endpoint 2024-09-12 16:54:29 -07:00
Marcus Moore 2047cfed09 Add tests for delete custom fields endpoint 2024-09-12 16:20:32 -07:00
Marcus Moore e3268d32df Add tests for delete consumable endpoint 2024-09-12 16:00:02 -07:00
Marcus Moore 6df8b0ac0e Add tests for delete component endpoint 2024-09-12 15:52:07 -07:00
Marcus Moore 910f13c1f7 Add tests for delete companies endpoint 2024-09-12 15:38:30 -07:00
Marcus Moore 8ce2512f55 Add tests for delete category endpoint 2024-09-12 13:54:44 -07:00
Marcus Moore 0ec415d4d0 Clean up 2024-09-12 13:46:22 -07:00
Marcus Moore 2044570e95 Add tests for delete asset model endpoint 2024-09-12 13:39:36 -07:00
Marcus Moore b336c6273d Pluralize test classes 2024-09-12 13:32:42 -07:00
Marcus Moore 5299b3e9f0 Remove code handled by CompanyableChildTrait 2024-09-12 13:29:44 -07:00
Marcus Moore 872b76b45f Add tests for delete asset maintenance endpoint 2024-09-12 13:29:10 -07:00
Marcus Moore 275cf4630e Add tests for delete asset endpoint 2024-09-12 13:16:37 -07:00
Marcus Moore 5c2660bd34 Introduce interface 2024-09-12 13:02:32 -07:00
Marcus Moore c7ae9d9dfa Add tests for delete accessory endpoint 2024-09-12 12:58:47 -07:00
Godfrey M 0bc98e971f refactoring modals with partials and fixing misalignments 2024-09-12 12:26:19 -07:00
snipe 8774da3921 Merge pull request #15492 from snipe/fixes/edit_to_archived_warning
Fix - warn user on changing status to undeployable when editing
2024-09-12 16:08:44 +01:00
Godfrey M c6c5cb73cf fixes consumables positioning with smaller media 2024-09-11 10:49:27 -07:00
snipe a97530367d Fixed tests again
Signed-off-by: snipe <snipe@snipe.net>
2024-09-11 17:29:22 +01:00
snipe 43250ae881 Updated tests
Signed-off-by: snipe <snipe@snipe.net>
2024-09-11 17:04:09 +01:00
snipe 04e96b8f20 Added tests
Signed-off-by: snipe <snipe@snipe.net>
2024-09-11 16:43:41 +01:00
snipe 98323185de Null and warn if editing asset to a non-deployabe state
Signed-off-by: snipe <snipe@snipe.net>
2024-09-11 16:43:33 +01:00
Brady Wetherington 9e5f6d656a Improve multi-asset create when using numeric prefixes to asset_tags 2024-09-11 15:45:01 +01:00
snipe 7e14f8c6d6 Merge remote-tracking branch 'origin/develop' 2024-09-11 12:25:28 +01:00
snipe ab3b655312 Fixed #15483 - show EOL by default
Signed-off-by: snipe <snipe@snipe.net>
2024-09-11 12:25:09 +01:00
snipe 601d8d7e5f Merge pull request #15486 from marcusmoore/fixes/custom-field-values
Fixed a couple bugs in CustomFieldSetDefaultValuesForModel component
2024-09-11 09:46:58 +01:00
Marcus Moore ca01261c1f Merge branch 'develop' into fixes/custom-field-values 2024-09-10 16:05:39 -07:00
Godfrey M 15183c4822 rephrased the ternary <-correctly spelled 2024-09-10 11:05:03 -07:00
snipe fddbdafb99 Fixed conflict
Signed-off-by: snipe <snipe@snipe.net>
2024-09-10 19:03:56 +01:00
snipe a5dbece1a9 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
#	public/css/build/app.css
#	public/css/build/overrides.css
#	public/css/dist/all.css
#	public/mix-manifest.json
2024-09-10 19:00:05 +01:00
snipe 4f0f72b29e Fixed version
Signed-off-by: snipe <snipe@snipe.net>
2024-09-10 18:15:12 +01:00
snipe 4183d1834f Pre-release assets
Signed-off-by: snipe <snipe@snipe.net>
2024-09-10 18:14:03 +01:00
snipe 713bb104ec Merge remote-tracking branch 'origin/develop' 2024-09-10 14:46:15 +01:00
snipe 4998d60f39 Merge pull request #15481 from snipe/localizations/2024-09-10
Updated translations
2024-09-10 14:43:27 +01:00
snipe 7cf30003b6 Updated strings
Signed-off-by: snipe <snipe@snipe.net>
2024-09-10 14:41:08 +01:00
snipe f6bf2d03c4 Merge pull request #15445 from Godmartinz/eula_confusion
Fixed priority for category eula vs default eula
2024-09-10 11:04:58 +01:00
snipe 6f44441a8b Merge pull request #15469 from marcusmoore/accessory_tests
Added UI tests for creating accessories
2024-09-10 11:04:23 +01:00
snipe e7e5dfbdfa Merge pull request #15470 from marcusmoore/company_tests
Added UI tests for creating companies
2024-09-10 11:04:08 +01:00
snipe d62315fbe4 Merge pull request #15472 from marcusmoore/testing/dashboard_counts
Added test for dashboard counts
2024-09-10 11:03:55 +01:00
snipe 7f3f77dec8 Merge pull request #15473 from marcusmoore/testing/accessory_api_tests
Added some permission tests for accessory api endpoints
2024-09-10 11:03:46 +01:00
snipe 82e56c6832 Merge pull request #15474 from marcusmoore/bug/sc-26730
Fixed login success message not being displayed
2024-09-10 09:37:02 +01:00
Marcus Moore 76c9015aa9 Add test case 2024-09-09 16:51:40 -07:00
Marcus Moore 5d5f421294 Add test case 2024-09-09 16:49:43 -07:00
Godfrey M 367f02af86 more partials and includes 2024-09-09 16:34:04 -07:00
Godfrey M 7a1c721eca making modal partials for reuse 2024-09-09 16:22:56 -07:00
Marcus Moore 6423df2133 Merge branch 'develop' into fixes/custom-field-values
# Conflicts:
#	resources/views/livewire/custom-field-set-default-values-for-model.blade.php
2024-09-09 16:07:37 -07:00
Marcus Moore dc6a5bf998 Reflash session so login message is displayed 2024-09-09 14:54:19 -07:00
Marcus Moore 0820dd9da4 Update test names 2024-09-09 14:36:32 -07:00
Marcus Moore aa6ab2df60 Add permission tests for some accessory api endpoints 2024-09-09 14:35:38 -07:00
Marcus Moore 22a2cc0256 Add test for dashboard counts 2024-09-09 13:21:10 -07:00
Godfrey M 57fab0268b made it a terenary 2024-09-09 13:02:25 -07:00
Godfrey M ad5768d8b2 fixes margin for the sidebar using rtl languages 2024-09-09 12:45:11 -07:00
Marcus Moore 35533c39d5 Merge branch 'develop' into company_tests 2024-09-09 12:18:02 -07:00
Marcus Moore de403f6e07 Merge branch 'develop' into accessory_tests 2024-09-09 12:17:53 -07:00
snipe 549dec9f9e Merge pull request #15468 from marcusmoore/coverage
Added coverage commands for Herd users
2024-09-09 20:13:01 +01:00
Marcus Moore d4426e4686 Add simple tests for company creation via UI 2024-09-09 11:03:00 -07:00
snipe b2a6349243 Merge pull request #15465 from snipe/update_city_on_bulk_user_edit
Correctly save user’s city on bulk edit
2024-09-09 10:06:42 +01:00
snipe c5dbc5f6b8 Correctly save user’s city on bulk edit
Signed-off-by: snipe <snipe@snipe.net>
2024-09-09 10:01:07 +01:00
snipe 7f2cae4f26 Merge remote-tracking branch 'origin/develop' 2024-09-09 03:56:05 +01:00
snipe ce97e2a30f Merge pull request #15463 from snipe/consumables_order_by_remaining
Added ability to sort on qty and remaining for consumables
2024-09-09 03:54:28 +01:00
snipe 7d9a0eba04 Added ability to sort on qty and remaining for consumables
Signed-off-by: snipe <snipe@snipe.net>
2024-09-09 03:49:58 +01:00
Marcus Moore 010f66f4c9 Add validation test 2024-09-04 15:48:11 -07:00
Marcus Moore 9c6718b459 Organize 2024-09-04 15:46:35 -07:00
Marcus Moore 9f832a93c9 Ensure user is stored 2024-09-04 15:44:52 -07:00
Marcus Moore 487d88c012 Add some ui tests for accessories 2024-09-04 15:43:01 -07:00
Marcus Moore 0e9f7153c0 Add composer commands for generating coverage reports via Herd 2024-09-04 15:13:45 -07:00
Godfrey M 7c8955b126 revert changes to label view 2024-09-04 12:38:35 -07:00
Godfrey M 20fa4c39f9 adds setEula to support\settings 2024-09-04 12:26:44 -07:00
Godfrey M f04a4a3cf5 adds test 2024-09-04 12:21:49 -07:00
Godfrey M cf07186ae8 gives priority to default eula being checked vs catregory eula 2024-09-03 12:23:23 -07:00
Marcus Moore 51d63d57c6 Hide the "Add default values" checkbox if no fieldset selected 2024-09-03 12:22:43 -07:00
snipe e34f549e4c Merge remote-tracking branch 'origin/develop' 2024-09-02 19:16:23 +01:00
snipe e1fcfc8dc1 Merge pull request #15440 from snipe/fixes/user_api_put_patch
Fixes  #15435 - user api put patch API route regression
2024-09-02 19:14:49 +01:00
snipe 9fe8a866e0 Updated test
Signed-off-by: snipe <snipe@snipe.net>
2024-09-02 19:07:21 +01:00
snipe e8e3060a75 Added tests
Signed-off-by: snipe <snipe@snipe.net>
2024-09-02 18:51:22 +01:00
snipe 6aaf2f623f Removed extra route
Signed-off-by: snipe <snipe@snipe.net>
2024-09-02 18:49:55 +01:00
snipe dfbccf50e8 Added patch/put back into resource routes
Signed-off-by: snipe <snipe@snipe.net>
2024-09-02 18:48:09 +01:00
snipe a8813cca94 Merge remote-tracking branch 'origin/develop' 2024-08-31 13:48:59 +01:00
snipe 13dbf9ee74 Added icon for dept
Signed-off-by: snipe <snipe@snipe.net>
2024-08-31 13:48:42 +01:00
snipe f8bbb7ad9b Merge pull request #15431 from snipe/add_employee_num_to_asset_overview
Added employee number to asset view
2024-08-31 13:47:25 +01:00
snipe 3c7d455ee3 Added employee number to asset view
Signed-off-by: snipe <snipe@snipe.net>
2024-08-31 13:38:38 +01:00
snipe 9fef27a448 Merge remote-tracking branch 'origin/develop' 2024-08-29 21:07:56 +01:00
snipe 12fa505972 Disabmiguate licenses company_id
Signed-off-by: snipe <snipe@snipe.net>
2024-08-29 21:07:30 +01:00
snipe d2b88a5107 Merge remote-tracking branch 'origin/develop' 2024-08-29 21:02:21 +01:00
snipe 4e4930ba62 Check for array
Signed-off-by: snipe <snipe@snipe.net>
2024-08-29 21:01:48 +01:00
snipe 4e35f389df Merge remote-tracking branch 'origin/develop'
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
2024-08-29 20:07:03 +01:00
snipe 76301bc30d Fixed typo
Signed-off-by: snipe <snipe@snipe.net>
2024-08-29 20:05:03 +01:00
snipe 964e105cf9 Merge pull request #15415 from snipe/rules/prevent_company_switch
Validation rules to prevent switching user companies if items are assigned to them
2024-08-29 19:20:03 +01:00
snipe 6fd24c7e14 Merge pull request #15418 from snipe/added_multiple_for_custom_report
Fixed #15416 - Added multiple selects for custom report
2024-08-29 18:55:11 +01:00
snipe 231bc1e2de Updated blade selectors
Signed-off-by: snipe <snipe@snipe.net>
2024-08-29 18:31:34 +01:00
snipe 37d04b7176 Some CSS tweaks for select2
Signed-off-by: snipe <snipe@snipe.net>
2024-08-29 17:52:01 +01:00
snipe e62a802926 Use whereIn instead of where =
Signed-off-by: snipe <snipe@snipe.net>
2024-08-29 17:51:44 +01:00
snipe 69e981364a Made multiple select
Signed-off-by: snipe <snipe@snipe.net>
2024-08-29 17:51:20 +01:00
snipe e5b9d9a28b Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/js/build/app.js
#	public/js/build/vendor.js
#	public/js/dist/all.js
#	public/mix-manifest.json
2024-08-29 15:04:32 +01:00
snipe abb4221539 Validation rules to prevent switchng user companies if assets are assigned
Signed-off-by: snipe <snipe@snipe.net>
2024-08-29 14:55:18 +01:00
snipe e4ebabdaba Merge pull request #15414 from uberbrady/fix_create_user
Use the null-safe property accessor for new-user creation
2024-08-29 14:19:51 +01:00
Brady Wetherington da1e383295 Use the null-safe property accessor for new-user creation 2024-08-29 14:09:23 +01:00
snipe b64ed254e0 Fixed tests
Signed-off-by: snipe <snipe@snipe.net>
2024-08-29 13:49:09 +01:00
snipe ba291edc42 Merge pull request #15412 from uberbrady/ImprovePatchPurchasePrice
Fix [FD-43836] PATCH of purchase_cost for assets for comma as decimal separator
2024-08-29 13:18:52 +01:00
Brady Wetherington ec2ea955d8 Fix PATCH of purchase_cost for assets for comma as decimal separator 2024-08-29 12:35:14 +01:00
snipe c197644ba7 Merge pull request #15284 from spencerrlongg/bug/sc-26584
[Multi-Company] Fixes Users Being Moved With Items Still Assigned
2024-08-29 11:38:15 +01:00
snipe 29b30cc5d3 Merge pull request #15411 from snipe/snyk/upgrade-webpack
Upgraded webpack
2024-08-29 11:29:44 +01:00
snipe 6af27516dc Upgraded webpack
Signed-off-by: snipe <snipe@snipe.net>
2024-08-29 11:29:00 +01:00
snipe a89f17a145 Merge pull request #15410 from snipe/snyk/upgrade-jquery-ui
Updated jquery UI
2024-08-29 11:25:56 +01:00
snipe de0565f5b3 Updated jquery UI
Signed-off-by: snipe <snipe@snipe.net>
2024-08-29 11:24:06 +01:00
snipe 4111ef0d78 Merge remote-tracking branch 'origin/develop' 2024-08-29 11:20:21 +01:00
snipe 68c708bdef Merge pull request #15409 from snipe/fixes-string
Corrected language string
2024-08-29 11:18:34 +01:00
snipe 5581950fee Corrected language string
Signed-off-by: snipe <snipe@snipe.net>
2024-08-29 11:17:17 +01:00
snipe cfa56e2219 Merge remote-tracking branch 'origin/develop' 2024-08-29 11:08:53 +01:00
snipe 58e366a063 Merge pull request #15408 from snipe/redirect-on-print-if-user-invalid
Check that the user exists before trying to print
2024-08-29 11:08:02 +01:00
snipe b06c527767 Check that the user exists before trying to print
Signed-off-by: snipe <snipe@snipe.net>
2024-08-29 11:06:30 +01:00
snipe 7f1dfcc935 Merge remote-tracking branch 'origin/develop' 2024-08-28 14:29:06 +01:00
snipe 26f28a862a Merge pull request #15404 from snipe/bug/sc-26717-model-delete
Set image to null if model is deleted
2024-08-28 14:26:03 +01:00
snipe 94c981e22c Set image to null if model is deleted
Signed-off-by: snipe <snipe@snipe.net>
2024-08-28 14:23:49 +01:00
snipe 6f3fb21fef Merge remote-tracking branch 'origin/develop' 2024-08-28 12:50:19 +01:00
snipe e8da7e2df2 Merge pull request #15403 from snipe/clean_up_depreciations
Fixed #15392 - filter by depreciation when showing models
2024-08-28 12:46:48 +01:00
snipe d635c86e00 Added tests
Signed-off-by: snipe <snipe@snipe.net>
2024-08-28 12:46:30 +01:00
snipe 406ff6984b Added click to select on models table
Signed-off-by: snipe <snipe@snipe.net>
2024-08-28 12:42:23 +01:00
snipe c6ddc501c5 Filter by depreciation_id
Signed-off-by: snipe <snipe@snipe.net>
2024-08-28 12:40:12 +01:00
snipe 4839181beb Added counts to API
Signed-off-by: snipe <snipe@snipe.net>
2024-08-28 12:40:01 +01:00
snipe 63a05c89a7 Added counts to show method
Signed-off-by: snipe <snipe@snipe.net>
2024-08-28 12:39:52 +01:00
snipe 385c4f69f7 Added counts to depreciation transformer
Signed-off-by: snipe <snipe@snipe.net>
2024-08-28 12:39:43 +01:00
snipe 486cd8c8c9 Nicer formatting for searchableAttributes
Signed-off-by: snipe <snipe@snipe.net>
2024-08-28 12:39:09 +01:00
snipe eb5d93b3c2 Added assets relationship
Signed-off-by: snipe <snipe@snipe.net>
2024-08-28 12:38:55 +01:00
snipe a5ff623484 Added asset, license, model count to API
Signed-off-by: snipe <snipe@snipe.net>
2024-08-28 12:38:43 +01:00
snipe b5a4389815 Added badge count, fixed model bulk edit menu
Signed-off-by: snipe <snipe@snipe.net>
2024-08-28 12:38:31 +01:00
snipe 7b5b559baa Merge pull request #15401 from snipe/fixes-15397-new-window-for-label
Opens label new window
2024-08-28 11:57:29 +01:00
snipe 67a9929745 Opens label new window
Signed-off-by: snipe <snipe@snipe.net>
2024-08-28 11:56:54 +01:00
snipe a48e79a1fc Merge remote-tracking branch 'origin/develop' 2024-08-27 07:37:53 +01:00
snipe 64c4433b98 Merge pull request #15396 from snipe/add_start_end_date_to_users_edit
Added `start_date` and `end_date` to user bulk edit
2024-08-27 07:36:37 +01:00
snipe 22bc088f6f Added start_date and end_date to user bulk edit
Signed-off-by: snipe <snipe@snipe.net>
2024-08-27 07:21:19 +01:00
snipe d3e8e06638 Add @swift2512 as a contributor 2024-08-26 14:07:06 +01:00
snipe c207d48430 Merge remote-tracking branch 'origin/develop' 2024-08-26 14:01:38 +01:00
snipe 1b933f7add Added s to fa icons
Signed-off-by: snipe <snipe@snipe.net>
2024-08-26 13:47:17 +01:00
snipe 991e48696a Merge remote-tracking branch 'origin/develop' 2024-08-26 10:26:06 +01:00
snipe 3fe891a05b Removed a few more commas
Signed-off-by: snipe <snipe@snipe.net>
2024-08-26 10:25:27 +01:00
snipe 7974885041 Merge remote-tracking branch 'origin/develop' 2024-08-26 10:24:19 +01:00
snipe f4c5b712f4 Removed colons
Signed-off-by: snipe <snipe@snipe.net>
2024-08-26 10:24:07 +01:00
snipe 4ef85bd529 Merge remote-tracking branch 'origin/develop' 2024-08-23 17:58:08 +01:00
snipe 4c8dc7818d Merge pull request #15389 from snipe/added_generate_label_to_button_stack
Fixed #15388 - Moved generate label  button
2024-08-23 17:57:00 +01:00
snipe 5c43a1f87c Use proper style for buttons
Signed-off-by: snipe <snipe@snipe.net>
2024-08-23 17:54:49 +01:00
snipe d3b265de8e Moved button on hardware
Signed-off-by: snipe <snipe@snipe.net>
2024-08-23 17:48:36 +01:00
snipe 263151658f Moved general label button
Signed-off-by: snipe <snipe@snipe.net>
2024-08-23 17:44:09 +01:00
snipe 6eab83a85a Merge remote-tracking branch 'origin/develop' 2024-08-23 15:22:53 +01:00
snipe aa86e07cd2 Fixed #15385 - small icon tweaks
Signed-off-by: snipe <snipe@snipe.net>
2024-08-23 15:22:39 +01:00
snipe cce1f87da6 Merge remote-tracking branch 'origin/develop' 2024-08-23 15:18:30 +01:00
snipe d92fa5de65 fa-fw on settings icon
Signed-off-by: snipe <snipe@snipe.net>
2024-08-23 15:17:25 +01:00
snipe b460e8dc83 Merge remote-tracking branch 'origin/develop' 2024-08-23 08:42:32 +01:00
snipe c589140ea0 Merge pull request #15383 from snipe/re-adds-checkout-button
Fixed #15378 - Corrected gate on checkin button on asset view
2024-08-23 08:42:04 +01:00
snipe 52894615ce More specific gate for checkin
Signed-off-by: snipe <snipe@snipe.net>
2024-08-23 08:40:41 +01:00
snipe 8546bbdd65 Fixed gate for checkout button
Signed-off-by: snipe <snipe@snipe.net>
2024-08-23 08:38:47 +01:00
snipe 50cb7e65c9 Merge remote-tracking branch 'origin/develop' 2024-08-23 07:32:39 +01:00
snipe cc2c8f76d0 Merge pull request #15375 from Godmartinz/fix-acceptance-reminder-command
Fixes the `acceptance-reminder` command
2024-08-23 07:31:29 +01:00
snipe 1ffa69c43c Merge pull request #15380 from snipe/fixed/fixed_nav_bracket
Added pull-right to angle bracket
2024-08-23 07:28:20 +01:00
snipe f85ebd7ffd Added pull-right to angle bracket
Signed-off-by: snipe <snipe@snipe.net>
2024-08-23 07:27:39 +01:00
snipe 78d355f136 Merge pull request #15377 from marcusmoore/fixes/custom-field-values-on-validation-error
Fixed custom field defaults being prematurely updated
2024-08-23 07:20:23 +01:00
snipe ec0346e4a8 Add @setpill as a contributor 2024-08-23 07:19:08 +01:00
snipe fc5eb37776 Merge pull request #15379 from setpill/fix/load-trustproxies-middleware
fixed #15374: load TrustProxies middleware in Kernel.php
2024-08-23 07:18:41 +01:00
Marcus Moore 9a73311a99 Fix nested checkboxes being updated as a group 2024-08-22 17:04:04 -07:00
Marcus Moore aec781e7df Be a little more explicit 2024-08-22 16:03:30 -07:00
setpill 1d7853cbfe fixed #15374: load TrustProxies middleware in Kernel.php 2024-08-22 23:41:27 +02:00
Marcus Moore 7f3c86165b Conditionally disable Add default values checkbox 2024-08-22 13:58:31 -07:00
Marcus Moore 10b45812c4 Improve id for checkboxes and radio buttons 2024-08-22 13:38:01 -07:00
Marcus Moore c3165717ed Handle old input 2024-08-22 13:20:04 -07:00
Marcus Moore d0a351a132 Add comment 2024-08-22 12:59:03 -07:00
Marcus Moore 68749e7e87 Simplify logic 2024-08-22 12:58:35 -07:00
Marcus Moore 0abb5637e0 WIP: handle old input 2024-08-22 12:54:54 -07:00
Marcus Moore af0a95be12 Simplify assertions 2024-08-22 10:18:23 -07:00
Marcus Moore d67975cb62 Implement fix 2024-08-22 10:18:23 -07:00
Marcus Moore 663b2fd844 Add test case 2024-08-22 10:18:23 -07:00
Marcus Moore bcace9d019 Point test to correct endpoint 2024-08-22 10:18:23 -07:00
Marcus Moore b59bf3e7dc Add failing test 2024-08-22 10:18:23 -07:00
Godfrey M 3957d670d0 fixes send acceptance reminder query 2024-08-22 10:04:46 -07:00
snipe 821dd158d1 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/css/build/app.css
#	public/css/build/overrides.css
#	public/css/dist/all.css
#	public/js/build/app.js
#	public/js/dist/all.js
#	public/mix-manifest.json
2024-08-22 15:50:20 +01:00
snipe 833dace2b4 Merge pull request #15373 from snipe/fixes/#15366_custom_fields
Fixed #15366 use the non-admin edit encrypted custom fields permissions
2024-08-22 15:00:16 +01:00
snipe 56e31d2303 Fixed #15366 - use permission for encrypted custom fields
Signed-off-by: snipe <snipe@snipe.net>
2024-08-22 14:58:09 +01:00
snipe ec365b0804 Merge pull request #15372 from StarlessNights/update-docker-compose-files
Fixed #15371: docker-compose files updated.
2024-08-22 14:49:13 +01:00
Iisakki Jaakkola aef0ac68c3 Need to use the long format for redis too in docker-compose file. 2024-08-22 16:10:00 +03:00
Iisakki Jaakkola f12f9a816f Update the official docker-compose file too while at it. 2024-08-22 15:47:12 +03:00
Iisakki Jaakkola a000d6454f Fix non-functional development docker-compose file. 2024-08-22 15:46:40 +03:00
snipe ca8864c061 Fixed small layout quirks in asset view
Signed-off-by: snipe <snipe@snipe.net>
2024-08-22 13:28:52 +01:00
snipe 423f4f9126 Merge pull request #14667 from Godmartinz/add_location_to_create_user_via_asset
Adds location select to the create new user via asset checkout
2024-08-22 13:25:41 +01:00
snipe 456c7d8d91 Merge pull request #15065 from Godmartinz/explicit_eol_removal_command
Adds `snipeit:remove-explicit-eols` command
2024-08-22 13:20:56 +01:00
snipe 54cfe3f6e6 Merge pull request #15156 from uberbrady/re-add-stalebot
Re-add stalebot-esque github Action
2024-08-22 13:20:10 +01:00
snipe 5e0b18104d Merge pull request #15369 from snipe/fixes/checkbox_on_restore
Fixed checkbox layout on modal from #15296
2024-08-22 12:59:20 +01:00
snipe 8b5d3f7fbd Fixed extra closing p tag
Signed-off-by: snipe <snipe@snipe.net>
2024-08-22 12:56:32 +01:00
snipe 744f43676d Fixed checkbox layout on modal from #15296
Signed-off-by: snipe <snipe@snipe.net>
2024-08-22 12:53:16 +01:00
snipe ec0b9b198f Merge pull request #15296 from uberbrady/expose_restore_sanitize
Expose the 'sanitize' system for backup restores to the web GUI
2024-08-22 12:43:07 +01:00
snipe 6c9a402685 Updated prod assets
Signed-off-by: snipe <snipe@snipe.net>
2024-08-22 11:20:52 +01:00
snipe 1b310f3a24 Merge remote-tracking branch 'origin/develop'
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
2024-08-22 11:20:42 +01:00
snipe 94300d81d6 Updated dev assets
Signed-off-by: snipe <snipe@snipe.net>
2024-08-22 11:19:32 +01:00
snipe bc9ea5a2ec Merge pull request #15352 from Godmartinz/mobile_breakpoint
Fixed Mobile misalignment of info on Assets and Users view pages
2024-08-22 11:18:06 +01:00
snipe 4635a6efc3 Merge pull request #15360 from snipe/more_print_fixes
More print fixes for asset view
2024-08-22 11:17:49 +01:00
snipe 9608414eae Merge pull request #15367 from snipe/fixes/15344_added_freeform_to_country_select2
Fixed #15344 - make select2 for countries freeform-ish
2024-08-22 11:06:13 +01:00
snipe 5efddf6f5b Allow clear on country dropdown
Signed-off-by: snipe <snipe@snipe.net>
2024-08-22 11:01:39 +01:00
snipe 305dc049a4 Added asterisk help text
Signed-off-by: snipe <snipe@snipe.net>
2024-08-22 11:01:28 +01:00
snipe 3ac0702094 Fixed #15344 - make select2 for countries freeform-ish
Signed-off-by: snipe <snipe@snipe.net>
2024-08-22 10:13:22 +01:00
snipe 47d8e2f8b9 Add @Scarzy as a contributor 2024-08-22 09:42:05 +01:00
Marcus Moore a2246b9645 Simplify assertions 2024-08-21 17:00:32 -07:00
Marcus Moore 1d89759706 Implement fix 2024-08-21 16:59:44 -07:00
Marcus Moore 206f8fe605 Add test case 2024-08-21 16:59:38 -07:00
Marcus Moore 21d2217619 Point test to correct endpoint 2024-08-21 16:54:16 -07:00
Marcus Moore 833bcb282f Add failing test 2024-08-21 16:49:29 -07:00
snipe 83dd9ce20e Merge pull request #15362 from r-xyz/model-files-api
Added #9413: AssetModel files endpoints to API
2024-08-21 23:15:24 +01:00
r-xyz a8eb76fd8d Fixed model files API routes. 2024-08-21 22:25:41 +02:00
r-xyz cd7db5c4a8 Fix some typos in models file handler. 2024-08-21 22:24:08 +02:00
r-xyz da7313bc9d Fix models files API routes. 2024-08-21 20:24:22 +02:00
r-xyz 4ec361c718 Add AssetModel files endpoints to API 2024-08-21 19:49:51 +02:00
Brady Wetherington 738ef442fd Rename .env var to have DB_ prefix for sanitize-by-default setting 2024-08-21 13:16:51 +01:00
snipe d29b3bfb9a Few more hidden-print classes
Signed-off-by: snipe <snipe@snipe.net>
2024-08-21 13:06:16 +01:00
snipe 6fdce3c536 Merge pull request #15358 from r-xyz/rename-docker-startup
Renamed  docker startup scripts coherently.
2024-08-21 13:02:50 +01:00
snipe 912bbf0e32 More print fixes
Signed-off-by: snipe <snipe@snipe.net>
2024-08-21 13:02:21 +01:00
snipe c54bff0f83 Merge remote-tracking branch 'origin/develop' 2024-08-21 12:24:13 +01:00
snipe 01c4fe6113 Merge pull request #15359 from uberbrady/improve_windows_upgrade
Fixed #15190 - Improvements to upgrade.php script to improve Windows experience
2024-08-21 12:12:23 +01:00
Brady Wetherington 0fa9f57971 Improvements to upgrade.php script to improve Windows experience 2024-08-21 11:53:38 +01:00
r-xyz 1ab29ec3a4 Rename docker startup scripts coherently. 2024-08-21 11:52:09 +02:00
snipe 7e475a0786 Merge pull request #15357 from snipe/tighten_category_view_translations
Fixed #15330 - Cleaned up category title
2024-08-21 10:41:17 +01:00
snipe 26b3c62ab8 Cleaned up category title
Signed-off-by: snipe <snipe@snipe.net>
2024-08-21 10:29:51 +01:00
snipe d3f30ced94 Merge remote-tracking branch 'origin/develop' 2024-08-21 10:13:57 +01:00
snipe d0acf5b8a6 Merge pull request #15356 from snipe/validate_location_parent
Fixed #15341 - validate parent ID
2024-08-21 10:12:58 +01:00
snipe 74fbc23823 Updated tests
Signed-off-by: snipe <snipe@snipe.net>
2024-08-21 10:09:35 +01:00
snipe a23dee52f2 Added tests
Signed-off-by: snipe <snipe@snipe.net>
2024-08-21 09:58:47 +01:00
snipe 4d03f1e110 Fixed #15341 - validate parent ID
Signed-off-by: snipe <snipe@snipe.net>
2024-08-21 09:46:18 +01:00
Godfrey M 963911f2e1 changed order of info stgack 2024-08-21 00:23:10 -07:00
Marcus Moore 59832126cb Improve comment 2024-08-20 16:52:51 -07:00
Marcus Moore 680cce3ee2 Align indents 2024-08-20 16:42:29 -07:00
Marcus Moore 6c5ec6a16c Get datepicker working 2024-08-20 16:41:24 -07:00
Marcus Moore 5d1f98bf93 Simplify by directly wire:modeling 2024-08-20 15:38:43 -07:00
Godfrey M 9d484077ae missed a file 2024-08-20 14:24:37 -07:00
Godfrey M 9858b0f37f fixes info tab for users and assets 2024-08-20 14:23:55 -07:00
snipe 973e2e5756 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2024-08-20 19:45:53 +01:00
snipe 09033b19a7 Bumped hash
Signed-off-by: snipe <snipe@snipe.net>
2024-08-20 19:44:13 +01:00
snipe 46ed076428 Merge remote-tracking branch 'origin/develop' 2024-08-20 19:42:56 +01:00
snipe 5fdeb9c413 Merge pull request #15351 from snipe/localizations/new_translations_2024-08-20
Updated languages
2024-08-20 19:42:08 +01:00
snipe 22d3734075 Merge pull request #15350 from marcusmoore/icon-component-updates
Fixed icon not rotated and simplified component
2024-08-20 19:34:38 +01:00
Marcus Moore eca6b03f44 Allow id to be rendered 2024-08-20 11:08:53 -07:00
Marcus Moore bbdbec7197 Rely on $attributes behavior rendering passed attributes 2024-08-20 11:00:39 -07:00
snipe 6c450d1338 Updated languages
Signed-off-by: snipe <snipe@snipe.net>
2024-08-20 18:18:17 +01:00
spencerrlongg a8cd1027f3 rm commented code 2024-08-20 11:40:15 -05:00
snipe d3a555ce91 Updated assets
Signed-off-by: snipe <snipe@snipe.net>
2024-08-20 11:49:39 +01:00
snipe 0f8e041809 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/css/build/app.css
#	public/css/build/overrides.css
#	public/css/dist/all.css
#	public/css/dist/bootstrap-table.css
#	public/js/dist/bootstrap-table.js
#	public/mix-manifest.json
2024-08-20 11:49:32 +01:00
snipe d99b306ae9 Merge pull request #15345 from snipe/add_trim_strings_middleware
Added TrimStrings middleware
2024-08-20 11:46:55 +01:00
snipe 74136761df Added TrimStrings middleware
Signed-off-by: snipe <snipe@snipe.net>
2024-08-20 11:45:13 +01:00
snipe f597d64339 Merge pull request #15342 from snipe/snyk/bs-tables
[Snyk] Upgrade bootstrap-table from 1.23.0 to 1.23.2
2024-08-20 10:17:26 +01:00
snipe 0072f1500e [Snyk] Upgrade bootstrap-table from 1.23.0 to 1.23.2
Signed-off-by: snipe <snipe@snipe.net>
2024-08-20 10:16:27 +01:00
snipe 64bed01a91 Merge pull request #15327 from snipe/update_button_style
Update icons to use blade components, standardize button colors and format
2024-08-20 10:13:43 +01:00
snipe f6319e11e7 Added fa-fw to sidebar elements
Signed-off-by: snipe <snipe@snipe.net>
2024-08-20 10:11:27 +01:00
snipe 5d9f988df3 Added fw class to topnav icons
Signed-off-by: snipe <snipe@snipe.net>
2024-08-20 10:01:49 +01:00
snipe f8c72fb0ac Merge pull request #15112 from marcusmoore/livewire-importer-improvements
Improved handling attempted access of deleted files in importer
2024-08-20 09:57:03 +01:00
akemidx 8e1111c681 Merge remote-tracking branch 'upstream/develop' into eol_date_range_for_reports 2024-08-19 19:33:44 -04:00
snipe 886514a25f Merge pull request #15336 from marcusmoore/fixes/remove-displayed-parentheses
Fixed `)` being added to expected asset checkin report email header
2024-08-19 22:46:08 +01:00
Marcus Moore fa765667f2 Merge branch 'develop' into livewire-importer-improvements 2024-08-19 14:41:58 -07:00
Marcus Moore 434bdcd6d4 Add missing parentheses to conditional 2024-08-19 14:31:47 -07:00
snipe be5f3f38f8 Settings pages
Signed-off-by: snipe <snipe@snipe.net>
2024-08-19 14:48:12 +01:00
snipe 08c3a25b39 Little more padding
Signed-off-by: snipe <snipe@snipe.net>
2024-08-19 14:16:57 +01:00
snipe 34cd4b6244 Added links to apple/google maps
Signed-off-by: snipe <snipe@snipe.net>
2024-08-19 14:15:36 +01:00
snipe d89c8682be Reversed location button ordering
Signed-off-by: snipe <snipe@snipe.net>
2024-08-19 13:46:31 +01:00
snipe 6f024849e9 Few more
Signed-off-by: snipe <snipe@snipe.net>
2024-08-19 13:39:24 +01:00
snipe e048f0955f More icons
Signed-off-by: snipe <snipe@snipe.net>
2024-08-19 13:27:21 +01:00
snipe 479b2b4fd3 More icons
Signed-off-by: snipe <snipe@snipe.net>
2024-08-19 13:23:08 +01:00
snipe 84f14a05bd Fixed logging for asset model restore
Signed-off-by: snipe <snipe@snipe.net>
2024-08-19 13:20:19 +01:00
snipe 8d52fa51b1 Fixed suppliers buttons
Signed-off-by: snipe <snipe@snipe.net>
2024-08-19 13:20:06 +01:00
snipe 229d8b9bf5 Added location restore
Signed-off-by: snipe <snipe@snipe.net>
2024-08-19 13:19:59 +01:00
snipe eb8d43a804 Updated buttons on models
Signed-off-by: snipe <snipe@snipe.net>
2024-08-19 12:32:44 +01:00
snipe f82266fade Cleaned up presenters
Signed-off-by: snipe <snipe@snipe.net>
2024-08-19 11:58:31 +01:00
snipe b4b6f7a35f Added css-consumable to overrides for table headers
Signed-off-by: snipe <snipe@snipe.net>
2024-08-19 11:58:21 +01:00
snipe 0bc995b87f Updated more icons
Signed-off-by: snipe <snipe@snipe.net>
2024-08-19 11:58:05 +01:00
snipe 59725f2031 Removed extra debugging in test
Signed-off-by: snipe <snipe@snipe.net>
2024-08-19 11:57:40 +01:00
snipe 00bc9ac806 Fixed spacing
Signed-off-by: snipe <snipe@snipe.net>
2024-08-18 22:39:14 +01:00
snipe f200960a57 Aaaand more
Signed-off-by: snipe <snipe@snipe.net>
2024-08-18 22:26:57 +01:00
snipe c700127f1a Updated user view
Signed-off-by: snipe <snipe@snipe.net>
2024-08-18 22:09:00 +01:00
snipe ae2f9571b4 And still more
Signed-off-by: snipe <snipe@snipe.net>
2024-08-18 21:57:37 +01:00
snipe a77dcad336 More links
Signed-off-by: snipe <snipe@snipe.net>
2024-08-18 20:30:53 +01:00
snipe 7ace9324b4 Added padlock sound
Signed-off-by: snipe <snipe@snipe.net>
2024-08-18 20:30:22 +01:00
snipe d2e889e927 Still more
Signed-off-by: snipe <snipe@snipe.net>
2024-08-18 19:21:59 +01:00
snipe 803bdb457c Added calendar
Signed-off-by: snipe <snipe@snipe.net>
2024-08-18 18:48:19 +01:00
snipe 7c9b1f6e38 Added the plus icon
Signed-off-by: snipe <snipe@snipe.net>
2024-08-18 18:39:22 +01:00
snipe d545537a43 More icons
Signed-off-by: snipe <snipe@snipe.net>
2024-08-18 18:34:13 +01:00
snipe 4d8904938d Added calendar icon for datepickers
Signed-off-by: snipe <snipe@snipe.net>
2024-08-18 18:24:26 +01:00
snipe 0c09f2b2c0 Moar icon replacement
Signed-off-by: snipe <snipe@snipe.net>
2024-08-18 18:13:49 +01:00
snipe bffba02511 Updated icons
Signed-off-by: snipe <snipe@snipe.net>
2024-08-18 17:26:44 +01:00
snipe 901f4df7ee Added more icons
Signed-off-by: snipe <snipe@snipe.net>
2024-08-18 17:03:36 +01:00
snipe 9337cba340 Added download
Signed-off-by: snipe <snipe@snipe.net>
2024-08-18 15:53:58 +01:00
snipe 2b0c67c263 Load the icon helper
Signed-off-by: snipe <snipe@snipe.net>
2024-08-18 15:51:00 +01:00
snipe da71f031f5 Use icon in hardware view
Signed-off-by: snipe <snipe@snipe.net>
2024-08-18 15:48:24 +01:00
snipe d2e585baa7 Added icon blade
Signed-off-by: snipe <snipe@snipe.net>
2024-08-18 15:47:45 +01:00
snipe a102c085df Added icon helper
Signed-off-by: snipe <snipe@snipe.net>
2024-08-18 15:47:37 +01:00
snipe e8a22f3c5b Merge remote-tracking branch 'origin/develop' 2024-08-18 04:55:04 +01:00
snipe cb40a82e79 Merge pull request #15324 from snipe/jerk_prevention
Prevent passing an array as login
2024-08-18 04:54:23 +01:00
snipe 4253acad4c Prevent passing an array as login
Signed-off-by: snipe <snipe@snipe.net>
2024-08-18 04:51:36 +01:00
snipe d843cf8dcc Merge remote-tracking branch 'origin/develop' 2024-08-17 00:52:10 +01:00
snipe 7e6ff3cbe6 Removed trailing rows
Signed-off-by: snipe <snipe@snipe.net>
2024-08-17 00:51:19 +01:00
snipe 1013dcae61 Merge remote-tracking branch 'origin/develop' 2024-08-17 00:38:44 +01:00
snipe e7ef3bf515 Merge pull request #15322 from snipe/importer_model_fixes
Importer model fixes
2024-08-17 00:37:37 +01:00
snipe a25efe53aa Removed some debugging
Signed-off-by: snipe <snipe@snipe.net>
2024-08-17 00:35:42 +01:00
snipe de059a715a Cleaner test CSV
Signed-off-by: snipe <snipe@snipe.net>
2024-08-17 00:30:49 +01:00
snipe 318aff1ef0 Fixed behavior for null model numbers
Signed-off-by: snipe <snipe@snipe.net>
2024-08-17 00:27:44 +01:00
snipe e96b9b2f4f Added test for models with same name but no model number
Signed-off-by: snipe <snipe@snipe.net>
2024-08-16 23:04:11 +01:00
snipe 3ae4a5caf0 Removed debugging
Signed-off-by: snipe <snipe@snipe.net>
2024-08-16 22:53:27 +01:00
snipe 559f0d2f90 Added string
Signed-off-by: snipe <snipe@snipe.net>
2024-08-16 22:53:21 +01:00
snipe 9b6a36c8aa Removed unusued parameter
Signed-off-by: snipe <snipe@snipe.net>
2024-08-16 22:45:57 +01:00
snipe 1a4aebf805 Added TwoColumnUniqueUndeletedTrait trait
Signed-off-by: snipe <snipe@snipe.net>
2024-08-16 22:45:47 +01:00
snipe 6ad7100aa3 Removed unused use statements
Signed-off-by: snipe <snipe@snipe.net>
2024-08-16 22:45:17 +01:00
snipe 5529669884 Added tests
Signed-off-by: snipe <snipe@snipe.net>
2024-08-16 22:44:03 +01:00
snipe b57283d8d1 Removed commented code
Signed-off-by: snipe <snipe@snipe.net>
2024-08-16 22:43:56 +01:00
snipe 7658f7c41d First shot
Signed-off-by: snipe <snipe@snipe.net>
2024-08-16 20:29:53 +01:00
spencerrlongg 70e5e0f9df get rid of dd 2024-08-16 12:52:06 -05:00
spencerrlongg dec4691c73 should be good to go now 2024-08-16 12:50:09 -05:00
snipe 48903b1402 Added Gate Pass Generator link
Signed-off-by: snipe <snipe@snipe.net>
2024-08-16 17:42:42 +01:00
snipe 7376c21f10 Removed dupe link, linked name
Signed-off-by: snipe <snipe@snipe.net>
2024-08-16 17:01:07 +01:00
snipe f921400579 Added link to UnifiSnipeSync
Signed-off-by: snipe <snipe@snipe.net>
2024-08-16 16:55:16 +01:00
snipe c30c649aaa Merge remote-tracking branch 'origin/develop' 2024-08-16 16:44:02 +01:00
snipe ad6d09b6ad Removed default label
Signed-off-by: snipe <snipe@snipe.net>
2024-08-16 16:43:51 +01:00
snipe bb1385369c Merge remote-tracking branch 'origin/develop'
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
2024-08-16 16:18:00 +01:00
snipe 43b338d612 Fixed translation
Signed-off-by: snipe <snipe@snipe.net>
2024-08-16 16:15:58 +01:00
snipe c1caf6088e Prod assets
Signed-off-by: snipe <snipe@snipe.net>
2024-08-16 13:12:13 +01:00
snipe 67655ad84b Dev assets
Signed-off-by: snipe <snipe@snipe.net>
2024-08-16 13:11:33 +01:00
snipe 12dfe71ea8 Merge remote-tracking branch 'origin/develop' 2024-08-16 12:48:42 +01:00
snipe ea2b1b0748 Merge pull request #15318 from snipe/localization/fixed_strings
Corrected some translations
2024-08-16 12:43:06 +01:00
snipe 856c57cb12 Corrected some translations
Signed-off-by: snipe <snipe@snipe.net>
2024-08-16 12:39:59 +01:00
snipe 90584ab803 Merge branch 'develop' of https://github.com/snipe/snipe-it into develop 2024-08-16 11:11:00 +01:00
snipe 184f54a6cd Removed extra spaces
Signed-off-by: snipe <snipe@snipe.net>
2024-08-16 11:10:57 +01:00
snipe f24031b974 Merge pull request #15206 from Godmartinz/dashboard_box_alignment
Fixed dashboard box overflow
2024-08-16 11:10:40 +01:00
snipe 0a7aaa54b6 Merge pull request #15282 from r-xyz/alpine-secrets
Added support for Docker secrets in Standard and alpine image.
2024-08-16 11:08:09 +01:00
snipe ca89268716 Merge remote-tracking branch 'origin/develop' 2024-08-16 11:02:56 +01:00
snipe 3167ee91d1 Added a setting test and validation on settings
Signed-off-by: snipe <snipe@snipe.net>
2024-08-16 10:51:49 +01:00
snipe e8f1190628 Added missing migration from #15314
Signed-off-by: snipe <snipe@snipe.net>
2024-08-16 10:44:28 +01:00
snipe 44f18d210e Remove MBP constraint
Signed-off-by: snipe <snipe@snipe.net>
2024-08-16 10:36:35 +01:00
snipe e8deecc9b4 Removed MBP constraint on model
This was creating a validation error since the name already exists

Signed-off-by: snipe <snipe@snipe.net>
2024-08-16 10:35:42 +01:00
snipe a79fe69bf4 Merge branch 'develop' of https://github.com/snipe/snipe-it into develop 2024-08-16 10:22:16 +01:00
snipe d49c33fbe3 Add @Glukose1 as a contributor 2024-08-16 10:22:05 +01:00
snipe de29c1d8a0 Merge pull request #15314 from Glukose1/features/add_setting_due_for_checkin_in_days
Added #15312: Add checkin due in days setting
2024-08-16 10:21:36 +01:00
snipe f9172594b2 Clearer time example display
Signed-off-by: snipe <snipe@snipe.net>
2024-08-16 10:14:43 +01:00
Marcus Moore 94d8a547b8 Merge branch 'develop' into livewire-importer-improvements 2024-08-15 13:47:49 -07:00
Marcus Moore 43b109fac0 Use cached values for textarea and radio input 2024-08-15 13:20:22 -07:00
Marcus Moore 75c1e7658f Improve method name 2024-08-15 10:43:41 -07:00
Marcus Moore e7c9c799bb Add wire:keys 2024-08-15 10:40:23 -07:00
Marcus Moore 6ab976f353 Use cached values for text input 2024-08-15 10:32:33 -07:00
snipe ec5731353a Merge remote-tracking branch 'origin/develop' 2024-08-15 15:53:52 +01:00
snipe b39a7c6f0c String constraint
Signed-off-by: snipe <snipe@snipe.net>
2024-08-15 15:42:11 +01:00
snipe a3d847151a Model name uniqueness
Signed-off-by: snipe <snipe@snipe.net>
2024-08-15 15:19:27 +01:00
snipe 3283704fe8 Updated assets
Signed-off-by: snipe <snipe@snipe.net>
2024-08-15 12:25:08 +01:00
snipe 540df32046 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
2024-08-15 12:24:59 +01:00
snipe 594f506641 Merge pull request #15305 from snipe/localizations/updated_languages_2024-08-15
Updated translation strings
2024-08-15 12:21:59 +01:00
snipe dd458dfa7f Updated strings
Signed-off-by: snipe <snipe@snipe.net>
2024-08-15 12:21:06 +01:00
snipe b917489f00 Corrected string
Signed-off-by: snipe <snipe@snipe.net>
2024-08-15 12:10:41 +01:00
snipe 75dfedcb82 Merge pull request #15304 from snipe/confetti_fun_mode_redux
Added confetti option
2024-08-15 11:37:34 +01:00
snipe 6216b4fc0d Use native browser control for required in addition to the css effect
Signed-off-by: snipe <snipe@snipe.net>
2024-08-15 11:35:56 +01:00
snipe 4356cb7b9b Added confetti option
Signed-off-by: snipe <snipe@snipe.net>
2024-08-15 11:32:42 +01:00
Glukose1 d8df52cc8f Implemented setting to specify the amount of days before an assets appers in the due for checkin page. Currently this uses the audit warning days but a sperated setting gives the possibility of defineing different values for each field. 2024-08-15 12:20:51 +02:00
spencerrlongg 9622e05cf5 correct api test 2024-08-14 18:41:06 -05:00
spencerrlongg afaf53cdfc failing ui test 2024-08-14 18:14:21 -05:00
spencerrlongg f031309f8f set up api controller for route/model binding 2024-08-14 16:09:15 -05:00
spencerrlongg 20ec420ba3 not quite done, api side needs some work 2024-08-14 13:53:29 -05:00
Marcus Moore ab63a19aff Initialize concept of cached values 2024-08-14 11:01:51 -07:00
spencerrlongg a70b94e707 Merge branch 'refs/heads/develop' into bug/sc-26584 2024-08-14 11:36:19 -05:00
r-xyz 0d7cf55a3a Add support for Docker secrets in Standard and alpine image. 2024-08-14 17:40:52 +02:00
Brady Wetherington 008bf036b5 Got rid of weird namespace declaration and commented-out data-toggle line 2024-08-14 16:09:34 +01:00
Brady Wetherington cc5ad456e6 Expose the 'sanitize' system for backup restores to the web GUI 2024-08-14 15:59:21 +01:00
Marcus Moore 038e86954b Improve property name 2024-08-13 17:30:53 -07:00
Marcus Moore f6c1642bf2 Use computed fields in CustomFieldSetDefaultValuesForModel component 2024-08-13 17:01:35 -07:00
spencerrlongg 120cfd13c5 translation 2024-08-13 14:07:40 -05:00
spencerrlongg 09f2739298 works, un-reassignable licenses are an issue 2024-08-13 13:45:41 -05:00
Godfrey M 5d1c48c071 fixes alignment, and box issue with pie chart 2024-08-13 10:11:49 -07:00
spencerrlongg ec863df007 rm conditional that might be unnecessary 2024-08-12 16:58:53 -05:00
spencerrlongg cc3b8e0681 this should more or less work, but i need to determine if this is the best way 2024-08-12 16:58:21 -05:00
spencerrlongg ff145abbe7 use array for eager loading, makes ide prettier 2024-08-12 16:13:03 -05:00
Marcus Moore 6521c02526 Merge branch 'develop' into livewire-importer-improvements
# Conflicts:
#	resources/views/livewire/importer.blade.php
2024-08-07 15:20:39 -07:00
Godfrey M bc0ff706b0 fixes dashboard box overflow 2024-08-01 10:31:39 -07:00
Brady Wetherington bb465dbfaa Cut down run number to 100 from 1000 2024-07-24 15:09:23 +01:00
Brady Wetherington 8cbcc237c0 Cleanup of Stale workflow for GH - set to debug-mode to start 2024-07-24 13:27:31 +01:00
Brady Wetherington 97e3af8fc9 WIP on new GitHub-backed stalebot settings 2024-07-24 12:33:26 +01:00
Brady Wetherington 914e29210a Initial rough stab at re-implementing stalebot 2024-07-24 12:33:26 +01:00
Marcus Moore 8d1cc22c58 Turn on legacy binding since other components still use it 2024-07-18 12:00:01 -07:00
Marcus Moore 7685de45f2 Turn off legacy binding 2024-07-17 17:12:14 -07:00
Marcus Moore 199e68ff29 Simplify computed propery 2024-07-17 17:10:12 -07:00
Marcus Moore 81bffccf01 Use better error message 2024-07-17 16:28:26 -07:00
Marcus Moore cfca1514c0 Swap file_id for activeFileId 2024-07-17 16:22:44 -07:00
Marcus Moore b4ed01243b Add more details 2024-07-17 13:40:41 -07:00
Marcus Moore 3772a21a51 Move comment up 2024-07-17 13:37:24 -07:00
Marcus Moore 04b6cb763f Add todo 2024-07-17 10:58:48 -07:00
Marcus Moore dd32341502 Display message if attempting to delete non-existent file 2024-07-16 17:21:18 -07:00
Marcus Moore f58e3114a2 Simplify destroy method and update list 2024-07-16 17:17:45 -07:00
Marcus Moore eba494ad8c Make $activeFile a computed property 2024-07-16 17:03:42 -07:00
Marcus Moore 7e89b58746 Move files to computed property 2024-07-16 16:08:42 -07:00
Marcus Moore b7744105a0 Migrate import type to component 2024-07-16 14:20:41 -07:00
Marcus Moore 69263f0e5b Migrate header row to component 2024-07-16 13:30:29 -07:00
Marcus Moore 017530ba4b Make updating hook more specific 2024-07-16 12:02:50 -07:00
Marcus Moore c8dad528a8 Migrate a couple items out of mount 2024-07-15 16:15:58 -07:00
Marcus Moore 256e989ba1 Add test for importer 2024-07-15 15:49:18 -07:00
Marcus Moore 9793016603 Remove unneeded AuthorizesRequests 2024-07-11 13:32:16 -07:00
Marcus Moore 9e06f2d17f Remove commented code 2024-07-11 13:22:10 -07:00
Godfrey M d4d19569ee adds execution timer 2024-07-11 10:52:47 -07:00
Godfrey M 43c7504f89 adds an all option, adds help context for all, seperates logic 2024-07-11 10:03:51 -07:00
Godfrey M 1fa6a763bc updated description 2024-07-10 11:09:57 -07:00
Godfrey M 726308bfd5 removed typo 2024-07-10 10:58:45 -07:00
Godfrey M 22ddb695f2 better description 2024-07-10 10:57:47 -07:00
Godfrey M 09b2feac54 updates assets with selected model to inherit asset model eol 2024-07-10 10:56:44 -07:00
Godfrey M 57e1df86c8 finds model and collects assets with such model 2024-07-10 10:21:24 -07:00
Robert-Azelis 3ea5d4ee40 Update BulkAssetsController.php
Fix for bulk updarte of purchase date to calculate new EOL
2024-05-02 12:55:17 +02:00
Godfrey M 5fa0c87ab0 null debugbar 2024-04-30 12:02:11 -07:00
Godfrey M 75aa01791a adds location select to the create new user vice asset checkout 2024-04-30 11:54:33 -07:00
akemidx 697595d963 Merge branch 'develop' into eol_date_range_for_reports 2023-11-21 16:07:26 -05:00
akemidx 0bdd8a5917 fixing key names 2023-08-02 16:40:38 -04:00
akemidx e35dd2daa1 asset_eol_date stuff 2023-07-26 17:45:18 -04:00
akemidx f71b69a739 adding eol fields 2023-07-26 17:31:06 -04:00
akemidx 499a3debcd this WILL break. i'm back to site not found which is something missing. otherwise the columns are either blank or another value like expected checkin i was using to test a bit 2023-07-11 14:08:55 -04:00
1744 changed files with 281293 additions and 8628 deletions
+36
View File
@@ -3181,6 +3181,42 @@
"contributions": [
"code"
]
},
{
"login": "Glukose1",
"name": "Glukose1",
"avatar_url": "https://avatars.githubusercontent.com/u/167117705?v=4",
"profile": "https://github.com/Glukose1",
"contributions": [
"code"
]
},
{
"login": "Scarzy",
"name": "Scarzy",
"avatar_url": "https://avatars.githubusercontent.com/u/1197791?v=4",
"profile": "https://github.com/Scarzy",
"contributions": [
"code"
]
},
{
"login": "setpill",
"name": "setpill",
"avatar_url": "https://avatars.githubusercontent.com/u/37372069?v=4",
"profile": "https://github.com/setpill",
"contributions": [
"code"
]
},
{
"login": "swift2512",
"name": "swift2512",
"avatar_url": "https://avatars.githubusercontent.com/u/3755203?v=4",
"profile": "https://github.com/swift2512",
"contributions": [
"bug"
]
}
]
}
+2
View File
@@ -1,6 +1,8 @@
# --------------------------------------------
# REQUIRED: DB SETUP
# --------------------------------------------
# https://mariadb.com/kb/en/mariadb-server-docker-official-image-environment-variables/
MYSQL_DATABASE=snipeit
MYSQL_USER=snipeit
MYSQL_PASSWORD=changeme1234
+2
View File
@@ -32,6 +32,8 @@ DB_PREFIX=null
DB_DUMP_PATH='/usr/bin'
DB_CHARSET=utf8mb4
DB_COLLATION=utf8mb4_unicode_ci
DB_SANITIZE_BY_DEFAULT=false
# --------------------------------------------
# OPTIONAL: SSL DATABASE SETTINGS
-43
View File
@@ -1,43 +0,0 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- pinned
- security
- :woman_technologist: ready for dev
- :moneybag: bounty
- :hand: bug
- "🔐 security"
- "👩‍💻 ready for dev"
- "💰 bounty"
- "✋ bug"
exemptMilestones: true
# Label to use when marking an issue as stale
staleLabel: stale
only: issues
# Comment to post when removing the stale label.
unmarkComment: >
Okay, it looks like this issue or feature request might still be important. We'll re-open
it for now. Thank you for letting us know!
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
Is this still relevant? We haven't heard from anyone in a bit. If so,
please comment with any updates or additional detail.
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Don't
take it personally, we just need to keep a handle on things. Thank you
for your contributions!
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: >
This issue has been automatically closed because it has not had
recent activity. If you believe this is still an issue, please confirm that
this issue is still happening in the most recent version of Snipe-IT and reply
to this thread to re-open it.
+40
View File
@@ -0,0 +1,40 @@
name: 'Close stale issues'
on:
schedule:
- cron: '30 1 * * *'
jobs:
stale:
runs-on: ubuntu-latest
permissions:
# contents: write # only for delete-branch option
issues: write
# pull-requests: write
steps:
- uses: actions/stale@v9
with:
debug-only: true
ascending: true
operations-per-run: 1000 # just while we're debugging
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 60
days-before-close: 7
exempt-all-milestones: true
stale-issue-message: >
Is this still relevant? We haven't heard from anyone in a bit. If so,
please comment with any updates or additional detail.
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Don't
take it personally, we just need to keep a handle on things. Thank you
for your contributions!
close-issue-message: >
This issue has been automatically closed because it has not had
recent activity. If you believe this is still an issue, please confirm that
this issue is still happening in the most recent version of Snipe-IT and reply
to this thread to re-open it.
# There doesn't seem to be a 'reopen issue message'?
# Since there is no 'stale-pr-message' - PR's should not be stale'd
stale-issue-label: stale
exempt-issue-labels: >
pinned,security,:woman_technologist: ready for dev,:moneybag: bounty,:hand: bug,🔐 security,👩‍💻 ready for dev,💰 bounty,✋ bug
+1
View File
@@ -47,6 +47,7 @@ storage/private_uploads/users/*
tests/_data/scenarios
tests/_output/*
tests/_support/_generated/*
tests/coverage/*
/npm-debug.log
/storage/oauth-private.key
/storage/oauth-public.key
+1
View File
@@ -52,6 +52,7 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
| [<img src="https://avatars.githubusercontent.com/u/47315739?v=4" width="110px;"/><br /><sub>bilias</sub>](https://github.com/bilias)<br />[💻](https://github.com/snipe/snipe-it/commits?author=bilias "Code") | [<img src="https://avatars.githubusercontent.com/u/2565989?v=4" width="110px;"/><br /><sub>coach1988</sub>](https://github.com/coach1988)<br />[💻](https://github.com/snipe/snipe-it/commits?author=coach1988 "Code") | [<img src="https://avatars.githubusercontent.com/u/11910225?v=4" width="110px;"/><br /><sub>MrM</sub>](https://github.com/mauro-miatello)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mauro-miatello "Code") | [<img src="https://avatars.githubusercontent.com/u/60405354?v=4" width="110px;"/><br /><sub>koiakoia</sub>](https://github.com/koiakoia)<br />[💻](https://github.com/snipe/snipe-it/commits?author=koiakoia "Code") | [<img src="https://avatars.githubusercontent.com/u/5323832?v=4" width="110px;"/><br /><sub>Mustafa Online</sub>](https://github.com/mustafa-online)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mustafa-online "Code") | [<img src="https://avatars.githubusercontent.com/u/104601439?v=4" width="110px;"/><br /><sub>franceslui</sub>](https://github.com/franceslui)<br />[💻](https://github.com/snipe/snipe-it/commits?author=franceslui "Code") | [<img src="https://avatars.githubusercontent.com/u/125313163?v=4" width="110px;"/><br /><sub>Q4kK</sub>](https://github.com/Q4kK)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Q4kK "Code") |
| [<img src="https://avatars.githubusercontent.com/u/55590532?v=4" width="110px;"/><br /><sub>squintfox</sub>](https://github.com/squintfox)<br />[💻](https://github.com/snipe/snipe-it/commits?author=squintfox "Code") | [<img src="https://avatars.githubusercontent.com/u/1380084?v=4" width="110px;"/><br /><sub>Jeff Clay</sub>](https://github.com/jeffclay)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jeffclay "Code") | [<img src="https://avatars.githubusercontent.com/u/52716446?v=4" width="110px;"/><br /><sub>Phil J R</sub>](https://github.com/PP-JN-RL)<br />[💻](https://github.com/snipe/snipe-it/commits?author=PP-JN-RL "Code") | [<img src="https://avatars.githubusercontent.com/u/1496725?v=4" width="110px;"/><br /><sub>i_virus</sub>](https://www.corelight.com/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=chandanchowdhury "Code") | [<img src="https://avatars.githubusercontent.com/u/1020541?v=4" width="110px;"/><br /><sub>Paul Grime</sub>](https://github.com/gitgrimbo)<br />[💻](https://github.com/snipe/snipe-it/commits?author=gitgrimbo "Code") | [<img src="https://avatars.githubusercontent.com/u/922815?v=4" width="110px;"/><br /><sub>Lee Porte</sub>](https://leeporte.co.uk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=LeePorte "Code") | [<img src="https://avatars.githubusercontent.com/u/23613427?v=4" width="110px;"/><br /><sub>BRYAN </sub>](https://github.com/bryanlopezinc)<br />[💻](https://github.com/snipe/snipe-it/commits?author=bryanlopezinc "Code") [⚠️](https://github.com/snipe/snipe-it/commits?author=bryanlopezinc "Tests") |
| [<img src="https://avatars.githubusercontent.com/u/64061710?v=4" width="110px;"/><br /><sub>U-H-T</sub>](https://github.com/U-H-T)<br />[💻](https://github.com/snipe/snipe-it/commits?author=U-H-T "Code") | [<img src="https://avatars.githubusercontent.com/u/5395363?v=4" width="110px;"/><br /><sub>Matt Tyree</sub>](https://github.com/Tyree)<br />[📖](https://github.com/snipe/snipe-it/commits?author=Tyree "Documentation") | [<img src="https://avatars.githubusercontent.com/u/292081?v=4" width="110px;"/><br /><sub>Florent Bervas</sub>](http://spoontux.net)<br />[💻](https://github.com/snipe/snipe-it/commits?author=FlorentDotMe "Code") | [<img src="https://avatars.githubusercontent.com/u/4498077?v=4" width="110px;"/><br /><sub>Daniel Albertsen</sub>](https://ditscheri.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=dbakan "Code") | [<img src="https://avatars.githubusercontent.com/u/100710244?v=4" width="110px;"/><br /><sub>r-xyz</sub>](https://github.com/r-xyz)<br />[💻](https://github.com/snipe/snipe-it/commits?author=r-xyz "Code") | [<img src="https://avatars.githubusercontent.com/u/47491036?v=4" width="110px;"/><br /><sub>Steven Mainor</sub>](https://github.com/DrekiDegga)<br />[💻](https://github.com/snipe/snipe-it/commits?author=DrekiDegga "Code") | [<img src="https://avatars.githubusercontent.com/u/65785975?v=4" width="110px;"/><br /><sub>arne-kroeger</sub>](https://github.com/arne-kroeger)<br />[💻](https://github.com/snipe/snipe-it/commits?author=arne-kroeger "Code") |
| [<img src="https://avatars.githubusercontent.com/u/167117705?v=4" width="110px;"/><br /><sub>Glukose1</sub>](https://github.com/Glukose1)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Glukose1 "Code") | [<img src="https://avatars.githubusercontent.com/u/1197791?v=4" width="110px;"/><br /><sub>Scarzy</sub>](https://github.com/Scarzy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Scarzy "Code") | [<img src="https://avatars.githubusercontent.com/u/37372069?v=4" width="110px;"/><br /><sub>setpill</sub>](https://github.com/setpill)<br />[💻](https://github.com/snipe/snipe-it/commits?author=setpill "Code") | [<img src="https://avatars.githubusercontent.com/u/3755203?v=4" width="110px;"/><br /><sub>swift2512</sub>](https://github.com/swift2512)<br />[🐛](https://github.com/snipe/snipe-it/issues?q=author%3Aswift2512 "Bug reports") |
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
+4 -4
View File
@@ -79,12 +79,12 @@ USER root
VOLUME ["/var/lib/snipeit"]
# Entrypoints
COPY docker/entrypoint_alpine.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
# Startup script
COPY docker/startup_alpine.sh /startup.sh
RUN chmod +x /startup.sh
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["/entrypoint.sh"]
CMD ["/startup.sh"]
EXPOSE 80
+3 -3
View File
@@ -97,7 +97,7 @@ RUN set -eux; \
VOLUME [ "/var/lib/snipeit" ]
COPY --chown=www-data:www-data docker/docker-secrets.env /var/www/html/.env
COPY --chmod=655 docker/docker-entrypoint.sh /usr/local/bin/docker-snipeit-entrypoint
COPY --chmod=655 docker/startup_alpine_fpm.sh /startup.sh
COPY docker/column-statistics.cnf /etc/mysql/conf.d/column-statistics.cnf
ENTRYPOINT [ "/usr/local/bin/docker-snipeit-entrypoint" ]
CMD [ "/usr/local/bin/docker-php-entrypoint", "php-fpm" ]
ENTRYPOINT [ "/startup.sh" ]
CMD [ "/startup.sh", "php-fpm" ]
+4 -3
View File
@@ -72,12 +72,13 @@ Since the release of the JSON REST API, several third-party developers have been
- [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.
- [Snipe-IT Kubernetes Helm Chart](https://github.com/t3n/helm-charts/tree/master/snipeit) - For more information, [click here](https://hub.helm.sh/charts/t3n/snipeit).
- [Snipe-IT Bulk Edit](https://github.com/bricelabelle/snipe-it-bulkedit) - Google Script files to use Google Sheets as a bulk checkout/checkin/edit tool for Snipe-it.
- [MosyleSnipeSync](https://github.com/RodneyLeeBrands/MosyleSnipeSync) by [@Karpadiem](https://github.com/Karpadiem) - Python script to synchronize information between Mosyle and Snipe-IT
- [Snipe-IT Bulk Edit](https://github.com/bricelabelle/snipe-it-bulkedit) - Google Script files to use Google Sheets as a bulk checkout/checkin/edit tool for Snipe-IT.
- [MosyleSnipeSync](https://github.com/RodneyLeeBrands/MosyleSnipeSync) by [@Karpadiem](https://github.com/Karpadiem) - Python script to synchronize information between Mosyle and Snipe-IT.
- [WWW::SnipeIT](https://github.com/SEDC/perl-www-snipeit) by [@SEDC](https://github.com/SEDC) - perl module for accessing the API
- [UniFi to Snipe-IT](https://github.com/RodneyLeeBrands/UnifiSnipeSync) by [@karpadiem](https://github.com/karpadiem) - Python script that synchronizes UniFi devices with Snipe-IT.
- [Kandji2Snipe](https://github.com/grokability/kandji2snipe) by [@briangoldstein](https://github.com/briangoldstein) - Python script that synchronizes Kandji with Snipe-IT.
- [SnipeAgent](https://github.com/ReticentRobot/SnipeAgent) by @ReticentRobot - Windows agent for Snipe-IT
- [SnipeAgent](https://github.com/ReticentRobot/SnipeAgent) by [@ReticentRobot](https://github.com/ReticentRobot) - Windows agent for Snipe-IT.
- [Gate Pass Generator](https://github.com/cha7uraAE/snipe-it-gate-pass-system) by [@cha7uraAE](https://github.com/cha7uraAE) - A Streamlit application for generating gate passes based on hardware data from a Snipe-IT API.
-----
+58 -47
View File
@@ -53,18 +53,22 @@ class LdapSync extends Command
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;
$ldap_result_phone = Setting::getSettings()->ldap_phone_field;
$ldap_result_jobtitle = Setting::getSettings()->ldap_jobtitle;
$ldap_result_country = Setting::getSettings()->ldap_country;
$ldap_result_location = Setting::getSettings()->ldap_location;
$ldap_result_dept = Setting::getSettings()->ldap_dept;
$ldap_result_manager = Setting::getSettings()->ldap_manager;
$ldap_map = [
"username" => Setting::getSettings()->ldap_username_field,
"last_name" => Setting::getSettings()->ldap_lname_field,
"first_name" => Setting::getSettings()->ldap_fname_field,
"active_flag" => Setting::getSettings()->ldap_active_flag,
"emp_num" => Setting::getSettings()->ldap_emp_num,
"email" => Setting::getSettings()->ldap_email,
"phone" => Setting::getSettings()->ldap_phone_field,
"jobtitle" => Setting::getSettings()->ldap_jobtitle,
"country" => Setting::getSettings()->ldap_country,
"location" => Setting::getSettings()->ldap_location,
"dept" => Setting::getSettings()->ldap_dept,
"manager" => Setting::getSettings()->ldap_manager,
];
$ldap_default_group = Setting::getSettings()->ldap_default_group;
$search_base = Setting::getSettings()->ldap_base_dn;
@@ -107,14 +111,21 @@ class LdapSync extends Command
}
/**
* If a filter has been specified, use that
* If a filter has been specified, use that, otherwise default to null
*/
if ($this->option('filter') != '') {
$results = Ldap::findLdapUsers($search_base, -1, $this->option('filter'));
$filter = $this->option('filter');
} else {
$results = Ldap::findLdapUsers($search_base);
$filter = null;
}
/**
* We only need to request the LDAP attributes that we process
*/
$attributes = array_values(array_filter($ldap_map));
$results = Ldap::findLdapUsers($search_base, -1, $filter, $attributes);
} catch (\Exception $e) {
if ($this->option('json_summary')) {
$json_summary = ['error' => true, 'error_message' => $e->getMessage(), 'summary' => []];
@@ -183,17 +194,17 @@ class LdapSync extends Command
}
$usernames = [];
for ($i = 0; $i < $location_users['count']; $i++) {
if (array_key_exists($ldap_result_username, $location_users[$i])) {
if (array_key_exists($ldap_map["username"], $location_users[$i])) {
$location_users[$i]['ldap_location_override'] = true;
$location_users[$i]['location_id'] = $ldap_loc['id'];
$usernames[] = $location_users[$i][$ldap_result_username][0];
$usernames[] = $location_users[$i][$ldap_map["username"]][0];
}
}
// Delete located users from the general group.
foreach ($results as $key => $generic_entry) {
if ((is_array($generic_entry)) && (array_key_exists($ldap_result_username, $generic_entry))) {
if (in_array($generic_entry[$ldap_result_username][0], $usernames)) {
if ((is_array($generic_entry)) && (array_key_exists($ldap_map["username"], $generic_entry))) {
if (in_array($generic_entry[$ldap_map["username"]][0], $usernames)) {
unset($results[$key]);
}
}
@@ -219,22 +230,22 @@ class LdapSync extends Command
for ($i = 0; $i < $results['count']; $i++) {
$item = [];
$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['username'] = $results[$i][$ldap_map["username"]][0] ?? '';
$item['employee_number'] = $results[$i][$ldap_map["emp_num"]][0] ?? '';
$item['lastname'] = $results[$i][$ldap_map["last_name"]][0] ?? '';
$item['firstname'] = $results[$i][$ldap_map["first_name"]][0] ?? '';
$item['email'] = $results[$i][$ldap_map["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] ?? '';
$item['location'] = $results[$i][$ldap_result_location][0] ?? '';
$item['telephone'] = $results[$i][$ldap_map["phone"]][0] ?? '';
$item['jobtitle'] = $results[$i][$ldap_map["jobtitle"]][0] ?? '';
$item['country'] = $results[$i][$ldap_map["country"]][0] ?? '';
$item['department'] = $results[$i][$ldap_map["dept"]][0] ?? '';
$item['manager'] = $results[$i][$ldap_map["manager"]][0] ?? '';
$item['location'] = $results[$i][$ldap_map["location"]][0] ?? '';
// ONLY if you are using the "ldap_location" option *AND* you have an actual result
if ($ldap_result_location && $item['location']) {
if ($ldap_map["location"] && $item['location']) {
$location = Location::firstOrCreate([
'name' => $item['location'],
]);
@@ -257,38 +268,38 @@ class LdapSync extends Command
}
//If a sync option is not filled in on the LDAP settings don't populate the user field
if($ldap_result_username != null){
if($ldap_map["username"] != null){
$user->username = $item['username'];
}
if($ldap_result_last_name != null){
if($ldap_map["last_name"] != null){
$user->last_name = $item['lastname'];
}
if($ldap_result_first_name != null){
if($ldap_map["first_name"] != null){
$user->first_name = $item['firstname'];
}
if($ldap_result_emp_num != null){
if($ldap_map["emp_num"] != null){
$user->employee_num = e($item['employee_number']);
}
if($ldap_result_email != null){
if($ldap_map["email"] != null){
$user->email = $item['email'];
}
if($ldap_result_phone != null){
if($ldap_map["phone"] != null){
$user->phone = $item['telephone'];
}
if($ldap_result_jobtitle != null){
if($ldap_map["jobtitle"] != null){
$user->jobtitle = $item['jobtitle'];
}
if($ldap_result_country != null){
if($ldap_map["country"] != null){
$user->country = $item['country'];
}
if($ldap_result_dept != null){
if($ldap_map["dept"] != null){
$user->department_id = $department->id;
}
if($ldap_result_location != null){
if($ldap_map["location"] != null){
$user->location_id = $location ? $location->id : null;
}
if($ldap_result_manager != null){
if($ldap_map["manager"] != null){
if($item['manager'] != null) {
// Check Cache first
if (isset($manager_cache[$item['manager']])) {
@@ -305,7 +316,7 @@ class LdapSync extends Command
$ldap_manager = [
"count" => 1,
0 => [
$ldap_result_username => [$item['manager']]
$ldap_map["username"] => [$item['manager']]
]
];
}
@@ -314,7 +325,7 @@ class LdapSync extends Command
// Get the Manager's username
// PHP LDAP returns every LDAP attribute as an array, and 90% of the time it's an array of just one item. But, hey, it's an array.
$ldapManagerUsername = $ldap_manager[0][$ldap_result_username][0];
$ldapManagerUsername = $ldap_manager[0][$ldap_map["username"]][0];
// Get User from Manager username.
$ldap_manager = User::where('username', $ldapManagerUsername)->first();
@@ -331,10 +342,10 @@ class LdapSync extends Command
}
// Sync activated state for Active Directory.
if ( !empty($ldap_result_active_flag)) { // IF we have an 'active' flag set....
if ( !empty($ldap_map["active_flag"])) { // IF we have an 'active' flag set....
// ....then *most* things that are truthy will activate the user. Anything falsey will deactivate them.
// (Specifically, we don't handle a value of '0.0' correctly)
$raw_value = @$results[$i][$ldap_result_active_flag][0];
$raw_value = @$results[$i][$ldap_map["active_flag"]][0];
$filter_var = filter_var($raw_value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
$boolean_cast = (bool)$raw_value;
@@ -0,0 +1,60 @@
<?php
namespace App\Console\Commands;
use App\Models\Asset;
use App\Models\AssetModel;
use Illuminate\Console\Command;
class RemoveExplicitEols extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'snipeit:remove-explicit-eols {--model_name= : The name of the asset model to update (use "all" to update all models)}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Removes explicit EOLs on assets with selected model so they may inherit the asset model EOL';
/**
* Execute the console command.
*/
public function handle()
{
$startTime = microtime(true);
if ($this->option('model_name') == 'all') {
$assets = Asset::all();
$this->updateAssets($assets);
} else {
$assetModel = AssetModel::where('name', '=', $this->option('model_name'))->first();
if ($assetModel) {
$assets = Asset::where('model_id', '=', $assetModel->id)->get();
$this->updateAssets($assets);
} else {
$this->error('Asset model not found');
}
}
$endTime = microtime(true);
$executionTime = ($endTime - $startTime);
$this->info('Command executed in ' . round($executionTime, 2) . ' seconds.');
}
private function updateAssets($assets)
{
foreach ($assets as $asset) {
$asset->eol_explicit = 0;
$asset->asset_eol_date = null;
$asset->save();
}
$this->info($assets->count() . ' Assets updated successfully');
}
}
@@ -47,7 +47,8 @@ class SendAcceptanceReminder extends Command
{
$pending = CheckoutAcceptance::pending()->where('checkoutable_type', 'App\Models\Asset')
->whereHas('checkoutable', function($query) {
$query->where('archived', 0);
$query->where('accepted_at', null)
->where('declined_at', null);
})
->with(['assignedTo', 'checkoutable.assignedTo', 'checkoutable.model', 'checkoutable.adminuser'])
->get();
+190
View File
@@ -0,0 +1,190 @@
<?php
namespace App\Helpers;
class IconHelper
{
public static function icon($type) {
switch ($type) {
case 'checkout':
return 'fa-solid fa-rotate-left';
case 'checkin':
return 'fa-solid fa-rotate-right';
case 'edit':
return 'fas fa-pencil-alt';
case 'clone':
return 'far fa-clone';
case 'delete':
return 'fas fa-trash';
case 'create':
return 'fa-solid fa-plus';
case 'audit':
return 'fa-solid fa-clipboard-check';
case '2fa reset':
return 'fa-solid fa-mobile-screen';
case 'new-user':
return 'fa-solid fa-user-plus';
case 'merged-user':
return 'fa-solid fa-people-arrows';
case 'delete-user':
return 'fa-solid fa-user-minus';
case 'update-user':
return 'fa-solid fa-user-pen';
case 'user':
return 'fa-solid fa-user';
case 'users':
return 'fas fa-users';
case 'restore':
return 'fa-solid fa-trash-arrow-up';
case 'external-link':
return 'fa fa-external-link';
case 'email':
return 'fa-regular fa-envelope';
case 'phone':
return 'fa-solid fa-phone';
case 'long-arrow-right':
return 'fas fa-long-arrow-alt-right';
case 'download':
return 'fas fa-download';
case 'checkmark':
return 'fas fa-check icon-white';
case 'x':
return 'fas fa-times';
case 'logout':
return 'fa fa-sign-out';
case 'admin-settings':
return 'fas fa-cogs';
case 'settings':
return 'fas fa-cog';
case 'angle-left':
return 'fas fa-angle-left';
case 'warning':
return 'fas fa-exclamation-triangle';
case 'kits':
return 'fas fa-object-group';
case 'assets':
case 'asset':
return 'fas fa-barcode';
case 'accessories':
case 'accessory':
return 'far fa-keyboard';
case 'components':
case 'component':
return 'far fa-hdd';
case 'consumables':
case 'consumable':
return 'fas fa-tint';
case 'licenses':
case 'license':
return 'far fa-save';
case 'requestable':
return 'fas fa-laptop';
case 'reports':
return 'fas fa-chart-bar';
case 'heart':
return 'fas fa-heart';
case 'circle':
return 'fa-regular fa-circle';
case 'circle-solid':
return 'fa-solid fa-circle';
case 'due':
return 'fas fa-history';
case 'import':
return 'fas fa-cloud-upload-alt';
case 'search':
return 'fas fa-search';
case 'alerts':
return 'far fa-flag';
case 'password':
return 'fa-solid fa-key';
case 'api-key':
return 'fa-solid fa-user-secret';
case 'nav-toggle':
return 'fas fa-bars';
case 'dashboard':
return 'fas fa-tachometer-alt';
case 'info-circle':
return 'fas fa-info-circle';
case 'caret-right':
return 'fa fa-caret-right';
case 'caret-up':
return 'fa fa-caret-up';
case 'caret-down':
return 'fa fa-caret-down';
case 'arrow-circle-right':
return 'fa fa-arrow-circle-right';
case 'minus':
return 'fas fa-minus';
case 'spinner':
return 'fas fa-spinner fa-spin';
case 'copy-clipboard':
return 'fa-regular fa-clipboard';
case 'paperclip':
return 'fas fa-paperclip';
case 'files':
return 'fa-regular fa-file';
case 'more-info':
return 'far fa-life-ring';
case 'calendar':
return 'fas fa-calendar';
case 'plus':
return 'fas fa-plus';
case 'history':
return 'fas fa-history';
case 'more-files':
return 'fa-solid fa-laptop-file';
case 'maintenances':
return 'fas fa-wrench';
case 'seats':
return 'far fa-list-alt';
case 'globe-us':
return 'fas fa-globe-americas';
case 'locked':
return 'fas fa-lock';
case 'unlocked':
return 'fas fa-lock';
case 'locations':
return 'fas fa-map-marker-alt';
case 'location':
return 'fas fa-map-marker-alt';
case 'superadmin':
return 'fas fa-crown';
case 'print':
return 'fa-solid fa-print';
case 'checkin-and-delete':
return 'fa-solid fa-user-xmark';
case 'branding':
return 'fas fa-copyright';
case 'general-settings':
return 'fa-solid fa-list-check';
case 'groups':
return 'fa-solid fa-user-group';
case 'bell':
return 'fa-solid fa-bell';
case 'hashtag':
return 'fa-solid fa-hashtag';
case 'asset-tags':
return 'fas fa-list-ol';
case 'labels':
return 'fas fa-tags';
case 'ldap':
return 'fas fa-sitemap';
case 'google':
return 'fa-brands fa-google';
case 'saml':
return 'fas fa-sign-in-alt';
case 'backups':
return 'fas fa-file-archive';
case 'logins':
return 'fas fa-crosshairs';
case 'oauth':
return 'fas fa-user-secret';
case 'employee_num' :
return 'fa-regular fa-id-card';
case 'department' :
return 'fa-solid fa-building-user';
}
}
}
@@ -73,7 +73,7 @@ class AccessoriesController extends Controller
$accessory->purchase_date = request('purchase_date');
$accessory->purchase_cost = request('purchase_cost');
$accessory->qty = request('qty');
$accessory->user_id = auth()->id();
$accessory->created_by = auth()->id();
$accessory->supplier_id = request('supplier_id');
$accessory->notes = request('notes');
@@ -78,7 +78,7 @@ class AccessoryCheckoutController extends Controller
AccessoryCheckout::create([
'accessory_id' => $accessory->id,
'created_at' => Carbon::now(),
'user_id' => Auth::id(),
'created_by' => auth()->id(),
'assigned_to' => $target->id,
'assigned_type' => $target::class,
'note' => $request->input('note'),
@@ -237,7 +237,11 @@ class AcceptanceController extends Controller
}
$acceptance->accept($sig_filename, $item->getEula(), $pdf_filename, $request->input('note'));
$acceptance->notify(new AcceptanceAssetAcceptedNotification($data));
try {
$acceptance->notify(new AcceptanceAssetAcceptedNotification($data));
} catch (\Exception $e) {
Log::warning($e);
}
event(new CheckoutAccepted($acceptance));
$return_msg = trans('admin/users/message.accepted');
@@ -56,8 +56,9 @@ class AccessoriesController extends Controller
];
$accessories = Accessory::select('accessories.*')->with('category', 'company', 'manufacturer', 'checkouts', 'location', 'supplier')
->withCount('checkouts as checkouts_count');
$accessories = Accessory::select('accessories.*')
->with('category', 'company', 'manufacturer', 'checkouts', 'location', 'supplier', 'adminuser')
->withCount('checkouts as checkouts_count');
if ($request->filled('search')) {
$accessories = $accessories->TextSearch($request->input('search'));
@@ -110,7 +111,10 @@ class AccessoriesController extends Controller
break;
case 'supplier':
$accessories = $accessories->OrderSupplier($order);
break;
break;
case 'created_by':
$accessories = $accessories->OrderByCreatedByName($order);
break;
default:
$accessories = $accessories->orderBy($column_sort, $order);
break;
@@ -287,7 +291,7 @@ class AccessoriesController extends Controller
AccessoryCheckout::create([
'accessory_id' => $accessory->id,
'created_at' => Carbon::now(),
'user_id' => Auth::id(),
'created_by' => auth()->id(),
'assigned_to' => $target->id,
'assigned_type' => $target::class,
'note' => $request->input('note'),
@@ -34,7 +34,7 @@ class AssetMaintenancesController extends Controller
$this->authorize('view', Asset::class);
$maintenances = AssetMaintenance::select('asset_maintenances.*')
->with('asset', 'asset.model', 'asset.location', 'asset.defaultLoc', 'supplier', 'asset.company', 'asset.assetstatus', 'admin');
->with('asset', 'asset.model', 'asset.location', 'asset.defaultLoc', 'supplier', 'asset.company', 'asset.assetstatus', 'adminuser');
if ($request->filled('search')) {
$maintenances = $maintenances->TextSearch($request->input('search'));
@@ -48,6 +48,10 @@ class AssetMaintenancesController extends Controller
$maintenances->where('asset_maintenances.supplier_id', '=', $request->input('supplier_id'));
}
if ($request->filled('created_by')) {
$maintenances->where('asset_maintenances.created_by', '=', $request->input('created_by'));
}
if ($request->filled('asset_maintenance_type')) {
$maintenances->where('asset_maintenance_type', '=', $request->input('asset_maintenance_type'));
}
@@ -69,7 +73,7 @@ class AssetMaintenancesController extends Controller
'asset_tag',
'asset_name',
'serial',
'user_id',
'created_by',
'supplier',
'is_warranty',
'status_label',
@@ -79,8 +83,8 @@ class AssetMaintenancesController extends Controller
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
switch ($sort) {
case 'user_id':
$maintenances = $maintenances->OrderAdmin($order);
case 'created_by':
$maintenances = $maintenances->OrderByCreatedBy($order);
break;
case 'supplier':
$maintenances = $maintenances->OrderBySupplier($order);
@@ -124,7 +128,7 @@ class AssetMaintenancesController extends Controller
// create a new model instance
$maintenance = new AssetMaintenance();
$maintenance->fill($request->all());
$maintenance->user_id = Auth::id();
$maintenance->created_by = auth()->id();
// Was the asset maintenance created?
if ($maintenance->save()) {
@@ -186,11 +190,8 @@ class AssetMaintenancesController extends Controller
{
$this->authorize('update', Asset::class);
// Check if the asset maintenance exists
$assetMaintenance = AssetMaintenance::findOrFail($assetMaintenanceId);
if (! Company::isCurrentUserHasAccess($assetMaintenance->asset)) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot delete a maintenance for that asset'));
}
$assetMaintenance = AssetMaintenance::findOrFail($assetMaintenanceId);
$assetMaintenance->delete();
@@ -0,0 +1,200 @@
<?php
namespace App\Http\Controllers\Api;
use App\Helpers\StorageHelper;
use Illuminate\Support\Facades\Storage;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Models\AssetModel;
use App\Models\Actionlog;
use App\Http\Requests\UploadFileRequest;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
/**
* This class controls file related actions related
* to assets for the Snipe-IT Asset Management application.
*
* Based on the Assets/AssetFilesController by A. Gianotto <snipe@snipe.net>
*
* @version v1.0
* @author [T. Scarsbrook] [<snipe@scarzybrook.co.uk>]
*/
class AssetModelFilesController extends Controller
{
/**
* Accepts a POST to upload a file to the server.
*
* @param \App\Http\Requests\UploadFileRequest $request
* @param int $assetModelId
* @since [v7.0.12]
* @author [r-xyz]
*/
public function store(UploadFileRequest $request, $assetModelId = null) : JsonResponse
{
// Start by checking if the asset being acted upon exists
if (! $assetModel = AssetModel::find($assetModelId)) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.does_not_exist')), 404);
}
// Make sure we are allowed to update this asset
$this->authorize('update', $assetModel);
if ($request->hasFile('file')) {
// If the file storage directory doesn't exist; create it
if (! Storage::exists('private_uploads/assetmodels')) {
Storage::makeDirectory('private_uploads/assetmodels', 775);
}
// Loop over the attached files and add them to the asset
foreach ($request->file('file') as $file) {
$file_name = $request->handleFile('private_uploads/assetmodels/','model-'.$assetModel->id, $file);
$assetModel->logUpload($file_name, e($request->get('notes')));
}
// All done - report success
return response()->json(Helper::formatStandardApiResponse('success', $assetModel, trans('admin/models/message.upload.success')));
}
// We only reach here if no files were included in the POST, so tell the user this
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.upload.nofiles')), 500);
}
/**
* List the files for an asset.
*
* @param int $assetModelId
* @since [v7.0.12]
* @author [r-xyz]
*/
public function list($assetModelId = null) : JsonResponse
{
// Start by checking if the asset being acted upon exists
if (! $assetModel = AssetModel::find($assetModelId)) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.does_not_exist')), 404);
}
// the asset is valid
if (isset($assetModel->id)) {
$this->authorize('view', $assetModel);
// Check that there are some uploads on this asset that can be listed
if ($assetModel->uploads->count() > 0) {
$files = array();
foreach ($assetModel->uploads as $upload) {
array_push($files, $upload);
}
// Give the list of files back to the user
return response()->json(Helper::formatStandardApiResponse('success', $files, trans('admin/models/message.upload.success')));
}
// There are no files.
return response()->json(Helper::formatStandardApiResponse('success', array(), trans('admin/models/message.upload.success')));
}
// Send back an error message
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.download.error')), 500);
}
/**
* Check for permissions and display the file.
*
* @param int $assetModelId
* @param int $fileId
* @return \Illuminate\Http\JsonResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
* @since [v7.0.12]
* @author [r-xyz]
*/
public function show($assetModelId = null, $fileId = null) : JsonResponse | StreamedResponse | Storage | StorageHelper | BinaryFileResponse
{
// Start by checking if the asset being acted upon exists
if (! $assetModel = AssetModel::find($assetModelId)) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.does_not_exist')), 404);
}
// the asset is valid
if (isset($assetModel->id)) {
$this->authorize('view', $assetModel);
// Check that the file being requested exists for the asset
if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $assetModel->id)->find($fileId)) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.download.no_match', ['id' => $fileId])), 404);
}
// Form the full filename with path
$file = 'private_uploads/assetmodels/'.$log->filename;
Log::debug('Checking for '.$file);
if ($log->action_type == 'audit') {
$file = 'private_uploads/audits/'.$log->filename;
}
// Check the file actually exists on the filesystem
if (! Storage::exists($file)) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.download.does_not_exist', ['id' => $fileId])), 404);
}
if (request('inline') == 'true') {
$headers = [
'Content-Disposition' => 'inline',
];
return Storage::download($file, $log->filename, $headers);
}
return StorageHelper::downloader($file);
}
// Send back an error message
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.download.error', ['id' => $fileId])), 500);
}
/**
* Delete the associated file
*
* @param int $assetModelId
* @param int $fileId
* @since [v7.0.12]
* @author [r-xyz]
*/
public function destroy($assetModelId = null, $fileId = null) : JsonResponse
{
// Start by checking if the asset being acted upon exists
if (! $assetModel = AssetModel::find($assetModelId)) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.does_not_exist')), 404);
}
$rel_path = 'private_uploads/assetmodels';
// the asset is valid
if (isset($assetModel->id)) {
$this->authorize('update', $assetModel);
// Check for the file
$log = Actionlog::find($fileId);
if ($log) {
// Check the file actually exists, and delete it
if (Storage::exists($rel_path.'/'.$log->filename)) {
Storage::delete($rel_path.'/'.$log->filename);
}
// Delete the record of the file
$log->delete();
// All deleting done - notify the user of success
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/models/message.deletefile.success')), 200);
}
// The file doesn't seem to really exist, so report an error
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.deletefile.error')), 500);
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.deletefile.error')), 500);
}
}
@@ -48,6 +48,8 @@ class AssetModelsController extends Controller
'assets_count',
'category',
'fieldset',
'deleted_at',
'updated_at',
];
$assetmodels = AssetModel::select([
@@ -67,7 +69,7 @@ class AssetModelsController extends Controller
'models.deleted_at',
'models.updated_at',
])
->with('category', 'depreciation', 'manufacturer', 'fieldset.fields.defaultValues')
->with('category', 'depreciation', 'manufacturer', 'fieldset.fields.defaultValues','adminuser')
->withCount('assets as assets_count');
if ($request->input('status')=='deleted') {
@@ -78,6 +80,10 @@ class AssetModelsController extends Controller
$assetmodels = $assetmodels->where('models.category_id', '=', $request->input('category_id'));
}
if ($request->filled('depreciation_id')) {
$assetmodels = $assetmodels->where('models.depreciation_id', '=', $request->input('depreciation_id'));
}
if ($request->filled('search')) {
$assetmodels->TextSearch($request->input('search'));
}
+47 -10
View File
@@ -56,6 +56,11 @@ class AssetsController extends Controller
public function index(Request $request, $action = null, $upcoming_status = null) : JsonResponse | array
{
// This handles the legacy audit endpoints :(
if ($action == 'audit') {
$action = 'audits';
}
$filter_non_deprecable_assets = false;
/**
@@ -121,7 +126,7 @@ class AssetsController extends Controller
}
$assets = Asset::select('assets.*')
->with('location', 'assetstatus', 'company', 'defaultLoc','assignedTo',
->with('location', 'assetstatus', 'company', 'defaultLoc','assignedTo', 'adminuser','model.depreciation',
'model.category', 'model.manufacturer', 'model.fieldset','supplier'); //it might be tempting to add 'assetlog' here, but don't. It blows up update-heavy users.
@@ -154,8 +159,8 @@ class AssetsController extends Controller
* Handle due and overdue audits and checkin dates
*/
switch ($action) {
case 'audits':
// Audit (singular) is left over from earlier legacy APIs
case 'audits' :
switch ($upcoming_status) {
case 'due':
$assets->DueForAudit($settings);
@@ -371,8 +376,33 @@ class AssetsController extends Controller
case 'assigned_to':
$assets->OrderAssigned($order);
break;
case 'created_by':
$assets->OrderByCreatedByName($order);
break;
default:
$assets->orderBy($column_sort, $order);
$numeric_sort = false;
// Search through the custom fields array to see if we're sorting on a custom field
if (array_search($column_sort, $all_custom_fields->pluck('db_column')->toArray()) !== false) {
// Check to see if this is a numeric field type
foreach ($all_custom_fields as $field) {
if (($field->db_column == $sort_override) && ($field->format == 'NUMERIC')) {
$numeric_sort = true;
break;
}
}
// This may not work for all databases, but it works for MySQL
if ($numeric_sort) {
$assets->orderByRaw($sort_override . ' * 1 ' . $order);
} else {
$assets->orderBy($sort_override, $order);
}
} else {
$assets->orderBy($column_sort, $order);
}
break;
}
@@ -568,7 +598,7 @@ class AssetsController extends Controller
$asset->model()->associate(AssetModel::find((int) $request->get('model_id')));
$asset->fill($request->validated());
$asset->user_id = Auth::id();
$asset->created_by = auth()->id();
/**
* this is here just legacy reasons. Api\AssetController
@@ -602,7 +632,7 @@ class AssetsController extends Controller
if ($field->field_encrypted == '1') {
Log::debug('This model field is encrypted in this fieldset.');
if (Gate::allows('admin')) {
if (Gate::allows('assets.view.encrypted_custom_fields')) {
// If input value is null, use custom field's default value
if (($field_val == null) && ($request->has('model_id') != '')) {
@@ -695,7 +725,7 @@ class AssetsController extends Controller
}
}
if ($field->field_encrypted == '1') {
if (Gate::allows('admin')) {
if (Gate::allows('assets.view.encrypted_custom_fields')) {
$field_val = Crypt::encrypt($field_val);
} else {
$problems_updating_encrypted_custom_fields = true;
@@ -750,9 +780,16 @@ class AssetsController extends Controller
if ($asset = Asset::find($id)) {
$this->authorize('delete', $asset);
DB::table('assets')
->where('id', $asset->id)
->update(['assigned_to' => null]);
if ($asset->assignedTo) {
$target = $asset->assignedTo;
$checkin_at = date('Y-m-d H:i:s');
$originalValues = $asset->getRawOriginal();
event(new CheckoutableCheckedIn($asset, $target, auth()->user(), 'Checkin on delete', $checkin_at, $originalValues));
DB::table('assets')
->where('id', $asset->id)
->update(['assigned_to' => null]);
}
$asset->delete();
@@ -43,6 +43,7 @@ class CategoriesController extends Controller
$categories = Category::select([
'id',
'created_by',
'created_at',
'updated_at',
'name', 'category_type',
@@ -50,8 +51,10 @@ class CategoriesController extends Controller
'eula_text',
'require_acceptance',
'checkin_email',
'image'
])->withCount('accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'licenses as licenses_count');
'image',
])
->with('adminuser')
->withCount('accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'licenses as licenses_count');
/*
@@ -91,13 +94,33 @@ class CategoriesController extends Controller
$categories->where('checkin_email', '=', $request->input('checkin_email'));
}
if ($request->filled('created_by')) {
$categories->where('created_by', '=', $request->input('created_by'));
}
if ($request->filled('created_at')) {
$categories->where('created_at', '=', $request->input('created_at'));
}
if ($request->filled('updated_at')) {
$categories->where('updated_at', '=', $request->input('updated_at'));
}
// Make sure the offset and limit are actually integers and do not exceed system limits
$offset = ($request->input('offset') > $categories->count()) ? $categories->count() : app('api_offset_value');
$limit = app('api_limit_value');
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'assets_count';
$categories->orderBy($sort, $order);
$sort_override = $request->input('sort');
$column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'assets_count';
switch ($sort_override) {
case 'created_by':
$categories = $categories->OrderByCreatedBy($order);
break;
default:
$categories = $categories->orderBy($column_sort, $order);
break;
}
$total = $categories->count();
$categories = $categories->skip($offset)->take($limit)->get();
@@ -42,7 +42,7 @@ class CompaniesController extends Controller
$companies = Company::withCount(['assets as assets_count' => function ($query) {
$query->AssetsForShow();
}])->withCount('licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'users as users_count');
}])->withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'users as users_count');
if ($request->filled('search')) {
$companies->TextSearch($request->input('search'));
@@ -56,17 +56,29 @@ class CompaniesController extends Controller
$companies->where('email', '=', $request->input('email'));
}
if ($request->filled('created_by')) {
$companies->where('created_by', '=', $request->input('created_by'));
}
// Make sure the offset and limit are actually integers and do not exceed system limits
$offset = ($request->input('offset') > $companies->count()) ? $companies->count() : app('api_offset_value');
$limit = app('api_limit_value');
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
$companies->orderBy($sort, $order);
$sort_override = $request->input('sort');
$column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'created_at';
switch ($sort_override) {
case 'created_by':
$companies = $companies->OrderByCreatedBy($order);
break;
default:
$companies = $companies->orderBy($column_sort, $order);
break;
}
$total = $companies->count();
$companies = $companies->skip($offset)->take($limit)->get();
return (new CompaniesTransformer)->transformCompanies($companies, $total);
@@ -47,7 +47,7 @@ class ComponentsController extends Controller
];
$components = Component::select('components.*')
->with('company', 'location', 'category', 'assets', 'supplier');
->with('company', 'location', 'category', 'assets', 'supplier', 'adminuser');
if ($request->filled('search')) {
$components = $components->TextSearch($request->input('search'));
@@ -98,6 +98,9 @@ class ComponentsController extends Controller
case 'supplier':
$components = $components->OrderSupplier($order);
break;
case 'created_by':
$components = $components->OrderByCreatedBy($order);
break;
default:
$components = $components->orderBy($column_sort, $order);
break;
@@ -270,7 +273,7 @@ class ComponentsController extends Controller
'component_id' => $component->id,
'created_at' => Carbon::now(),
'assigned_qty' => $request->get('assigned_qty', 1),
'user_id' => auth()->id(),
'created_by' => auth()->id(),
'asset_id' => $request->get('assigned_to'),
'note' => $request->get('note'),
]);
@@ -86,9 +86,15 @@ class ConsumablesController extends Controller
case 'company':
$consumables = $consumables->OrderCompany($order);
break;
case 'remaining':
$consumables = $consumables->OrderRemaining($order);
break;
case 'supplier':
$consumables = $consumables->OrderSupplier($order);
break;
case 'created_by':
$consumables = $consumables->OrderByCreatedBy($order);
break;
default:
// This array is what determines which fields should be allowed to be sorted on ON the table itself.
// These must match a column on the consumables table directly.
@@ -207,7 +213,7 @@ class ConsumablesController extends Controller
$consumable = Consumable::with(['consumableAssignments'=> function ($query) {
$query->orderBy($query->getModel()->getTable().'.created_at', 'DESC');
},
'consumableAssignments.admin'=> function ($query) {
'consumableAssignments.adminuser'=> function ($query) {
},
'consumableAssignments.user'=> function ($query) {
},
@@ -225,7 +231,8 @@ class ConsumablesController extends Controller
'name' => ($consumable_assignment->user) ? $consumable_assignment->user->present()->nameUrl() : 'Deleted User',
'created_at' => Helper::getFormattedDateObject($consumable_assignment->created_at, 'datetime'),
'note' => ($consumable_assignment->note) ? e($consumable_assignment->note) : null,
'admin' => ($consumable_assignment->admin) ? $consumable_assignment->admin->present()->nameUrl() : null,
'admin' => ($consumable_assignment->adminuser) ? $consumable_assignment->adminuser->present()->nameUrl() : null, // legacy, so we don't change the shape of the response
'created_by' => ($consumable_assignment->adminuser) ? $consumable_assignment->adminuser->present()->nameUrl() : null,
];
}
@@ -274,7 +281,7 @@ class ConsumablesController extends Controller
$consumable->users()->attach($consumable->id,
[
'consumable_id' => $consumable->id,
'user_id' => $user->id,
'created_by' => $user->id,
'assigned_to' => $request->input('assigned_to'),
'note' => $request->input('note'),
]
@@ -97,7 +97,7 @@ class DepartmentsController extends Controller
$department->fill($request->all());
$department = $request->handleImages($department);
$department->user_id = auth()->id();
$department->created_by = auth()->id();
$department->manager_id = ($request->filled('manager_id') ? $request->input('manager_id') : null);
if ($department->save()) {
@@ -20,9 +20,23 @@ class DepreciationsController extends Controller
public function index(Request $request) : JsonResponse | array
{
$this->authorize('view', Depreciation::class);
$allowed_columns = ['id','name','months','depreciation_min', 'depreciation_type','created_at'];
$allowed_columns = [
'id',
'name',
'months',
'depreciation_min',
'depreciation_type',
'created_at',
'assets_count',
'models_count',
'licenses_count',
];
$depreciations = Depreciation::select('id','name','months','depreciation_min','depreciation_type','user_id','created_at','updated_at');
$depreciations = Depreciation::select('id','name','months','depreciation_min','depreciation_type','created_at','updated_at', 'created_by')
->with('adminuser')
->withCount('assets as assets_count')
->withCount('models as models_count')
->withCount('licenses as licenses_count');
if ($request->filled('search')) {
$depreciations = $depreciations->TextSearch($request->input('search'));
@@ -31,10 +45,18 @@ class DepreciationsController extends Controller
// Make sure the offset and limit are actually integers and do not exceed system limits
$offset = ($request->input('offset') > $depreciations->count()) ? $depreciations->count() : app('api_offset_value');
$limit = app('api_limit_value');
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
$depreciations->orderBy($sort, $order);
$sort_override = $request->input('sort');
$column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'created_at';
switch ($sort_override) {
case 'created_by':
$depreciations = $depreciations->OrderByCreatedBy($order);
break;
default:
$depreciations = $depreciations->orderBy($column_sort, $order);
break;
}
$total = $depreciations->count();
$depreciations = $depreciations->skip($offset)->take($limit)->get();
+21 -6
View File
@@ -23,9 +23,8 @@ class GroupsController extends Controller
$this->authorize('superadmin');
$this->authorize('view', Group::class);
$allowed_columns = ['id', 'name', 'created_at', 'users_count'];
$groups = Group::select('id', 'name', 'permissions', 'created_at', 'updated_at', 'created_by')->with('admin')->withCount('users as users_count');
$groups = Group::select('id', 'name', 'permissions', 'created_at', 'updated_at', 'created_by')->with('adminuser')->withCount('users as users_count');
if ($request->filled('search')) {
$groups = $groups->TextSearch($request->input('search'));
@@ -35,13 +34,29 @@ class GroupsController extends Controller
$groups->where('name', '=', $request->input('name'));
}
// Make sure the offset and limit are actually integers and do not exceed system limits
$offset = ($request->input('offset') > $groups->count()) ? $groups->count() : app('api_offset_value');
$limit = app('api_limit_value');
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
$groups->orderBy($sort, $order);
switch ($request->input('sort')) {
case 'created_by':
$groups = $groups->OrderByCreatedBy($order);
break;
default:
// This array is what determines which fields should be allowed to be sorted on ON the table itself.
// These must match a column on the consumables table directly.
$allowed_columns = [
'id',
'name',
'created_at',
'users_count',
];
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
$groups = $groups->orderBy($sort, $order);
break;
}
$total = $groups->count();
$groups = $groups->skip($offset)->take($limit)->get();
@@ -65,7 +65,7 @@ class ImportController extends Controller
ini_set('auto_detect_line_endings', '1');
}
$reader = Reader::createFromFileObject($file->openFile('r')); //file pointer leak?
$reader->setDelimiter(request('delimiter', ','));
try {
$import->header_row = $reader->fetchOne(0);
} catch (JsonEncodingException $e) {
@@ -133,6 +133,7 @@ class ImportController extends Controller
}
$import->filesize = filesize($path.'/'.$file_name);
$import->delimiter = request('delimiter');
$import->save();
$results[] = $import;
@@ -107,7 +107,7 @@ class LicenseSeatsController extends Controller
// attempt to update the license seat
$licenseSeat->fill($request->all());
$licenseSeat->user_id = auth()->id();
$licenseSeat->created_by = auth()->id();
// check if this update is a checkin operation
// 1. are relevant fields touched at all?
@@ -27,7 +27,7 @@ class LicensesController extends Controller
$licenses = License::with('company', 'manufacturer', 'supplier','category', 'adminuser')->withCount('freeSeats as free_seats_count');
if ($request->filled('company_id')) {
$licenses->where('company_id', '=', $request->input('company_id'));
$licenses->where('licenses.company_id', '=', $request->input('company_id'));
}
if ($request->filled('name')) {
@@ -70,8 +70,8 @@ class LicensesController extends Controller
$licenses->where('depreciation_id', '=', $request->input('depreciation_id'));
}
if ($request->filled('user_id')) {
$licenses->where('user_id', '=', $request->input('user_id'));
if ($request->filled('created_by')) {
$licenses->where('created_by', '=', $request->input('created_by'));
}
if (($request->filled('maintained')) && ($request->input('maintained')=='true')) {
@@ -117,7 +117,7 @@ class LicensesController extends Controller
$licenses = $licenses->leftJoin('companies', 'licenses.company_id', '=', 'companies.id')->orderBy('companies.name', $order);
break;
case 'created_by':
$licenses = $licenses->OrderCreatedBy($order);
$licenses = $licenses->OrderByCreatedBy($order);
break;
default:
$allowed_columns =
@@ -182,7 +182,7 @@ class LicensesController extends Controller
public function show($id) : JsonResponse | array
{
$this->authorize('view', License::class);
$license = License::withCount('freeSeats')->findOrFail($id);
$license = License::withCount('freeSeats as free_seats_count')->findOrFail($id);
$license = $license->load('assignedusers', 'licenseSeats.user', 'licenseSeats.asset');
return (new LicensesTransformer)->transformLicense($license);
@@ -220,7 +220,6 @@ class LicensesController extends Controller
*/
public function destroy($id) : JsonResponse
{
//
$license = License::findOrFail($id);
$this->authorize('delete', $license);
@@ -25,11 +25,42 @@ class ManufacturersController extends Controller
public function index(Request $request) : JsonResponse | array
{
$this->authorize('view', Manufacturer::class);
$allowed_columns = ['id', 'name', 'url', 'support_url', 'support_email', 'warranty_lookup_url', 'support_phone', 'created_at', 'updated_at', 'image', 'assets_count', 'consumables_count', 'components_count', 'licenses_count'];
$allowed_columns = [
'id',
'name',
'url',
'support_url',
'support_email',
'warranty_lookup_url',
'support_phone',
'created_at',
'updated_at',
'image',
'assets_count',
'consumables_count',
'components_count',
'licenses_count'
];
$manufacturers = Manufacturer::select(
['id', 'name', 'url', 'support_url', 'warranty_lookup_url', 'support_email', 'support_phone', 'created_at', 'updated_at', 'image', 'deleted_at']
)->withCount('assets as assets_count')->withCount('licenses as licenses_count')->withCount('consumables as consumables_count')->withCount('accessories as accessories_count');
$manufacturers = Manufacturer::select([
'id',
'name',
'url',
'support_url',
'warranty_lookup_url',
'support_email',
'support_phone',
'created_by',
'created_at',
'updated_at',
'image',
'deleted_at',
])
->with('adminuser')
->withCount('assets as assets_count')
->withCount('licenses as licenses_count')
->withCount('consumables as consumables_count')
->withCount('accessories as accessories_count');
if ($request->input('deleted') == 'true') {
$manufacturers->onlyTrashed();
@@ -66,10 +97,18 @@ class ManufacturersController extends Controller
// Make sure the offset and limit are actually integers and do not exceed system limits
$offset = ($request->input('offset') > $manufacturers->count()) ? $manufacturers->count() : app('api_offset_value');
$limit = app('api_limit_value');
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
$manufacturers->orderBy($sort, $order);
$sort_override = $request->input('sort');
$column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'created_at';
switch ($sort_override) {
case 'created_by':
$manufacturers = $manufacturers->OrderByCreatedBy($order);
break;
default:
$manufacturers = $manufacturers->orderBy($column_sort, $order);
break;
}
$total = $manufacturers->count();
$manufacturers = $manufacturers->skip($offset)->take($limit)->get();
@@ -181,7 +220,7 @@ class ManufacturersController extends Controller
$logaction->item_type = Manufacturer::class;
$logaction->item_id = $manufacturer->id;
$logaction->created_at = date('Y-m-d H:i:s');
$logaction->user_id = auth()->id();
$logaction->created_by = auth()->id();
$logaction->logaction('restore');
return response()->json(Helper::formatStandardApiResponse('success', trans('admin/manufacturers/message.restore.success')), 200);
@@ -23,9 +23,8 @@ class PredefinedKitsController extends Controller
public function index(Request $request) : JsonResponse | array
{
$this->authorize('view', PredefinedKit::class);
$allowed_columns = ['id', 'name'];
$kits = PredefinedKit::query();
$kits = PredefinedKit::query()->with('adminuser');
if ($request->filled('search')) {
$kits = $kits->TextSearch($request->input('search'));
@@ -36,8 +35,25 @@ class PredefinedKitsController extends Controller
$limit = app('api_limit_value');
$order = $request->input('order') === 'desc' ? 'desc' : 'asc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'name';
$kits->orderBy($sort, $order);
switch ($request->input('sort')) {
case 'created_by':
$kits = $kits->OrderByCreatedBy($order);
break;
default:
// This array is what determines which fields should be allowed to be sorted on ON the table itself.
// These must match a column on the consumables table directly.
$allowed_columns = [
'id',
'name',
'created_at',
'updated_at',
];
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
$kits = $kits->orderBy($sort, $order);
break;
}
$total = $kits->count();
$kits = $kits->skip($offset)->take($limit)->get();
@@ -246,7 +262,7 @@ class PredefinedKitsController extends Controller
$relation = $kit->models();
if ($relation->find($model_id)) {
return response()->json(Helper::formatStandardApiResponse('error', null, ['model' => 'Model already attached to kit']));
return response()->json(Helper::formatStandardApiResponse('error', null, ['model' => trans('admin/kits/general.model_already_attached')]));
}
$relation->attach($model_id, ['quantity' => $quantity]);
@@ -20,7 +20,7 @@ class ReportsController extends Controller
{
$this->authorize('reports.view');
$actionlogs = Actionlog::with('item', 'user', 'admin', 'target', 'location');
$actionlogs = Actionlog::with('item', 'user', 'adminuser', 'target', 'location');
if ($request->filled('search')) {
$actionlogs = $actionlogs->TextSearch(e($request->input('search')));
@@ -48,8 +48,8 @@ class ReportsController extends Controller
$actionlogs = $actionlogs->where('action_type', '=', $request->input('action_type'))->orderBy('created_at', 'desc');
}
if ($request->filled('user_id')) {
$actionlogs = $actionlogs->where('user_id', '=', $request->input('user_id'));
if ($request->filled('created_by')) {
$actionlogs = $actionlogs->where('created_by', '=', $request->input('created_by'));
}
if ($request->filled('action_source')) {
@@ -68,13 +68,14 @@ class ReportsController extends Controller
'id',
'created_at',
'target_id',
'user_id',
'created_by',
'accept_signature',
'action_type',
'note',
'remote_ip',
'user_agent',
'action_source',
'action_date',
];
@@ -86,8 +87,8 @@ class ReportsController extends Controller
$order = ($request->input('order') == 'asc') ? 'asc' : 'desc';
switch ($request->input('sort')) {
case 'admin':
$actionlogs->OrderAdmin($order);
case 'created_by':
$actionlogs->OrderByCreatedBy($order);
break;
default:
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
@@ -25,9 +25,17 @@ class StatuslabelsController extends Controller
public function index(Request $request) : array
{
$this->authorize('view', Statuslabel::class);
$allowed_columns = ['id', 'name', 'created_at', 'assets_count', 'color', 'notes', 'default_label'];
$allowed_columns = [
'id',
'name',
'created_at',
'assets_count',
'color',
'notes',
'default_label'
];
$statuslabels = Statuslabel::withCount('assets as assets_count');
$statuslabels = Statuslabel::with('adminuser')->withCount('assets as assets_count');
if ($request->filled('search')) {
$statuslabels = $statuslabels->TextSearch($request->input('search'));
@@ -54,10 +62,18 @@ class StatuslabelsController extends Controller
// Make sure the offset and limit are actually integers and do not exceed system limits
$offset = ($request->input('offset') > $statuslabels->count()) ? $statuslabels->count() : app('api_offset_value');
$limit = app('api_limit_value');
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
$statuslabels->orderBy($sort, $order);
$sort_override = $request->input('sort');
$column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'created_at';
switch ($sort_override) {
case 'created_by':
$statuslabels = $statuslabels->OrderByCreatedBy($order);
break;
default:
$statuslabels = $statuslabels->orderBy($column_sort, $order);
break;
}
$total = $statuslabels->count();
$statuslabels = $statuslabels->skip($offset)->take($limit)->get();
+9 -20
View File
@@ -206,6 +206,10 @@ class UsersController extends Controller
$users->where('autoassign_licenses', '=', $request->input('autoassign_licenses'));
}
if ($request->filled('locale')) {
$users = $users->where('users.locale', '=', $request->input('locale'));
}
if (($request->filled('deleted')) && ($request->input('deleted') == 'true')) {
$users = $users->onlyTrashed();
@@ -276,6 +280,7 @@ class UsersController extends Controller
'end_date',
'autoassign_licenses',
'website',
'locale',
];
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'first_name';
@@ -427,13 +432,10 @@ class UsersController extends Controller
* @param \Illuminate\Http\Request $request
* @param int $id
*/
public function update(SaveUserRequest $request, $id) : JsonResponse
public function update(SaveUserRequest $request, User $user): JsonResponse
{
$this->authorize('update', User::class);
if ($user = User::find($id)) {
$this->authorize('update', $user);
/**
@@ -443,12 +445,10 @@ class UsersController extends Controller
*
*/
if ((($id == 1) || ($id == 2)) && (config('app.lock_passwords'))) {
if ((($user->id == 1) || ($user->id == 2)) && (config('app.lock_passwords'))) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'Permission denied. You cannot update user information via API on the demo.'));
}
$user->fill($request->all());
if ($user->id == $request->input('manager_id')) {
@@ -473,16 +473,13 @@ class UsersController extends Controller
$user->permissions = $permissions_array;
}
// Update the location of any assets checked out to this user
Asset::where('assigned_type', User::class)
->where('assigned_to', $user->id)->update(['location_id' => $request->input('location_id', null)]);
app('App\Http\Requests\ImageUploadRequest')->handleImages($user, 600, 'image', 'avatars', 'avatar');
if ($user->save()) {
// Check if the request has groups passed and has a value, AND that the user us a superuser
if (($request->has('groups')) && (auth()->user()->isSuperUser())) {
@@ -496,18 +493,10 @@ class UsersController extends Controller
// Sync the groups since the user is a superuser and the groups pass validation
$user->groups()->sync($request->input('groups'));
}
return response()->json(Helper::formatStandardApiResponse('success', (new UsersTransformer)->transformUser($user), trans('admin/users/message.success.update')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $user->getErrors()));
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found', compact('id'))));
}
/**
@@ -702,7 +691,7 @@ class UsersController extends Controller
$logaction->item_type = User::class;
$logaction->item_id = $user->id;
$logaction->created_at = date('Y-m-d H:i:s');
$logaction->user_id = auth()->id();
$logaction->created_by = auth()->id();
$logaction->logaction('2FA reset');
return response()->json(['message' => trans('admin/settings/general.two_factor_reset_success')], 200);
@@ -752,7 +741,7 @@ class UsersController extends Controller
$logaction->item_type = User::class;
$logaction->item_id = $user->id;
$logaction->created_at = date('Y-m-d H:i:s');
$logaction->user_id = auth()->id();
$logaction->created_by = auth()->id();
$logaction->logaction('restore');
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.success.restored')), 200);
@@ -109,7 +109,7 @@ class AssetMaintenancesController extends Controller
$assetMaintenance->title = $request->input('title');
$assetMaintenance->start_date = $request->input('start_date');
$assetMaintenance->completion_date = $request->input('completion_date');
$assetMaintenance->user_id = Auth::id();
$assetMaintenance->created_by = auth()->id();
if (($assetMaintenance->completion_date !== null)
&& ($assetMaintenance->start_date !== '')
+12 -11
View File
@@ -78,7 +78,7 @@ class AssetModelsController extends Controller
$model->manufacturer_id = $request->input('manufacturer_id');
$model->category_id = $request->input('category_id');
$model->notes = $request->input('notes');
$model->user_id = Auth::id();
$model->created_by = auth()->id();
$model->requestable = $request->has('requestable');
if ($request->input('fieldset_id') != '') {
@@ -151,17 +151,17 @@ class AssetModelsController extends Controller
$model->notes = $request->input('notes');
$model->requestable = $request->input('requestable', '0');
$this->removeCustomFieldsDefaultValues($model);
$model->fieldset_id = $request->input('fieldset_id');
if ($this->shouldAddDefaultValues($request->input())) {
if (!$this->assignCustomFieldsDefaultValues($model, $request->input('default_values'))){
return redirect()->back()->withInput()->with('error', trans('admin/custom_fields/message.fieldset_default_value.error'));
}
}
if ($model->save()) {
$this->removeCustomFieldsDefaultValues($model);
if ($this->shouldAddDefaultValues($request->input())) {
if (!$this->assignCustomFieldsDefaultValues($model, $request->input('default_values'))) {
return redirect()->back()->withInput()->with('error', trans('admin/custom_fields/message.fieldset_default_value.error'));
}
}
if ($model->wasChanged('eol')) {
if ($model->eol > 0) {
$newEol = $model->eol;
@@ -202,6 +202,7 @@ class AssetModelsController extends Controller
if ($model->image) {
try {
Storage::disk('public')->delete('models/'.$model->image);
$model->update(['image' => null]);
} catch (\Exception $e) {
Log::info($e);
}
@@ -233,10 +234,10 @@ class AssetModelsController extends Controller
if ($model->restore()) {
$logaction = new Actionlog();
$logaction->item_type = User::class;
$logaction->item_type = AssetModel::class;
$logaction->item_id = $model->id;
$logaction->created_at = date('Y-m-d H:i:s');
$logaction->user_id = auth()->id();
$logaction->created_by = auth()->id();
$logaction->logaction('restore');
@@ -2,6 +2,7 @@
namespace App\Http\Controllers\Assets;
use App\Events\CheckoutableCheckedIn;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Requests\ImageUploadRequest;
@@ -132,7 +133,7 @@ class AssetsController extends Controller
$asset->model_id = $request->input('model_id');
$asset->order_number = $request->input('order_number');
$asset->notes = $request->input('notes');
$asset->user_id = Auth::id();
$asset->created_by = auth()->id();
$asset->status_id = request('status_id');
$asset->warranty_months = request('warranty_months', null);
$asset->purchase_cost = request('purchase_cost');
@@ -165,7 +166,7 @@ class AssetsController extends Controller
if (($model) && ($model->fieldset)) {
foreach ($model->fieldset->fields as $field) {
if ($field->field_encrypted == '1') {
if (Gate::allows('admin')) {
if (Gate::allows('assets.view.encrypted_custom_fields')) {
if (is_array($request->input($field->db_column))) {
$asset->{$field->db_column} = Crypt::encrypt(implode(', ', $request->input($field->db_column)));
} else {
@@ -328,16 +329,21 @@ class AssetsController extends Controller
}
$asset->supplier_id = $request->input('supplier_id', null);
$asset->expected_checkin = $request->input('expected_checkin', null);
// If the box isn't checked, it's not in the request at all.
$asset->requestable = $request->filled('requestable');
$asset->requestable = $request->input('requestable', 0);
$asset->rtd_location_id = $request->input('rtd_location_id', null);
$asset->byod = $request->input('byod', 0);
$status = Statuslabel::find($asset->status_id);
$status = Statuslabel::find($request->input('status_id'));
if ($status && $status->archived) {
// This is a non-deployable status label - we should check the asset back in.
if (($status && $status->getStatuslabelType() != 'deployable') && ($target = $asset->assignedTo)) {
$originalValues = $asset->getRawOriginal();
$asset->assigned_to = null;
$asset->assigned_type = null;
$asset->accepted = null;
event(new CheckoutableCheckedIn($asset, $target, auth()->user(), 'Checkin on asset update', date('Y-m-d H:i:s'), $originalValues));
}
if ($asset->assigned_to == '') {
@@ -388,7 +394,7 @@ class AssetsController extends Controller
foreach ($model->fieldset->fields as $field) {
if ($field->field_encrypted == '1') {
if (Gate::allows('admin')) {
if (Gate::allows('assets.view.encrypted_custom_fields')) {
if (is_array($request->input($field->db_column))) {
$asset->{$field->db_column} = Crypt::encrypt(implode(', ', $request->input($field->db_column)));
} else {
@@ -422,7 +428,7 @@ class AssetsController extends Controller
* @param int $assetId
* @since [v1.0]
*/
public function destroy($assetId) : RedirectResponse
public function destroy(Request $request, $assetId) : RedirectResponse
{
// Check if the asset exists
if (is_null($asset = Asset::find($assetId))) {
@@ -432,9 +438,17 @@ class AssetsController extends Controller
$this->authorize('delete', $asset);
DB::table('assets')
->where('id', $asset->id)
->update(['assigned_to' => null]);
if ($asset->assignedTo) {
$target = $asset->assignedTo;
$checkin_at = date('Y-m-d H:i:s');
$originalValues = $asset->getRawOriginal();
event(new CheckoutableCheckedIn($asset, $target, auth()->user(), 'Checkin on delete', $checkin_at, $originalValues));
DB::table('assets')
->where('id', $asset->id)
->update(['assigned_to' => null]);
}
if ($asset->image) {
try {
@@ -739,7 +753,7 @@ class AssetsController extends Controller
Actionlog::firstOrCreate([
'item_id' => $asset->id,
'item_type' => Asset::class,
'user_id' => auth()->id(),
'created_by' => auth()->id(),
'note' => 'Checkout imported by '.auth()->user()->present()->fullName().' from history importer',
'target_id' => $item[$asset_tag][$batch_counter]['user_id'],
'target_type' => User::class,
@@ -767,7 +781,7 @@ class AssetsController extends Controller
Actionlog::firstOrCreate([
'item_id' => $item[$asset_tag][$batch_counter]['asset_id'],
'item_type' => Asset::class,
'user_id' => auth()->id(),
'created_by' => auth()->id(),
'note' => 'Checkin imported by '.auth()->user()->present()->fullName().' from history importer',
'target_id' => null,
'created_at' => $checkin_date,
@@ -10,6 +10,7 @@ use App\Models\AssetModel;
use App\Models\Statuslabel;
use App\Models\Setting;
use App\View\Label;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
@@ -271,6 +272,23 @@ class BulkAssetsController extends Controller
$this->conditionallyAddItem($custom_field_column);
}
if (!($asset->eol_explicit)) {
if ($request->filled('model_id')) {
$model = AssetModel::find($request->input('model_id'));
if ($model->eol > 0) {
if ($request->filled('purchase_date')) {
$this->update_array['asset_eol_date'] = Carbon::parse($request->input('purchase_date'))->addMonths($model->eol)->format('Y-m-d');
} else {
$this->update_array['asset_eol_date'] = Carbon::parse($asset->purchase_date)->addMonths($model->eol)->format('Y-m-d');
}
} else {
$this->update_array['asset_eol_date'] = null;
}
} elseif (($request->filled('purchase_date')) && ($asset->model->eol > 0)) {
$this->update_array['asset_eol_date'] = Carbon::parse($request->input('purchase_date'))->addMonths($asset->model->eol)->format('Y-m-d');
}
}
/**
* Blank out fields that were requested to be blanked out via checkbox
*/
@@ -281,6 +299,9 @@ class BulkAssetsController extends Controller
if ($request->input('null_purchase_date')=='1') {
$this->update_array['purchase_date'] = null;
if (!($asset->eol_explicit)) {
$this->update_array['asset_eol_date'] = null;
}
}
if ($request->input('null_expected_checkin_date')=='1') {
@@ -508,8 +508,8 @@ class LoginController extends Controller
protected function validator(array $data)
{
return Validator::make($data, [
'username' => 'required',
'password' => 'required',
'username' => 'required|not_array',
'password' => 'required|not_array',
]);
}
@@ -69,7 +69,7 @@ class CategoriesController extends Controller
$category->use_default_eula = $request->input('use_default_eula', '0');
$category->require_acceptance = $request->input('require_acceptance', '0');
$category->checkin_email = $request->input('checkin_email', '0');
$category->user_id = Auth::id();
$category->created_by = auth()->id();
$category = $request->handleImages($category);
if ($category->save()) {
@@ -60,6 +60,7 @@ final class CompaniesController extends Controller
$company->phone = $request->input('phone');
$company->fax = $request->input('fax');
$company->email = $request->input('email');
$company->created_by = auth()->id();
$company = $request->handleImages($company);
@@ -106,7 +106,7 @@ class ComponentCheckoutController extends Controller
$component->asset_id = $request->input('asset_id');
$component->assets()->attach($component->id, [
'component_id' => $component->id,
'user_id' => auth()->user()->id,
'created_by' => auth()->user()->id,
'created_at' => date('Y-m-d H:i:s'),
'assigned_qty' => $request->input('assigned_qty'),
'asset_id' => $request->input('asset_id'),
@@ -81,7 +81,7 @@ class ComponentsController extends Controller
$component->purchase_date = $request->input('purchase_date', null);
$component->purchase_cost = $request->input('purchase_cost', null);
$component->qty = $request->input('qty');
$component->user_id = Auth::id();
$component->created_by = auth()->id();
$component->notes = $request->input('notes');
$component = $request->handleImages($component);
@@ -95,7 +95,7 @@ class ConsumableCheckoutController extends Controller
for($i = 0; $i < $quantity; $i++){
$consumable->users()->attach($consumable->id, [
'consumable_id' => $consumable->id,
'user_id' => $admin_user->id,
'created_by' => $admin_user->id,
'assigned_to' => e($request->input('assigned_to')),
'note' => $request->input('note'),
]);
@@ -81,7 +81,7 @@ class ConsumablesController extends Controller
$consumable->purchase_date = $request->input('purchase_date');
$consumable->purchase_cost = $request->input('purchase_cost');
$consumable->qty = $request->input('qty');
$consumable->user_id = Auth::id();
$consumable->created_by = auth()->id();
$consumable->notes = $request->input('notes');
@@ -221,7 +221,7 @@ class ConsumablesController extends Controller
$consumable = clone $consumable_to_close;
$consumable->id = null;
$consumable->image = null;
$consumable->user_id = null;
$consumable->created_by = null;
return view('consumables/edit')->with('item', $consumable);
}
@@ -104,7 +104,7 @@ class CustomFieldsController extends Controller
"auto_add_to_fieldsets" => $request->get("auto_add_to_fieldsets", 0),
"show_in_listview" => $request->get("show_in_listview", 0),
"show_in_requestable_list" => $request->get("show_in_requestable_list", 0),
"user_id" => Auth::id()
"user_id" => auth()->id()
]);
@@ -248,7 +248,7 @@ class CustomFieldsController extends Controller
$field->name = trim(e($request->get("name")));
$field->element = e($request->get("element"));
$field->field_values = $request->get("field_values");
$field->user_id = Auth::id();
$field->created_by = auth()->id();
$field->help_text = $request->get("help_text");
$field->show_in_email = $show_in_email;
$field->is_unique = $request->get("is_unique", 0);
@@ -90,7 +90,7 @@ class CustomFieldsetsController extends Controller
$fieldset = new CustomFieldset([
'name' => $request->get('name'),
'user_id' => auth()->id(),
'created_by' => auth()->id(),
]);
$validator = Validator::make($request->all(), $fieldset->rules);
@@ -5,6 +5,7 @@ namespace App\Http\Controllers;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Http\RedirectResponse;
use \Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Session;
/**
@@ -44,6 +45,8 @@ class DashboardController extends Controller
return view('dashboard')->with('asset_stats', $asset_stats)->with('counts', $counts);
} else {
Session::reflash();
// Redirect to the profile page
return redirect()->intended('account/view-assets');
}
@@ -51,7 +51,7 @@ class DepartmentsController extends Controller
$this->authorize('create', Department::class);
$department = new Department;
$department->fill($request->all());
$department->user_id = auth()->id();
$department->created_by = auth()->id();
$department->manager_id = ($request->filled('manager_id') ? $request->input('manager_id') : null);
$department->location_id = ($request->filled('location_id') ? $request->input('location_id') : null);
$department->company_id = ($request->filled('company_id') ? $request->input('company_id') : null);
@@ -61,7 +61,7 @@ class DepreciationsController extends Controller
// Depreciation data
$depreciation->name = $request->input('name');
$depreciation->months = $request->input('months');
$depreciation->user_id = Auth::id();
$depreciation->created_by = auth()->id();
$request->validate([
'depreciation_min' => [
@@ -193,13 +193,20 @@ class DepreciationsController extends Controller
*/
public function show($id) : View | RedirectResponse
{
if (is_null($depreciation = Depreciation::find($id))) {
// Redirect to the blogs management page
return redirect()->route('depreciations.index')->with('error', trans('admin/depreciations/message.does_not_exist'));
}
$depreciation = Depreciation::withCount('assets as assets_count')
->withCount('models as models_count')
->withCount('licenses as licenses_count')
->find($id);
$this->authorize('view', $depreciation);
return view('depreciations/view', compact('depreciation'));
if ($depreciation) {
return view('depreciations/view', compact('depreciation'));
}
return redirect()->route('depreciations.index')->with('error', trans('admin/depreciations/message.does_not_exist'));
}
}
@@ -62,10 +62,10 @@ class CheckoutKitController extends Controller
$checkout_result = $this->kitService->checkout($request, $kit, $user);
if (Arr::has($checkout_result, 'errors') && count($checkout_result['errors']) > 0) {
return redirect()->back()->with('error', trans('general.checkout_error'))->with('error_messages', $checkout_result['errors']);
return redirect()->back()->with('error', trans('admin/kits/general.checkout_error'))->with('error_messages', $checkout_result['errors']);
}
return redirect()->back()->with('success', trans('general.checkout_success'))
return redirect()->back()->with('success', trans('admin/kits/general.checkout_success'))
->with('assets', Arr::get($checkout_result, 'assets', null))
->with('accessories', Arr::get($checkout_result, 'accessories', null))
->with('consumables', Arr::get($checkout_result, 'consumables', null));
@@ -55,6 +55,7 @@ class PredefinedKitsController extends Controller
// Create a new Predefined Kit
$kit = new PredefinedKit;
$kit->name = $request->input('name');
$kit->created_by = auth()->id();
if (! $kit->save()) {
return redirect()->back()->withInput()->withErrors($kit->getErrors());
@@ -77,7 +77,7 @@ class LicenseCheckoutController extends Controller
$this->authorize('checkout', $license);
$licenseSeat = $this->findLicenseSeatToCheckout($license, $seatId);
$licenseSeat->user_id = Auth::id();
$licenseSeat->created_by = auth()->id();
$licenseSeat->notes = $request->input('notes');
@@ -99,7 +99,7 @@ class LicensesController extends Controller
$license->supplier_id = $request->input('supplier_id');
$license->category_id = $request->input('category_id');
$license->termination_date = $request->input('termination_date');
$license->user_id = Auth::id();
$license->created_by = auth()->id();
$license->min_amt = $request->input('min_amt');
session()->put(['redirect_option' => $request->get('redirect_option')]);
+44 -2
View File
@@ -3,6 +3,7 @@
namespace App\Http\Controllers;
use App\Http\Requests\ImageUploadRequest;
use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\Location;
use App\Models\User;
@@ -74,7 +75,7 @@ class LocationsController extends Controller
$location->zip = $request->input('zip');
$location->ldap_ou = $request->input('ldap_ou');
$location->manager_id = $request->input('manager_id');
$location->user_id = auth()->id();
$location->created_by = auth()->id();
$location->phone = request('phone');
$location->fax = request('fax');
@@ -193,7 +194,13 @@ class LocationsController extends Controller
*/
public function show($id = null) : View | RedirectResponse
{
$location = Location::find($id);
$location = Location::withCount('assignedAssets as assigned_assets_count')
->withCount('assets as assets_count')
->withCount('rtd_assets as rtd_assets_count')
->withCount('children as children_count')
->withCount('users as users_count')
->withTrashed()
->find($id);
if (isset($location->id)) {
return view('locations/view', compact('location'));
@@ -249,6 +256,41 @@ class LocationsController extends Controller
}
/**
* Restore a given Asset Model (mark as un-deleted)
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @param int $id
*/
public function postRestore($id) : RedirectResponse
{
$this->authorize('create', Location::class);
if ($location = Location::withTrashed()->find($id)) {
if ($location->deleted_at == '') {
return redirect()->back()->with('error', trans('general.not_deleted', ['item_type' => trans('general.location')]));
}
if ($location->restore()) {
$logaction = new Actionlog();
$logaction->item_type = Location::class;
$logaction->item_id = $location->id;
$logaction->created_at = date('Y-m-d H:i:s');
$logaction->created_by = auth()->id();
$logaction->logaction('restore');
return redirect()->route('locations.index')->with('success', trans('admin/locations/message.restore.success'));
}
// Check validation
return redirect()->back()->with('error', trans('general.could_not_restore', ['item_type' => trans('general.location'), 'error' => $location->getErrors()->first()]));
}
return redirect()->back()->with('error', trans('admin/models/message.does_not_exist'));
}
public function print_all_assigned($id) : View | RedirectResponse
{
if ($location = Location::where('id', $id)->first()) {
@@ -61,7 +61,7 @@ class ManufacturersController extends Controller
$this->authorize('create', Manufacturer::class);
$manufacturer = new Manufacturer;
$manufacturer->name = $request->input('name');
$manufacturer->user_id = Auth::id();
$manufacturer->created_by = auth()->id();
$manufacturer->url = $request->input('url');
$manufacturer->support_url = $request->input('support_url');
$manufacturer->warranty_lookup_url = $request->input('warranty_lookup_url');
@@ -219,7 +219,7 @@ class ManufacturersController extends Controller
$logaction->item_type = Manufacturer::class;
$logaction->item_id = $manufacturer->id;
$logaction->created_at = date('Y-m-d H:i:s');
$logaction->user_id = auth()->id();
$logaction->created_by = auth()->id();
$logaction->logaction('restore');
// Redirect them to the deleted page if there are more, otherwise the section index
@@ -50,6 +50,7 @@ class ProfileController extends Controller
$user->skin = $request->input('skin');
$user->phone = $request->input('phone');
$user->enable_sounds = $request->input('enable_sounds', false);
$user->enable_confetti = $request->input('enable_confetti', false);
if (! config('app.lock_passwords')) {
$user->locale = $request->input('locale', 'en-US');
+5 -1
View File
@@ -703,6 +703,10 @@ class ReportsController extends Controller
$assets->whereBetween('assets.expected_checkin', [$request->input('expected_checkin_start'), $request->input('expected_checkin_end')]);
}
if (($request->filled('asset_eol_date_start')) && ($request->filled('asset_eol_date_end'))) {
$assets->whereBetween('assets.asset_eol_date', [$request->input('asset_eol_date_start'), $request->input('asset_eol_date_end')]);
}
if (($request->filled('last_audit_start')) && ($request->filled('last_audit_end'))) {
$last_audit_start = Carbon::parse($request->input('last_audit_start'))->startOfDay();
$last_audit_end = Carbon::parse($request->input('last_audit_end'))->endOfDay();
@@ -778,7 +782,7 @@ class ReportsController extends Controller
}
if ($request->filled('eol')) {
$row[] = ($asset->asset_eol_date) ? $asset->asset_eol_date : '';
$row[] = ($asset->purchase_date != '') ? $asset->asset_eol_date : '';
}
if ($request->filled('order')) {
+24 -7
View File
@@ -181,7 +181,7 @@ class SettingsController extends Controller
$settings->brand = 1;
$settings->locale = $request->input('locale', 'en-US');
$settings->default_currency = $request->input('default_currency', 'USD');
$settings->user_id = 1;
$settings->created_by = 1;
$settings->email_domain = $request->input('email_domain');
$settings->email_format = $request->input('email_format');
$settings->next_auto_tag_base = 1;
@@ -637,6 +637,7 @@ class SettingsController extends Controller
$setting->alert_threshold = $request->input('alert_threshold');
$setting->audit_interval = $request->input('audit_interval');
$setting->audit_warning_days = $request->input('audit_warning_days');
$setting->due_checkin_days = $request->input('due_checkin_days');
$setting->show_alerts_in_menu = $request->input('show_alerts_in_menu', '0');
if ($setting->save()) {
@@ -1203,7 +1204,7 @@ class SettingsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v6.0]
*/
public function postRestore($filename = null) : RedirectResponse
public function postRestore(Request $request, $filename = null): RedirectResponse
{
if (! config('app.lock_passwords')) {
@@ -1223,13 +1224,29 @@ class SettingsController extends Controller
Log::debug('Attempting to restore from: '. storage_path($path).'/'.$filename);
// run the restore command
Artisan::call('snipeit:restore',
[
$restore_params = [
'--force' => true,
'--no-progress' => true,
'filename' => storage_path($path).'/'.$filename
]);
'filename' => storage_path($path) . '/' . $filename
];
if ($request->input('clean')) {
Log::debug("Attempting 'clean' - first, guessing prefix...");
Artisan::call('snipeit:restore', [
'--sanitize-guess-prefix' => true,
'filename' => storage_path($path) . '/' . $filename
]);
$guess_prefix_output = Artisan::output();
Log::debug("Sanitize output is: $guess_prefix_output");
list($prefix, $_output) = explode("\n", $guess_prefix_output);
Log::debug("prefix is: '$prefix'");
$restore_params['--sanitize-with-prefix'] = $prefix;
}
// run the restore command
Artisan::call('snipeit:restore',
$restore_params
);
// If it's greater than 300, it probably worked
$output = Artisan::output();
@@ -69,7 +69,7 @@ class StatuslabelsController extends Controller
// Save the Statuslabel data
$statusLabel->name = $request->input('name');
$statusLabel->user_id = Auth::id();
$statusLabel->created_by = auth()->id();
$statusLabel->notes = $request->input('notes');
$statusLabel->deployable = $statusType['deployable'];
$statusLabel->pending = $statusType['pending'];
+1 -1
View File
@@ -62,7 +62,7 @@ class SuppliersController extends Controller
$supplier->email = request('email');
$supplier->notes = request('notes');
$supplier->url = $supplier->addhttp(request('url'));
$supplier->user_id = Auth::id();
$supplier->created_by = auth()->id();
$supplier = $request->handleImages($supplier);
if ($supplier->save()) {
@@ -13,6 +13,7 @@ use App\Models\Group;
use App\Models\LicenseSeat;
use App\Models\ConsumableAssignment;
use App\Models\Consumable;
use App\Models\Setting;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
@@ -30,12 +31,12 @@ class BulkUsersController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.7]
* @param Request $request
* @return \Illuminate\Contracts\View\View
* @return \Illuminate\Contracts\View\View | \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function edit(Request $request)
{
$this->authorize('update', User::class);
$this->authorize('view', User::class);
// Make sure there were users selected
if (($request->filled('ids')) && (count($request->input('ids')) > 0)) {
@@ -47,16 +48,18 @@ class BulkUsersController extends Controller
// bulk edit, display the bulk edit form
if ($request->input('bulk_actions') == 'edit') {
$this->authorize('update', User::class);
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') {
$this->authorize('delete', User::class);
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') {
$this->authorize('delete', User::class);
if (($request->filled('ids')) && (count($request->input('ids')) > 1)) {
return view('users/confirm-merge')->with('users', $users);
// Not enough users selected, send them back
@@ -76,6 +79,33 @@ class BulkUsersController extends Controller
}
return redirect()->back()->with('success', trans('admin/users/message.password_resets_sent'));
} elseif ($request->input('bulk_actions') == 'print') {
$users = User::query()
->with([
'assets.assetlog',
'assets.assignedAssets.assetlog',
'assets.assignedAssets.defaultLoc',
'assets.assignedAssets.location',
'assets.assignedAssets.model.category',
'assets.defaultLoc',
'assets.location',
'assets.model.category',
'accessories.assetlog',
'accessories.category',
'accessories.manufacturer',
'consumables.assetlog',
'consumables.category',
'consumables.manufacturer',
'licenses.category',
])
->withTrashed()
->findMany($request->input('ids'));
$users->each(fn($user) => $this->authorize('view', $user));
return view('users.print')
->with('users', $users)
->with('settings', Setting::getSettings());
}
}
@@ -101,7 +131,7 @@ class BulkUsersController extends Controller
$user_raw_array = $request->input('ids');
// Remove the user from any updates.
$user_raw_array = array_diff($user_raw_array, [Auth::id()]);
$user_raw_array = array_diff($user_raw_array, [auth()->id()]);
$manager_conflict = false;
$users = User::whereIn('id', $user_raw_array)->where('id', '!=', auth()->id())->get();
@@ -116,6 +146,9 @@ class BulkUsersController extends Controller
->conditionallyAddItem('remote')
->conditionallyAddItem('ldap_import')
->conditionallyAddItem('activated')
->conditionallyAddItem('start_date')
->conditionallyAddItem('end_date')
->conditionallyAddItem('city')
->conditionallyAddItem('autoassign_licenses');
@@ -146,13 +179,24 @@ class BulkUsersController extends Controller
$this->update_array['company_id'] = null;
}
if ($request->input('null_start_date')=='1') {
$this->update_array['start_date'] = null;
}
if ($request->input('null_end_date')=='1') {
$this->update_array['end_date'] = null;
}
if ($request->input('null_locale')=='1') {
$this->update_array['locale'] = null;
}
if (! $manager_conflict) {
$this->conditionallyAddItem('manager_id');
}
// Save the updated info
User::whereIn('id', $user_raw_array)
->where('id', '!=', Auth::id())->update($this->update_array);
->where('id', '!=', auth()->id())->update($this->update_array);
if (array_key_exists('location_id', $this->update_array)){
Asset::where('assigned_type', User::class)
@@ -214,7 +258,7 @@ class BulkUsersController extends Controller
$user_raw_array = request('ids');
if (($key = array_search(Auth::id(), $user_raw_array)) !== false) {
if (($key = array_search(auth()->id(), $user_raw_array)) !== false) {
unset($user_raw_array[$key]);
}
@@ -279,7 +323,7 @@ class BulkUsersController extends Controller
$logAction->item_type = $itemType;
$logAction->target_id = $item->assigned_to;
$logAction->target_type = User::class;
$logAction->user_id = Auth::id();
$logAction->created_at = auth()->id();
$logAction->note = 'Bulk checkin items';
$logAction->logaction('checkin from');
}
@@ -293,7 +337,7 @@ class BulkUsersController extends Controller
$logAction->item_type = Accessory::class;
$logAction->target_id = $accessoryUserRow->assigned_to;
$logAction->target_type = User::class;
$logAction->user_id = Auth::id();
$logAction->created_at = auth()->id();
$logAction->note = 'Bulk checkin items';
$logAction->logaction('checkin from');
}
@@ -307,7 +351,7 @@ class BulkUsersController extends Controller
$logAction->item_type = Consumable::class;
$logAction->target_id = $consumableUserRow->assigned_to;
$logAction->target_type = User::class;
$logAction->user_id = Auth::id();
$logAction->created_at = auth()->id();
$logAction->note = 'Bulk checkin items';
$logAction->logaction('checkin from');
}
@@ -46,7 +46,7 @@ class UserFilesController extends Controller
$logAction = new Actionlog();
$logAction->item_id = $user->id;
$logAction->item_type = User::class;
$logAction->user_id = Auth::id();
$logAction->created_by = auth()->id();
$logAction->note = $request->input('notes');
$logAction->target_id = null;
$logAction->created_at = date("Y-m-d H:i:s");
+83 -79
View File
@@ -186,7 +186,7 @@ class UsersController extends Controller
{
$this->authorize('update', User::class);
$user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find($id);
$user = User::with(['assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc'])->withTrashed()->find($id);
if ($user) {
@@ -214,83 +214,79 @@ class UsersController extends Controller
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function update(SaveUserRequest $request, $id = null)
public function update(SaveUserRequest $request, User $user)
{
$this->authorize('update', User::class);
// This is a janky hack to prevent people from changing admin demo user data on the public demo.
// The $ids 1 and 2 are special since they are seeded as superadmins in the demo seeder.
// Thanks, jerks. You are why we can't have nice things. - snipe
if ((($id == 1) || ($id == 2)) && (config('app.lock_passwords'))) {
if ((($user->id == 1) || ($user->id == 2)) && (config('app.lock_passwords'))) {
return redirect()->route('users.index')->with('error', trans('general.permission_denied_superuser_demo'));
}
// We need to reverse the UI specific logic for our
// permissions here before we update the user.
$permissions = $request->input('permissions', []);
app('request')->request->set('permissions', $permissions);
$user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find($id);
$user->load(['assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc'])->withTrashed();
// User is valid - continue...
if ($user) {
$this->authorize('update', $user);
$this->authorize('update', $user);
// Figure out of this user was an admin before this edit
$orig_permissions_array = $user->decodePermissions();
$orig_superuser = '0';
if (is_array($orig_permissions_array)) {
if (array_key_exists('superuser', $orig_permissions_array)) {
$orig_superuser = $orig_permissions_array['superuser'];
}
// Figure out of this user was an admin before this edit
$orig_permissions_array = $user->decodePermissions();
$orig_superuser = '0';
if (is_array($orig_permissions_array)) {
if (array_key_exists('superuser', $orig_permissions_array)) {
$orig_superuser = $orig_permissions_array['superuser'];
}
}
// Only save groups if the user is a superuser
if (auth()->user()->isSuperUser()) {
$user->groups()->sync($request->input('groups'));
}
// Only save groups if the user is a superuser
if (auth()->user()->isSuperUser()) {
$user->groups()->sync($request->input('groups'));
}
// Update the user fields
$user->username = trim($request->input('username'));
$user->email = trim($request->input('email'));
$user->first_name = $request->input('first_name');
$user->last_name = $request->input('last_name');
$user->two_factor_optin = $request->input('two_factor_optin') ?: 0;
$user->locale = $request->input('locale');
$user->employee_num = $request->input('employee_num');
$user->activated = $request->input('activated', 0);
$user->jobtitle = $request->input('jobtitle', null);
$user->phone = $request->input('phone');
$user->location_id = $request->input('location_id', null);
$user->company_id = Company::getIdForUser($request->input('company_id', null));
$user->manager_id = $request->input('manager_id', null);
$user->notes = $request->input('notes');
$user->department_id = $request->input('department_id', null);
$user->address = $request->input('address', null);
$user->city = $request->input('city', null);
$user->state = $request->input('state', null);
$user->country = $request->input('country', null);
// if a user is editing themselves we should always keep activated true
$user->activated = $request->input('activated', $request->user()->is($user) ? 1 : 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', 0);
// Update the user fields
$user->username = trim($request->input('username'));
$user->email = trim($request->input('email'));
$user->first_name = $request->input('first_name');
$user->last_name = $request->input('last_name');
$user->two_factor_optin = $request->input('two_factor_optin') ?: 0;
$user->locale = $request->input('locale');
$user->employee_num = $request->input('employee_num');
$user->activated = $request->input('activated', 0);
$user->jobtitle = $request->input('jobtitle', null);
$user->phone = $request->input('phone');
$user->location_id = $request->input('location_id', null);
$user->company_id = Company::getIdForUser($request->input('company_id', null));
$user->manager_id = $request->input('manager_id', null);
$user->notes = $request->input('notes');
$user->department_id = $request->input('department_id', null);
$user->address = $request->input('address', null);
$user->city = $request->input('city', null);
$user->state = $request->input('state', null);
$user->country = $request->input('country', null);
// if a user is editing themselves we should always keep activated true
$user->activated = $request->input('activated', $request->user()->is($user) ? 1 : 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', 0);
// Update the location of any assets checked out to this user
Asset::where('assigned_type', User::class)
->where('assigned_to', $user->id)
->update(['location_id' => $request->input('location_id', null)]);
// Update the location of any assets checked out to this user
Asset::where('assigned_type', User::class)
->where('assigned_to', $user->id)
->update(['location_id' => $request->input('location_id', null)]);
// Do we want to update the user password?
if ($request->filled('password')) {
$user->password = bcrypt($request->input('password'));
}
// Do we want to update the user password?
if ($request->filled('password')) {
$user->password = bcrypt($request->input('password'));
}
// Update the location of any assets checked out to this user
@@ -318,13 +314,7 @@ class UsersController extends Controller
return redirect()->to(Helper::getRedirectOption($request, $user->id, 'Users'))
->with('success', trans('admin/users/message.success.update'));
}
return redirect()->back()->withInput()->withErrors($user->getErrors());
}
return redirect()->route('users.index')->with('error', trans('admin/users/message.user_not_found', compact('id')));
}
/**
@@ -382,7 +372,7 @@ class UsersController extends Controller
$logaction->item_type = User::class;
$logaction->item_id = $user->id;
$logaction->created_at = date('Y-m-d H:i:s');
$logaction->user_id = auth()->id();
$logaction->created_by = auth()->id();
$logaction->logaction('restore');
// Redirect them to the deleted page if there are more, otherwise the section index
@@ -601,29 +591,43 @@ class UsersController extends Controller
/**
* Print inventory
*
* @author Aladin Alaily
* @since [v1.8]
* @return \Illuminate\Http\RedirectResponse
* @author Aladin Alaily
*/
public function printInventory($id)
{
$this->authorize('view', User::class);
$user = User::where('id', $id)->withTrashed()->first();
// Make sure they can view this particular user
$this->authorize('view', $user);
$user = User::where('id', $id)
->with([
'assets.assetlog',
'assets.assignedAssets.assetlog',
'assets.assignedAssets.defaultLoc',
'assets.assignedAssets.location',
'assets.assignedAssets.model.category',
'assets.defaultLoc',
'assets.location',
'assets.model.category',
'accessories.assetlog',
'accessories.category',
'accessories.manufacturer',
'consumables.assetlog',
'consumables.category',
'consumables.manufacturer',
'licenses.category',
])
->withTrashed()
->first();
$assets = Asset::where('assigned_to', $id)->where('assigned_type', User::class)->with('model', 'model.category')->get();
$accessories = $user->accessories()->get();
$consumables = $user->consumables()->get();
if ($user) {
$this->authorize('view', $user);
return view('users/print')->with('assets', $assets)
->with('licenses', $user->licenses()->get())
->with('accessories', $accessories)
->with('consumables', $consumables)
->with('show_user', $user)
->with('settings', Setting::getSettings());
return view('users.print')
->with('users', [$user])
->with('settings', Setting::getSettings());
}
return redirect()->route('users.index')->with('error', trans('admin/users/message.user_not_found', compact('id')));
}
/**
+11 -3
View File
@@ -13,6 +13,7 @@ use App\Notifications\RequestAssetNotification;
use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use \Illuminate\Contracts\View\View;
use Log;
/**
* This controller handles all actions related to the ability for users
@@ -179,8 +180,11 @@ class ViewAssetsController extends Controller
$asset->decrement('requests_counter', 1);
$logaction->logaction('request canceled');
$settings->notify(new RequestAssetCancelation($data));
try {
$settings->notify(new RequestAssetCancelation($data));
} catch (\Exception $e) {
Log::warning($e);
}
return redirect()->route('requestable-assets')
->with('success')->with('success', trans('admin/hardware/message.requests.canceled'));
}
@@ -188,7 +192,11 @@ class ViewAssetsController extends Controller
$logaction->logaction('requested');
$asset->request();
$asset->increment('requests_counter', 1);
$settings->notify(new RequestAssetNotification($data));
try {
$settings->notify(new RequestAssetNotification($data));
} catch (\Exception $e) {
Log::warning($e);
}
return redirect()->route('requestable-assets')->with('success')->with('success', trans('admin/hardware/message.requests.success'));
}
+3
View File
@@ -14,6 +14,7 @@ class Kernel extends HttpKernel
* @var array
*/
protected $middleware = [
\App\Http\Middleware\TrustProxies::class,
\App\Http\Middleware\NoSessionStore::class,
\Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Session\Middleware\StartSession::class,
@@ -21,6 +22,7 @@ class Kernel extends HttpKernel
\App\Http\Middleware\CheckForSetup::class,
\App\Http\Middleware\CheckForDebug::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\App\Http\Middleware\TrimStrings::class,
\App\Http\Middleware\SecurityHeaders::class,
\App\Http\Middleware\PreventBackHistory::class,
\Illuminate\Http\Middleware\HandleCors::class,
@@ -48,6 +50,7 @@ class Kernel extends HttpKernel
'api' => [
'auth:api',
\App\Http\Middleware\CheckLocale::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
+1 -1
View File
@@ -60,7 +60,7 @@ class ItemImportRequest extends FormRequest
$fieldMappings = array_change_key_case(array_flip($import->field_map), CASE_LOWER);
}
$importer->setCallbacks([$this, 'log'], [$this, 'progress'], [$this, 'errorCallback'])
->setUserId(Auth::id())
->setUserId(auth()->id())
->setUpdating($this->get('import-update'))
->setShouldNotify($this->get('send-welcome'))
->setUsernameFormat('firstname.lastname')
+4
View File
@@ -6,6 +6,7 @@ use App\Models\Setting;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
use App\Rules\UserCannotSwitchCompaniesIfItemsAssigned;
class SaveUserRequest extends FormRequest
{
@@ -34,6 +35,7 @@ class SaveUserRequest extends FormRequest
$rules = [
'department_id' => 'nullable|exists:departments,id',
'manager_id' => 'nullable|exists:users,id',
'company_id' => ['nullable','exists:companies,id']
];
switch ($this->method()) {
@@ -52,11 +54,13 @@ class SaveUserRequest extends FormRequest
$rules['first_name'] = 'required|string|min:1';
$rules['username'] = 'required_unless:ldap_import,1|string|min:1';
$rules['password'] = Setting::passwordComplexityRulesSaving('update').'|confirmed';
$rules['company_id'] = [new UserCannotSwitchCompaniesIfItemsAssigned()];
break;
// Save only what's passed
case 'PATCH':
$rules['password'] = Setting::passwordComplexityRulesSaving('update');
$rules['company_id'] = [new UserCannotSwitchCompaniesIfItemsAssigned()];
break;
default:
+2
View File
@@ -9,6 +9,7 @@ use App\Models\Setting;
use Carbon\Carbon;
use Carbon\Exceptions\InvalidFormatException;
use Illuminate\Support\Facades\Gate;
use App\Rules\AssetCannotBeCheckedOutToNondeployableStatus;
class StoreAssetRequest extends ImageUploadRequest
{
@@ -61,6 +62,7 @@ class StoreAssetRequest extends ImageUploadRequest
return array_merge(
$modelRules,
['status_id' => [new AssetCannotBeCheckedOutToNondeployableStatus()]],
parent::rules(),
);
}
+7
View File
@@ -4,6 +4,7 @@ namespace App\Http\Requests;
use App\Http\Requests\Traits\MayContainCustomFields;
use App\Models\Asset;
use App\Models\Setting;
use Illuminate\Support\Facades\Gate;
use Illuminate\Validation\Rule;
@@ -41,6 +42,12 @@ class UpdateAssetRequest extends ImageUploadRequest
],
);
// if the purchase cost is passed in as a string **and** the digit_separator is ',' (as is common in the EU)
// then we tweak the purchase_cost rule to make it a string
if (Setting::getSettings()->digit_separator === '1.234,56' && is_string($this->input('purchase_cost'))) {
$rules['purchase_cost'] = ['nullable', 'string'];
}
return $rules;
}
}
@@ -11,15 +11,17 @@ trait TwoColumnUniqueUndeletedTrait
* @param string $field
* @return string
*/
protected function prepareTwoColumnUniqueUndeletedRule($parameters, $field)
protected function prepareTwoColumnUniqueUndeletedRule($parameters)
{
$column = $parameters[0];
$value = $this->{$parameters[0]};
// This is an existing model we're updating so ignore the current ID ($this->getKey())
if ($this->exists) {
return 'two_column_unique_undeleted:'.$this->table.','.$this->getKey().','.$column.','.$value;
}
// This is a new record, so we can ignore the current ID
return 'two_column_unique_undeleted:'.$this->table.',0,'.$column.','.$value;
}
}
@@ -38,9 +38,12 @@ 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' => (int) $accessory->numRemaining(),
'remaining_qty' => (int) ($accessory->qty - $accessory->checkouts_count),
'checkouts_count' => $accessory->checkouts_count,
'created_by' => ($accessory->adminuser) ? [
'id' => (int) $accessory->adminuser->id,
'name'=> e($accessory->adminuser->present()->fullName()),
] : null,
'created_at' => Helper::getFormattedDateObject($accessory->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($accessory->updated_at, 'datetime'),
@@ -57,7 +60,7 @@ class AccessoriesTransformer
$permissions_array['user_can_checkout'] = false;
if ($accessory->numRemaining() > 0) {
if (($accessory->qty - $accessory->checkouts_count) > 0) {
$permissions_array['user_can_checkout'] = true;
}
@@ -176,11 +176,17 @@ class ActionlogsTransformer
'next_audit_date' => ($actionlog->itemType()=='asset') ? Helper::getFormattedDateObject($actionlog->calcNextAuditDate(null, $actionlog->item), 'date'): null,
'days_to_next_audit' => $actionlog->daysUntilNextAudit($settings->audit_interval, $actionlog->item),
'action_type' => $actionlog->present()->actionType(),
'admin' => ($actionlog->admin) ? [
'id' => (int) $actionlog->admin->id,
'name' => e($actionlog->admin->getFullNameAttribute()),
'first_name'=> e($actionlog->admin->first_name),
'last_name'=> e($actionlog->admin->last_name)
'admin' => ($actionlog->adminuser) ? [
'id' => (int) $actionlog->adminuser->id,
'name' => e($actionlog->adminuser->getFullNameAttribute()),
'first_name'=> e($actionlog->adminuser->first_name),
'last_name'=> e($actionlog->adminuser->last_name)
] : null,
'created_by' => ($actionlog->adminuser) ? [
'id' => (int) $actionlog->adminuser->id,
'name' => e($actionlog->adminuser->getFullNameAttribute()),
'first_name'=> e($actionlog->adminuser->first_name),
'last_name'=> e($actionlog->adminuser->last_name)
] : null,
'target' => ($actionlog->target) ? [
'id' => (int) $actionlog->target->id,
@@ -64,7 +64,14 @@ class AssetMaintenancesTransformer
'start_date' => Helper::getFormattedDateObject($assetmaintenance->start_date, 'date'),
'asset_maintenance_time' => $assetmaintenance->asset_maintenance_time,
'completion_date' => Helper::getFormattedDateObject($assetmaintenance->completion_date, 'date'),
'user_id' => ($assetmaintenance->admin) ? ['id' => $assetmaintenance->admin->id, 'name'=> e($assetmaintenance->admin->getFullNameAttribute())] : null,
'user_id' => ($assetmaintenance->adminuser) ? [
'id' => $assetmaintenance->adminuser->id,
'name'=> e($assetmaintenance->admin->getFullNameAttribute())
] : null, // legacy to not change the shape of the API
'created_by' => ($assetmaintenance->adminuser) ? [
'id' => (int) $assetmaintenance->adminuser->id,
'name'=> e($assetmaintenance->adminuser->present()->fullName()),
] : null,
'created_at' => Helper::getFormattedDateObject($assetmaintenance->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($assetmaintenance->updated_at, 'datetime'),
'is_warranty'=> $assetmaintenance->is_warranty,
+5 -1
View File
@@ -80,13 +80,17 @@ class AssetsTransformer
'assigned_to' => $this->transformAssignedTo($asset),
'warranty_months' => ($asset->warranty_months > 0) ? e($asset->warranty_months.' '.trans('admin/hardware/form.months')) : null,
'warranty_expires' => ($asset->warranty_months > 0) ? Helper::getFormattedDateObject($asset->warranty_expires, 'date') : null,
'created_by' => ($asset->adminuser) ? [
'id' => (int) $asset->adminuser->id,
'name'=> e($asset->adminuser->present()->fullName()),
] : null,
'created_at' => Helper::getFormattedDateObject($asset->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($asset->updated_at, 'datetime'),
'last_audit_date' => Helper::getFormattedDateObject($asset->last_audit_date, 'datetime'),
'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 ? $asset->purchase_date->diffForHumans() : '',
'age' => $asset->purchase_date ? $asset->purchase_date->locale(app()->getLocale())->diffForHumans() : '',
'last_checkout' => Helper::getFormattedDateObject($asset->last_checkout, 'datetime'),
'last_checkin' => Helper::getFormattedDateObject($asset->last_checkin, 'datetime'),
'expected_checkin' => Helper::getFormattedDateObject($asset->expected_checkin, 'date'),
@@ -62,6 +62,10 @@ class CategoriesTransformer
'consumables_count' => (int) $category->consumables_count,
'components_count' => (int) $category->components_count,
'licenses_count' => (int) $category->licenses_count,
'created_by' => ($category->adminuser) ? [
'id' => (int) $category->adminuser->id,
'name'=> e($category->adminuser->present()->fullName()),
] : null,
'created_at' => Helper::getFormattedDateObject($category->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($category->updated_at, 'datetime'),
];
@@ -30,14 +30,18 @@ class CompaniesTransformer
'fax' => ($company->fax!='') ? e($company->fax): null,
'email' => ($company->email!='') ? e($company->email): null,
'image' => ($company->image) ? Storage::disk('public')->url('companies/'.e($company->image)) : null,
'created_at' => Helper::getFormattedDateObject($company->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($company->updated_at, 'datetime'),
'assets_count' => (int) $company->assets_count,
'licenses_count' => (int) $company->licenses_count,
'accessories_count' => (int) $company->accessories_count,
'consumables_count' => (int) $company->consumables_count,
'components_count' => (int) $company->components_count,
'users_count' => (int) $company->users_count,
'created_by' => ($company->adminuser) ? [
'id' => (int) $company->adminuser->id,
'name'=> e($company->adminuser->present()->fullName()),
] : null,
'created_at' => Helper::getFormattedDateObject($company->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($company->updated_at, 'datetime'),
];
$permissions_array['available_actions'] = [
@@ -47,6 +47,10 @@ class ComponentsTransformer
'name' => e($component->company->name),
] : null,
'notes' => ($component->notes) ? Helper::parseEscapedMarkedownInline($component->notes) : null,
'created_by' => ($component->adminuser) ? [
'id' => (int) $component->adminuser->id,
'name'=> e($component->adminuser->present()->fullName()),
] : null,
'created_at' => Helper::getFormattedDateObject($component->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($component->updated_at, 'datetime'),
'user_can_checkout' => ($component->numRemaining() > 0) ? 1 : 0,
@@ -40,6 +40,10 @@ class ConsumablesTransformer
'purchase_date' => Helper::getFormattedDateObject($consumable->purchase_date, 'date'),
'qty' => (int) $consumable->qty,
'notes' => ($consumable->notes) ? Helper::parseEscapedMarkedownInline($consumable->notes) : null,
'created_by' => ($consumable->adminuser) ? [
'id' => (int) $consumable->adminuser->id,
'name'=> e($consumable->adminuser->present()->fullName()),
] : null,
'created_at' => Helper::getFormattedDateObject($consumable->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($consumable->updated_at, 'datetime'),
];
@@ -63,15 +63,12 @@ class DepreciationReportTransformer
*/
if (($asset->model) && ($asset->model->depreciation)) {
$depreciated_value = Helper::formatCurrencyOutput($asset->getDepreciatedValue());
if($asset->model->eol==0 || $asset->model->eol==null ){
$monthly_depreciation = Helper::formatCurrencyOutput($asset->purchase_cost / $asset->model->depreciation->months);
}
else {
$monthly_depreciation = Helper::formatCurrencyOutput(($asset->model->eol > 0 ? ($asset->purchase_cost / $asset->model->eol) : 0));
}
$monthly_depreciation =Helper::formatCurrencyOutput($asset->purchase_cost / $asset->model->depreciation->months);
$diff = Helper::formatCurrencyOutput(($asset->purchase_cost - $asset->getDepreciatedValue()));
}
else if($asset->model->eol !== null) {
$monthly_depreciation = Helper::formatCurrencyOutput(($asset->model->eol > 0 ? ($asset->purchase_cost / $asset->model->eol) : 0));
}
if ($asset->assigned) {
$checkout_target = $asset->assigned->name;
@@ -28,6 +28,13 @@ class DepreciationsTransformer
'name' => e($depreciation->name),
'months' => $depreciation->months.' '.trans('general.months'),
'depreciation_min' => $depreciation->depreciation_type === 'percent' ? $depreciation->depreciation_min.'%' : $depreciation->depreciation_min,
'assets_count' => $depreciation->assets_count,
'models_count' => $depreciation->models_count,
'licenses_count' => $depreciation->licenses_count,
'created_by' => ($depreciation->adminuser) ? [
'id' => (int) $depreciation->adminuser->id,
'name'=> e($depreciation->adminuser->present()->fullName()),
] : null,
'created_at' => Helper::getFormattedDateObject($depreciation->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($depreciation->updated_at, 'datetime')
];
+4 -1
View File
@@ -26,7 +26,10 @@ class GroupsTransformer
'name' => e($group->name),
'permissions' => json_decode($group->permissions),
'users_count' => (int) $group->users_count,
'created_by' => ($group->admin) ? e($group->admin->present()->fullName) : null,
'created_by' => ($group->adminuser) ? [
'id' => (int) $group->adminuser->id,
'name'=> e($group->adminuser->present()->fullName()),
] : null,
'created_at' => Helper::getFormattedDateObject($group->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($group->updated_at, 'datetime'),
];
@@ -61,7 +61,7 @@ class LicensesTransformer
'checkin' => Gate::allows('checkin', License::class),
'clone' => Gate::allows('create', License::class),
'update' => Gate::allows('update', License::class),
'delete' => (Gate::allows('delete', License::class) && ($license->seats == $license->availCount()->count())) ? true : false,
'delete' => (Gate::allows('delete', License::class) && ($license->free_seats_count > 0)) ? true : false,
];
$array += $permissions_array;
@@ -36,6 +36,10 @@ class ManufacturersTransformer
'licenses_count' => (int) $manufacturer->licenses_count,
'consumables_count' => (int) $manufacturer->consumables_count,
'accessories_count' => (int) $manufacturer->accessories_count,
'created_by' => ($manufacturer->adminuser) ? [
'id' => (int) $manufacturer->adminuser->id,
'name'=> e($manufacturer->adminuser->present()->fullName()),
] : null,
'created_at' => Helper::getFormattedDateObject($manufacturer->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($manufacturer->updated_at, 'datetime'),
'deleted_at' => Helper::getFormattedDateObject($manufacturer->deleted_at, 'datetime'),
@@ -2,6 +2,7 @@
namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\PredefinedKit;
use App\Models\SnipeModel;
use Illuminate\Support\Facades\Gate;
@@ -30,6 +31,12 @@ class PredefinedKitsTransformer
$array = [
'id' => (int) $kit->id,
'name' => e($kit->name),
'created_by' => ($kit->adminuser) ? [
'id' => (int) $kit->adminuser->id,
'name'=> e($kit->adminuser->present()->fullName()),
] : null,
'created_at' => Helper::getFormattedDateObject($kit->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($kit->updated_at, 'datetime'),
];
$permissions_array['available_actions'] = [
@@ -30,6 +30,10 @@ class StatuslabelsTransformer
'default_label' => ($statuslabel->default_label == '1') ? true : false,
'assets_count' => (int) $statuslabel->assets_count,
'notes' => e($statuslabel->notes),
'created_by' => ($statuslabel->adminuser) ? [
'id' => (int) $statuslabel->adminuser->id,
'name'=> e($statuslabel->adminuser->present()->fullName()),
] : null,
'created_at' => Helper::getFormattedDateObject($statuslabel->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($statuslabel->updated_at, 'datetime'),
];
+6 -4
View File
@@ -71,8 +71,10 @@ class AssetImporter extends ItemImporter
$asset = Asset::where(['asset_tag'=> (string) $asset_tag])->first();
if ($asset) {
if (! $this->updating) {
$this->log('A matching Asset '.$asset_tag.' already exists');
return;
$exists_error = trans('general.import_asset_tag_exists', ['asset_tag' => $asset_tag]);
$this->log($exists_error);
$this->addErrorToBag($asset, 'asset_tag', $exists_error);
return $exists_error;
}
$this->log('Updating Asset');
@@ -175,7 +177,7 @@ class AssetImporter extends ItemImporter
$this->log('Asset '.$this->item['name'].' with serial number '.$this->item['serial'].' was created');
// If we have a target to checkout to, lets do so.
//-- user_id is a property of the abstract class Importer, which this class inherits from and it's set by
//-- created_by is a property of the abstract class Importer, which this class inherits from and it's set by
//-- the class that needs to use it (command importer or GUI importer inside the project).
if (isset($target) && ($target !== false)) {
if (!is_null($asset->assigned_to)){
@@ -184,7 +186,7 @@ class AssetImporter extends ItemImporter
}
}
$asset->fresh()->checkOut($target, $this->user_id, $checkout_date, null, 'Checkout from CSV Importer', $asset->name);
$asset->fresh()->checkOut($target, $this->created_by, $checkout_date, null, 'Checkout from CSV Importer', $asset->name);
}
return;
+1 -1
View File
@@ -58,7 +58,7 @@ class ComponentImporter extends ItemImporter
if (isset($this->item['asset_tag']) && ($asset = Asset::where('asset_tag', $this->item['asset_tag'])->first())) {
$component->assets()->attach($component->id, [
'component_id' => $component->id,
'user_id' => $this->user_id,
'created_by' => $this->created_by,
'created_at' => date('Y-m-d H:i:s'),
'assigned_qty' => 1, // Only assign the first one to the asset
'asset_id' => $asset->id,
+14 -5
View File
@@ -22,7 +22,7 @@ abstract class Importer
* @var
*/
protected $user_id;
protected $created_by;
/**
* Are we updating items in the import
* @var bool
@@ -129,8 +129,10 @@ abstract class Importer
// However, for testing we also support passing a string directly
if (is_file($file)) {
$this->csv = Reader::createFromPath($file);
$this->csv->setDelimiter($this->delimiter);
} else {
$this->csv = Reader::createFromString($file);
$this->csv->setDelimiter($this->delimiter);
}
$this->tempPassword = substr(str_shuffle('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'), 0, 40);
}
@@ -281,6 +283,13 @@ abstract class Importer
}
}
protected function addErrorToBag($item, $field, $error_message)
{
if ($this->errorCallback) {
call_user_func($this->errorCallback, $item, $field, [$field => [$error_message]]);
}
}
/**
* Finds the user matching given data, or creates a new one if there is no match.
* This is NOT used by the User Import, only for Asset/Accessory/etc where
@@ -388,7 +397,7 @@ abstract class Importer
}
/**
* Matches a user by user_id if user_name provided is a number
* Matches a user by created_by if user_name provided is a number
* @param string $user_name users full name from csv
* @return User User Matching ID
*/
@@ -405,13 +414,13 @@ abstract class Importer
/**
* Sets the Id of User performing import.
*
* @param mixed $user_id the user id
* @param mixed $created_by the user id
*
* @return self
*/
public function setUserId($user_id)
public function setUserId($created_by)
{
$this->user_id = $user_id;
$this->created_by = $created_by;
return $this;
}
+29 -16
View File
@@ -94,7 +94,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['created_by'] = $this->created_by;
$this->item['serial'] = $this->findCsvMatch($row, 'serial');
// NO need to call this method if we're running the user import.
// TODO: Merge these methods.
@@ -196,64 +196,77 @@ class ItemImporter extends Importer
{
$condition = array();
$asset_model_name = $this->findCsvMatch($row, 'asset_model');
$asset_model_category = $this->findCsvMatch($row, 'category');
$asset_modelNumber = $this->findCsvMatch($row, 'model_number');
// TODO: At the moment, this means we can't update the model number if the model name stays the same.
if (! $this->shouldUpdateField($asset_model_name)) {
return;
}
if ((empty($asset_model_name)) && (! empty($asset_modelNumber))) {
$asset_model_name = $asset_modelNumber;
} elseif ((empty($asset_model_name)) && (empty($asset_modelNumber))) {
$asset_model_name = 'Unknown';
}
if ((!empty($asset_model_name)) && (empty($asset_modelNumber))) {
$condition[] = ['name', '=', $asset_model_name];
} elseif ((!empty($asset_model_name)) && (!empty($asset_modelNumber))) {
$condition[] = ['name', '=', $asset_model_name];
$condition[] = ['model_number', '=', $asset_modelNumber];
$asset_model = AssetModel::select('id');
if (!empty($asset_model_name)) {
$asset_model = $asset_model->where('name', '=', $asset_model_name);
if (!empty($asset_modelNumber)) {
$asset_model = $asset_model->where('model_number', '=', $asset_modelNumber);
}
}
$editingModel = $this->updating;
$asset_model = AssetModel::where($condition)->first();
$asset_model = $asset_model->first();
if ($asset_model) {
if (! $this->updating) {
$this->log('A matching model already exists, returning it.');
return $asset_model->id;
}
$this->log('Matching Model found, updating it.');
$item = $this->sanitizeItemForStoring($asset_model, $editingModel);
$item['name'] = $asset_model_name;
$item['notes'] = $this->findCsvMatch($row, 'model_notes');
if(!empty($asset_modelNumber)){
if (!empty($asset_modelNumber)){
$item['model_number'] = $asset_modelNumber;
}
$asset_model->update($item);
$asset_model->save();
$this->log('Asset Model Updated');
return $asset_model->id;
}
$this->log('No Matching Model, Creating a new one');
}
$this->log('No Matching Model, Creating a new one');
$asset_model = new AssetModel();
$item = $this->sanitizeItemForStoring($asset_model, $editingModel);
$item['name'] = $asset_model_name;
$item['model_number'] = $asset_modelNumber;
$item['notes'] = $this->findCsvMatch($row, 'model_notes');
$item['category_id'] = $this->createOrFetchCategory($asset_model_category);
$asset_model->fill($item);
//$asset_model = AssetModel::firstOrNew($item);
$item = null;
if ($asset_model->save()) {
$this->log('Asset Model '.$asset_model_name.' with model number '.$asset_modelNumber.' was created');
return $asset_model->id;
}
$this->log('Asset Model Errors: '.$asset_model->getErrors());
$this->logError($asset_model, 'Asset Model "'.$asset_model_name.'"');
return null;
@@ -288,7 +301,7 @@ class ItemImporter extends Importer
$category = new Category();
$category->name = $asset_category;
$category->category_type = $item_type;
$category->user_id = $this->user_id;
$category->created_by = $this->created_by;
if ($category->save()) {
$this->log('Category '.$asset_category.' was created');
@@ -412,7 +425,7 @@ class ItemImporter extends Importer
//Otherwise create a manufacturer.
$manufacturer = new Manufacturer();
$manufacturer->name = trim($item_manufacturer);
$manufacturer->user_id = $this->user_id;
$manufacturer->created_by = $this->created_by;
if ($manufacturer->save()) {
$this->log('Manufacturer '.$manufacturer->name.' was created');
@@ -453,7 +466,7 @@ class ItemImporter extends Importer
$location->city = '';
$location->state = '';
$location->country = '';
$location->user_id = $this->user_id;
$location->created_by = $this->created_by;
if ($location->save()) {
$this->log('Location '.$asset_location.' was created');
@@ -489,7 +502,7 @@ class ItemImporter extends Importer
$supplier = new Supplier();
$supplier->name = $item_supplier;
$supplier->user_id = $this->user_id;
$supplier->created_by = $this->created_by;
if ($supplier->save()) {
$this->log('Supplier '.$item_supplier.' was created');
+2 -2
View File
@@ -103,13 +103,13 @@ class LicenseImporter extends ItemImporter
if ($checkout_target) {
$targetLicense->assigned_to = $checkout_target->id;
$targetLicense->user_id = Auth::id();
$targetLicense->created_by = auth()->id();
if ($asset) {
$targetLicense->asset_id = $asset->id;
}
$targetLicense->save();
} elseif ($asset) {
$targetLicense->user_id = Auth::id();
$targetLicense->created_by = auth()->id();
$targetLicense->asset_id = $asset->id;
$targetLicense->save();
}
+1 -1
View File
@@ -65,7 +65,7 @@ class LocationImporter extends ItemImporter
$this->item['ldap_ou'] = trim($this->findCsvMatch($row, 'ldap_ou'));
$this->item['manager'] = trim($this->findCsvMatch($row, 'manager'));
$this->item['manager_username'] = trim($this->findCsvMatch($row, 'manager_username'));
$this->item['user_id'] = auth()->id();
$this->item['created_by'] = auth()->id();
if ($this->findCsvMatch($row, 'parent_location')) {
$this->item['parent_id'] = $this->createOrFetchLocation(trim($this->findCsvMatch($row, 'parent_location')));
+1 -1
View File
@@ -165,7 +165,7 @@ class UserImporter extends ItemImporter
$department = new department();
$department->name = $department_name;
$department->user_id = $this->user_id;
$department->created_by = $this->created_by;
if ($department->save()) {
$this->log('department ' . $department_name . ' was created');
+40 -34
View File
@@ -11,6 +11,7 @@ use App\Models\Consumable;
use App\Models\LicenseSeat;
use App\Models\Recipients\AdminRecipient;
use App\Models\Setting;
use App\Models\User;
use App\Notifications\CheckinAccessoryNotification;
use App\Notifications\CheckinAssetNotification;
use App\Notifications\CheckinLicenseSeatNotification;
@@ -43,30 +44,31 @@ class CheckoutableListener
* Make a checkout acceptance and attach it in the notification
*/
$acceptance = $this->getCheckoutAcceptance($event);
$notifiables = $this->getNotifiables($event);
// Send email notifications
try {
if (! $event->checkedOutTo->locale) {
Notification::locale(Setting::getSettings()->locale)->send(
$this->getNotifiables($event),
$this->getCheckoutNotification($event, $acceptance)
);
} else {
Notification::send(
$this->getNotifiables($event),
$this->getCheckoutNotification($event, $acceptance)
);
foreach ($notifiables as $notifiable) {
if ($notifiable instanceof User && $notifiable->email != '') {
if (! $event->checkedOutTo->locale){
Notification::locale(Setting::getSettings()->locale)->send($notifiable, $this->getCheckoutNotification($event, $acceptance));
}
else {
Notification::send($notifiable, $this->getCheckoutNotification($event, $acceptance));
}
}
}
// Send Webhook notification
if ($this->shouldSendWebhookNotification()) {
//slack doesn't include the url in its messaging format so this is needed to hit the endpoint
if(Setting::getSettings()->webhook_selected =='slack' || Setting::getSettings()->webhook_selected =='general') {
Notification::route('slack', Setting::getSettings()->webhook_endpoint)
->notify($this->getCheckoutNotification($event));
}
// Slack doesn't include the URL in its messaging format, so this is needed to hit the endpoint
if (Setting::getSettings()->webhook_selected === 'slack' || Setting::getSettings()->webhook_selected === 'general') {
Notification::route('slack', Setting::getSettings()->webhook_endpoint)
->notify($this->getCheckoutNotification($event, $acceptance));
} else {
Notification::route(Setting::getSettings()->webhook_selected, Setting::getSettings()->webhook_endpoint)
->notify($this->getCheckoutNotification($event, $acceptance));
}
}
} catch (ClientException $e) {
Log::debug("Exception caught during checkout notification: " . $e->getMessage());
@@ -75,6 +77,7 @@ class CheckoutableListener
}
}
/**
* Notify the user and post to webhook about the checked in checkoutable
*/
@@ -101,25 +104,28 @@ class CheckoutableListener
}
}
$notifiables = $this->getNotifiables($event);
// Send email notifications
try {
// Use default locale
if (! $event->checkedOutTo->locale) {
Notification::locale(Setting::getSettings()->locale)->send(
$this->getNotifiables($event),
$this->getCheckinNotification($event)
);
} else {
Notification::send(
$this->getNotifiables($event),
$this->getCheckinNotification($event)
);
foreach ($notifiables as $notifiable) {
if ($notifiable instanceof User && $notifiable->email != '') {
if (! $event->checkedOutTo->locale){
Notification::locale(Setting::getSettings()->locale)->send($notifiable, $this->getCheckoutNotification($event, $acceptance));
}
else {
Notification::send($notifiable, $this->getCheckinNotification($event));
}
}
}
//slack doesn't include the url in its messaging format so this is needed to hit the endpoint
if(Setting::getSettings()->webhook_selected =='slack' || Setting::getSettings()->webhook_selected =='general') {
if ($this->shouldSendWebhookNotification()) {
// Send Webhook notification
if ($this->shouldSendWebhookNotification()) {
// Slack doesn't include the URL in its messaging format, so this is needed to hit the endpoint
if (Setting::getSettings()->webhook_selected === 'slack' || Setting::getSettings()->webhook_selected === 'general') {
Notification::route('slack', Setting::getSettings()->webhook_endpoint)
->notify($this->getCheckinNotification($event));
} else {
Notification::route(Setting::getSettings()->webhook_selected, Setting::getSettings()->webhook_endpoint)
->notify($this->getCheckinNotification($event));
}
}
+2 -2
View File
@@ -111,7 +111,7 @@ class LogListener
$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 ?? null;
$logaction->created_by = $event->admin->id ?? null;
$logaction->save();
// Add a record to the users being merged TO
@@ -122,7 +122,7 @@ class LogListener
$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 ?? null;
$logaction->created_by = $event->admin->id ?? null;
$logaction->save();
@@ -2,6 +2,8 @@
namespace App\Livewire;
use App\Models\CustomField;
use Livewire\Attributes\Computed;
use Livewire\Component;
use App\Models\CustomFieldset;
@@ -12,37 +14,95 @@ class CustomFieldSetDefaultValuesForModel extends Component
public $add_default_values;
public $fieldset_id;
public $fields;
public $model_id;
public function mount()
public array $selectedValues = [];
public function mount($model_id = null)
{
if(is_null($this->model_id)){
return;
}
$this->model = AssetModel::find($this->model_id); // It's possible to do some clever route-model binding here, but let's keep it simple, shall we?
$this->fieldset_id = $this->model->fieldset_id;
$this->model_id = $model_id;
$this->fieldset_id = $this->model?->fieldset_id;
$this->add_default_values = ($this->model?->defaultValues->count() > 0);
$this->fields = null;
if ($fieldset = CustomFieldset::find($this->fieldset_id)) {
$this->fields = CustomFieldset::find($this->fieldset_id)->fields;
}
$this->add_default_values = ($this->model->defaultValues->count() > 0);
$this->initializeSelectedValuesArray();
$this->populatedSelectedValuesArray();
}
public function updatedFieldsetId()
#[Computed]
public function model()
{
if (CustomFieldset::find($this->fieldset_id)) {
$this->fields = CustomFieldset::find($this->fieldset_id)->fields;
return AssetModel::find($this->model_id);
}
#[Computed]
public function fields()
{
$customFieldset = CustomFieldset::find($this->fieldset_id);
if ($customFieldset) {
return $customFieldset?->fields;
}
return collect();
}
public function render()
{
return view('livewire.custom-field-set-default-values-for-model');
}
/**
* Livewire property binding plays nicer with arrays when it knows
* which keys will be present instead of them being
* dynamically added (this is especially true for checkboxes).
*
* Let's go ahead and initialize selectedValues with all the potential keys (custom field db_columns).
*
* @return void
*/
private function initializeSelectedValuesArray(): void
{
CustomField::all()->each(function ($field) {
$this->selectedValues[$field->db_column] = null;
if ($field->element === 'checkbox') {
$this->selectedValues[$field->db_column] = [];
}
});
}
/**
* Populate the selectedValues array with the
* default values or old input for each field.
*
* @return void
*/
private function populatedSelectedValuesArray(): void
{
$this->fields->each(function ($field) {
$this->selectedValues[$field->db_column] = $this->getSelectedValueForField($field);
});
}
private function getSelectedValueForField(CustomField $field)
{
$defaultValue = $field->defaultValue($this->model_id);
// if old() contains a value for default_values that means
// the user has submitted the form and we were redirected
// back with the old input.
// Let's use what they had previously set.
if (old('default_values')) {
$defaultValue = old('default_values.' . $field->id);
}
// on first load the default value for checkboxes will be
// a comma-separated string but if we're loading the page
// with old input then it was already parsed into an array.
if ($field->element === 'checkbox' && is_string($defaultValue)) {
$defaultValue = explode(', ', $defaultValue);
}
return $defaultValue;
}
}
+111 -101
View File
@@ -3,30 +3,25 @@
namespace App\Livewire;
use App\Models\CustomField;
use Livewire\Component;
use App\Models\Import;
use Illuminate\Support\Facades\Storage;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Livewire\Attributes\Computed;
use Livewire\Component;
class Importer extends Component
{
use AuthorizesRequests;
public $files;
public $progress; //upload progress - '-1' means don't show
public $progress = -1; //upload progress - '-1' means don't show
public $progress_message;
public $progress_bar_class;
public $progress_bar_class = 'progress-bar-warning';
public $message; //status/error message?
public $message_type; //success/error?
//originally from ImporterFile
public $import_errors; //
public ?Import $activeFile = null;
public $activeFileId;
public $headerRow = [];
public $typeOfImport;
public $importTypes;
public $columnOptions;
public $statusType;
@@ -35,7 +30,6 @@ class Importer extends Component
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?
// Make these variables public - we set the properties in the constructor so we can localize them (versus the old static arrays)
public $accessories_fields;
@@ -46,16 +40,16 @@ class Importer extends Component
public $consumables_fields;
public $components_fields;
public $aliases_fields;
public $delimiter;
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'
'headerRow' => 'array',
'typeOfImport' => 'string',
'field_map' => 'array',
'delimiter' => 'in:comma,semicolon,pipe',
];
/**
@@ -68,15 +62,13 @@ class Importer extends Component
{
$tmp = array();
if ($this->activeFile) {
$tmp = array_combine($this->activeFile->header_row, $this->field_map);
$tmp = array_combine($this->headerRow, $this->field_map);
$tmp = array_filter($tmp);
}
return json_encode($tmp);
}
private function getColumns($type)
{
switch ($type) {
@@ -115,76 +107,66 @@ class Importer extends Component
return $results;
}
public function updating($name, $new_import_type)
public function updatingTypeOfImport($type)
{
if ($name == "activeFile.import_type") {
// 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_fields 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.
// go through each header, find a matching field to try and map it to.
foreach ($this->headerRow 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[$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_fields 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[$type] as $v => $text) {
if (strcasecmp($text, $header) === 0) { // case-INSENSITIVe on purpose!
$this->field_map[$i] = $v;
continue 2; //don't bother with the alias check, go to the next header
}
// 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_fields
foreach ($this->aliases_fields 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
}
}
// if you got here, we didn't find a match. Try the $aliases_fields
foreach ($this->aliases_fields 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[$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 :(
}
// 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';
$this->importTypes = [
'asset' => trans('general.assets'),
'accessory' => trans('general.accessories'),
'asset' => trans('general.assets'),
'accessory' => trans('general.accessories'),
'consumable' => trans('general.consumables'),
'component' => trans('general.components'),
'license' => trans('general.licenses'),
'user' => trans('general.users'),
'location' => trans('general.locations'),
'component' => trans('general.components'),
'license' => trans('general.licenses'),
'user' => trans('general.users'),
'location' => trans('general.locations'),
];
/**
* These are the item-type specific columns
*/
$this->accessories_fields = [
$this->accessories_fields = [
'company' => trans('general.company'),
'location' => trans('general.location'),
'quantity' => trans('general.qty'),
@@ -307,7 +289,7 @@ class Importer extends Component
'manufacturer' => trans('general.manufacturer'),
];
$this->users_fields = [
$this->users_fields = [
'id' => trans('general.id'),
'company' => trans('general.company'),
'location' => trans('general.location'),
@@ -332,12 +314,12 @@ class Importer extends Component
'website' => trans('general.website'),
'avatar' => trans('general.image'),
'gravatar' => trans('general.importer.gravatar'),
'start_date' => trans('general.start_date'),
'end_date' => trans('general.end_date'),
'employee_num' => trans('general.employee_number'),
'start_date' => trans('general.start_date'),
'end_date' => trans('general.end_date'),
'employee_num' => trans('general.employee_number'),
];
$this->locations_fields = [
$this->locations_fields = [
'name' => trans('general.item_name_var', ['item' => trans('general.location')]),
'address' => trans('general.address'),
'address2' => trans('general.importer.address2'),
@@ -374,6 +356,12 @@ class Importer extends Component
'model name',
'model',
],
'eol_date' =>
[
'eol',
'eol date',
'asset eol date',
],
'gravatar' =>
[
'gravatar',
@@ -504,19 +492,16 @@ class Importer extends Component
];
$this->columnOptions[''] = $this->getColumns(''); //blank mode? I don't know what this is supposed to mean
foreach($this->importTypes AS $type => $name) {
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)
{
$this->clearMessage();
$this->activeFile = Import::find($id);
$this->activeFileId = $id;
if (!$this->activeFile) {
$this->message = trans('admin/hardware/message.import.file_missing');
@@ -525,15 +510,17 @@ class Importer extends Component
return;
}
$this->headerRow = $this->activeFile->header_row;
$this->typeOfImport = $this->activeFile->import_type;
$this->field_map = null;
foreach($this->activeFile->header_row as $element) {
if(isset($this->activeFile->field_map[$element])) {
foreach ($this->headerRow 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->file_id = $id;
$this->import_errors = null;
$this->statusText = null;
@@ -541,21 +528,33 @@ class Importer extends Component
public function destroy($id)
{
// TODO: why don't we just do File::find($id)? This seems dumb.
foreach($this->files as $file) {
if ($id == $file->id) {
if (Storage::delete('private_uploads/imports/'.$file->file_path)) {
$file->delete();
$this->authorize('import');
$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';
}
}
$import = Import::find($id);
// Check that the import wasn't deleted after while page was already loaded...
// @todo: next up...handle the file being missing for other interactions...
// for example having an import open in two tabs, deleting it, and then changing
// the import type in the other tab. The error message below wouldn't display in that case.
if (!$import) {
$this->message = trans('admin/hardware/message.import.file_already_deleted');
$this->message_type = 'danger';
return;
}
if (Storage::delete('private_uploads/imports/' . $import->file_path)) {
$import->delete();
$this->message = trans('admin/hardware/message.import.file_delete_success');
$this->message_type = 'success';
unset($this->files);
return;
}
$this->message = trans('admin/hardware/message.import.file_delete_error');
$this->message_type = 'danger';
}
public function clearMessage()
@@ -564,11 +563,22 @@ class Importer extends Component
$this->message_type = null;
}
#[Computed]
public function files()
{
return Import::orderBy('id', 'desc')->get();
}
#[Computed]
public function activeFile()
{
return Import::find($this->activeFileId);
}
public function render()
{
$this->files = Import::orderBy('id','desc')->get(); //HACK - slows down renders.
return view('livewire.importer')
->extends('layouts.default')
->section('content');
->extends('layouts.default')
->section('content');
}
}

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