Compare commits

...

2809 Commits

Author SHA1 Message Date
snipe 53330514ac Updated field name
Signed-off-by: snipe <snipe@snipe.net>
2024-11-02 15:09:03 +00:00
snipe ba226d9ba3 Added undeployable?
Signed-off-by: snipe <snipe@snipe.net>
2024-10-31 11:04:43 +00:00
snipe 95d136284d Few more fixes
Signed-off-by: snipe <snipe@snipe.net>
2024-10-28 22:02:48 +00:00
snipe f5aea7b0d5 Changed status label to use status_type instead of booleans
Signed-off-by: snipe <snipe@snipe.net>
2024-10-28 11:37:17 +00:00
snipe dfc63641dc Merge pull request #15550 from uberbrady/fix_multi_create_partial_failure
Fix multi create partial failure (fixes: [RB-18591])
2024-10-24 11:40:50 +01:00
snipe 07a51ec8b1 Merge pull request #15712 from Godmartinz/fix_import-progress-bar
Upgraded `livewire v3.5.9 => v3.5.12`
2024-10-24 10:03:10 +01:00
snipe e0ec6795b5 Use crucial for seeded data
Signed-off-by: snipe <snipe@snipe.net>
2024-10-24 01:27:50 +01:00
snipe 5509d756b7 Merge pull request #15722 from Godmartinz/fix_component_factory
Fixed Component Factory: use manufacturer factory for `manufactuer_id`
2024-10-24 01:12:11 +01:00
Godfrey M b16a978f1b uses manufacturer factory for manufactuer_id 2024-10-23 16:25:51 -07:00
snipe 55ba6279a4 Use trans_choice on alert menu
Signed-off-by: snipe <snipe@snipe.net>
2024-10-23 19:14:17 +01:00
snipe a9eea830e3 Added manufacturer and model number to component seeders
Signed-off-by: snipe <snipe@snipe.net>
2024-10-23 19:05:34 +01:00
snipe af564935d5 Merge pull request #15720 from snipe/15695_adds_manufacturer_and_model_number_to_components
Fixed #15695 - Added manufacturer and model_number to components
2024-10-23 17:56:04 +01:00
snipe 3ee76be7e3 Added manufacturer and model_number to components
Signed-off-by: snipe <snipe@snipe.net>
2024-10-23 17:50:22 +01:00
snipe d58f87862c Merge pull request #15719 from snipe/#15717_adds_qty_to_consumable
Fixed #15717 - Added ability to checkout consumables in variable qty via API
2024-10-23 15:09:50 +01:00
snipe 0b6859c491 Added ability to checkout consumables in variable qty
Signed-off-by: snipe <snipe@snipe.net>
2024-10-23 15:05:35 +01:00
Godfrey M 727c0e458c remove translation 2024-10-22 14:34:39 -07:00
Godfrey M 870dc747db oops 2024-10-22 14:27:32 -07:00
Godfrey M 0fb3d83fac revert controller change 2024-10-22 14:26:54 -07:00
Godfrey M 0d59ccd6a6 upgraded livewire v3.5.9 => v3.5.12 2024-10-22 14:23:26 -07:00
snipe 5da3ce3564 Merge pull request #15711 from marcusmoore/fixes/custom-fieldset-checkboxes
Fixed custom field checkboxes on asset edit page
2024-10-22 22:10:20 +01:00
snipe c3bbca30ad Merge pull request #15710 from snipe/fixes_lightbox_for_avif
Fixes #15701 - load avif files properly in lightbox
2024-10-22 22:07:50 +01:00
snipe 37f14fff3b Fixed typo
Signed-off-by: snipe <snipe@snipe.net>
2024-10-22 22:07:28 +01:00
snipe eb6c51fabd Fixes #15701 - load avif files properly in lightbox
Signed-off-by: snipe <snipe@snipe.net>
2024-10-22 22:04:57 +01:00
Marcus Moore 5ecd2b6293 Default checkbox elements to an empty array 2024-10-22 14:04:05 -07:00
snipe dccb788a88 Merge pull request #15691 from marcusmoore/fixes/get-id-for-current-user
Updated `Company::getIdForCurrentUser()` to return null in certain scenarios
2024-10-22 17:44:30 +01:00
Marcus Moore d10fe77ee7 Merge branch 'develop' into fixes/get-id-for-current-user 2024-10-22 09:38:31 -07:00
snipe 5e1d792bba Merge pull request #15687 from NebelKreis/fix/dashboard-title-casing
Fixed #15686: Corrected capitalization for dashboard section titles by removing strtolower()
2024-10-22 16:52:28 +01:00
snipe 9cf71976f6 Fixed #15706 - Removed purchase order number from asset import
Signed-off-by: snipe <snipe@snipe.net>
2024-10-22 16:51:42 +01:00
snipe 15745d9737 Merge pull request #15566 from Godmartinz/status-label-error-message
Fixed Status Labels Error Message
2024-10-22 16:39:44 +01:00
snipe bd97955b9e Bumped hash
Signed-off-by: snipe <snipe@snipe.net>
2024-10-22 16:38:46 +01:00
snipe 252d99421c Merge pull request #15689 from snipe/better_handle_inline_files
Better handle inline files in file listing
2024-10-22 16:26:48 +01:00
snipe 5767a98ad8 Merge pull request #15649 from bryanlopezinc/ImproveImporting
Improve import performance
2024-10-22 16:26:23 +01:00
snipe 0c820cbc0d Merge pull request #15598 from spencerrlongg/bug/custom_field_validation_issue
Custom Field Existence Validation Issue
2024-10-22 15:56:12 +01:00
snipe db81701621 Merge branch 'develop' into better_handle_inline_files 2024-10-22 15:44:24 +01:00
snipe a05c33febf Squashed commit of the following:
commit 147fcfb8eb
Merge: 58a3d09b5 fdcc17ca2
Author: snipe <snipe@snipe.net>
Date:   Tue Oct 22 15:12:55 2024 +0100

    Merge pull request #15676 from Toreg87/fixes/api_create_user_fmcs

    Fix user creation with FullMultipleCompanySupport enabled over API

commit 58a3d09b5f
Merge: 30a06a594 867fa2f36
Author: snipe <snipe@snipe.net>
Date:   Tue Oct 22 14:55:42 2024 +0100

    Merge pull request #15703 from marcusmoore/bug/sc-27188

    Linked accessory files in activity report

commit 30a06a5942
Merge: 6c6af78e0 ce3086317
Author: snipe <snipe@snipe.net>
Date:   Tue Oct 22 11:47:06 2024 +0100

    Merge pull request #15693 from marcusmoore/chore/remove-parallel-testing

    Removed brianium/paratest

commit 6c6af78e08
Merge: 9b06bbb6c 3f79fd7ea
Author: snipe <snipe@snipe.net>
Date:   Tue Oct 22 11:46:04 2024 +0100

    Merge pull request #15705 from marcusmoore/tests/icon-component-test

    Added test to ensure icon component does not end in newline

commit 3f79fd7ea7
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Mon Oct 21 17:07:40 2024 -0700

    Add test to ensure icon component does not end in newline

commit 9b06bbb6c3
Merge: 46ad1d072 d7f70146f
Author: snipe <snipe@snipe.net>
Date:   Mon Oct 21 22:38:26 2024 +0100

    Merge pull request #15704 from marcusmoore/bug/remove-extra-icon

    Removed second icon in accessory file list

commit ce30863177
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Mon Oct 21 13:57:04 2024 -0700

    Remove brianium/paratest dependency

commit d7f70146f4
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Mon Oct 21 13:48:25 2024 -0700

    Remove extra icon in accessory file upload list

commit 867fa2f36e
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Mon Oct 21 12:40:24 2024 -0700

    Display file in activity report for accessories

commit 0933a2d4ea
Author: Marcus Moore <contact@marcusmoore.io>
Date:   Thu Oct 17 18:01:48 2024 -0700

    Remove --parallel flag

commit 46ad1d072f
Merge: bcb4bd9eb 3cf746d7d
Author: snipe <snipe@snipe.net>
Date:   Thu Oct 17 15:29:47 2024 +0100

    Merge pull request #15680 from uberbrady/bulk_checkout_to_bulk_actions

    Bulk checkout to bulk actions

commit bcb4bd9eb4
Merge: 250037540 f50ccbcc4
Author: snipe <snipe@snipe.net>
Date:   Thu Oct 17 10:20:13 2024 +0100

    Merge pull request #15683 from Toreg87/fixes/outdated_comment

    Fix outdated comment in CompanyableTrait

commit f50ccbcc49
Author: Tobias Regnery <tobias.regnery@gmail.com>
Date:   Thu Oct 17 11:07:28 2024 +0200

    Fix outdated comment in CompanyableTrait

    As of commit 5800e8d the user model uses CompanyableTrait so remove this clearly outdated comment

commit 3cf746d7df
Author: Brady Wetherington <bwetherington@grokability.com>
Date:   Wed Oct 16 23:13:32 2024 +0100

    Rework the bulk checkout to not change how all checkouts work

commit 6b7af802af
Author: Brady Wetherington <bwetherington@grokability.com>
Date:   Thu Oct 10 13:28:23 2024 +0100

    Add 'bulk checkout' as one of the bulk actions in the bulk actions toolbar

commit fdcc17ca2c
Author: Tobias Regnery <tobias.regnery@gmail.com>
Date:   Wed Oct 16 11:18:24 2024 +0200

    Fix user creation with FullMultipleCompanySupport enabled over API

    It is currently possible as a non-superuser to create a new user or patch an existing user with arbitrary company over the API if FullMultipleCompanySupport is enabled.
    Altough a highly unlikely scenario as the user needs permission to create API keys and new users, it is a bug that should get fixed.

    Add a call to getIdForCurrentUser() to normalize the company_id if FullMultipleCompanySupport is enabled.

Signed-off-by: snipe <snipe@snipe.net>
2024-10-22 15:43:19 +01:00
snipe 147fcfb8eb Merge pull request #15676 from Toreg87/fixes/api_create_user_fmcs
Fix user creation with FullMultipleCompanySupport enabled over API
2024-10-22 15:12:55 +01:00
snipe 58a3d09b5f Merge pull request #15703 from marcusmoore/bug/sc-27188
Linked accessory files in activity report
2024-10-22 14:55:42 +01:00
snipe 30a06a5942 Merge pull request #15693 from marcusmoore/chore/remove-parallel-testing
Removed brianium/paratest
2024-10-22 11:47:06 +01:00
snipe 6c6af78e08 Merge pull request #15705 from marcusmoore/tests/icon-component-test
Added test to ensure icon component does not end in newline
2024-10-22 11:46:04 +01:00
Marcus Moore 3f79fd7ea7 Add test to ensure icon component does not end in newline 2024-10-21 17:07:40 -07:00
snipe 9b06bbb6c3 Merge pull request #15704 from marcusmoore/bug/remove-extra-icon
Removed second icon in accessory file list
2024-10-21 22:38:26 +01:00
Marcus Moore ce30863177 Remove brianium/paratest dependency 2024-10-21 13:57:04 -07:00
Marcus Moore d7f70146f4 Remove extra icon in accessory file upload list 2024-10-21 13:48:25 -07:00
Marcus Moore 867fa2f36e Display file in activity report for accessories 2024-10-21 12:40:24 -07:00
Marcus Moore e1882ee6d2 Add comment 2024-10-21 12:21:45 -07:00
Marcus Moore 7eee239378 use is_numeric instead of is_int 2024-10-21 12:20:28 -07:00
Marcus Moore 4188849ae1 Add failing test case 2024-10-21 12:19:48 -07:00
snipe 787e651778 Fixed todos with log message
Signed-off-by: snipe <snipe@snipe.net>
2024-10-21 16:52:21 +01:00
snipe ef9b6e3b07 Code cleanup
Signed-off-by: snipe <snipe@snipe.net>
2024-10-21 16:34:54 +01:00
snipe 06c599cc17 Added method to show or download file
Signed-off-by: snipe <snipe@snipe.net>
2024-10-21 16:34:03 +01:00
snipe 6105323877 Use plural class name for src
Signed-off-by: snipe <snipe@snipe.net>
2024-10-21 14:11:20 +01:00
Marcus Moore 0933a2d4ea Remove --parallel flag 2024-10-17 18:01:48 -07:00
Marcus Moore a8d853c44a Remove focus group tags 2024-10-17 15:26:27 -07:00
Marcus Moore 7e1b47708e Fix failing test ensuring company id is an integer 2024-10-17 15:18:41 -07:00
Marcus Moore 979e4502ff Have getIdForCurrentUser method return null if FMCS enabled, user is not super admin, and does not have company 2024-10-17 15:14:39 -07:00
Marcus Moore 99dd51a965 Improve name 2024-10-17 14:53:18 -07:00
Marcus Moore 15c2169477 Scaffold additional tests 2024-10-17 14:31:05 -07:00
Marcus Moore 50fa6ce335 Scaffold tests 2024-10-17 14:12:22 -07:00
Marcus Moore 159a1d3f43 Be more explicit 2024-10-17 11:48:55 -07:00
snipe d1149730be Apply blade component to files views
Signed-off-by: snipe <snipe@snipe.net>
2024-10-17 16:31:17 +01:00
snipe 46ad1d072f Merge pull request #15680 from uberbrady/bulk_checkout_to_bulk_actions
Bulk checkout to bulk actions
2024-10-17 15:29:47 +01:00
NebelKreis 780ed91a10 Fix: Removed strtolower() from dashboard titles
This fix ensures the correct capitalization in different languages.
2024-10-17 16:09:25 +02:00
snipe bcb4bd9eb4 Merge pull request #15683 from Toreg87/fixes/outdated_comment
Fix outdated comment in CompanyableTrait
2024-10-17 10:20:13 +01:00
Tobias Regnery f50ccbcc49 Fix outdated comment in CompanyableTrait
As of commit 5800e8d the user model uses CompanyableTrait so remove this clearly outdated comment
2024-10-17 11:07:28 +02:00
snipe 0e9b3c9119 Check for existence before trying to get the icon
Signed-off-by: snipe <snipe@snipe.net>
2024-10-17 00:27:39 +01:00
snipe 4933aa5784 Add StorageHelper to app config
Signed-off-by: snipe <snipe@snipe.net>
2024-10-17 00:27:04 +01:00
snipe d67addc69e Removed filetype column - it’s dumb
Signed-off-by: snipe <snipe@snipe.net>
2024-10-17 00:21:43 +01:00
snipe 02c80ff18a Added comment
Signed-off-by: snipe <snipe@snipe.net>
2024-10-17 00:18:40 +01:00
snipe c01190fac2 Conditionally add content-type
Signed-off-by: snipe <snipe@snipe.net>
2024-10-17 00:18:34 +01:00
snipe 017884f843 Added checks and filetype display
Signed-off-by: snipe <snipe@snipe.net>
2024-10-17 00:09:09 +01:00
snipe c49921f50f Removed unused (maybe?) API endpoint
Signed-off-by: snipe <snipe@snipe.net>
2024-10-17 00:08:54 +01:00
snipe c49abb6aea Refactor the UserFilesController show method for simpler inlining
Signed-off-by: snipe <snipe@snipe.net>
2024-10-17 00:08:38 +01:00
snipe ccd2019448 Removed unusded use statements
Signed-off-by: snipe <snipe@snipe.net>
2024-10-17 00:08:04 +01:00
snipe 96191a5e93 Added method to decide if the file should be inlinable
Signed-off-by: snipe <snipe@snipe.net>
2024-10-17 00:07:54 +01:00
snipe c56affd663 Added SVG icon
Signed-off-by: snipe <snipe@snipe.net>
2024-10-17 00:07:37 +01:00
Brady Wetherington 3cf746d7df Rework the bulk checkout to not change how all checkouts work 2024-10-16 23:13:32 +01:00
Brady Wetherington 6b7af802af Add 'bulk checkout' as one of the bulk actions in the bulk actions toolbar 2024-10-16 22:02:45 +01:00
Marcus Moore 604a964462 Improve scenario descriptions 2024-10-16 11:52:24 -07:00
Marcus Moore 2f72c66614 Add additional case 2024-10-16 11:30:06 -07:00
Tobias Regnery fdcc17ca2c Fix user creation with FullMultipleCompanySupport enabled over API
It is currently possible as a non-superuser to create a new user or patch an existing user with arbitrary company over the API if FullMultipleCompanySupport is enabled.
Altough a highly unlikely scenario as the user needs permission to create API keys and new users, it is a bug that should get fixed.

Add a call to getIdForCurrentUser() to normalize the company_id if FullMultipleCompanySupport is enabled.
2024-10-16 11:47:18 +02:00
Marcus Moore cba1a56040 Improve readability? 2024-10-15 17:38:11 -07:00
Marcus Moore d9afde4610 Write failing test 2024-10-15 17:00:22 -07:00
Marcus Moore 42095c0167 Add reference link 2024-10-15 13:02:22 -07:00
snipe 2500375400 Merge pull request #15672 from uberbrady/ldap_location_fixes
Clean up how we use the '$location' in LDAP sync command
2024-10-15 17:34:35 +01:00
Brady Wetherington e4e1d0d50a Clean up how we use the '$location' in LDAP sync command 2024-10-15 17:26:31 +01:00
snipe 16c8264e76 Merge pull request #15671 from snipe/bug/sc-27147
Bug/sc 27147
2024-10-15 16:42:34 +01:00
snipe 0ae9ce0aa9 Cannot sort by updated at on Users [sc-27147]
Signed-off-by: snipe <snipe@snipe.net>
2024-10-15 16:41:45 +01:00
snipe 50b8f180b3 More logical grouping in allow_columns
Signed-off-by: snipe <snipe@snipe.net>
2024-10-15 16:41:39 +01:00
snipe 914a647204 Merge pull request #15669 from snipe/remlove_ou_requirenedess
Fixed #15663 - remove requiredness for OU
2024-10-15 12:47:15 +01:00
snipe e9225ff3ea Switch to regular HTML for input form field
Signed-off-by: snipe <snipe@snipe.net>
2024-10-15 12:43:10 +01:00
snipe d0d4159088 Fixed typo
Signed-off-by: snipe <snipe@snipe.net>
2024-10-15 12:42:09 +01:00
snipe 69b6080bd8 Merge pull request #15666 from snipe/updated_readme_llm
Added LLM note
2024-10-15 10:31:29 +01:00
snipe b997d728fb Added LLM note
Signed-off-by: snipe <snipe@snipe.net>
2024-10-15 10:30:34 +01:00
snipe ddead359d0 Merge pull request #15660 from Toreg87/fixes/api_asset_create_fmcs2
Refactor asset creation with API
2024-10-14 14:29:34 +01:00
Tobias Regnery f3c4e55667 Refactor asset creation with API
Commit fb4fe3004 restored the previous behaviour to check the company_id in case of FullMultipleCompanySupport.
But after rereading the code and the laravel documentation, the check is already there where it belongs in AssetStoreRequest::prepareForValidation()
The bug is the is_int-check of the request input in prepareForValidation(). Is is of type string even if it is a numeric value, so the call to getIdForCurrentUser() never happend.
Fix this by removing the check and the now redundant call to getIdForCurrentUser().
Wrong values will get caught by the model-level validation rules.
2024-10-14 15:14:41 +02:00
snipe 0d35335da7 Removed debugging
Signed-off-by: snipe <snipe@snipe.net>
2024-10-11 16:06:17 +01:00
snipe feaa714304 Nicer disabled button
Signed-off-by: snipe <snipe@snipe.net>
2024-10-11 14:23:57 +01:00
snipe e1a70023b1 Merge pull request #15655 from Toreg87/fixes/api_asset_create_fmcs
Fixes #15654 Fix asset creation with API and FullMultipleCompanySupport
2024-10-11 11:45:48 +01:00
snipe de62359c67 Merge pull request #15533 from marcusmoore/testing/fmcs-accessories
Added tests for accessory api controller
2024-10-11 11:29:34 +01:00
snipe 12bda8fc7b Merge pull request #15653 from snipe/15651_admin_user_on_maintenances
Fixed #15651 - admin user now displaying on maintenances page
2024-10-11 11:27:18 +01:00
Tobias Regnery fb4fe30049 Fix asset creation with API and FullMultipleCompanySupport
It is currently possible to create an asset with arbitrary company without being superuser and FullMultipleCompanySupport enabled.
This bug goes back to 75ac7f80b9 which is part of version 6.3.0.
Fix this by restoring the previous behaviour to check the company_id with getIdForCurrentUser().
2024-10-11 12:19:20 +02:00
snipe b054017c9f Fixed #15651 - admin user now displaying on maintenances page
Signed-off-by: snipe <snipe@snipe.net>
2024-10-11 11:16:24 +01:00
bryanlopezinc 524a442724 Improved import performance 2024-10-10 23:32:07 +01:00
snipe 8aa298f6b0 Merge pull request #15644 from snipe/form_requests_for_settings
Form requests for settings
2024-10-10 12:30:53 +01:00
snipe 1f34657734 Fixed test
Signed-off-by: snipe <snipe@snipe.net>
2024-10-10 12:30:35 +01:00
snipe 0856ee648e Merge pull request #15648 from snipe/update_packages
Updated livewire to 3.5.2
2024-10-10 12:23:14 +01:00
snipe 1dafc970df Updated livewire to 3.5.2
Signed-off-by: snipe <snipe@snipe.net>
2024-10-10 12:19:57 +01:00
snipe 94a074a193 Merge pull request #15601 from snipe/check_db_on_healthcheck
Fixed #15439 - check database on healthcheck
2024-10-10 01:11:10 +01:00
snipe 2d49e1eff2 Merge pull request #15637 from akemidx/bug/sc-26614
FIXED: Badge counter showing deleted assets on User page
2024-10-10 01:09:11 +01:00
snipe 705bc6f0c0 Merge pull request #15642 from uberbrady/fix_bulk_checkout
Fix bulk checkout to users, assets, and locations
2024-10-10 01:08:25 +01:00
snipe b5b93fdd3a Make ldap username required
Signed-off-by: snipe <snipe@snipe.net>
2024-10-10 00:27:00 +01:00
snipe d9432baf7a Mlore ldap style improvements
Signed-off-by: snipe <snipe@snipe.net>
2024-10-09 23:51:20 +01:00
snipe 90be2a4498 Use newer naming convention for errors
Signed-off-by: snipe <snipe@snipe.net>
2024-10-09 22:26:30 +01:00
snipe 3886da8941 Remove form request from get LDAP method
Signed-off-by: snipe <snipe@snipe.net>
2024-10-09 22:15:49 +01:00
snipe 130e0c6242 More validation
Signed-off-by: snipe <snipe@snipe.net>
2024-10-09 22:15:37 +01:00
snipe 4361a10818 Added string
Signed-off-by: snipe <snipe@snipe.net>
2024-10-09 22:15:30 +01:00
snipe aa8048ac15 Blade changes for ldap
Signed-off-by: snipe <snipe@snipe.net>
2024-10-09 22:15:25 +01:00
snipe 710e738e8e Fixed tests
Signed-off-by: snipe <snipe@snipe.net>
2024-10-09 22:15:16 +01:00
snipe 3705b91439 Added more validation
Signed-off-by: snipe <snipe@snipe.net>
2024-10-09 20:51:34 +01:00
snipe 707bdad192 Updated test
Signed-off-by: snipe <snipe@snipe.net>
2024-10-09 20:33:56 +01:00
snipe 242fe33f97 Switch to regular HTML input
Signed-off-by: snipe <snipe@snipe.net>
2024-10-09 20:33:42 +01:00
snipe ded79469c1 Remove unused controller method
Signed-off-by: snipe <snipe@snipe.net>
2024-10-09 20:33:29 +01:00
snipe d9fbf330e5 Fixed translations
Signed-off-by: snipe <snipe@snipe.net>
2024-10-09 20:33:15 +01:00
snipe 2cb9ac26cd Renamed test
Signed-off-by: snipe <snipe@snipe.net>
2024-10-09 19:57:04 +01:00
snipe 185bc966e6 Cleaned up use statements in tests
Signed-off-by: snipe <snipe@snipe.net>
2024-10-09 19:46:47 +01:00
snipe a7f7e4938f Added form action
Signed-off-by: snipe <snipe@snipe.net>
2024-10-09 19:31:56 +01:00
snipe 2883e79193 Removed unecessary assets creation
Signed-off-by: snipe <snipe@snipe.net>
2024-10-09 19:30:55 +01:00
snipe 9c4191ae0a Basic tests
Signed-off-by: snipe <snipe@snipe.net>
2024-10-09 19:30:42 +01:00
snipe 3a77b83e9c Added space
Signed-off-by: snipe <snipe@snipe.net>
2024-10-09 19:30:34 +01:00
snipe d9be2b5a5e Trying to use the email_array translation
Signed-off-by: snipe <snipe@snipe.net>
2024-10-09 19:30:25 +01:00
snipe 69c43c610c Fixed typo
Signed-off-by: snipe <snipe@snipe.net>
2024-10-09 19:30:00 +01:00
snipe 4f957bcf71 Required flag
Signed-off-by: snipe <snipe@snipe.net>
2024-10-09 18:34:53 +01:00
snipe 5cda7cce48 Only accept a positive number for thresholds
Signed-off-by: snipe <snipe@snipe.net>
2024-10-09 18:21:40 +01:00
snipe 41b94e7128 Fixed form input group
Signed-off-by: snipe <snipe@snipe.net>
2024-10-09 18:19:26 +01:00
snipe aa55fa6ff4 Switch to form requests for settings
Signed-off-by: snipe <snipe@snipe.net>
2024-10-09 18:16:34 +01:00
Brady Wetherington 67a605c9a5 Fix bulk checkout to users, assets, and locations 2024-10-09 17:01:26 +01:00
akemidx c2663ea1e0 withouttrashed 2024-10-08 16:38:33 -04:00
snipe 3ee5713740 Merge pull request #15631 from snipe/test/importer-tests
Add importer tests
2024-10-07 23:13:15 +01:00
snipe ab8a22f77e Merge pull request #15630 from marcusmoore/bug/sc-27028
Only show EULA when available on print users page
2024-10-07 22:56:23 +01:00
snipe 56e7ea6677 Merge pull request #15616 from marcusmoore/test/importer-test-updates
Improve importer tests
2024-10-07 22:29:35 +01:00
snipe 26d7572bcc Merge pull request #15603 from marcusmoore/fixes/add-reguard
Added `Model::reguard()` to importer
2024-10-07 22:28:53 +01:00
Marcus Moore 8c9132aff9 Hide EULA text and button when nothing will be displayed 2024-10-07 14:22:49 -07:00
snipe 382ebef8ca Merge pull request #15621 from sniff122/develop
Docker Env: Change trusted proxies to RFC1918
2024-10-07 21:26:21 +01:00
snipe 2be88cb955 Merge pull request #15624 from snipe/fixed_line_break_on_print_all_for_users
Removed duplicate JS and removed line break before user section
2024-10-07 11:14:24 +01:00
snipe 3f36d5f9b3 Removed duplicate CSS and removed line break before user section
Signed-off-by: snipe <snipe@snipe.net>
2024-10-07 11:08:02 +01:00
Lewis Foster f76da48448 Docker Env: Change trusted proxies to RFC1918 2024-10-05 18:27:42 +01:00
Marcus Moore 8035326675 Add test 2024-10-03 16:53:19 -07:00
Marcus Moore dfdd85abb1 Remove unused imports 2024-10-03 15:14:07 -07:00
Marcus Moore 063ea1892b Add trait to clean up files after test runs 2024-10-03 15:02:03 -07:00
Marcus Moore e213053775 Swap factory syntax 2024-10-03 13:59:58 -07:00
Marcus Moore 88d549e7c5 Remove unused data provider method 2024-10-03 13:40:37 -07:00
Marcus Moore 983a25aa5f Simplify permission tests 2024-10-03 13:39:54 -07:00
Marcus Moore bde05d6ed9 Use new() instead of times() 2024-10-03 13:15:49 -07:00
Marcus Moore b5ffe54bd0 Swap assertEquals parameter order 2024-10-03 13:15:02 -07:00
Marcus Moore 863c0a8b60 Fix import_type for accessory state 2024-10-03 11:43:02 -07:00
Marcus Moore 32551d55d7 Merge pull request #15579 from bryanlopezinc/ImportTests
Add Import data tests
2024-10-03 11:39:21 -07:00
snipe 7fc498a597 Merge pull request #15613 from snipe/css_fixes_for_long_values
Smarter word-wrapping on long text
2024-10-03 17:39:18 +01:00
snipe cb281c6408 Tweaked line height
Signed-off-by: snipe <snipe@snipe.net>
2024-10-03 17:33:46 +01:00
snipe f483cd448f Smarter work-wrapping on long text
Signed-off-by: snipe <snipe@snipe.net>
2024-10-03 17:27:37 +01:00
snipe 78ca1026fd Merge pull request #15612 from snipe/fixes_print_assigned_in_profile
Fixes print assigned in profile
2024-10-03 16:24:32 +01:00
snipe 722d5a58e7 Added isset on users
Signed-off-by: snipe <snipe@snipe.net>
2024-10-03 16:19:38 +01:00
snipe 7461c3e0ca Change controller to assume a collection. (This is dumb, but whatever)
Signed-off-by: snipe <snipe@snipe.net>
2024-10-03 16:19:27 +01:00
snipe 3c0f4181ae Use the newer button style
Signed-off-by: snipe <snipe@snipe.net>
2024-10-03 16:19:06 +01:00
snipe 3699d79363 Merge pull request #15610 from uberbrady/fix_numeric_sort_bug
Fix numeric sort 'ambiguous order clause' error
2024-10-03 14:34:00 +01:00
Brady Wetherington 350b627ce1 Fix numeric sort 'ambiguous order clause' error 2024-10-03 14:23:40 +01:00
Marcus Moore ee046a8688 Add matching Model::reguard() 2024-10-02 10:50:40 -07:00
snipe b34a7c8aad Removed die()
Signed-off-by: snipe <snipe@snipe.net>
2024-10-02 15:48:35 +01:00
snipe f92bf5dc20 Updated language for failure
Signed-off-by: snipe <snipe@snipe.net>
2024-10-02 15:39:27 +01:00
snipe 4d9e85026a Fixed #15439 - check database on healthcheck
Signed-off-by: snipe <snipe@snipe.net>
2024-10-02 15:36:01 +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
spencerrlongg 3153bbb13f dumb fix 2024-10-01 17:04:18 -05:00
Marcus Moore 3dc64cc5e0 Reference accessory checkout and not the accessory 2024-10-01 13:35:39 -07: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
Marcus Moore 5b90d79494 Use created_by 2024-10-01 11:50:48 -07: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
Marcus Moore fdfea390fb Merge branch 'develop' into testing/fmcs-accessories 2024-09-30 12:59:27 -07: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
bryanlopezinc e807cfab86 Merge branch 'develop' into importTests 2024-09-30 12:47:52 +01:00
bryanlopezinc 0b3f458561 Added tests for Import feature 2024-09-30 12:42:41 +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 3f74ff25d2 fixed error message 2024-09-25 16:19:09 -07: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
Brady Wetherington b6340532d7 Improve the error and success messages and linking 2024-09-24 17:15:39 +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
Brady Wetherington c71411465a First pass at better-handling those annoying Rollbars we keep getting 2024-09-24 15:17:35 +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
Marcus Moore d609ed50a4 Merge branch 'develop' into testing/fmcs-accessories 2024-09-19 13:20:55 -07: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
Marcus Moore d639d6fbc1 Add tests for accessory select list endpoint 2024-09-19 12:21:54 -07:00
snipe 74088ea581 Optimize isDeletable counts
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 20:13:38 +01:00
Marcus Moore fff069824b Add tests for update accessory endpoint 2024-09-19 12:11:03 -07: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
Marcus Moore a5be18bb14 Add test for limit and offset 2024-09-19 11:55:15 -07: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
Marcus Moore 2137890496 Remove dead code 2024-09-19 11:33:20 -07:00
snipe ebf6ce6980 Refactor for fewer queries
Signed-off-by: snipe <snipe@snipe.net>
2024-09-19 19:27:10 +01:00
Marcus Moore 9b22d6d493 Add tests for accessory checkouts endpoint 2024-09-19 11:24:01 -07: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
Marcus Moore 86f13a9735 Add index test 2024-09-18 16:13:34 -07:00
Godfrey M c40209f500 seperates emails and webhook notifications 2024-09-18 15:23:44 -07:00
Marcus Moore a071fff954 Implement tests 2024-09-18 12:32:14 -07:00
Marcus Moore 8b50ef077d Implement test 2024-09-18 11:58:33 -07:00
Marcus Moore 607f29030f Stub out test 2024-09-18 11:53:27 -07:00
Marcus Moore a6bcd3c0c2 Add validation test 2024-09-18 11:47:59 -07:00
Marcus Moore 9b293afaac Remove more dead code 2024-09-18 11:28:29 -07:00
Marcus Moore 636c776620 Remove dead code 2024-09-18 11:27:37 -07:00
Marcus Moore d5f659024c Add test for logging 2024-09-18 11:27:09 -07:00
Marcus Moore 832e50a71e Implement test 2024-09-18 11:19:41 -07:00
Marcus Moore fa19686248 Implement test 2024-09-18 11:18:21 -07:00
Marcus Moore c021609c13 Merge branch 'develop' into testing/fmcs-accessories 2024-09-18 10:42:58 -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
Marcus Moore 7b31df7c14 Begin additional test case 2024-09-17 09:11:58 -07: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 12fd9cd97a Update interface name 2024-09-16 17:00:08 -07:00
Marcus Moore 9e03c4ba6f Merge branch 'testing/fmcs' into testing/fmcs-accessories 2024-09-16 16:58:46 -07:00
Marcus Moore 3519a82ddd Fix name: TestsFullMultipleCompaniesSupport 2024-09-16 16:55:20 -07:00
Marcus Moore 8eb1c487bc implement FMCS test for accessory index 2024-09-16 16:52:10 -07:00
Marcus Moore e835637ef0 Add accessory checkin test 2024-09-16 16:40:10 -07:00
Marcus Moore eb35608bb5 Remove call handled by form request 2024-09-16 16:35:33 -07:00
Marcus Moore 3f07f682de Migrate existing tests to TestsPermissionsRequirement 2024-09-16 16:35:21 -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
snipe 85486fa58c Merge remote-tracking branch 'origin/develop' 2024-08-15 10:53:54 +01:00
snipe 10dc1f1368 Re-pull the accessory checkout
Signed-off-by: snipe <snipe@snipe.net>
2024-08-15 10:51:49 +01:00
snipe 3618df2ec5 Merge remote-tracking branch 'origin/develop' 2024-08-15 10:44:39 +01:00
snipe 8f7bce7aad Re-added UI for checkout to non-users for accessories
Signed-off-by: snipe <snipe@snipe.net>
2024-08-15 10:44:27 +01:00
snipe a201f22fdb Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2024-08-15 10:36:12 +01:00
snipe 6070d530cf Merge remote-tracking branch 'origin/develop' 2024-08-15 10:35:33 +01:00
snipe 4d66f7c93f Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2024-08-15 10:35:02 +01:00
snipe 6c0cf94473 Merge remote-tracking branch 'origin/develop' 2024-08-15 10:28:08 +01:00
snipe 381003eeab Cleaned up asset tag field on quickscan checkin
Signed-off-by: snipe <snipe@snipe.net>
2024-08-15 10:27:31 +01:00
snipe c3d4c821f3 Merge pull request #15303 from snipe/features/#15301_optional_status_to_quickscan_checkin
Fixed #15301 - Added optional status to quickscan checkin
2024-08-15 10:26:04 +01:00
snipe d8038ac483 Removed status label list
Signed-off-by: snipe <snipe@snipe.net>
2024-08-15 10:17:08 +01:00
snipe d268f25f16 Make asset tag required
Signed-off-by: snipe <snipe@snipe.net>
2024-08-15 10:16:57 +01:00
snipe 01c69c8f8f Allow optional status label on quickscan checkin
Signed-off-by: snipe <snipe@snipe.net>
2024-08-15 10:08:48 +01: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
snipe 3e29457094 Merge pull request #15292 from snipe/features/updated_phpinsights
Updated phpinsights
2024-08-14 12:12:40 +01:00
snipe 0b3ac2a9cd Updated phpinsights
Signed-off-by: snipe <snipe@snipe.net>
2024-08-14 12:08:49 +01:00
snipe bf4b915168 Merge remote-tracking branch 'origin/develop' 2024-08-14 10:45:13 +01:00
snipe 0f1e5181a6 Nicer input layout for bulk edit name
Signed-off-by: snipe <snipe@snipe.net>
2024-08-14 10:09:14 +01:00
snipe 0a9c2e354f Merge remote-tracking branch 'origin/develop' 2024-08-14 10:02:43 +01:00
snipe e544007185 Merge pull request #15291 from snipe/features/bulk_update_asset_name
Added asset name to bulk asset edit
2024-08-14 10:02:09 +01:00
snipe 4b690e8e1f Updated test to check for nulling
Signed-off-by: snipe <snipe@snipe.net>
2024-08-14 10:01:56 +01:00
snipe 371afde52d Bulk edit asset name
Signed-off-by: snipe <snipe@snipe.net>
2024-08-14 09:52:25 +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
snipe 7a6a2e3d92 Merge pull request #15290 from marcusmoore/test-fixes
Fixed component check in test
2024-08-14 00:00:55 +01:00
Marcus Moore 3f8ac59f4c Reference the entry in the components_assets table 2024-08-13 15:31:16 -07:00
snipe 74e7b1cfa5 Merge pull request #15286 from marcusmoore/test-updates
Implemented artisan test case
2024-08-13 20:46:46 +01:00
Marcus Moore ae0a6d66f3 Update tests
https://masteringlaravel.io/daily/2024-02-09-watch-out-for-this-when-testing-artisan-commands
2024-08-13 12:16:08 -07:00
Marcus Moore 321839e074 Fix namespace 2024-08-13 12:14:56 -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
snipe e9fc455a30 Merge pull request #15192 from Godmartinz/status_labels_check_emails
Added status labels to confirmation emails
2024-08-13 18:24:15 +01:00
Godfrey M 8af4126de1 removed indent from blades 2024-08-13 10:21:33 -07:00
Godfrey M 5d1c48c071 fixes alignment, and box issue with pie chart 2024-08-13 10:11:49 -07:00
snipe 47f1b3b14e 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-13 16:48:06 +01:00
snipe 3044af9410 Merge pull request #15280 from snipe/bug/sc-23294
Fixed select2 “x” color on multi-select and border color
2024-08-13 16:46:56 +01:00
snipe 4f0f0af83b Make the border radius match the rest of the site
Signed-off-by: snipe <snipe@snipe.net>
2024-08-13 16:46:26 +01:00
snipe 198afee946 Fixed select2 “x” color on mult-select and border color
Signed-off-by: snipe <snipe@snipe.net>
2024-08-13 16:42:23 +01:00
snipe def0af652d Merge pull request #15279 from TelecomsSansFrontieres/fix_missing-translate-item-assets
Fix: add missing admin/hardware/table.name key
2024-08-13 16:35:25 +01:00
Florent Bervas 20e4ba0590 lang: relocated translation key to existing item in general 2024-08-13 15:07:54 +00:00
snipe 72fd9977e5 Merge pull request #15277 from uberbrady/silence_saml_errors
Fixed: [sc-26355] Attempt to de-escalate SAML login and logout errors
2024-08-13 15:51:03 +01:00
Brady Wetherington 10f35c682b Re-add space 2024-08-13 15:49:51 +01:00
snipe 198b76ebc2 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-13 15:47:00 +01:00
snipe 6e84c29ce4 Merge pull request #15278 from snipe/print_view_improvements
Fixed #14821 - Hide UI elements from print view on assets
2024-08-13 15:45:30 +01:00
snipe 389a06aac5 Hide UI elements from print view on assets
Signed-off-by: snipe <snipe@snipe.net>
2024-08-13 15:40:51 +01:00
Brady Wetherington 4b96721393 Attempt to de-escalate SAML login and logout errors 2024-08-13 14:55:13 +01:00
snipe e42ee0c0e1 Merge pull request #15276 from snipe/css_updates
Bold selected tab for better readability
2024-08-13 14:21:45 +01:00
snipe 277a0fd16a Make selected tab bold
Signed-off-by: snipe <snipe@snipe.net>
2024-08-13 14:19:41 +01:00
snipe c163d6774f Merge pull request #15198 from spencerrlongg/feature/add_trait_to_request
Add MayContainCustomFields Trait to Asset Update Request
2024-08-13 14:12:52 +01:00
snipe 5546f9676a Merge remote-tracking branch 'origin/develop' 2024-08-13 13:51:33 +01:00
snipe 9e73eaf955 Merge pull request #15275 from snipe/added_tooltips_to_top_bar
Added tooltips to top nav shortcuts
2024-08-13 13:50:27 +01:00
snipe 1b2094f4e2 Added tooltips to top nav shortcuts
Signed-off-by: snipe <snipe@snipe.net>
2024-08-13 13:49:13 +01: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
snipe 46caa478d2 Merge remote-tracking branch 'origin/develop' 2024-08-12 20:47:45 +01:00
snipe e6106aa7cf Merge pull request #15272 from snipe/fixes/added_selectlist_permission_for_reports
Added reporting-only access for selectlists
2024-08-12 20:47:17 +01:00
snipe b45a8f4b5f Added reporting-only access for selectlists
Signed-off-by: snipe <snipe@snipe.net>
2024-08-12 20:44:17 +01:00
snipe 4d8569e754 Merge remote-tracking branch 'origin/develop' 2024-08-12 18:01:21 +01:00
snipe c9f8a84d48 Merge pull request #15270 from snipe/fixes/make_dashboard_pie_respect_show_in_list
Fixed #15247 - make pie chart on dashboard respect the “show archived…
2024-08-12 17:59:27 +01:00
snipe ac1543d568 Fixed #15247 - make pie chart on dashboard respect the “show archived” setting
Signed-off-by: snipe <snipe@snipe.net>
2024-08-12 17:54:42 +01:00
snipe 4dc57f95e2 Merge remote-tracking branch 'origin/develop' 2024-08-12 16:38:23 +01:00
snipe 9d354ca657 Merge pull request #15266 from uberbrady/checkout_to_fixer
Checkout-to fixer
2024-08-12 16:34:19 +01:00
snipe 316ee6f810 Merge remote-tracking branch 'origin/develop' 2024-08-12 16:30:53 +01:00
snipe 3f2139349e Allow better fallthrough on image
Signed-off-by: snipe <snipe@snipe.net>
2024-08-12 16:30:21 +01:00
snipe f56dd582f9 Merge pull request #15269 from snipe/fixes/smaller_email_logo
Fixes ##15236 - smaller email logo
2024-08-12 16:27:59 +01:00
snipe 225ab47b8e Simplified logic
Signed-off-by: snipe <snipe@snipe.net>
2024-08-12 16:23:09 +01:00
snipe 4c350bd5a3 Remove the regular logo fallback, make image capped by height
Signed-off-by: snipe <snipe@snipe.net>
2024-08-12 16:21:58 +01:00
snipe 509cc812ea Merge remote-tracking branch 'origin/develop' 2024-08-12 15:58:40 +01:00
snipe e7fb29fced Fixed copy area for serial
Signed-off-by: snipe <snipe@snipe.net>
2024-08-12 15:58:30 +01:00
Brady Wetherington a2d11b43de Whoops, these were accidentally committed 2024-08-12 13:50:46 +01:00
Brady Wetherington f80cf666b1 Mark tests as incomplete for the new artisan assigned_to fixer 2024-08-12 13:46:56 +01:00
snipe d5f66bc0dd Merge remote-tracking branch 'origin/develop' 2024-08-12 10:10:59 +01:00
snipe ce5be8ac24 Merge pull request #15100 from Godmartinz/depreciation_percentage
Added Depreciation Percentage as an option
2024-08-12 10:10:25 +01:00
snipe 1e213c31ef Merge remote-tracking branch 'origin/develop' 2024-08-11 10:26:16 +01:00
snipe 1777bb4b93 Pulled searchable relation on model - needs revisit
Signed-off-by: snipe <snipe@snipe.net>
2024-08-11 10:26:02 +01:00
snipe 91874dfe0b Merge remote-tracking branch 'origin/develop' 2024-08-10 19:37:37 +01:00
snipe 5c6c655cdc Added sounds to quickscan checkin
Signed-off-by: snipe <snipe@snipe.net>
2024-08-10 19:37:18 +01:00
snipe 0e6eda5e8a Merge remote-tracking branch 'origin/develop' 2024-08-10 18:29:41 +01:00
snipe 60eb602156 Merge pull request #15264 from snipe/fixes/fixed_admin_ordering_on_report
Fixed #15252 - admin ordering on activity report
2024-08-10 18:26:15 +01:00
snipe 24560b9362 Updated prod assets
Signed-off-by: snipe <snipe@snipe.net>
2024-08-10 18:24:49 +01:00
snipe 76b114d820 Added test
Signed-off-by: snipe <snipe@snipe.net>
2024-08-10 18:21:41 +01:00
snipe ce33deed86 Remove unused use statement
Signed-off-by: snipe <snipe@snipe.net>
2024-08-10 17:14:34 +01:00
snipe 1e6c172f18 Removed unusued use statement
Signed-off-by: snipe <snipe@snipe.net>
2024-08-10 17:14:20 +01:00
snipe a1ce9b9285 Added query scope for ordering by admin
Signed-off-by: snipe <snipe@snipe.net>
2024-08-10 17:00:50 +01:00
snipe 6ec3693030 Load admin on actionlog
Signed-off-by: snipe <snipe@snipe.net>
2024-08-10 17:00:34 +01:00
snipe 71729f0b16 Load admin and model on assets
Signed-off-by: snipe <snipe@snipe.net>
2024-08-10 17:00:20 +01:00
snipe 1c229a8e08 Made notes field sortable
Signed-off-by: snipe <snipe@snipe.net>
2024-08-10 17:00:11 +01:00
snipe 07b1e3fb90 Fixed tests
Signed-off-by: snipe <snipe@snipe.net>
2024-08-10 16:55:48 +01:00
snipe 6294516271 Merge pull request #15263 from snipe/really/remove_pound_sign_for_order_number
Fixed #15248 Removed pound symbol from order number on asset view
2024-08-10 16:18:40 +01:00
snipe f3331b5045 Removed pound symbol from order number on asset view
Signed-off-by: snipe <snipe@snipe.net>
2024-08-10 16:17:07 +01:00
snipe 6a06a91fa2 Merge pull request #15262 from snipe/synk/jquery-validation-from-1.20.1-to-1.21.0
Upgrade jquery-validation from 1.20.1 to 1.21.0
2024-08-10 16:07:47 +01:00
snipe 0cba5ba67e Upgrade jquery-validation from 1.20.1 to 1.21.0
Signed-off-by: snipe <snipe@snipe.net>
2024-08-10 16:06:14 +01:00
snipe b815352a45 Merge pull request #15261 from snipe/security/upgrade_fontawesome
[Snyk] Upgrade @fortawesome/fontawesome-free from 6.5.2 to 6.6.0
2024-08-10 15:57:10 +01:00
snipe 2f299dbb20 Upgrade fontawesome, generate dev assets
Signed-off-by: snipe <snipe@snipe.net>
2024-08-10 15:51:24 +01:00
snipe f76fbe75e0 Merge pull request #15221 from marcusmoore/fixes/bulk-checkin-logging
Fixed accessories and consumables not being logged correctly during bulk check-in
2024-08-08 10:43:59 +01:00
snipe cc1e356c35 Merge pull request #15232 from marcusmoore/shift-126036
Updated PHPUnit to v10
2024-08-08 01:23:07 +01:00
snipe 8094f3c0e1 Merge pull request #15245 from spencerrlongg/bug/acceptance_issue
Fixed Issue with Acceptances Being Created
2024-08-08 01:22:34 +01:00
snipe 900beaa955 Merge pull request #15244 from snipe/features/play_sound_on_audit
Fixes #10560 - optional ability to play sound on audit
2024-08-08 00:58:30 +01: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
spencerrlongg 2412333152 added conditional to listener 2024-08-07 16:53:06 -05:00
Marcus Moore 4a2d2f7336 Improve variable name 2024-08-07 13:32:30 -07:00
Marcus Moore d03baa4613 Make diff cleaner 2024-08-07 13:29:45 -07:00
Marcus Moore 41437e4d8f Merge branch 'develop' into fixes/bulk-checkin-logging
# Conflicts:
#	app/Http/Controllers/Users/BulkUsersController.php
2024-08-07 13:06:59 -07:00
snipe 7d220dd8c2 set default
Signed-off-by: snipe <snipe@snipe.net>
2024-08-07 20:58:04 +01:00
snipe a99ec062e6 Added checkbox for preferences
Signed-off-by: snipe <snipe@snipe.net>
2024-08-07 20:49:07 +01:00
snipe 8fe6395287 Added migration
Signed-off-by: snipe <snipe@snipe.net>
2024-08-07 20:41:13 +01:00
snipe b4d51599ee Added sound effects
Signed-off-by: snipe <snipe@snipe.net>
2024-08-07 20:38:50 +01:00
snipe 9350a20189 Include accessories count
This isn’t exactly right right now

Signed-off-by: snipe <snipe@snipe.net>
2024-08-07 20:19:47 +01:00
snipe 889d5da71e Check for accessories on bulk items
Signed-off-by: snipe <snipe@snipe.net>
2024-08-07 20:04:32 +01:00
snipe 5546ab08c2 Only delete user records in accessories_checkouts for bulk delete
Signed-off-by: snipe <snipe@snipe.net>
2024-08-07 19:53:18 +01:00
snipe ef183f256c Merge pull request #15242 from Godmartinz/shortcut_option
Fixed shortcuts to be optional now
2024-08-07 18:56:27 +01:00
Godfrey M 3a96e501cc use old school input 2024-08-07 10:54:06 -07:00
Godfrey M 6b1784f2ee makes shortcuts optional 2024-08-07 10:47:16 -07:00
snipe 1a872b1643 Merge remote-tracking branch 'origin/develop' 2024-08-07 18:15:44 +01:00
snipe deef9ad181 Merge pull request #15241 from snipe/partial_revert_for_checkout_accessories_to_non_user
Partial revert for checkout accessories to non user
2024-08-07 18:15:08 +01:00
snipe 0dc7e8b8dc Temp removed other selector
Signed-off-by: snipe <snipe@snipe.net>
2024-08-07 18:04:52 +01:00
snipe a5f075548a Default to user
Signed-off-by: snipe <snipe@snipe.net>
2024-08-07 18:04:39 +01:00
Brady Wetherington 1706ddd511 working fixup script, but failing tests. But I have tests! 2024-08-07 16:06:00 +01:00
Marcus Moore a220986d16 Switch to snake case 2024-08-06 16:13:51 -07:00
Marcus Moore 2a8ac81eed Fix namespace 2024-08-06 15:22:13 -07:00
Marcus Moore d3cb3c03d2 Rerun composer update using php 8.1 2024-08-06 15:01:01 -07:00
Marcus Moore c60bc5cdbe Change indents back to 2 2024-08-06 13:51:44 -07:00
Marcus Moore 6cfbf835c7 Migrate phpunit.xml
vendor/bin/phpunit --migrate-configuration
2024-08-06 13:37:53 -07:00
Marcus Moore 047b77e038 Composer update for phpunit, collision, and paratest
composer update phpunit/phpunit nunomaduro/collision brianium/paratest --with-all-dependencies
2024-08-06 13:34:51 -07:00
snipe 766b370264 Merge pull request #15229 from marcusmoore/bug/sc-26552
Disallowed checking out components to different companies and fixed number remaining counts
2024-08-06 21:33:55 +01:00
snipe da33277234 Merge pull request #15230 from marcusmoore/fixes/test-namespaces
Fixed handful of test namespaces
2024-08-06 21:32:11 +01:00
Marcus Moore 3e832e5e94 Revert "Define test classes as final"
This reverts commit 95516b0343.
2024-08-06 13:31:17 -07:00
Marcus Moore 82e795b642 Revert "Add return types to test methods"
This reverts commit 83fb6826ee.
2024-08-06 13:30:34 -07:00
Shift 95516b0343 Define test classes as final 2024-08-06 20:25:22 +00:00
Shift 83fb6826ee Add return types to test methods 2024-08-06 20:25:22 +00:00
Shift b1e92ab866 Declare data providers as static 2024-08-06 20:25:21 +00:00
Shift 96241cb67c Adopt PHP attributes in test classes 2024-08-06 20:25:21 +00:00
Shift b680dab5c9 Ignore PHPUnit cache folder 2024-08-06 20:25:19 +00:00
Shift 984840dc82 Bump PHPUnit dependencies 2024-08-06 20:25:18 +00:00
Marcus Moore 84e447af09 Fix test namespaces 2024-08-06 13:21:36 -07:00
Marcus Moore c7ddabcc8b Check for FMCS when checking out component 2024-08-06 12:27:15 -07:00
Marcus Moore bee80fcf8a Remove global scope when counting check outs 2024-08-06 12:16:06 -07:00
Marcus Moore 0aff35b622 Scaffold additional failed tests 2024-08-06 12:07:34 -07:00
Godfrey M 46a6a84ecb adds migration and translations 2024-08-06 11:07:39 -07:00
Marcus Moore 374812f8fe Add failing test 2024-08-06 10:48:38 -07:00
Marcus Moore 94e00b8a3e Use new accessory checkout relationship 2024-08-05 17:26:11 -07:00
Marcus Moore f2b78d18a4 Merge branch 'develop' into fixes/bulk-checkin-logging
# Conflicts:
#	app/Http/Controllers/Users/BulkUsersController.php
2024-08-05 17:25:54 -07:00
Marcus Moore 17eccfcd8b Formatting 2024-08-05 16:58:27 -07:00
Marcus Moore 01e4382d20 Formatting 2024-08-05 16:58:17 -07:00
Marcus Moore 1c664af326 Remove todo outside of scope 2024-08-05 16:58:08 -07:00
Marcus Moore 392d34422a Remove code handled by ConsumableAssignment:: call above 2024-08-05 16:57:40 -07:00
Marcus Moore 35e7a3163c Implement test case 2024-08-05 16:54:31 -07:00
Marcus Moore 96fafa6952 Improve readability 2024-08-05 16:36:29 -07:00
Marcus Moore a55693211f Move test class 2024-08-05 16:27:04 -07:00
Marcus Moore 1acd24fdbe Re-order helpers 2024-08-05 16:26:25 -07:00
Marcus Moore 59b7d5db4b Remove comment 2024-08-05 16:25:14 -07:00
Marcus Moore 16aa47509b Implement test for assets 2024-08-05 16:24:52 -07:00
Marcus Moore d1bb3ef6bf Scaffold two tests 2024-08-05 16:19:09 -07:00
Marcus Moore 5cd9dd4a67 Add assertion to ensure user cannot perform bulk actions on self 2024-08-05 16:17:24 -07:00
Marcus Moore fc405d9d73 Assert redirected to correct place 2024-08-05 16:14:01 -07:00
Marcus Moore 5786ff5035 Add assertion for success message 2024-08-05 16:11:07 -07:00
Marcus Moore 8a206a6d92 Add assertion 2024-08-05 16:10:12 -07:00
Marcus Moore 67b3ab820f Add todo comments 2024-08-05 16:10:08 -07:00
Marcus Moore b06501dd02 Add assertions 2024-08-05 16:02:59 -07:00
Marcus Moore e3049fffd4 Remove comment 2024-08-05 15:50:53 -07:00
Marcus Moore 5ecdb7e07c Add validation test 2024-08-05 15:50:09 -07:00
Marcus Moore 4ed3347f52 Add permission check 2024-08-05 15:43:38 -07:00
Marcus Moore 364775dcfe Improve readability 2024-08-05 15:42:03 -07:00
Marcus Moore bfebcdc7ed Improve variable name 2024-08-05 15:22:35 -07:00
Marcus Moore 480e4f3a69 Improve readability 2024-08-05 15:16:40 -07:00
Marcus Moore 78a0417ee9 Add another user into the mix 2024-08-05 15:11:18 -07:00
snipe b83d148b37 Merge pull request #15217 from TelecomsSansFrontieres/feature_extend-search-by-tag
Feature: Extend search capabilities to other assets attributes
2024-08-05 15:38:51 +01:00
Florent Bervas ad794248fe add a warning message if asset tag not found 2024-08-05 13:54:33 +00:00
Florent Bervas b804791ff6 feature: extend search capabilities to other assets attributes 2024-08-05 12:26:29 +00:00
snipe c45bf870b7 Merge pull request #15211 from snipe/feaures/15205_copy_asset_tag
Fixed #15205 - adds copy to asset tag
2024-08-02 20:59:53 +01:00
snipe a0bd8b6049 Fixed #15205 - adds copy to asset tag
Signed-off-by: snipe <snipe@snipe.net>
2024-08-02 20:56:31 +01:00
Godfrey M ae4f278df1 edited terenaries on notifs 2024-08-01 11:13:20 -07:00
Godfrey M bc0ff706b0 fixes dashboard box overflow 2024-08-01 10:31:39 -07:00
snipe 28abb8d8cc Hotfix for 405 update asset
Signed-off-by: snipe <snipe@snipe.net>
2024-08-01 12:30:35 +01:00
snipe 24d948a3f6 Merge pull request #15204 from snipe/fixes/405_on_api_asset_update
Fixed (temp) put route
2024-08-01 12:28:23 +01:00
snipe c1c9c3554e Fixed (temp) put route
Signed-off-by: snipe <snipe@snipe.net>
2024-08-01 12:27:02 +01:00
snipe fcea564afa Fixed button label
Signed-off-by: snipe <snipe@snipe.net>
2024-07-31 21:44:27 +01:00
snipe f44abd0b28 Fixed button label
Signed-off-by: snipe <snipe@snipe.net>
2024-07-31 21:43:09 +01:00
Godfrey M 854903805b one more spot 2024-07-31 12:16:41 -07:00
Godfrey M 868f117b67 Merge branch 'status_labels_check_emails' of github.com:Godmartinz/snipe-it into status_labels_check_emails 2024-07-31 12:03:56 -07:00
Godfrey M b6cac4baae corrects ? usage 2024-07-31 12:03:36 -07:00
snipe 4fcb3df1d9 Merge pull request #15199 from Godmartinz/fix-signature-pad
adds closing brackets to signature pad
2024-07-31 19:23:33 +01:00
Godfrey M b60e22bcb4 adds closing brackets to signature pad 2024-07-31 11:10:33 -07:00
spencerrlongg 61312c2eec oops, mysql 2024-07-31 12:07:50 -05:00
spencerrlongg b0063b1d4a test written 2024-07-31 11:57:35 -05:00
akemidx fffcbdc44d Merge remote-tracking branch 'upstream/develop' into upstream/dev 2024-07-31 07:14:06 -04:00
akemidx 8d1fa362f7 restoring code 2024-07-31 07:13:42 -04:00
snipe 31a2765b30 Merge pull request #15145 from Godmartinz/purge-storage
Added user storage files to purge command
2024-07-31 10:16:08 +01:00
snipe e79a5b7efe Merge pull request #15193 from Godmartinz/admin-settings
Fixed admin boxes alignment
2024-07-31 08:54:44 +01:00
snipe ca531e85f3 Merge pull request #15194 from spencerrlongg/bug/sc-26247
Fixed A Translation Issue With Auth
2024-07-31 08:54:09 +01:00
spencerrlongg 0941c0944a ok, found issue, but need to test some things now... 2024-07-30 22:55:15 -05:00
spencerrlongg 9b80843c77 tests a little broken, added some nullchecks 2024-07-30 21:44:22 -05:00
spencerrlongg 8684a3efc3 delete note, add trait to other request 2024-07-30 21:22:46 -05:00
akemidx fccfce2ae8 first thought 2024-07-30 19:27:37 -04:00
Godfrey M 935d2ce29a fixes admin box alignment 2024-07-30 15:05:09 -07:00
spencerrlongg 437ddc01b4 removed extraneous $request->validate() arguments 2024-07-30 16:26:24 -05:00
Godfrey Martinez f19e58b352 Merge pull request #21 from Godmartinz/status_labels_check_emails_checkout
adds Status labels to check in and out emails
2024-07-30 09:41:05 -07:00
Godfrey M eb6f330e67 adds status to check in and out 2024-07-30 09:38:39 -07:00
Godfrey M f19899543d changed error to info 2024-07-30 09:18:17 -07:00
snipe 3a2611f8e1 Merge pull request #14565 from spencerrlongg/bug/sc-23936
Checks that custom fields exist before saving
2024-07-30 11:36:55 +01:00
Godfrey M 53ad312700 added missing closing bracket 2024-07-29 15:17:32 -07:00
Godfrey M 89d375daad add indents 2024-07-29 15:15:41 -07:00
Godfrey M d46f9776fe remove text 2024-07-29 15:14:58 -07:00
Godfrey M f9a47c8a9f adds a try catch 2024-07-29 15:12:48 -07:00
Godfrey M e395ee1878 adds a try catch 2024-07-29 15:12:32 -07:00
snipe 4971c54b05 Fixed seeder
Signed-off-by: snipe <snipe@snipe.net>
2024-07-29 20:17:25 +01:00
snipe 4c5b82ae37 Merge pull request #15188 from Godmartinz/1d_barcode_select_bug
Fixed 1d barcode targeting.
2024-07-29 20:00:21 +01:00
Spencer Long fd7082c30f Merge branch 'develop' into bug/sc-23936 2024-07-29 14:00:00 -05:00
snipe 8d0b72293f Merge branch 'develop' of https://github.com/snipe/snipe-it into develop 2024-07-29 18:51:19 +01:00
snipe f3d98f90c0 Add @arne-kroeger as a contributor 2024-07-29 18:51:12 +01:00
snipe 4eccb5ffc6 Merge pull request #15185 from arne-kroeger/feat/accesspories-checkout-to-location-or-asset
Added #14979: add checkout to location and assets functionality to accessories
2024-07-29 18:50:48 +01:00
Godfrey M 86049624c7 retargeted new label engine to correct 1d column 2024-07-29 10:42:26 -07:00
snipe 3972782033 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2024-07-29 18:27:56 +01:00
snipe 33b86057d1 Version bump
Signed-off-by: snipe <snipe@snipe.net>
2024-07-29 18:27:01 +01:00
arne-kroeger 3c3b922eae Adjusted newly added tests to new checkout form 2024-07-29 19:15:01 +02:00
arne-kroeger e8d0147075 Adjusted missing down on migration and code smells 2024-07-29 19:04:10 +02:00
snipe c2bcc2e2d9 Merge remote-tracking branch 'origin/develop' 2024-07-29 14:39:13 +01:00
snipe 55f9886412 Merge pull request #15187 from snipe/feature/sc-26458
Use the `pwd_secure_min` value (plus 5) for generated password
2024-07-29 14:38:39 +01:00
snipe a77ece01a6 Fixed test name
Signed-off-by: snipe <snipe@snipe.net>
2024-07-29 14:34:10 +01:00
snipe 1c1101aeac Use the pwd_secure_min value (plus 5) for generated password
Signed-off-by: snipe <snipe@snipe.net>
2024-07-29 14:26:18 +01:00
snipe de04ead55d Merge remote-tracking branch 'origin/develop' 2024-07-29 10:11:39 +01:00
snipe bc18fac97e Fixed missing div
Signed-off-by: snipe <snipe@snipe.net>
2024-07-29 10:11:11 +01:00
arne-kroeger 3a0b03348e added additional tests 2024-07-29 11:06:36 +02:00
arne-kroeger b18baf74d2 added options to checkout accessoires to locations and assets
Added #14979: add checkout functionality to accessoires
2024-07-29 10:54:53 +02:00
snipe 28c7355697 Fixed missing div
Signed-off-by: snipe <snipe@snipe.net>
2024-07-29 09:52:38 +01:00
snipe 0dd0baa511 Merge remote-tracking branch 'origin/develop' 2024-07-27 10:12:23 +01:00
snipe c3a296c19f Added qr code back
Signed-off-by: snipe <snipe@snipe.net>
2024-07-27 10:12:13 +01:00
snipe f6cc923e01 Merge remote-tracking branch 'origin/develop' 2024-07-26 17:29:46 +01:00
snipe aab29fbb6b Use translated string for restore
Signed-off-by: snipe <snipe@snipe.net>
2024-07-26 16:47:40 +01:00
snipe d9d3ff27ae Merge remote-tracking branch 'origin/develop' 2024-07-26 15:31:52 +01:00
snipe 614d05acb5 Merge pull request #15170 from uberbrady/simplify_css_skin_building
Dynamically iterate through the skin listing to build skins
2024-07-26 15:14:24 +01:00
snipe e4a82edd3f Merge pull request #15172 from snipe/features/blade_component_for_submit
Use blade component for submit redirect on asset edit/create
2024-07-26 15:13:30 +01:00
snipe eceaa72781 And more tests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-26 15:07:43 +01:00
snipe ddf45c5ee9 Renamed test
Signed-off-by: snipe <snipe@snipe.net>
2024-07-26 15:00:16 +01:00
snipe ff100c0b9f Added more tests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-26 14:58:10 +01:00
snipe 037cc4d098 More tests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-26 14:27:07 +01:00
snipe ff6e6ef88c Added more tests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-26 13:43:10 +01:00
snipe e8ec11652f Very basic checkin tests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-26 13:16:31 +01:00
snipe cd7f276c40 Fixed logging for component
Signed-off-by: snipe <snipe@snipe.net>
2024-07-26 13:09:21 +01:00
snipe fc8bb82a02 Made dropdown wider
Signed-off-by: snipe <snipe@snipe.net>
2024-07-26 12:48:18 +01:00
snipe 5d7f1f77a3 Added redirect to checkin/checkout controllers
Signed-off-by: snipe <snipe@snipe.net>
2024-07-26 12:48:07 +01:00
snipe 5dea3f4495 Added blade component to checkin/checkout pages
Signed-off-by: snipe <snipe@snipe.net>
2024-07-26 12:47:33 +01:00
snipe c6e709cd36 Added parameters
Signed-off-by: snipe <snipe@snipe.net>
2024-07-26 12:45:06 +01:00
Brady Wetherington daf5a80081 Use a similar loop for the minification step for CSS 2024-07-26 12:03:03 +01:00
snipe 759ab78f80 Added more redirects
Signed-off-by: snipe <snipe@snipe.net>
2024-07-26 11:27:36 +01:00
snipe b6d9f736e3 Pulled use session
Signed-off-by: snipe <snipe@snipe.net>
2024-07-26 10:41:28 +01:00
snipe 243ab51def Fixed back button
Signed-off-by: snipe <snipe@snipe.net>
2024-07-26 10:40:48 +01:00
snipe c5603a0e10 Merge remote-tracking branch 'origin/develop' 2024-07-26 10:26:23 +01:00
snipe 57f6ecb1da Added created_by to license view
Signed-off-by: snipe <snipe@snipe.net>
2024-07-26 10:24:13 +01:00
snipe 64082ada1e Updated test
Signed-off-by: snipe <snipe@snipe.net>
2024-07-25 22:08:51 +01:00
snipe 068535a80c Removed logging
Signed-off-by: snipe <snipe@snipe.net>
2024-07-25 22:08:46 +01:00
snipe 08f4fe5f35 Add status messages to redirect
Signed-off-by: snipe <snipe@snipe.net>
2024-07-25 22:02:34 +01:00
snipe 018b5684fc Refactor helper method for redirection
Signed-off-by: snipe <snipe@snipe.net>
2024-07-25 22:02:03 +01:00
snipe 73a80a5fbc Use blade component for redirect option
Signed-off-by: snipe <snipe@snipe.net>
2024-07-25 21:35:13 +01:00
Brady Wetherington 4c8bf9ae19 Dynamically iterate through the skin listing to build skins 2024-07-25 21:20:06 +01:00
snipe f77d300549 Merge pull request #15169 from uberbrady/create_directories_when_needed_on_restore
Create intermediate directories on restore if needed - Fixes [SC-25950]
2024-07-25 18:45:54 +01:00
snipe 62655be2d0 Fixed BYOD label
Signed-off-by: snipe <snipe@snipe.net>
2024-07-25 18:41:37 +01:00
Brady Wetherington eb938bdba3 Create intermediate directories on restore if needed 2024-07-25 18:40:26 +01:00
snipe 129d3b35fb Merge pull request #15168 from uberbrady/improve_restore_sanitization
Improve restore sanitization - Fixes [sc-24840]
2024-07-25 18:20:05 +01:00
Brady Wetherington 84df23e1f6 Better handle older SQL dumps that got created in Windows format 2024-07-25 18:07:25 +01:00
snipe a439d8abe8 Use fully qualified use statements
Signed-off-by: snipe <snipe@snipe.net>
2024-07-25 16:08:46 +01:00
snipe 24b7659c23 Merge pull request #15150 from marcusmoore/chore/sc-26113
Registered custom anonymous blade component directory
2024-07-25 16:08:01 +01:00
Marcus Moore 44dbbeb608 Add accessory and consumable specific checkin methods 2024-07-24 14:17:49 -07:00
Marcus Moore 7161b6416e Add failing test for accessories and consumables checkin 2024-07-24 14:16:42 -07:00
snipe 1331bffaca Merge remote-tracking branch 'origin/develop' 2024-07-24 21:42:41 +01:00
snipe 9b422e5c97 Baremetrics BMPay breaks with CSP turned [sc-25011]
Signed-off-by: snipe <snipe@snipe.net>
2024-07-24 21:42:20 +01:00
snipe 0c86855392 Merge remote-tracking branch 'origin/develop' 2024-07-24 21:04:20 +01:00
snipe 962ae5231d Merge pull request #15162 from snipe/fixes/added_location_assets_endpoint
Added assets endpoint for locations
2024-07-24 21:03:43 +01:00
snipe 590d13061a One more test
Signed-off-by: snipe <snipe@snipe.net>
2024-07-24 20:57:26 +01:00
snipe c3a2cdeee9 Added assets endpoint for locations
Signed-off-by: snipe <snipe@snipe.net>
2024-07-24 20:53:58 +01:00
snipe ef77fb91c0 Merge remote-tracking branch 'origin/develop' 2024-07-24 20:20:37 +01:00
snipe 02bd8d7ea1 Merge pull request #15161 from snipe/fixes/500_when_depreciation_is_active_but_no_purchase_date
Fixes 500 when depreciation is active but no purchase date
2024-07-24 20:20:10 +01:00
snipe da4ec145d7 Removed test no longer needed due to validation
Signed-off-by: snipe <snipe@snipe.net>
2024-07-24 20:17:30 +01:00
snipe ef145e47b4 Added tests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-24 20:13:15 +01:00
snipe adf58a06da Added check for purchase date
Signed-off-by: snipe <snipe@snipe.net>
2024-07-24 20:13:11 +01:00
snipe 63f0b5279d Added check for purchase_date
Signed-off-by: snipe <snipe@snipe.net>
2024-07-24 20:13:01 +01:00
Godfrey Martinez c96ccbb6cb Merge branch 'develop' into depreciation_percentage 2024-07-24 12:12:28 -07:00
Godfrey M 950fff31ed fix conflicts 2024-07-24 12:12:04 -07:00
Godfrey M f05d8281f3 fixes alignment for error msg 2024-07-24 12:06:56 -07:00
Godfrey M d5c9fa823e adds translations 2024-07-24 11:39:33 -07:00
Godfrey M 99741db645 adds status labels to confirmation emails 2024-07-24 11:24:30 -07:00
snipe 90d5a6d8ab Merge remote-tracking branch 'origin/develop' 2024-07-24 19:16:56 +01:00
snipe 5b8529bc83 Fixed pluralization
Signed-off-by: snipe <snipe@snipe.net>
2024-07-24 19:16:08 +01:00
snipe f76c68f0ed Merge remote-tracking branch 'origin/develop' 2024-07-24 18:10:23 +01:00
snipe 8368fb5c41 Merge pull request #15160 from snipe/fixes/allow_cloning_of_deleted_assets
Allow cloning of deleted assets
2024-07-24 18:09:55 +01:00
snipe d1c39a737f Fixed double semicolon
Signed-off-by: snipe <snipe@snipe.net>
2024-07-24 18:09:32 +01:00
snipe 425bfa4318 Added test
Signed-off-by: snipe <snipe@snipe.net>
2024-07-24 18:06:21 +01:00
snipe 293abbd1d0 Allow cloning of deleted assets
Signed-off-by: snipe <snipe@snipe.net>
2024-07-24 17:49:38 +01:00
snipe b64b774bd5 Use route model binding on clone, removed unneeded route
Signed-off-by: snipe <snipe@snipe.net>
2024-07-24 17:49:21 +01:00
snipe 466ab1e3c0 Removed the banner since we already warn
Signed-off-by: snipe <snipe@snipe.net>
2024-07-24 17:40:24 +01:00
snipe daa9e7810e Merge pull request #15158 from snipe/fixes/ui_cleanup_for_asset_view
Cleaned up UI on asset view
2024-07-24 17:34:17 +01:00
snipe 95a0f3dbe5 Cleaned up UI on asset view
Signed-off-by: snipe <snipe@snipe.net>
2024-07-24 17:26:55 +01:00
Brady Wetherington bb465dbfaa Cut down run number to 100 from 1000 2024-07-24 15:09:23 +01:00
snipe e5ab12496f Merge pull request #15151 from snipe/snyk-fix-067da5564c4d29b025cd356b125e6ad9
[Snyk] Security upgrade alpine from 3.18.6 to 3.19
2024-07-24 14:22:57 +01:00
snipe 4b906e39be Merge pull request #15155 from snipe/fix_new_alpine
Switch dockerfile to using php8.2 instead of 8.1 due to Alpine changes
2024-07-24 14:00:21 +01:00
Brady Wetherington 0dc8f27240 Switch dockerfile to using php8.2 instead of 8.1 due to Alpine changes 2024-07-24 13:56:27 +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
snipe c4135c71d4 Merge remote-tracking branch 'origin/develop' 2024-07-24 13:05:16 +01:00
snipe 172da4d655 Merge pull request #15154 from snipe/fixes/15103_show_eol_to_users
Fixes #15103 - Added EOL and audit into to user profile assets
2024-07-24 13:03:50 +01:00
snipe 6f8ccd4e10 Fixes #15103 - Added EOL and audit into to user profile assets
Signed-off-by: snipe <snipe@snipe.net>
2024-07-24 12:54:33 +01:00
snipe 8d36a75342 Merge remote-tracking branch 'origin/develop' 2024-07-24 12:41:20 +01:00
snipe 9457e5b890 Merge pull request #15153 from snipe/fixes/mail_backup_config
Fixed env var for backup config - related to #14964
2024-07-24 12:40:46 +01:00
snipe bce7a278ae Fixed env var for backup config - related to #14964
Signed-off-by: snipe <snipe@snipe.net>
2024-07-24 12:38:58 +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
snipe a6041ae525 Merge remote-tracking branch 'origin/develop' 2024-07-24 10:41:36 +01:00
snipe ab1e097b7c Early return for requiredness
Signed-off-by: snipe <snipe@snipe.net>
2024-07-24 10:41:14 +01:00
snipe a781f84aea Merge remote-tracking branch 'origin/develop' 2024-07-24 10:36:23 +01:00
snipe 90a2a808d6 Merge pull request #15149 from spencerrlongg/bug/check_requiredness
Fixed: Requiredness Check Bug
2024-07-24 10:33:45 +01:00
snipe 73e2d8e305 Merge remote-tracking branch 'origin/develop' 2024-07-24 10:32:54 +01:00
snyk-bot 0e1e13f54a fix: Dockerfile.alpine to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-ALPINE318-BUSYBOX-6913411
- https://snyk.io/vuln/SNYK-ALPINE318-BUSYBOX-7249236
- https://snyk.io/vuln/SNYK-ALPINE318-BUSYBOX-7249265
- https://snyk.io/vuln/SNYK-ALPINE318-BUSYBOX-7249419
- https://snyk.io/vuln/SNYK-ALPINE318-BUSYBOX-7249419
2024-07-24 09:11:01 +00:00
Marcus Moore 869c06f454 Register anonymous blade component namespace 2024-07-23 15:41:58 -07:00
spencerrlongg b61ab423ca ok NOW it should be fine 2024-07-23 17:35:48 -05:00
spencerrlongg 090a595c99 conflict 2024-07-23 17:34:17 -05:00
Spencer Long bc417308c7 Merge branch 'develop' into bug/check_requiredness 2024-07-23 17:32:43 -05:00
spencerrlongg e77e16b9aa this works 2024-07-23 17:22:20 -05:00
spencerrlongg 0ae297634e ugh 2024-07-23 16:59:58 -05:00
spencerrlongg 0f2f559d7a test works, helper still needs work. pushing to check something 2024-07-23 16:46:29 -05:00
snipe 57b5b12952 Merge pull request #15148 from marcusmoore/fixes/dates-in-user-import
Fixed start_date and end_date in user importer
2024-07-23 22:37:19 +01:00
snipe 9baaaae1a3 Merge remote-tracking branch 'origin/develop' 2024-07-23 22:15:57 +01:00
snipe 1f4118a146 Fixed rule
Signed-off-by: snipe <snipe@snipe.net>
2024-07-23 22:15:37 +01:00
Marcus Moore f4a3823d88 Handle empty strings for dates by converting them to null 2024-07-23 13:57:28 -07:00
snipe b2a69efc9d Merge remote-tracking branch 'origin/develop' 2024-07-23 21:42:12 +01:00
snipe 00ebc8b64d Merge pull request #15136 from snipe/fixes/cookie_serialization
Remove cookie serialization
2024-07-23 21:41:44 +01:00
snipe effd273245 Merge pull request #14458 from spencerrlongg/bug/sc-24884
Add Form Request and Tests for Update Asset API Method
2024-07-23 20:57:47 +01:00
snipe 7858c72b98 Fixed string
Signed-off-by: snipe <snipe@snipe.net>
2024-07-23 20:45:12 +01:00
snipe 09e2c0beab Merge pull request #15147 from uberbrady/fix_setup_ssl_check
Fix setup ssl check
2024-07-23 20:32:13 +01:00
spencerrlongg e8864ffb01 test added, permission fixed 2024-07-23 14:29:17 -05:00
Brady Wetherington d893de2b7e Merge branch 'develop' into fix_setup_ssl_check 2024-07-23 20:24:38 +01:00
Brady Wetherington 7f7cfef81b Mark test as Incomplete, and downgrade error back to debug for tests 2024-07-23 20:24:05 +01:00
Godfrey M d01972bbe5 adds tests for amount and percent 2024-07-23 11:53:59 -07:00
spencerrlongg b9fdb5880a quick push 2024-07-23 13:48:43 -05:00
spencerrlongg 1139ed676a $id to $asset->id (thanks tests) 2024-07-23 13:03:25 -05:00
Spencer Long 64be353156 Merge branch 'develop' into bug/sc-24884 2024-07-23 12:55:19 -05:00
Godfrey M 750015684d purges user storage files 2024-07-23 10:42:50 -07:00
snipe 992d16664d Merge remote-tracking branch 'origin/develop' 2024-07-23 18:26:54 +01:00
snipe 900c19b76d Merge pull request #15143 from snipe/fixes/no-NO-language
Switch to nb-NO from no-NO for Norwegian
2024-07-23 18:25:27 +01:00
snipe effd2bce24 Fixed test to use nb-NO
Signed-off-by: snipe <snipe@snipe.net>
2024-07-23 18:22:13 +01:00
snipe de8816d837 Merge pull request #15144 from snipe/localization/updated_strings_2024_07_23
Updated translations
2024-07-23 18:17:45 +01:00
snipe 593554daed Updated translations
Signed-off-by: snipe <snipe@snipe.net>
2024-07-23 18:14:19 +01:00
snipe fecd877e8b Migration
Signed-off-by: snipe <snipe@snipe.net>
2024-07-23 17:35:06 +01:00
snipe ba6d8ae8c7 Switch to nb-NO from no-NO
Signed-off-by: snipe <snipe@snipe.net>
2024-07-23 17:15:44 +01:00
snipe 175862d3c9 Added route param to message
Signed-off-by: snipe <snipe@snipe.net>
2024-07-23 16:37:01 +01:00
Brady Wetherington 5eea08088d Improve .env file checking to not validate SSL certificates 2024-07-23 16:03:02 +01:00
snipe c752c2a125 Make the passport cookie name configurable
Signed-off-by: snipe <snipe@snipe.net>
2024-07-22 14:22:19 +01:00
snipe 4ac4f9b0a9 Customize cookie name
Signed-off-by: snipe <snipe@snipe.net>
2024-07-22 14:17:16 +01:00
snipe 09abcb44bb Remove cookie serialization
Signed-off-by: snipe <snipe@snipe.net>
2024-07-22 13:49:47 +01:00
snipe 7f566b9152 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/css/dist/all.css
#	public/css/dist/bootstrap-table.css
#	public/js/dist/bootstrap-table.js
#	public/mix-manifest.json
2024-07-22 10:56:37 +01:00
snipe 30835fe9ba Merge pull request #15134 from snipe/upgrade_bs_table
[Snyk] Upgrade bootstrap-table from 1.22.5 to 1.23.0 #15131
2024-07-22 10:50:53 +01:00
snipe 910e98b573 [Snyk] Upgrade bootstrap-table from 1.22.5 to 1.23.0 #15131
Signed-off-by: snipe <snipe@snipe.net>
2024-07-22 10:45:35 +01:00
snipe 4623e40077 Merge pull request #15133 from snipe/fixes/load_english_separately_for_table_locale
Load the english file again in case BS table doesn’t have a translation
2024-07-22 10:40:01 +01:00
snipe 20868b9ede Load the english file again in case BS table doesn’t have a translation
Signed-off-by: snipe <snipe@snipe.net>
2024-07-22 10:30:42 +01:00
snipe efc84efabf Merge pull request #15132 from snipe/fixes/disable_remote_login_force_via_env
Hides the “Disable Other Login Mechanisms” option via env
2024-07-22 10:20:34 +01:00
snipe 7c7fa96334 Pulled from the app.php as well
Signed-off-by: snipe <snipe@snipe.net>
2024-07-22 10:19:55 +01:00
snipe e08acb851c Removed env part, just check for the remote user login
Signed-off-by: snipe <snipe@snipe.net>
2024-07-22 10:18:33 +01:00
snipe bbad84c6cc Hides the “Disable Other Login Mechanisms” option via env
Signed-off-by: snipe <snipe@snipe.net>
2024-07-22 10:13:59 +01:00
snipe f2acb98afa Merge pull request #15128 from snipe/fixes/nicer_consumables_layout
Nicer consumables layout
2024-07-20 17:01:15 +01:00
snipe 38affea3f3 More updates
Signed-off-by: snipe <snipe@snipe.net>
2024-07-20 16:57:10 +01:00
snipe cea31c5b11 Added more generic buttons with variables
Signed-off-by: snipe <snipe@snipe.net>
2024-07-20 16:53:01 +01:00
snipe 254e2f120b Added clone to consumables
Signed-off-by: snipe <snipe@snipe.net>
2024-07-20 16:40:32 +01:00
snipe 2bfee0c29a Few more tweaks
Signed-off-by: snipe <snipe@snipe.net>
2024-07-20 16:21:11 +01:00
snipe c08bd8f88b Nicer consumables layout
Signed-off-by: snipe <snipe@snipe.net>
2024-07-20 16:11:45 +01:00
snipe 9818c2f033 Merge remote-tracking branch 'origin/develop' 2024-07-20 08:08:51 +01:00
snipe f63fd25ce0 Fixed default
Signed-off-by: snipe <snipe@snipe.net>
2024-07-20 08:08:29 +01:00
snipe 57ecdd6765 Merge remote-tracking branch 'origin/develop' 2024-07-20 07:43:37 +01:00
snipe 9d890b35c6 Merge pull request #15127 from snipe/fixes/small_default_avatar_tweaks
Fixes #15076 - Removes ability to remove the default avatar from disk
2024-07-20 07:42:39 +01:00
snipe 8fc5c0b5be Use other default avatar, not in the avatars directory
Signed-off-by: snipe <snipe@snipe.net>
2024-07-20 07:34:40 +01:00
snipe c4e7448d31 Updated strings
Signed-off-by: snipe <snipe@snipe.net>
2024-07-20 07:25:56 +01:00
snipe ffd2687734 Updated language
Signed-off-by: snipe <snipe@snipe.net>
2024-07-20 07:25:46 +01:00
snipe 6f3eedf5e6 Removed restoreDefaultAvatar method
Signed-off-by: snipe <snipe@snipe.net>
2024-07-20 07:25:27 +01:00
snipe 241eb7b031 One more bad sig
Signed-off-by: snipe <snipe@snipe.net>
2024-07-20 06:06:27 +01:00
snipe ca399794c3 Fixed incorrect signature
Signed-off-by: snipe <snipe@snipe.net>
2024-07-20 06:05:01 +01:00
snipe 736d4cc59a Use new deleting method in ImageUploadRequest
Signed-off-by: snipe <snipe@snipe.net>
2024-07-20 05:55:34 +01:00
snipe ad85f8be2f Cleaned up
Signed-off-by: snipe <snipe@snipe.net>
2024-07-20 05:55:12 +01:00
snipe be17ef4047 Added option to restore from default demo
Signed-off-by: snipe <snipe@snipe.net>
2024-07-20 05:55:06 +01:00
snipe c6c006f143 Added restore from demo method
Signed-off-by: snipe <snipe@snipe.net>
2024-07-20 05:54:40 +01:00
snipe 10856516ac Split out the image deletion into a separate method
Signed-off-by: snipe <snipe@snipe.net>
2024-07-20 03:40:16 +01:00
snipe beac4c8b8a Updated tests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-20 03:39:54 +01:00
snipe b39b39bc8a Ignore the test uploads directory
Signed-off-by: snipe <snipe@snipe.net>
2024-07-20 03:39:05 +01:00
snipe e373be7dde Skip deleting default avatar from disk on delete
Signed-off-by: snipe <snipe@snipe.net>
2024-07-20 01:01:27 +01:00
snipe ca7c0aa47c Added default avatar to seeder
Signed-off-by: snipe <snipe@snipe.net>
2024-07-20 00:59:25 +01:00
snipe 48a8cf6b70 Removed unused default avatar
Signed-off-by: snipe <snipe@snipe.net>
2024-07-20 00:58:57 +01:00
snipe 7ba1646703 Remove unusued default avatar
Signed-off-by: snipe <snipe@snipe.net>
2024-07-20 00:58:42 +01:00
snipe daa550cc82 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2024-07-20 00:31:08 +01:00
snipe e9f9d3c259 Bumped hash
Signed-off-by: snipe <snipe@snipe.net>
2024-07-20 00:30:03 +01:00
snipe 63377853b8 Merge pull request #15125 from snipe/fixes/display_avatar_on_user_edit
Show existing images on user edit page
2024-07-20 00:29:28 +01:00
snipe fc86eefeac Show existing images on user edit page
Signed-off-by: snipe <snipe@snipe.net>
2024-07-20 00:27:28 +01:00
snipe a98ad76c6a Merge remote-tracking branch 'origin/develop' 2024-07-19 22:55:09 +01:00
snipe 32c768792a Merge pull request #15124 from snipe/fixes/path_for_crypt_in_importer
Fixed use statement for Crypt in the importer, removed unused statements
2024-07-19 22:54:18 +01:00
snipe 793cf27318 Fixed use statement
Signed-off-by: snipe <snipe@snipe.net>
2024-07-19 22:50:24 +01:00
snipe ba568b7975 Merge pull request #15123 from snipe/tests/added_bulk_delete_assets
Added tests for bulk asset deletion and restore
2024-07-19 22:36:09 +01:00
snipe 4b5bd76225 Fixed notification use statement
Signed-off-by: snipe <snipe@snipe.net>
2024-07-19 22:27:03 +01:00
snipe a54403ef01 Added bulk asset delete test
Signed-off-by: snipe <snipe@snipe.net>
2024-07-19 22:26:52 +01:00
snipe 13262c5125 Merge remote-tracking branch 'origin/develop' 2024-07-19 20:05:47 +01:00
snipe 9ea38fbb3a Merge pull request #15122 from snipe/fixes/15121_bulk_delete_and_restore
Fixed #15121 - bulk delete restore logging
2024-07-19 20:03:32 +01:00
snipe 94619e3284 Fixed #15121 - bulk delete restore logging
Signed-off-by: snipe <snipe@snipe.net>
2024-07-19 19:56:58 +01:00
snipe 8b05ef6db4 Updated url checks
Signed-off-by: snipe <snipe@snipe.net>
2024-07-19 19:48:03 +01:00
snipe 8e03083b83 Merge branch 'develop' of https://github.com/snipe/snipe-it into develop 2024-07-19 19:07:53 +01:00
snipe dc2debcd83 Add @DrekiDegga as a contributor 2024-07-19 19:07:41 +01:00
snipe b7ab8b9e8f Merge pull request #14530 from DrekiDegga/develop
Added #14426: Makes all Manufacturer links dynamic, not just warranty lookup
2024-07-19 19:07:25 +01:00
snipe c50ab1af67 Merge branch 'develop' into develop 2024-07-19 19:00:56 +01:00
snipe 7773d334ba Merge pull request #15120 from snipe/updated_localizations
Updated strings
2024-07-19 17:54:30 +01:00
snipe 2a0697022e Updated strings
Signed-off-by: snipe <snipe@snipe.net>
2024-07-19 17:47:22 +01:00
Marcus Moore 8d1cc22c58 Turn on legacy binding since other components still use it 2024-07-18 12:00:01 -07:00
snipe e1eb963962 Updated prod assets
Signed-off-by: snipe <snipe@snipe.net>
2024-07-18 19:11:51 +01:00
snipe 87c2dc5bb5 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-07-18 19:11:41 +01:00
snipe 06efcd3c46 Merge branch 'develop' of https://github.com/snipe/snipe-it into develop 2024-07-18 18:55:18 +01:00
snipe faa791e94c Merge pull request #15101 from snipe/localizations/more_strings
More localizations
2024-07-18 18:51:35 +01:00
snipe e328dec9f9 Merge branch 'develop' into localizations/more_strings 2024-07-18 18:51:17 +01:00
snipe 8e60a7b22b Merge pull request #15110 from marcusmoore/fixes/test-namespace-fixes
Fixed a coupled test namespaces
2024-07-18 18:50:27 +01:00
snipe 958b6035e1 Add @r-xyz as a contributor 2024-07-18 18:49:59 +01:00
snipe 94e0739a74 Merge pull request #15115 from r-xyz/alpine-upload-limit
Improved Docker environment settings: implement `PHP_UPLOAD_LIMIT` for Alpine images
2024-07-18 18:49:00 +01:00
snipe 4465aef991 Merge pull request #15114 from snipe/checkout_multiple_accessories
Checkout multiple of an accessory in one checkout
2024-07-18 17:38:19 +01:00
snipe 822bc6f085 Removed response in form request
Signed-off-by: snipe <snipe@snipe.net>
2024-07-18 17:37:45 +01:00
snipe 19bd99d159 Updated count
Signed-off-by: snipe <snipe@snipe.net>
2024-07-18 17:33:24 +01:00
r-xyz 5c17fefb08 Implement PHP_UPLOAD_LIMIT in Alpine images. 2024-07-18 11:54:58 +02:00
snipe ee589ca112 Merge pull request #15088 from mauro-miatello/develop
Added EULAs in print user's assets
2024-07-18 09:09:34 +01:00
snipe f984b45de2 Merge branch 'develop' into checkout_multiple_accessories 2024-07-18 05:11:51 +01:00
snipe d56252c6b3 Added more back :(
Signed-off-by: snipe <snipe@snipe.net>
2024-07-18 05:10:45 +01:00
snipe 44b950cb8e Added back in missing validation
Signed-off-by: snipe <snipe@snipe.net>
2024-07-18 05:07:50 +01:00
snipe 985714d504 Test passing now - I hope
Signed-off-by: snipe <snipe@snipe.net>
2024-07-18 05:04:17 +01:00
snipe 97ead7120e Use from routes for posting
Signed-off-by: snipe <snipe@snipe.net>
2024-07-18 04:54:07 +01:00
snipe 670021a482 Apply the optimize fix
Signed-off-by: snipe <snipe@snipe.net>
2024-07-18 04:43:46 +01:00
snipe 9858cc5baf Removed debugging
Signed-off-by: snipe <snipe@snipe.net>
2024-07-18 04:43:30 +01:00
snipe fa5b59cf21 Added qty
Signed-off-by: snipe <snipe@snipe.net>
2024-07-18 04:29:49 +01:00
snipe 0ef58a9aef Added translation
Signed-off-by: snipe <snipe@snipe.net>
2024-07-18 03:48:42 +01:00
snipe 0c4e498df3 Removed debugging
Signed-off-by: snipe <snipe@snipe.net>
2024-07-18 03:48:35 +01:00
snipe b5b60f22d5 Removed int
Signed-off-by: snipe <snipe@snipe.net>
2024-07-18 03:48:21 +01:00
snipe 2f0c74aef0 Updated tests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-18 03:48:06 +01:00
snipe f56006fb6b More refactoring
Signed-off-by: snipe <snipe@snipe.net>
2024-07-18 01:46:53 +01: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
snipe 79a13e3618 Added numCheckedOut method
Signed-off-by: snipe <snipe@snipe.net>
2024-07-18 00:26:58 +01:00
snipe d9b7df5b85 Added form requests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-18 00:26:42 +01:00
snipe 0c933bcc5d Cleaned up controllers, use form requests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-18 00:25:42 +01:00
snipe 4c4b0f722a Added qty to email notification
Signed-off-by: snipe <snipe@snipe.net>
2024-07-18 00:25:29 +01:00
snipe 6c3cafa72f Added tests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-18 00:25:07 +01:00
snipe 16ae23dbeb Updated validation strings
Signed-off-by: snipe <snipe@snipe.net>
2024-07-18 00:25:00 +01:00
snipe 4f3064bdb1 Added store accesstory form request
Signed-off-by: snipe <snipe@snipe.net>
2024-07-18 00:24:51 +01:00
snipe 2b0627c1f6 Added accessory checkout request
Signed-off-by: snipe <snipe@snipe.net>
2024-07-18 00:24:28 +01:00
Marcus Moore cfca1514c0 Swap file_id for activeFileId 2024-07-17 16:22:44 -07:00
snipe 345a4306e8 Added SubstituteBindings
Signed-off-by: snipe <snipe@snipe.net>
2024-07-17 23:02:10 +01:00
snipe beb0836d69 Updated route
Signed-off-by: snipe <snipe@snipe.net>
2024-07-17 23:01:44 +01: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
snipe 1eb16cdb02 Merge pull request #15111 from marcusmoore/fixes/optimize-test
Undo `optimize` command in test after it is completed
2024-07-17 21:03:01 +01:00
snipe 05e278d08b Added qty to email
Signed-off-by: snipe <snipe@snipe.net>
2024-07-17 20:58:21 +01:00
snipe c21821a864 Added new form fields
Signed-off-by: snipe <snipe@snipe.net>
2024-07-17 20:58:12 +01:00
Marcus Moore a56f3f85f8 Clear the config and route caching done by optimize command after test 2024-07-17 12:21:46 -07:00
Marcus Moore ba13b9924b Fix test namespaces 2024-07-17 11:04:35 -07:00
Marcus Moore 04b6cb763f Add todo 2024-07-17 10:58:48 -07:00
snipe 239824681d Merge pull request #15075 from akemidx/checkintranslation
FIXED: Missing Translation on a Tooltip
2024-07-17 18:16:02 +01:00
snipe 0ac82fbbe1 Merge pull request #15084 from snipe/fixes_ldap_sync_locale
Fixes #15067 - updated ldap sync locale to use `app()->getLocale()`
2024-07-17 18:15:32 +01:00
snipe 8c5a9fa38f Merge pull request #15089 from snipe/dependabot/github_actions/develop/codacy/codacy-analysis-cli-action-4.4.5
Bump codacy/codacy-analysis-cli-action from 4.4.1 to 4.4.5
2024-07-17 16:47:28 +01:00
snipe 2f8306cba8 Merge remote-tracking branch 'origin/develop' 2024-07-17 16:27:16 +01:00
Godfrey M baa7e7d561 clean up 2024-07-16 20:27:38 -07:00
Godfrey M ffaacc04ef cleaned up calculateDepreciation method 2024-07-16 20:24:18 -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
snipe 65dcb2a9bd Merge pull request #15085 from snipe/small_tweaks_to_oauth_page
Small layout tweaks to oauth page
2024-07-16 21:36:17 +01:00
snipe d5e1dc54c6 Use translated strings for action log meta
This is only partially complete and I mostly hate it

Signed-off-by: snipe <snipe@snipe.net>
2024-07-16 21:35:45 +01:00
Marcus Moore 69263f0e5b Migrate header row to component 2024-07-16 13:30:29 -07:00
snipe a3b2912e89 Updated string
Signed-off-by: snipe <snipe@snipe.net>
2024-07-16 21:16:23 +01:00
snipe 7f412ec3f5 Missing string
Signed-off-by: snipe <snipe@snipe.net>
2024-07-16 21:14:41 +01:00
snipe 94e881e5f0 Cleared up language
Signed-off-by: snipe <snipe@snipe.net>
2024-07-16 21:11:03 +01:00
Godfrey M 5bb47e290f validates percentage on store and new depreciations 2024-07-16 13:07:12 -07:00
snipe d53a032402 More consistent UI for indented checkboxes
Signed-off-by: snipe <snipe@snipe.net>
2024-07-16 21:07:03 +01:00
snipe 70d95877d8 Translations for license checkout errors
Signed-off-by: snipe <snipe@snipe.net>
2024-07-16 21:02:58 +01:00
Godfrey M 48821f8391 updates transformer, api controller 2024-07-16 12:58:23 -07:00
snipe bb00edda4e Added basic jquery validation translations
Signed-off-by: snipe <snipe@snipe.net>
2024-07-16 20:54:48 +01:00
Godfrey M aaa2858337 battling with handling depreciation percentage and amount 2024-07-16 12:25:19 -07:00
Marcus Moore 017530ba4b Make updating hook more specific 2024-07-16 12:02:50 -07:00
snipe 4895023f3b Translate import button
Signed-off-by: snipe <snipe@snipe.net>
2024-07-16 19:56:02 +01:00
snipe 0ed637f0ce Translate importer header
Signed-off-by: snipe <snipe@snipe.net>
2024-07-16 19:41:47 +01:00
snipe 45bf428092 Translated “seat” for license seat view
Signed-off-by: snipe <snipe@snipe.net>
2024-07-16 19:04:51 +01:00
snipe e6f2c457a8 Handle localization better, clearer indenting on addresses
Signed-off-by: snipe <snipe@snipe.net>
2024-07-16 19:01:50 +01:00
snipe 04f723327e Fixed translation
Signed-off-by: snipe <snipe@snipe.net>
2024-07-16 19:01:23 +01:00
snipe 4a9bd95ed3 Added language support for select2
Signed-off-by: snipe <snipe@snipe.net>
2024-07-16 18:40:10 +01:00
snipe 78bd950daa Added select2 language files
Signed-off-by: snipe <snipe@snipe.net>
2024-07-16 18:39:42 +01:00
snipe d3070a0be1 Merge remote-tracking branch 'origin/develop' 2024-07-16 17:24:16 +01:00
snipe a0d461d3e2 Merge pull request #15099 from snipe/fixes/15094_wrong_translation_string
Fixed #15094 - wrong translation string for model on checkout
2024-07-16 17:23:46 +01:00
snipe eb9e276ba7 Fixed #15094 - wrong translation string for model on checkout
Signed-off-by: snipe <snipe@snipe.net>
2024-07-16 17:14:13 +01:00
snipe 0a70bcc0a9 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	.all-contributorsrc
#	CONTRIBUTORS.md
2024-07-16 16:12:26 +01:00
snipe 35160f88e0 Corrected return type
Signed-off-by: snipe <snipe@snipe.net>
2024-07-16 16:09:08 +01: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
dependabot[bot] 0ddb447c4c Bump codacy/codacy-analysis-cli-action from 4.4.1 to 4.4.5
Bumps [codacy/codacy-analysis-cli-action](https://github.com/codacy/codacy-analysis-cli-action) from 4.4.1 to 4.4.5.
- [Release notes](https://github.com/codacy/codacy-analysis-cli-action/releases)
- [Commits](https://github.com/codacy/codacy-analysis-cli-action/compare/v4.4.1...v4.4.5)

---
updated-dependencies:
- dependency-name: codacy/codacy-analysis-cli-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-15 08:39:24 +00:00
MrM e49c96a35e Added EULAs in print user's assets
Added EULAs when we want to print all assets assigned to a users and ask him/her to sign.
2024-07-14 19:10:33 +02:00
snipe 2d1aeca949 Re-use existing string
Signed-off-by: snipe <snipe@snipe.net>
2024-07-13 18:24:56 +01:00
snipe e06e4db4b7 Small layout tweaks to oauth page
Signed-off-by: snipe <snipe@snipe.net>
2024-07-13 18:16:03 +01:00
snipe 51242fcbb2 Merge branch 'develop' of https://github.com/snipe/snipe-it into develop 2024-07-13 16:09:03 +01:00
snipe 99be9ddb47 Add @dbakan as a contributor 2024-07-13 16:08:56 +01:00
snipe be4317361d Merge pull request #15082 from dbakan/fix/optimize-command
Fixed #10224: fix route names for optimize command
2024-07-13 16:08:32 +01:00
Daniel Albertsen a175b6a38b fix routes and tests 2024-07-13 16:36:14 +02:00
Daniel Albertsen 431da6c903 add test to ensure artisan optimize works 2024-07-13 16:36:14 +02:00
snipe ab6b8f520e Fixed field name
Signed-off-by: snipe <snipe@snipe.net>
2024-07-13 15:25:37 +01:00
snipe 24e58d1455 Do not update users who already exist since that locale may have been overirrden manually
Signed-off-by: snipe <snipe@snipe.net>
2024-07-13 15:20:04 +01:00
snipe f91ad6b2db Use app()->getLocale() to determine imported user’s language
Signed-off-by: snipe <snipe@snipe.net>
2024-07-13 15:15:44 +01:00
snipe eed253bd2f Use app helped instead of facade
Signed-off-by: snipe <snipe@snipe.net>
2024-07-13 15:15:18 +01:00
snipe b68fcf1de5 Added unaccepted asset test
Signed-off-by: snipe <snipe@snipe.net>
2024-07-12 12:19:40 +01:00
snipe 39810f9ba5 Merge remote-tracking branch 'origin/develop' 2024-07-12 11:05:10 +01:00
snipe d21ebc6f0d Fixed return type
Signed-off-by: snipe <snipe@snipe.net>
2024-07-12 11:04:56 +01:00
akemidx ad818cf886 missing translation 2024-07-11 17:13:47 -04: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
snipe fb7d533ff7 Merge pull request #15073 from marcusmoore/feature/livewire-url-prefix
Allow setting a prefix for Livewire's update and asset urls
2024-07-11 21:04:50 +01:00
Marcus Moore 9dd3827222 Allow setting a prefix for Livewire's update and asset urls 2024-07-11 12:43:29 -07:00
snipe 5697370dfe Merge pull request #14722 from Godmartinz/unaccepted_reminder_command
Adds a command to resend acceptance emails
2024-07-11 20:37:04 +01:00
snipe 7464c3622e Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2024-07-11 19:07:54 +01:00
snipe 5132aa0254 Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 19:07:30 +01:00
Godfrey M d4d19569ee adds execution timer 2024-07-11 10:52:47 -07:00
snipe 1a541ce220 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	.all-contributorsrc
#	CONTRIBUTORS.md
2024-07-11 18:38:57 +01:00
Godfrey M 43c7504f89 adds an all option, adds help context for all, seperates logic 2024-07-11 10:03:51 -07:00
snipe aebe96913a Add @FlorentDotMe as a contributor 2024-07-11 17:31:20 +01:00
snipe 78d24eb451 Merge pull request #15069 from TelecomsSansFrontieres/fix_print-all-assets
Fixed inconsistent attributes order in Print All Assigned report
2024-07-11 17:30:41 +01:00
snipe c5c5ac58e5 Merge pull request #15071 from snipe/fixes/small_consumables_optimizations
Small consumables optimizations
2024-07-11 17:27:41 +01:00
snipe 1527679f4b Handle deletions on the observer
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 17:26:43 +01:00
snipe c2fe3b5459 Use the observer to delete associated files and detach users
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 17:00:38 +01:00
snipe d4a66f9b6c Use better icon for deleting
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 17:00:12 +01:00
snipe 23f1489b2b Added history tab
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 16:46:49 +01:00
snipe 5108b1f3ed Capture the log meta for what was changed
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 16:35:16 +01:00
snipe 58bc84436c Fixed incorrect jquery validation class
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 16:23:05 +01:00
snipe 2415408a50 Prevent ludicrious amount of min_qty
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 16:22:41 +01:00
snipe 00d7b36c36 Eager load suppliers
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 16:22:22 +01:00
snipe 67d6f7119d Prevent a ludicrous amount of consumables
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 16:22:04 +01:00
snipe 42dbc894e0 Better handle numRemaining for consumables
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 16:21:45 +01:00
snipe 94bfe7d9c8 Require the user exists
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 16:18:42 +01:00
snipe d9a114090b Added buttons
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 16:18:33 +01:00
snipe b10441c928 Detach associated pivot records
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 16:01:18 +01:00
snipe e123eeea9e Added error message if category type is invalid
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 16:00:20 +01:00
snipe 9676d934d2 Drop the with users on the create checkout screen
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 16:00:08 +01:00
snipe 759bb822ff Make sure the user exists
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 15:59:18 +01:00
snipe abd79219dd Use form request to check for valid category
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 15:26:24 +01:00
snipe 2b5463475c Added test
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 15:25:26 +01:00
snipe a7a1a377da Added form request for consumables
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 15:25:07 +01:00
snipe a6b2f5df1d Added tests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 15:24:56 +01:00
snipe da2b64c96d Added string
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 15:24:08 +01:00
snipe 9e9b07f10f Removed duplicate status check
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 15:23:59 +01:00
snipe 82743abadc Cleans up the consumables index controller
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 14:15:18 +01:00
snipe c1937b6ea8 Merge remote-tracking branch 'origin/develop' 2024-07-11 12:01:28 +01:00
snipe 498a443230 Derp
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 12:01:06 +01:00
snipe 7584c30722 Merge remote-tracking branch 'origin/develop' 2024-07-11 12:00:25 +01:00
snipe 34b49ef079 Fixed typo
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 11:59:47 +01:00
Florent Bervas d9a53460ff Fix design inconsistency between assets and assigned assets in Print All Assigned report 2024-07-11 09:41:58 +00:00
snipe 62f4b75156 Merge remote-tracking branch 'origin/develop' 2024-07-11 10:08:25 +01:00
snipe 5364838fc0 Merge branch 'develop' of https://github.com/snipe/snipe-it into develop 2024-07-11 10:08:10 +01:00
snipe 8be44f9cf2 Check for time until depreciated
Signed-off-by: snipe <snipe@snipe.net>
2024-07-11 10:07:58 +01:00
snipe 68136ea217 Merge pull request #15052 from snipe/jerm/handle-windows-ca-jank-in-upgrade-script
upgrade.php: If we're on windows, make sure we can load intermediate certificates
2024-07-11 09:11:37 +01: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
snipe 3d5b1b6c6d Merge remote-tracking branch 'origin/develop' 2024-07-10 17:09:56 +01:00
snipe ec063b4af5 Updated PHP min version
Signed-off-by: snipe <snipe@snipe.net>
2024-07-10 17:07:44 +01:00
snipe bfa42ff84a Merge pull request #15051 from snipe/jerm/add-upgrade-script-debugging
upgrade.php: More helpful output when we can't read .upgrade_requirements.json
2024-07-10 16:51:30 +01:00
snipe 5f4ee39f2b Merge remote-tracking branch 'origin/develop' 2024-07-10 16:13:00 +01:00
snipe 22aca1af53 Fixed typo
Signed-off-by: snipe <snipe@snipe.net>
2024-07-10 16:12:20 +01:00
snipe 45d7e2dc42 Merge remote-tracking branch 'origin/develop' 2024-07-10 08:56:29 +01:00
snipe 71a5d07698 Fixes #15056 - only try to load avatars if one exists or default is set
Signed-off-by: snipe <snipe@snipe.net>
2024-07-10 08:56:14 +01:00
snipe fb10c1439a Merge pull request #15057 from spencerrlongg/bug/sc-23212-2
Fixes Potential Exception
2024-07-10 08:27:59 +01:00
snipe c58c592fb0 Merge pull request #15059 from Godmartinz/export_options
Fixed missing print user assigned filter
2024-07-10 08:25:24 +01:00
spencerrlongg 6932a63217 make some naming a little clearer 2024-07-09 16:32:44 -05:00
snipe 18f7ca860d Merge remote-tracking branch 'origin/develop' 2024-07-09 19:52:20 +01:00
snipe 1a1ccd6bdc Type constrains one more time - who thought this was a good idea?
Signed-off-by: snipe <snipe@snipe.net>
2024-07-09 19:50:58 +01:00
Godfrey M 624632d0ca removed push and endpush 2024-07-09 11:41:31 -07:00
spencerrlongg 66255291da test working 2024-07-09 11:13:06 -05:00
spencerrlongg 33b2c7b78a push so i can do something else 2024-07-09 10:35:16 -05:00
snipe ea881ff95e Merge remote-tracking branch 'origin/develop' 2024-07-09 13:42:03 +01:00
snipe 34e1ff88db Added StreamedResponse
Signed-off-by: snipe <snipe@snipe.net>
2024-07-09 13:41:50 +01:00
snipe c1916d6fe4 Merge remote-tracking branch 'origin/develop' 2024-07-09 13:39:07 +01:00
snipe f4ffbcf76e Fixed wonky layout on accessory files
Signed-off-by: snipe <snipe@snipe.net>
2024-07-09 13:38:50 +01:00
snipe da9932d147 Merge remote-tracking branch 'origin/develop' 2024-07-09 13:36:06 +01:00
snipe 8a547dab20 Fixed type constraint
Signed-off-by: snipe <snipe@snipe.net>
2024-07-09 13:35:57 +01:00
snipe 14fa5d778d Merge pull request #15055 from snipe/more_translations
Fixed API key missing translations
2024-07-09 13:19:46 +01:00
snipe 5597992d63 Fixed API key missing translations
Signed-off-by: snipe <snipe@snipe.net>
2024-07-09 13:17:46 +01:00
snipe da42127a7c Merge remote-tracking branch 'origin/develop' 2024-07-09 11:54:17 +01:00
snipe 595408d21f On more binaryfile response
Signed-off-by: snipe <snipe@snipe.net>
2024-07-09 11:54:07 +01:00
snipe 090410edb5 Merge remote-tracking branch 'origin/develop' 2024-07-09 11:48:30 +01:00
snipe 491a0f3959 One more typehint
Signed-off-by: snipe <snipe@snipe.net>
2024-07-09 11:47:53 +01:00
Jeremy Price c8fe002688 upgrade.php: If we're on windows, make sure we can load intermediate certificates
According to https://github.com/curl/curl/issues/12155 and https://github.com/curl/curl/commit/2d6333101a71129a6a802eb93f84a5ac89e34479

Some corporate Windows proxy (mis)configurations don't pass along
intermediate certificates in their TLS handshakes, breaking lots of
things that don't work around it.

This creates a problem in our curl calls when checking for
.upgrade_requirements.json, and seems to be the source of errors for a
few of our users: https://github.com/snipe/snipe-it/issues/14826#issuecomment-2197611342

In this change, we detect when running on windows environments and load
the curl option that works around this.
2024-07-08 22:13:14 -07:00
Jeremy Price 25fabcc1be More helpful output when we can't read .upgrade_requirements.json
Handle json decode errors and display the raw output in such cases, to
better understand what's happening and help debugging
2024-07-08 22:12:09 -07:00
snipe 43d4bc8dc4 Merge remote-tracking branch 'origin/develop' 2024-07-08 22:13:19 +01:00
snipe 09cc9b92d1 Fixed #15050 - erroneous deleted remark
Signed-off-by: snipe <snipe@snipe.net>
2024-07-08 22:13:07 +01:00
snipe ebcc48ec80 Merge remote-tracking branch 'origin/develop' 2024-07-08 22:02:25 +01:00
snipe bf060d43a7 Fixed typehint on assets controller
Signed-off-by: snipe <snipe@snipe.net>
2024-07-08 22:02:11 +01:00
snipe 9b838cedd1 Fixed typehint on asset model files
Signed-off-by: snipe <snipe@snipe.net>
2024-07-08 22:00:45 +01:00
snipe 5ca62f3ef8 Merge remote-tracking branch 'origin/develop' 2024-07-08 21:39:31 +01:00
snipe abf194fbcf Added default avatar into repo
Signed-off-by: snipe <snipe@snipe.net>
2024-07-08 21:38:25 +01:00
snipe 211f98e971 Revert
Signed-off-by: snipe <snipe@snipe.net>
2024-07-08 21:38:03 +01:00
snipe 7f1931af9c Grr
Signed-off-by: snipe <snipe@snipe.net>
2024-07-08 21:37:17 +01:00
snipe 7dcb45d7f3 Skip default.png as default
Signed-off-by: snipe <snipe@snipe.net>
2024-07-08 21:33:56 +01:00
spencerrlongg 8650923b01 new branch cuz test merge 2024-07-08 12:55:59 -05:00
snipe 9c304f238a Merge pull request #15029 from snipe/fixes/small_docblock_fixes
General cleanup - Docblock fixes, adding type hinting, added tests, added asset model form validator
2024-07-08 17:43:50 +01:00
snipe 202f5077de Removed return
Signed-off-by: snipe <snipe@snipe.net>
2024-07-08 17:41:20 +01:00
snipe 4c19b4d831 Added aria-hidden="true" to error icon for accessibility
Signed-off-by: snipe <snipe@snipe.net>
2024-07-08 17:39:38 +01:00
snipe 3ae16ff8ca Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
#	public/js/build/vendor.js
#	public/js/dist/all.js
#	public/mix-manifest.json
2024-07-08 15:53:42 +01:00
snipe f3bf74a540 Updated language files
Signed-off-by: snipe <snipe@snipe.net>
2024-07-08 15:51:19 +01:00
snipe de6a230838 Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2024-07-08 15:35:35 +01:00
snipe 2e2f59b290 Updated production assets
Signed-off-by: snipe <snipe@snipe.net>
2024-07-08 15:29:36 +01:00
snipe cf92dde1ca Merge pull request #15046 from snipe/localize_bootstrap_table
Added localization for bootstrap-tables
2024-07-08 15:20:39 +01:00
snipe 86c0a3ecad Added localization for bootstrap-tables
Signed-off-by: snipe <snipe@snipe.net>
2024-07-08 15:12:37 +01:00
snipe 3b3a7e2757 Added more PHP in pgsql tests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-08 14:58:26 +01:00
snipe c72b36b84a Upgraded acorn from 8.11.3 to 8.12.0
Signed-off-by: snipe <snipe@snipe.net>
2024-07-08 14:40:26 +01:00
snipe ee1afc63f9 Merge pull request #15045 from snipe/snyk/upgrade-jquery_validation
Snyk - Updated jquery validation
2024-07-08 14:38:14 +01:00
snipe 8438652e7d Updated jquery validation
Signed-off-by: snipe <snipe@snipe.net>
2024-07-08 14:30:06 +01:00
snipe c16db436d3 Merge remote-tracking branch 'origin/develop' 2024-07-08 13:21:38 +01:00
snipe ac9df2fc08 Merge pull request #15043 from snipe/fixes/custom_fields_on_audit
Fixed #15037 - Removed custom fieldsets on auditing - it’s not used (yet)
2024-07-08 13:20:59 +01:00
snipe eba24b9242 Removed custom fieldsets on auditing - it’s not used
Signed-off-by: snipe <snipe@snipe.net>
2024-07-08 13:19:05 +01:00
snipe 8c6ecd35ec Added more basic tests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 11:56:24 +01:00
snipe e98823f7fa Added 403 to sad panda page
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 11:54:49 +01:00
snipe a8ddb2f44a Added non-circular tests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 11:29:30 +01:00
snipe f32bf35c22 Fixed another rename :-/
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 10:50:03 +01:00
snipe 978a0272a5 Sigh. Renamed again
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 08:37:31 +01:00
snipe 283f24b213 Derp. Renamed file
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 08:34:17 +01:00
snipe 97775fb790 Location test additions
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 08:29:00 +01:00
snipe 7455bf329d Added more locations tests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 08:21:31 +01:00
snipe 24ad74f136 Updated factories
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 08:21:18 +01:00
snipe 16d65631aa Removed duplicate tests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 07:54:22 +01:00
snipe 0a7e053985 Added basic Department UI tests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 07:53:02 +01:00
snipe 1d65781d8d More type-hinting
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 07:07:20 +01:00
snipe 0d6fd2643d More tweaks to the form request
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 05:59:39 +01:00
snipe b3cc7b1578 More tests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 05:59:28 +01:00
snipe 2a796fdc09 Format error
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 03:23:48 +01:00
snipe a0914ccb28 Fleshed out tests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 03:22:56 +01:00
snipe efb9d107cf Removed debugging
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 03:22:03 +01:00
snipe 34bde52f74 Fixed typos
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 03:21:34 +01:00
snipe 75da626c85 Check for category ID
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 03:21:24 +01:00
snipe 1d45e0df79 Added model create test
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 03:20:54 +01:00
snipe 5ebcc3b1a0 More type hinting
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 02:36:55 +01:00
snipe 6da6411f3b Added location API index test
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 01:46:36 +01:00
snipe 4089b4cd68 Added category tests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 01:46:09 +01:00
snipe 96d1aea54a More cleanup
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 00:54:50 +01:00
snipe 8baef8d7c5 Derp. Fixed typo
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 00:26:28 +01:00
snipe 7215746d7a Prevent users from editing category types if there are still items
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 00:23:02 +01:00
snipe 6761ff44cc Removed parens
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 00:22:46 +01:00
snipe 1f28bf14c1 Added category tests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-05 00:21:58 +01:00
snipe d3b62aa918 Few more
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 22:52:49 +01:00
snipe a1eafc108d Moar typehinting
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 22:37:58 +01:00
snipe 7330bf5832 Check for invalid
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 21:52:47 +01:00
snipe d834ef5104 Updated string
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 21:52:37 +01:00
snipe ef56f599d2 Use asset model request
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 21:52:29 +01:00
snipe 0f43b3f8f9 Added another test
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 21:52:16 +01:00
snipe c570759370 Fixed tests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 21:14:58 +01:00
snipe 066ec8e26e Added (failing) tests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 20:50:18 +01:00
snipe cc6f1cd585 Added asset model request :(
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 20:50:11 +01:00
snipe ae9085b11f Modernize use statements, switch to auth()
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 20:49:22 +01:00
snipe e98284fff5 Modernized helpers and use statements
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 20:48:35 +01:00
snipe 89f01d75d7 Updated test names, added tests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 19:59:10 +01:00
snipe 8eb68d3901 Merge remote-tracking branch 'origin/develop' 2024-07-04 17:10:43 +01:00
snipe edd61705dc Merge pull request #15027 from snipe/feature/sc-26112/allow_default_avatar
Added #15015 - ability for admins to select default avatar
2024-07-04 17:10:10 +01:00
snipe 3f20e29901 Moved gthe settings for remote loading to the branding section
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 16:55:47 +01:00
snipe 36ae162626 Changed my mind :)
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 16:48:05 +01:00
snipe 00f7cb9dbb Reverse the order for default gravatar
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 16:46:12 +01:00
snipe 1ca3dc26eb Removed extra debugging
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 16:36:48 +01:00
snipe 2f3be267b3 Added some logic around deleting images
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 16:33:22 +01:00
snipe 5b8f6910fb Marked tests as incomplete :(
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 16:33:08 +01:00
snipe 9fe26ba814 Reverted the validation - might have an impact on quickstart setup
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 13:25:39 +01:00
snipe 5e97ed1c7e Added migration
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 13:24:11 +01:00
snipe 947fb7af7a Added tests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 13:24:03 +01:00
snipe 44bcc157e5 Updated icon
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 13:23:46 +01:00
snipe 278bf3da13 Updated language
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 13:23:38 +01:00
snipe 446bc81d3a Updated presenter to use new avatar
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 13:23:31 +01:00
snipe 9527aac242 Make site name required at the model
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 13:23:17 +01:00
snipe c57f1f9d7d Use null coalescence
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 13:22:56 +01:00
snipe e372527d13 Added default_avatar to settings
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 13:22:36 +01:00
snipe 96be1e1275 Removed duplicate locale directive
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 02:14:10 +01:00
snipe 8ce17d0585 Merge pull request #15025 from snipe/security/upgrade_webpack
Upgrade webpack from 5.91.0 to 5.92.0 #15008
2024-07-04 01:08:17 +01:00
snipe 6af1eaa4e4 Updated webpack to 5.92
Signed-off-by: snipe <snipe@snipe.net>
2024-07-04 01:07:26 +01:00
snipe da01487301 Merge pull request #15023 from snipe/improvements/optimize_queries_for_user_bulk_actions
Added files column to bulk user delete, optimized queries
2024-07-03 23:45:09 +01:00
snipe 708d7b5fc5 Use icons for consistency
Signed-off-by: snipe <snipe@snipe.net>
2024-07-03 23:43:44 +01:00
snipe 62b5a159a9 Added files column
Signed-off-by: snipe <snipe@snipe.net>
2024-07-03 23:31:09 +01:00
snipe fc7809192d Merge remote-tracking branch 'origin/develop' 2024-07-03 23:20:24 +01:00
snipe a6d04509a5 Merge pull request #15016 from snipe/improved_user_merge
Fixed #15005 - Improvements  on user merge
2024-07-03 23:19:50 +01:00
snipe 0071596274 Added upload count
Signed-off-by: snipe <snipe@snipe.net>
2024-07-03 23:18:43 +01:00
snipe 59f66051f8 More eager loading
Signed-off-by: snipe <snipe@snipe.net>
2024-07-03 23:18:37 +01:00
snipe 9f1e59cf78 Marcus’ nitpicks
Signed-off-by: snipe <snipe@snipe.net>
2024-07-03 23:01:41 +01:00
snipe f1f68b8ef6 Merge pull request #15022 from spencerrlongg/livewire-delete-button
Resolved Potential Issue when Deleting Personal Access Tokens
2024-07-03 22:24:25 +01:00
snipe f22c3cdda9 Merge pull request #15021 from snipe/fixes/removed_non_counts
Removed non-counts from allowed array
2024-07-03 22:21:17 +01:00
snipe 5e15cc3bbe Added markIncompleteIfSqlite() method
Signed-off-by: snipe <snipe@snipe.net>
2024-07-03 22:18:31 +01:00
spencerrlongg a6690493b0 resolved 2024-07-03 16:12:55 -05:00
snipe 17a6335d13 Added test
Signed-off-by: snipe <snipe@snipe.net>
2024-07-03 22:12:06 +01:00
akemidx ca57f6de85 adding in item=>asset, missed in first commit 2024-07-03 17:07:50 -04:00
snipe aefaabdb1a Removed non-counts from allowed array
Signed-off-by: snipe <snipe@snipe.net>
2024-07-03 21:40:43 +01:00
snipe 9211c8d3b1 Fixed test
Signed-off-by: snipe <snipe@snipe.net>
2024-07-03 20:57:21 +01:00
snipe eff1980df5 Added console test
Signed-off-by: snipe <snipe@snipe.net>
2024-07-03 20:52:22 +01:00
snipe 1553ba5630 Added null coalescence for admin id in case via cli
Signed-off-by: snipe <snipe@snipe.net>
2024-07-03 20:52:12 +01:00
snipe ec24120d2a Allow admin to be nullable (for cli)
Signed-off-by: snipe <snipe@snipe.net>
2024-07-03 20:50:35 +01:00
snipe 50df750202 Add merge event
Signed-off-by: snipe <snipe@snipe.net>
2024-07-03 20:50:23 +01:00
snipe dab4aced48 Renamed test
Signed-off-by: snipe <snipe@snipe.net>
2024-07-03 20:50:09 +01:00
snipe 1774952312 Added additional assertions
Signed-off-by: snipe <snipe@snipe.net>
2024-07-03 20:19:12 +01:00
snipe d66d6e70a6 Added checkedOutToUser factory for consumables
Signed-off-by: snipe <snipe@snipe.net>
2024-07-03 20:18:53 +01:00
snipe 4635e9269d Added user update log factory
Signed-off-by: snipe <snipe@snipe.net>
2024-07-03 20:18:34 +01:00
snipe 574867536d Standardize query for merging
Signed-off-by: snipe <snipe@snipe.net>
2024-07-03 19:41:34 +01:00
snipe 5488a4d118 One more test
Signed-off-by: snipe <snipe@snipe.net>
2024-07-03 14:36:27 +01:00
snipe e34f3c7c2c Fixed typo
Signed-off-by: snipe <snipe@snipe.net>
2024-07-03 14:32:41 +01:00
snipe ceaff7b645 Added tests
Signed-off-by: snipe <snipe@snipe.net>
2024-07-03 14:30:11 +01:00
snipe d27a025347 Added factories
Signed-off-by: snipe <snipe@snipe.net>
2024-07-03 14:30:06 +01:00
snipe 2b2853a183 Added acceptance model
Signed-off-by: snipe <snipe@snipe.net>
2024-07-03 14:29:58 +01:00
snipe a25263f868 Transfer files and acceptances on merge
Signed-off-by: snipe <snipe@snipe.net>
2024-07-03 14:29:49 +01:00
snipe 4b9727067b Merge pull request #15010 from snipe/fixes/translation_strings
Added missing translations
2024-07-03 12:43:50 +01:00
snipe 00fc392a12 Added missing traslations
Signed-off-by: snipe <snipe@snipe.net>
2024-07-03 12:41:04 +01:00
spencerrlongg e79111fed5 fix test :( 2024-07-02 16:01:18 -05:00
spencerrlongg 423b48279b merge 2024-07-02 15:53:28 -05:00
spencerrlongg 6f29c0a7cf Merge branch 'refs/heads/develop' into bug/sc-24884
# Conflicts:
#	routes/api.php
2024-07-02 15:48:39 -05:00
snipe 27bc16604b Add @Galaxy102 as a contributor 2024-07-02 09:48:32 +01:00
snipe 86ae4a3513 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2024-07-02 09:37:40 +01:00
snipe 1da90fe1ec Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2024-07-02 09:37:05 +01:00
snipe 25ba50d6f7 Merge pull request #14870 from Galaxy102/feature/rotate-labels
Add Label Template: Use with endless 62mm Brother printer rolls
2024-07-02 08:45:42 +01:00
snipe f22e99aec8 Merge pull request #14983 from snipe/fixes/use_more_modern_request_syntax_in_blades
Use more modern reference for input text
2024-07-02 08:43:34 +01:00
snipe f027fd5f21 Merge pull request #14986 from marcusmoore/bug/sc-25926
Fixed extension requirement checking in upgrade script
2024-07-02 08:42:45 +01:00
snipe 37a038c24f Merge pull request #15001 from marcusmoore/features/link-user-table-counts-to-section
Added links on user table to tabs on show user page
2024-07-02 08:37:05 +01:00
spencerrlongg 0b60cbc531 remove $rules2 2024-07-01 19:37:49 -05:00
Marcus Moore 3a8f825de5 Link user table counts to section in user show 2024-07-01 14:06:05 -07:00
snipe d2df83cf2f Merge pull request #14999 from marcusmoore/fixes/hide-edit-profile-button
Removed "Edit Your Profile" button from View Assets page if user is not able to edit their profile
2024-07-01 18:15:47 +01:00
Marcus Moore d481850d4c Add @can around Edit Your Profile button on view assets page 2024-07-01 10:11:27 -07:00
snipe e502968707 Prod assets
Signed-off-by: snipe <snipe@snipe.net>
2024-07-01 10:00:28 +01:00
snipe 12dcac4994 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/css/dist/all.css
#	public/css/dist/bootstrap-table.css
#	public/js/build/app.js
#	public/js/dist/all.js
#	public/js/dist/bootstrap-table.js
#	public/mix-manifest.json
2024-07-01 10:00:15 +01:00
Konstantin Köhring 6c55e2bd9d Add a Brother compatible 62mm wide label.
Tested with QL-600. Set print mode to landscape.
2024-06-28 09:49:53 +02:00
Konstantin Köhring 2fd357c346 Add rotation attribute to Label class to allow rotation of the generated label PDF.
This is necessary when printing labels with width = label width.
2024-06-28 09:49:53 +02:00
Marcus Moore 0a5e58201a Correctly account for "or" dependent extensions in upgrade script 2024-06-27 12:38:50 -07:00
snipe d687b20467 Use more modern reference for input text
Signed-off-by: snipe <snipe@snipe.net>
2024-06-27 15:05:47 +01:00
snipe 7dbcedad40 Merge pull request #14981 from uberbrady/fix_backup_translations
Fixed #14976, #14975, #14973 - Translation strings aren't always working
2024-06-27 14:36:52 +01:00
snipe b6e8d28ed3 Merge pull request #14982 from snipe/fixes/check_for_user_on_patch_api
Check that the user exists before trying to fill the request
2024-06-27 14:36:21 +01:00
snipe 85ce47f5bb Updated tests
Signed-off-by: snipe <snipe@snipe.net>
2024-06-27 14:21:27 +01:00
snipe 55c98cc27a Check that the user exists before trying to fill the request
Signed-off-by: snipe <snipe@snipe.net>
2024-06-27 14:05:28 +01:00
snipe 422f3ec81e Updated assets
Signed-off-by: snipe <snipe@snipe.net>
2024-06-27 13:53:38 +01:00
snipe 54fb91c03b Merge pull request #14831 from marcusmoore/chore/sc-23725/livewire3
Updated Livewire to v3
2024-06-27 13:21:52 +01:00
Brady Wetherington 6df9742664 Built a workaround for backup notification translations 2024-06-27 13:17:16 +01:00
snipe f23a221750 Merge pull request #14942 from snipe/updates/start_moving_from_collective_forms
WIP - First start at switching to regular html labels
2024-06-27 13:12:29 +01:00
snipe 1837da4508 Merge branch 'develop' 2024-06-26 13:46:40 +01:00
snipe 4637accb51 Built assets, bumped version
Signed-off-by: snipe <snipe@snipe.net>
2024-06-26 13:35:24 +01:00
snipe 74f067d893 Merge pull request #14974 from uberbrady/improve_saml_behind_proxy
Fixed #14895 and #14919 - set SAML baseurl to a sensible default for docker users and users behind a reverse proxy
2024-06-26 13:34:18 +01:00
snipe 43773954cd Merge pull request #14966 from Godmartinz/css_issue
Fixed importer table background color
2024-06-26 13:33:14 +01:00
Brady Wetherington 30cafef9f2 Add a reasonable-looking SAML baseurl, mosty for users behind proxies 2024-06-26 13:25:11 +01:00
snipe e1a6b441d7 Merge remote-tracking branch 'origin/develop' 2024-06-26 12:53:18 +01:00
snipe 251f2d82b3 Updated language strings
Signed-off-by: snipe <snipe@snipe.net>
2024-06-26 12:53:03 +01:00
snipe e905550778 Merge pull request #14971 from snipe/fixes/updated_translation_string
Fixes #14968 - translate forbidden page
2024-06-26 11:25:51 +01:00
snipe adee99db34 Fixes #14968 - translate forbidden page
Signed-off-by: snipe <snipe@snipe.net>
2024-06-26 11:21:56 +01:00
Godfrey M eda2eb2283 fixes all dark modes 2024-06-25 10:24:35 -07:00
Godfrey M a7123a04ba fixes importer background color 2024-06-25 10:19:18 -07:00
Marcus Moore 8a562f1d15 Bump Livewire to 3.5.1 2024-06-25 10:16:44 -07:00
Marcus Moore d4861a74df Merge branch 'develop' into chore/sc-23725/livewire3
# Conflicts:
#	composer.lock
2024-06-25 10:15:50 -07:00
snipe 8971cc4b8b Merge pull request #14963 from snipe/fixes/updated_translation_string
Added avif to translation string
2024-06-25 13:45:10 +01:00
snipe bca6dd41d2 Added avif to translation string
Signed-off-by: snipe <snipe@snipe.net>
2024-06-25 13:39:36 +01:00
snipe 23c1d664fe Prod assets
Signed-off-by: snipe <snipe@snipe.net>
2024-06-24 22:07:01 +01:00
snipe c891342fdb Bumoed version
Signed-off-by: snipe <snipe@snipe.net>
2024-06-24 22:06:52 +01:00
snipe 221c4eeb0c Dev assets
Signed-off-by: snipe <snipe@snipe.net>
2024-06-24 21:59:27 +01:00
snipe bbb1fbfbe8 Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2024-06-24 21:59:09 +01:00
snipe 5a874a90ac Merge pull request #14951 from snipe/features/disallow_profile_editing
Added ability to disallow profile editing
2024-06-24 14:11:48 +01:00
snipe 1c14c2fdef Added gates to controller
Signed-off-by: snipe <snipe@snipe.net>
2024-06-24 14:05:21 +01:00
snipe 73a038afd4 Save new setting
Signed-off-by: snipe <snipe@snipe.net>
2024-06-24 14:03:01 +01:00
snipe 4d55765e28 Added checkbox to settings
Signed-off-by: snipe <snipe@snipe.net>
2024-06-24 14:02:53 +01:00
snipe 2b43f3cb84 Added gate to auth service provider
Signed-off-by: snipe <snipe@snipe.net>
2024-06-24 14:02:40 +01:00
snipe 52c4885335 Added method for checking if the user can edit their own profile
Signed-off-by: snipe <snipe@snipe.net>
2024-06-24 14:02:17 +01:00
snipe aa5fe52e89 Added gate in blade
Signed-off-by: snipe <snipe@snipe.net>
2024-06-24 14:01:56 +01:00
snipe ce107dd688 New strings
Signed-off-by: snipe <snipe@snipe.net>
2024-06-24 14:01:39 +01:00
snipe 72affd7a5b Added migration
Signed-off-by: snipe <snipe@snipe.net>
2024-06-24 14:01:31 +01:00
snipe ba4c51dd68 Removed duplicate key
Signed-off-by: snipe <snipe@snipe.net>
2024-06-24 14:01:25 +01:00
snipe 294fb1f774 Merge pull request #14925 from snipe/fixes/added_2fa_string
Additional translation strings
2024-06-24 12:11:45 +01:00
snipe a846afe733 Merge pull request #14950 from snipe/localization/updated_strings_20240621
Updated translations
2024-06-24 11:44:06 +01:00
snipe 5fb3cea0bb Updated translations
Signed-off-by: snipe <snipe@snipe.net>
2024-06-24 11:41:20 +01:00
snipe 4ae89c23cd Merge pull request #14947 from snipe/dependabot/github_actions/develop/docker/build-push-action-6
Bump docker/build-push-action from 5 to 6
2024-06-24 11:27:04 +01:00
snipe 3d32fe662b Merge pull request #14949 from snipe/fixes/depreciation_format
Check that there is a depreciation date before formatting
2024-06-24 11:11:43 +01:00
snipe 468674a517 Check that there is a depreciation date before formatting
Signed-off-by: snipe <snipe@snipe.net>
2024-06-24 11:07:41 +01:00
dependabot[bot] ebe4354a85 Bump docker/build-push-action from 5 to 6
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5 to 6.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v5...v6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-24 08:14:34 +00:00
snipe f47bc5ea7d Updated hardware checkin
Signed-off-by: snipe <snipe@snipe.net>
2024-06-23 19:40:52 +01:00
snipe 427615f627 Fiest start at switching to regular html labels
Signed-off-by: snipe <snipe@snipe.net>
2024-06-23 18:24:23 +01:00
snipe 829b560794 Merge pull request #14941 from snipe/updates/updated_phpunit
Updated PHPunit
2024-06-23 17:43:29 +01:00
snipe f97a15c5c3 Updated PHPunit
Signed-off-by: snipe <snipe@snipe.net>
2024-06-23 17:33:01 +01:00
snipe 25fcf523e3 Merge pull request #14937 from snipe/fixes/user_improvements
Fixed #14935 - improvements and more tests around user deletion
2024-06-22 21:41:07 +01:00
snipe c1be94c4ad Added another base test
Signed-off-by: snipe <snipe@snipe.net>
2024-06-22 20:37:49 +01:00
snipe 3a05d72124 Based restore API test
Signed-off-by: snipe <snipe@snipe.net>
2024-06-22 20:35:40 +01:00
snipe 7ec44e46ce Added ability check for restoring users at all
Signed-off-by: snipe <snipe@snipe.net>
2024-06-22 20:35:28 +01:00
snipe 060b17df01 Pulled duplicated test
Signed-off-by: snipe <snipe@snipe.net>
2024-06-22 20:34:49 +01:00
snipe 74c78d7577 Added back in commented out test
Signed-off-by: snipe <snipe@snipe.net>
2024-06-22 20:09:04 +01:00
snipe 1ef0c1adac Fixed tests! And added more!!
Signed-off-by: snipe <snipe@snipe.net>
2024-06-22 20:07:46 +01:00
snipe c2e649e2bf Fixed small permissions issue
Signed-off-by: snipe <snipe@snipe.net>
2024-06-22 20:07:37 +01:00
snipe 196db9718e Use class name instead
Signed-off-by: snipe <snipe@snipe.net>
2024-06-22 19:55:58 +01:00
snipe 9f5b264e04 Normalize the tests between UI and API
Signed-off-by: snipe <snipe@snipe.net>
2024-06-22 19:51:56 +01:00
snipe 3825f5fb61 Added more permissions tests to user delete UI
Signed-off-by: snipe <snipe@snipe.net>
2024-06-22 19:47:59 +01:00
snipe e60dbc883c Removed test code
Signed-off-by: snipe <snipe@snipe.net>
2024-06-22 19:42:34 +01:00
snipe bbbfa91db9 Fixed wonky rule
Signed-off-by: snipe <snipe@snipe.net>
2024-06-22 19:40:26 +01:00
snipe 5ec8e2da66 Breaking tests :(
Signed-off-by: snipe <snipe@snipe.net>
2024-06-22 19:33:44 +01:00
snipe 9e59bd5687 Cleaned up controller code a bit
Signed-off-by: snipe <snipe@snipe.net>
2024-06-22 19:33:36 +01:00
snipe 1d26ccac4e Check for the additional auth for that user
Signed-off-by: snipe <snipe@snipe.net>
2024-06-22 19:33:06 +01:00
snipe 0e2526f627 Removed comment
Signed-off-by: snipe <snipe@snipe.net>
2024-06-22 19:32:49 +01:00
snipe dd9e9c7a6d Fixed return types
Signed-off-by: snipe <snipe@snipe.net>
2024-06-22 18:49:49 +01:00
snipe e19922abd0 Cleaned up UI controller
Signed-off-by: snipe <snipe@snipe.net>
2024-06-22 18:49:35 +01:00
snipe d27bde6047 Added deleted factory for tests
Signed-off-by: snipe <snipe@snipe.net>
2024-06-22 18:36:24 +01:00
snipe 61f76dedc6 Added test
Signed-off-by: snipe <snipe@snipe.net>
2024-06-22 18:36:08 +01:00
snipe 06737f45ad Added test
Signed-off-by: snipe <snipe@snipe.net>
2024-06-22 18:36:02 +01:00
snipe 65e8765bdd Added tests
Signed-off-by: snipe <snipe@snipe.net>
2024-06-22 17:45:42 +01:00
snipe c6a0212384 Merge remote-tracking branch 'origin/master' into develop 2024-06-22 17:33:12 +01:00
snipe e03614d91b Added withtrashed back in
Signed-off-by: snipe <snipe@snipe.net>
2024-06-22 16:40:32 +01:00
snipe b82770d0a8 One more small fix
Signed-off-by: snipe <snipe@snipe.net>
2024-06-22 16:38:29 +01:00
snipe 55e1326164 Fixed #14935 - user does not exist
Signed-off-by: snipe <snipe@snipe.net>
2024-06-22 16:24:18 +01:00
snipe b0aff68c8b Merge pull request #14934 from snipe/tests/added_workflow_for_php_8_3
Added php 8.3 test
2024-06-21 22:04:05 +01:00
snipe 6a99855c8c Added php 8.3 test
Signed-off-by: snipe <snipe@snipe.net>
2024-06-21 21:47:40 +01:00
snipe 665aa6eb23 Merge pull request #14924 from snipe/fixes/possible_nicer_handling_for_defaultStatusLabel
Possible fix for #14915 - error on import when status label is not provided and no deployable statuses can be found
2024-06-21 21:37:22 +01:00
snipe 42caacbaf9 Merge pull request #14932 from snipe/fixes/small_deprecations
Fixed small deprecation warnings for PHP8.2
2024-06-21 21:26:16 +01:00
snipe 3531256c3f Fixed deprecations
Signed-off-by: snipe <snipe@snipe.net>
2024-06-21 21:06:43 +01:00
snipe 9a0db72eb4 More strings
Signed-off-by: snipe <snipe@snipe.net>
2024-06-20 15:40:38 +01:00
snipe e11a42cf68 Re-use login string
Signed-off-by: snipe <snipe@snipe.net>
2024-06-20 15:32:00 +01:00
snipe 114769c2d9 Made requestable items more generic in translations
Signed-off-by: snipe <snipe@snipe.net>
2024-06-20 15:26:45 +01:00
snipe 9594596b8a Fixed another hard-coded string
Signed-off-by: snipe <snipe@snipe.net>
2024-06-20 15:22:27 +01:00
snipe 69cf697aa3 Added 2fa translation string
Signed-off-by: snipe <snipe@snipe.net>
2024-06-20 15:20:52 +01:00
snipe 45dbe5cb77 Return the id, not the entire status label
Signed-off-by: snipe <snipe@snipe.net>
2024-06-20 15:05:38 +01:00
snipe a1ff35f6ce Possible fix for #14915
Signed-off-by: snipe <snipe@snipe.net>
2024-06-20 14:47:46 +01:00
snipe 077a6949e2 docs: add @Tyree as a contributor 2024-06-20 14:42:19 +01:00
snipe 44022f07ca docs: update @bryanlopezinc as a contributor 2024-06-20 14:41:22 +01:00
snipe 30c1e1e86a Merge remote-tracking branch 'origin/develop' 2024-06-20 14:32:46 +01:00
snipe 9a90813877 Merge pull request #14923 from snipe/localizations/updated_strings
Updated language strings
2024-06-20 14:29:13 +01:00
snipe 1113218c6c Updated strings
Signed-off-by: snipe <snipe@snipe.net>
2024-06-20 14:23:15 +01:00
snipe 2556c80250 Merge pull request #14922 from snipe/fixes/incorrect_translation_path
Fixed incorrect translation path
2024-06-20 14:10:32 +01:00
snipe 8f8a5c639b Updated profile translation string path
Signed-off-by: snipe <snipe@snipe.net>
2024-06-20 14:09:25 +01:00
snipe 9e9c37c1e8 Fixed weird linebreaks
Signed-off-by: snipe <snipe@snipe.net>
2024-06-20 14:09:11 +01:00
snipe 6cbdbcb1f1 Merge pull request #14791 from Godmartinz/label-option-limit
Added some  style changes in label field selector for the `DefaultLabel` template
2024-06-20 13:51:49 +01:00
snipe c8835bf5db Merge remote-tracking branch 'origin/develop' 2024-06-20 13:40:37 +01:00
snipe 6dfedac7a7 Merge pull request #14912 from bryanlopezinc/addIsWritableTest
Add storage path permissions test
2024-06-20 13:38:56 +01:00
snipe 83794eaf33 Merge pull request #14921 from snipe/fixes/14918_added_lastname_dot_firstname
Added lastname.firstname as email format
2024-06-20 13:38:30 +01:00
snipe bd1f43f9ee Added lastname.firstname as email format
Signed-off-by: snipe <snipe@snipe.net>
2024-06-20 13:36:48 +01:00
snipe 66ffe21ce2 Merge remote-tracking branch 'origin/develop' 2024-06-20 13:09:54 +01:00
snipe f2e86b7d30 Merge pull request #14920 from snipe/fixes/backup_notifications
Fixed backup notification translations
2024-06-20 13:09:26 +01:00
snipe 5251e6787d Use two-letter fallback code
Ugh, I hate this

Signed-off-by: snipe <snipe@snipe.net>
2024-06-20 12:58:00 +01:00
snipe 856aee0a72 Updated laravel-backup
Signed-off-by: snipe <snipe@snipe.net>
2024-06-20 12:57:35 +01:00
snipe 6b4c71f966 Updated config
Signed-off-by: snipe <snipe@snipe.net>
2024-06-20 12:57:25 +01:00
snipe dd6d040da5 Added translations
Signed-off-by: snipe <snipe@snipe.net>
2024-06-20 12:56:43 +01:00
bryanlopezinc 203b60383f Added storage path permissions test for SettingsController@getSetupIndex 2024-06-19 17:46:59 +01:00
snipe 61ced0b221 Merge remote-tracking branch 'origin/develop' 2024-06-19 11:41:11 +01:00
snipe ae7675fee0 Added audit date validation back in
Signed-off-by: snipe <snipe@snipe.net>
2024-06-19 11:37:15 +01:00
snipe 66ed26fbf9 Merge remote-tracking branch 'origin/develop' 2024-06-19 11:13:47 +01:00
snipe 98662c2a77 Merge pull request #14908 from snipe/fixes/importer_audit_date
Fixes/importer audit date
2024-06-19 11:12:12 +01:00
snipe 7099358985 Added accessor/mutator
Signed-off-by: snipe <snipe@snipe.net>
2024-06-19 11:11:50 +01:00
snipe 9a706b3e3e Removed datetime validation
Signed-off-by: snipe <snipe@snipe.net>
2024-06-19 11:05:31 +01:00
snipe 71c9b03779 Fixed incorrect field name
Signed-off-by: snipe <snipe@snipe.net>
2024-06-19 11:05:22 +01:00
snipe dc7b9315b5 Merge remote-tracking branch 'origin/develop' 2024-06-19 10:35:54 +01:00
snipe 6c17b141db Removed duplicate locations_id search
Signed-off-by: snipe <snipe@snipe.net>
2024-06-19 10:35:21 +01:00
snipe 5d2cca855e Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2024-06-19 10:31:04 +01:00
snipe 61e10be04d Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2024-06-19 10:29:50 +01:00
snipe 20d5587851 Merge remote-tracking branch 'origin/develop' 2024-06-19 10:23:18 +01:00
snipe d8eccf03f1 Merge pull request #14896 from snipe/fixes/tls_loading
Possible fix for proxy/reverse proxy
2024-06-19 10:22:36 +01:00
snipe 6e40b58dc5 Merge remote-tracking branch 'origin/develop' 2024-06-19 01:21:52 +01:00
Marcus Moore 30dd8bcf2b Update Livewire 2024-06-18 15:10:59 -07:00
Marcus Moore f0a11be0b8 Merge branch 'develop' into chore/sc-23725/livewire3
# Conflicts:
#	composer.lock
2024-06-18 15:10:46 -07:00
snipe b8882fa00e Merge pull request #14900 from marcusmoore/fixes/81-install
Fixed unable to install on PHP 8.1
2024-06-18 21:53:30 +01:00
Marcus Moore af337b7018 Move debugbar back to dev dependencies but without updating other packages 2024-06-18 09:46:08 -07:00
Marcus Moore f60267d208 Revert "Reverted debugbar back into require vs require-dev"
This reverts commit ce338c632d.
2024-06-18 09:42:21 -07:00
snipe a0c844f4f6 Merge remote-tracking branch 'origin/develop' 2024-06-18 16:12:20 +01:00
snipe 7b84b92e72 Merge pull request #14899 from snipe/fixes/revert_debugbar_dev
Fixed #14898 - (regression) Reverted debugbar back into require vs require-dev
2024-06-18 16:09:51 +01:00
snipe ce338c632d Reverted debugbar back into require vs require-dev
Signed-off-by: snipe <snipe@snipe.net>
2024-06-18 16:06:38 +01:00
snipe d9f70c16f7 Possible fix proxy/reverse proxy
Signed-off-by: snipe <snipe@snipe.net>
2024-06-18 14:44:35 +01:00
snipe d0299de898 Merge remote-tracking branch 'origin/develop' 2024-06-18 11:25:55 +01:00
snipe 9380c9ec81 Merge pull request #14894 from snipe/fixes/14882_archived_scoping_on_models
Fixed #14882 - Properly scope archived based on settings
2024-06-18 11:24:55 +01:00
snipe 941582ac2a Properly scope archived based on settings
Signed-off-by: snipe <snipe@snipe.net>
2024-06-18 10:27:11 +01:00
snipe 04560b4475 Merge remote-tracking branch 'origin/develop' 2024-06-18 10:13:57 +01:00
snipe 0b30ad0da2 Removed test file - #14890
Signed-off-by: snipe <snipe@snipe.net>
2024-06-18 10:12:57 +01:00
snipe cb6ea2c6fb Merge remote-tracking branch 'origin/develop' 2024-06-18 09:59:43 +01:00
snipe 89a5bbb10e Merge pull request #14893 from snipe/fixes/rb_3792_ambiguous_query
Prefaced fields with “users” for clarity
2024-06-18 09:58:44 +01:00
snipe 2f59bb74cd Prefaced fields with “users” for clarity
Signed-off-by: snipe <snipe@snipe.net>
2024-06-18 09:52:41 +01:00
snipe 6c6a3649ea Production assets
Signed-off-by: snipe <snipe@snipe.net>
2024-06-18 09:33:07 +01:00
snipe 05b97db747 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2024-06-18 09:32:30 +01:00
snipe 543e4c0666 Bumped version file
Signed-off-by: snipe <snipe@snipe.net>
2024-06-18 09:31:49 +01:00
snipe e28619f769 Bumped papaparse library
Signed-off-by: snipe <snipe@snipe.net>
2024-06-18 09:30:24 +01:00
snipe 4d8c2d3f4e Merge pull request #14886 from marcusmoore/fixes/debugbar
Bumped debugbar from v3.13.0 to v3.13.5 to fix issue with session messages
2024-06-18 09:22:18 +01:00
snipe f53eeb8b33 Merge pull request #14887 from marcusmoore/fixes/fix-test-namespace
Fixed namespace for ViewUserTest
2024-06-18 09:20:58 +01:00
snipe aba6d9b338 Merge pull request #14885 from marcusmoore/tests/asset-model-test-improvements
Added more tests around Asset Model
2024-06-18 09:20:45 +01:00
snipe cd5bef414c Merge pull request #14884 from marcusmoore/fix/actionlogcontroller-fix
Fixed missing `}`
2024-06-18 09:20:26 +01:00
Marcus Moore 4f2d2ae4b8 Fix namespace for ViewUserTest 2024-06-17 16:37:24 -07:00
Marcus Moore 1bd0ab7389 Move barryvdh/laravel-debugbar from require to require-dev 2024-06-17 16:28:08 -07:00
Marcus Moore 8799276c6e Bump debugbar from v3.13.0 to v3.13.5 2024-06-17 16:25:39 -07:00
Marcus Moore 672aabf4ac Add more tests for Asset Model index and store methods 2024-06-17 14:51:59 -07:00
Marcus Moore 796d6909d5 Add missing } 2024-06-17 14:40:06 -07:00
Marcus Moore a3dea99bbb Fix category edit form component 2024-06-17 14:24:16 -07:00
Marcus Moore fc351a1896 Remove .live from oauth clients 2024-06-17 13:03:27 -07:00
Marcus Moore d9164281ab Merge branch 'develop' into chore/sc-23725/livewire3
# Conflicts:
#	resources/views/livewire/oauth-clients.blade.php
2024-06-17 12:57:04 -07:00
snipe cbb5b6e846 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2024-06-17 15:58:27 +01:00
snipe 08bd39dbba Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2024-06-17 15:57:32 +01:00
snipe 430808e180 Merge remote-tracking branch 'origin/develop' 2024-06-17 15:52:13 +01:00
snipe 6976dc2b26 Merge pull request #14879 from snipe/fixes/better_ui_for_oauth
Fixed weird layout in admin oauth [sc-25673]
2024-06-17 15:51:11 +01:00
snipe 27063d5bae Fix weird layout in admin oauth [sc-25673]
Signed-off-by: snipe <snipe@snipe.net>
2024-06-17 15:44:07 +01:00
snipe 5be86b9dbb Merge remote-tracking branch 'origin/develop' 2024-06-17 13:43:45 +01:00
snipe afc78524fc Merge pull request #14877 from snipe/fixes/spatie-backup-config
Updated config
2024-06-17 13:42:02 +01:00
snipe eb33a2451f Updated config
Signed-off-by: snipe <snipe@snipe.net>
2024-06-17 13:36:52 +01:00
snipe 891a0a0965 Merge branch 'develop' of https://github.com/snipe/snipe-it into develop 2024-06-17 13:05:31 +01:00
snipe 50f0797850 Added aria hidden to icon
Signed-off-by: snipe <snipe@snipe.net>
2024-06-17 13:05:27 +01:00
snipe 36cdf0e0be Merge pull request #14876 from snipe/fixes/small_footer_issues
Fixed small footer issues
2024-06-17 12:53:52 +01:00
snipe d9cc3c3ec7 Removed extra divs
Signed-off-by: snipe <snipe@snipe.net>
2024-06-17 12:52:23 +01:00
snipe 069a1608de Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2024-06-17 12:10:13 +01:00
snipe 60accfd601 Bumped version file
Signed-off-by: snipe <snipe@snipe.net>
2024-06-17 12:09:30 +01:00
snipe b1f2051b43 Merge remote-tracking branch 'origin/develop' 2024-06-17 11:58:11 +01:00
snipe 233e4af7f8 Added base asset models test
Signed-off-by: snipe <snipe@snipe.net>
2024-06-17 11:57:30 +01:00
snipe dc1b808a28 Fixed static request
Signed-off-by: snipe <snipe@snipe.net>
2024-06-17 11:47:21 +01:00
snipe 91a423e60e Bumped php max version
Signed-off-by: snipe <snipe@snipe.net>
2024-06-17 11:27:55 +01:00
snipe bd03a6d206 Production assets
Signed-off-by: snipe <snipe@snipe.net>
2024-06-17 11:18:44 +01:00
snipe d87da78eb5 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	app/Http/Controllers/Users/UsersController.php
#	config/version.php
#	public/css/build/AdminLTE.css
#	public/css/build/app.css
#	public/css/build/overrides.css
#	public/css/dist/all.css
#	public/css/dist/bootstrap-table.css
#	public/js/build/app.js
#	public/js/build/vendor.js
#	public/js/dist/all-defer.js
#	public/js/dist/all.js
#	public/js/dist/bootstrap-table.js
#	public/mix-manifest.json
2024-06-17 11:18:33 +01:00
snipe f3e82c2c80 Updated languages
Signed-off-by: snipe <snipe@snipe.net>
2024-06-17 10:59:17 +01:00
snipe 569f05a99e Built prod assets
Signed-off-by: snipe <snipe@snipe.net>
2024-06-17 10:45:04 +01:00
snipe ece7c22df9 Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2024-06-17 10:44:20 +01:00
snipe 4eefd39172 Bumped requirements
Signed-off-by: snipe <snipe@snipe.net>
2024-06-17 10:42:59 +01:00
snipe daae5d6859 Merge pull request #14724 from phil-flip/develop
Added Proper Docker Compose and .env.docker-setup files
2024-06-16 15:49:15 +01:00
snipe df76769a29 Merge pull request #14871 from marcusmoore/chore/move-test
Moved `AssetFilesTest`
2024-06-13 23:10:36 +01:00
Marcus Moore fe72639925 Move AssetFilesTest 2024-06-13 14:25:25 -07:00
Marcus Moore c3e6e1144f Merge branch 'develop' into chore/sc-23725/livewire3 2024-06-12 15:12:40 -07:00
snipe cacb5d62dc Merge pull request #14800 from snipe/fixes/importer_tweaks
Importer tweaks
2024-06-12 12:51:11 +01:00
snipe a8b47a55bc Merge pull request #14801 from snipe/fixes/companyable_trait_on_users
Allow CompanyableTrait trait on users
2024-06-12 12:42:56 +01:00
snipe 3159fdec9f FFS
Signed-off-by: snipe <snipe@snipe.net>
2024-06-12 12:40:43 +01:00
snipe ea990a5381 Fixed tests
Signed-off-by: snipe <snipe@snipe.net>
2024-06-12 12:31:41 +01:00
snipe 134183ef16 Shuffled tests around again
Signed-off-by: snipe <snipe@snipe.net>
2024-06-12 12:12:15 +01:00
snipe 67ab2536bc Updated test names
Signed-off-by: snipe <snipe@snipe.net>
2024-06-12 12:03:33 +01:00
snipe 756a2ac25c Added API tests
Signed-off-by: snipe <snipe@snipe.net>
2024-06-12 11:58:12 +01:00
snipe acaceb4103 Moved tests
Signed-off-by: snipe <snipe@snipe.net>
2024-06-12 11:57:50 +01:00
snipe 7e3d66ec53 Merge branch 'develop' into fixes/companyable_trait_on_users 2024-06-12 11:27:26 +01:00
snipe 1ca9bb5aa8 Merge pull request #14698 from Scarzy/features/asset_file_upload_from_api
Added #9413: Asset file upload from API
2024-06-12 11:18:06 +01:00
snipe c641b733e1 Merge pull request #14834 from bryanlopezinc/AddAppUrlTest
Added test for app url config
2024-06-12 11:14:17 +01:00
snipe 16cf6bc852 Merge pull request #14843 from marcusmoore/chore/sc-25767
Added GitHub workflow for tests in Postgres
2024-06-12 09:53:55 +01:00
Marcus Moore c51b7d7104 Inline variable 2024-06-10 12:22:23 -07:00
Marcus Moore 5c0ca92fd7 Switch to using workflow_dispatch for PostgreSQL tests 2024-06-10 10:24:10 -07:00
snipe 241e9bc253 Merge pull request #14847 from uberbrady/users_index_api_optimization
Optimization for listings of large numbers of users
2024-06-10 13:57:49 +01:00
Brady Wetherington c8820adb56 Add two new 'with()' relationships to Users API index query 2024-06-10 13:29:53 +01:00
snipe 0f4c6dd5b0 Merge pull request #14830 from snipe/chore/sc-25756/better_validation_for_relations_on_delete
Better validation for relations on delete
2024-06-07 18:10:41 +01:00
snipe f8ab9f62f6 Merge pull request #14842 from Godmartinz/adjust-preview-window
Fixed label preview window position
2024-06-07 18:09:56 +01:00
Phil 217ed03b8e add DB_PORT 2024-06-07 12:04:10 +02:00
Godfrey M 77e6058e4c remembers chosen label 2024-06-06 13:55:15 -07:00
Godfrey M 4a60026162 moves preview down by field definitions 2024-06-06 13:42:06 -07:00
Godfrey M 3621292a0e removes unnecessary height 2024-06-06 13:28:05 -07:00
Marcus Moore 6c296ccf8e Use "postgres" instead of "postgres:14" 2024-06-06 13:27:39 -07:00
Godfrey M 6df1c36011 oops 2024-06-06 13:24:02 -07:00
Marcus Moore 924da00f3e Add Postgres GitHub workflow for tests 2024-06-06 13:21:00 -07:00
Godfrey M 44dae22a3c adjust label preview window 2024-06-06 13:18:19 -07:00
bryanlopezinc d35e251d6e Added test for app url config 2024-06-05 21:46:43 +01:00
snipe e19d2d6ec9 Merge pull request #14832 from snipe/fixes/added_consumables_to_inventory_email
Fixed #14812 - added consumables to individual inventory report
2024-06-05 20:42:35 +01:00
snipe 871255f28c Fixed #14812 - added consumables to individual inventory report
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 20:40:45 +01:00
Marcus Moore 9044aa4ed9 Import class 2024-06-05 11:48:47 -07:00
Marcus Moore 60c7efae3c Remove commented code 2024-06-05 11:48:10 -07:00
Marcus Moore 48fc6ca60e Remove commented code 2024-06-05 11:46:57 -07:00
snipe 7ac315e1eb Fixed tests
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 14:50:45 +01:00
snipe 374c6845d6 Added test if user has assets
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 14:16:28 +01:00
snipe c5cbe37007 Added view permissions for the redirects
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 14:13:51 +01:00
snipe a2346e4666 Changed numbers
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 14:09:57 +01:00
snipe 2479ccc4c6 Fixed accessory assignment
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 14:07:18 +01:00
snipe 64dd8f5d65 Missed a use statement
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 14:03:33 +01:00
snipe 47420a802a More (failing) tests
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 14:02:04 +01:00
snipe 5cdb2b7163 Check that the user was not aready deleted
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 14:00:35 +01:00
snipe d4c080c7e4 Use the form request on the UI controller
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 13:40:32 +01:00
snipe 065a47a446 Use the DeleteUser request
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 13:28:44 +01:00
snipe 5bd9ecb8df Created DeleteUser request
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 13:28:37 +01:00
snipe 1cdec61be6 Use more modern mutator/accessory syntax
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 10:56:54 +01:00
snipe b0ddb26e73 Fixed variable name, $field
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 10:28:35 +01:00
snipe 181bafd012 Fixed tests
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 10:28:35 +01:00
snipe e054fc1ef1 Removed noisy import debugging, made nicer output
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 10:28:35 +01:00
snipe 9d9ad86dd5 Added mutators and accessors for dates
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 10:28:35 +01:00
snipe afe4e5d62e Added date parser
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 10:28:35 +01:00
snipe 52950f1322 Refactored date parsing
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 10:28:35 +01:00
snipe 026c80992e Pull the log reference
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 10:28:35 +01:00
snipe 0ee2b74ff3 Added date parsers for new date fields
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 10:28:35 +01:00
snipe 3a0f7eca54 Put asset EOL date back in the Item Importer
I have no idea why this is necessary

Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 10:28:35 +01:00
snipe f4d530b4b1 Removed filename column since it’s never worked
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 10:28:35 +01:00
snipe 4ccbfb56a4 Make sure the status label is deployable
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 10:28:35 +01:00
snipe d02904c9a3 Added new fields
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 10:28:35 +01:00
snipe c8279c0b99 Moved asset-only date stuff into the asset importer
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 10:28:35 +01:00
snipe f4f184e115 Removed noisy debugging
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 10:28:35 +01:00
snipe b2a86e312b Added last_checkout and last_checkin as fillable
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 10:28:35 +01:00
snipe 9d56617caf Moved expected checkin date on view
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 10:28:35 +01:00
snipe de7b8940fe Merge pull request #14828 from fe80/fix/controller-signature-s3
fix(ActionlogController): add missin class Illuminate\Support\Facades…
2024-06-05 09:58:03 +01:00
snipe 09e94ec176 Reordered withTrashed() and find()
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 09:57:24 +01:00
snipe 832ceeba56 Fixed missing endpush
Signed-off-by: snipe <snipe@snipe.net>
2024-06-05 09:57:10 +01:00
fe80 ea7c3c8485 fix(ActionlogController): add missing class Illuminate\Support\Facades\Storage 2024-06-05 10:55:27 +02:00
snipe bc36c8074e Merge pull request #14807 from bryanlopezinc/AddTestToCheckEnvVisibility
Added test for .env visibility for setup page
2024-06-05 09:50:54 +01:00
snipe 9fccafa3ac Merge pull request #14816 from uberbrady/hotfix_autoincrement_workaround
Don't save next autoincrement base if it's going to fail, next
2024-06-05 09:47:40 +01:00
snipe fa083098fc Merge pull request #14819 from snipe/localization/new_strings_2024_06_03
Updated strings
2024-06-05 09:46:41 +01:00
snipe 7688c437c0 Merge pull request #14824 from Godmartinz/select-2-redirect-fix
Fixed select 2 Behavior
2024-06-05 09:46:25 +01:00
snipe 697ac83040 Merge pull request #14825 from marcusmoore/chore/test-organization
Re-organized test suite
2024-06-05 09:46:08 +01:00
snipe a742105c21 Merge pull request #14827 from fe80/fix/controller-signature-s3
fix(ActionlogController): correct signature image for s3 bucket
2024-06-05 09:40:21 +01:00
fe80 7a76ec9e02 fix(ActionlogController): correct signature image for s3 bucket 2024-06-05 10:08:15 +02:00
Marcus Moore b2a0e7958b Inject alpine on label engine page 2024-06-04 17:03:36 -07:00
Marcus Moore 99439f0a5c Define property 2024-06-04 16:14:07 -07:00
Marcus Moore ef91c8123e Remove unneeded re-render of select2 2024-06-04 15:49:57 -07:00
Marcus Moore 5eb5742b3d Define property 2024-06-04 15:49:39 -07:00
Marcus Moore 296cf3e34b Update OauthClients component 2024-06-04 15:37:41 -07:00
Marcus Moore e98c3f92c1 Update domain name 2024-06-04 10:49:29 -07:00
Marcus Moore d202dfc225 Organize API tests into domains 2024-06-04 10:48:53 -07:00
Godfrey M 6202f6157a fix select2 behavior 2024-06-04 08:41:00 -07:00
Marcus Moore b1e8e5389b Make most test names singular 2024-06-03 16:54:59 -07:00
Marcus Moore 95f6381da4 Update tests names to VerbNounTest 2024-06-03 16:53:15 -07:00
Marcus Moore b07e3b4a91 Remove API from test class name 2024-06-03 16:50:56 -07:00
Marcus Moore 86bd9a2674 Move test method to existing test 2024-06-03 16:49:44 -07:00
Marcus Moore 29a36839aa Move existing API checkin and checkout tests under domain directory 2024-06-03 16:29:53 -07:00
snipe 85cb7c92e7 Updated strings
Signed-off-by: snipe <snipe@snipe.net>
2024-06-03 20:44:40 +01:00
Brady Wetherington e827bc9a07 Tests on asset tags that are maximum integers and *almost* maximum... 2024-06-03 17:31:56 +01:00
snipe a6f19a1657 docs: add @U-H-T as a contributor 2024-06-03 17:06:43 +01:00
snipe 6229d0c616 Merge pull request #14758 from U-H-T/features/add_logo_support_for_Brother_TZe24
add logo support for Brother TZe24mm labels
2024-06-03 17:02:18 +01:00
snipe bc6c969f21 Merge pull request #14814 from snipe/dependabot/github_actions/develop/crowdin/github-action-2
Bump crowdin/github-action from 1 to 2
2024-06-03 16:58:10 +01:00
snipe 8f4ede7785 Merge pull request #14817 from snipe/fixes/hotfix_for_14815
Fixes #14815 - Fixed translation string
2024-06-03 16:48:54 +01:00
snipe 877adb082c Fixed translation string
Signed-off-by: snipe <snipe@snipe.net>
2024-06-03 16:40:52 +01:00
Brady Wetherington 90818bb147 Don't save next autoincrement base if it's going to fail, next 2024-06-03 15:58:57 +01:00
dependabot[bot] f767a94c84 Bump crowdin/github-action from 1 to 2
Bumps [crowdin/github-action](https://github.com/crowdin/github-action) from 1 to 2.
- [Release notes](https://github.com/crowdin/github-action/releases)
- [Commits](https://github.com/crowdin/github-action/compare/v1...v2)

---
updated-dependencies:
- dependency-name: crowdin/github-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-03 08:18:51 +00:00
bryanlopezinc 89e50b94d3 Fix Failing sqlite test 2024-06-03 08:09:05 +01:00
snipe c4d97d095f Merge pull request #14809 from snipe/features/more_tests
Added a few more tests
2024-06-01 04:25:19 +01:00
snipe 67fb3f10d5 Tightened up tests with better checks
Signed-off-by: snipe <snipe@snipe.net>
2024-06-01 04:24:47 +01:00
snipe ea8d390596 MOAR TESTS
Signed-off-by: snipe <snipe@snipe.net>
2024-06-01 04:01:09 +01:00
snipe cff382605c Fixed some missing strings and checks
Signed-off-by: snipe <snipe@snipe.net>
2024-06-01 04:01:04 +01:00
snipe 52af8afac2 Added company scoping test
Signed-off-by: snipe <snipe@snipe.net>
2024-06-01 03:10:29 +01:00
snipe 03b0268dc2 Fixed typo
Signed-off-by: snipe <snipe@snipe.net>
2024-06-01 03:00:45 +01:00
snipe c09e93e288 Updated delete users API tests, moved non-API tests
Signed-off-by: snipe <snipe@snipe.net>
2024-06-01 02:59:04 +01:00
snipe 694e3b7f3a Fixed typo
Signed-off-by: snipe <snipe@snipe.net>
2024-06-01 00:42:16 +01:00
snipe 32c367090b Updated test names
Signed-off-by: snipe <snipe@snipe.net>
2024-05-31 23:13:27 +01:00
snipe abcfe2b757 Derp. Spelling.
Signed-off-by: snipe <snipe@snipe.net>
2024-05-31 23:12:13 +01:00
snipe f7687008b7 Added more tests
Signed-off-by: snipe <snipe@snipe.net>
2024-05-31 23:10:59 +01:00
snipe b156264684 Tidied up scoping to be better for testing
Signed-off-by: snipe <snipe@snipe.net>
2024-05-31 23:10:53 +01:00
snipe 3f9a80942e Removed manual companyable from non-API views
Signed-off-by: snipe <snipe@snipe.net>
2024-05-31 23:10:23 +01:00
snipe dc62e393c3 Hotfix for user permissions
Signed-off-by: snipe <snipe@snipe.net>
2024-05-31 21:22:21 +01:00
snipe 46be0f6610 Merge pull request #14808 from snipe/fixes/small_redirect_tweaks
Small UI tweaks and redirects when asset model is invalid
2024-05-31 20:46:07 +01:00
snipe dd0a16c3d5 Added tests
Signed-off-by: snipe <snipe@snipe.net>
2024-05-31 20:42:32 +01:00
snipe a15ed6eaee Wrap disabled <a> links in a span for tooltips
Signed-off-by: snipe <snipe@snipe.net>
2024-05-31 19:29:29 +01:00
snipe 3005565bba Slight tweak to language
Signed-off-by: snipe <snipe@snipe.net>
2024-05-31 19:29:12 +01:00
snipe cf45e7536f Redirect with error if model is invalid
Signed-off-by: snipe <snipe@snipe.net>
2024-05-31 18:51:58 +01:00
snipe 1d97d95c10 UI and styling tweaks
Signed-off-by: snipe <snipe@snipe.net>
2024-05-31 18:48:34 +01:00
snipe 4a1b1675cb Use storage helper
Signed-off-by: snipe <snipe@snipe.net>
2024-05-31 18:48:09 +01:00
snipe 8c5249ba4b Disable buttons on view page if model is invalid
Signed-off-by: snipe <snipe@snipe.net>
2024-05-31 18:47:53 +01:00
snipe b936591240 Warn and disable on checkout if model is invalid
Signed-off-by: snipe <snipe@snipe.net>
2024-05-31 18:47:34 +01:00
snipe 76e664d647 Warn and disable the checkout button if model is invalid
Signed-off-by: snipe <snipe@snipe.net>
2024-05-31 18:47:18 +01:00
snipe 0253c2a756 Lauout tweaks, warn and disable button if model is invalid
Signed-off-by: snipe <snipe@snipe.net>
2024-05-31 18:46:57 +01:00
snipe d27613f55c Updated strings
Signed-off-by: snipe <snipe@snipe.net>
2024-05-31 18:46:41 +01:00
snipe ca8d478e87 Redirect if model is invalid
Signed-off-by: snipe <snipe@snipe.net>
2024-05-31 18:46:32 +01:00
bryanlopezinc c63c17d49f Added test for .env visibility for setup page 2024-05-31 17:33:57 +01:00
snipe 801e58d52e Removed manual scoping
Signed-off-by: snipe <snipe@snipe.net>
2024-05-31 06:58:15 +01:00
snipe 06e9625c64 Use hasUser() to avoid table collisions and infinite loop
Signed-off-by: snipe <snipe@snipe.net>
2024-05-31 06:58:07 +01:00
snipe 5800e8d8e9 Added companyable trait
Signed-off-by: snipe <snipe@snipe.net>
2024-05-31 06:57:34 +01:00
snipe 623aa58163 Removed unused statement
Signed-off-by: snipe <snipe@snipe.net>
2024-05-31 06:57:25 +01:00
snipe 45cfec5b29 Merge pull request #14797 from bryanlopezinc/AddTestsForSettings
Added test for setup page
2024-05-31 02:31:35 +01:00
Marcus Moore 5a9a231359 Remove alpinejs 2024-05-30 16:57:20 -07:00
Marcus Moore 1736bf5510 Merge branch 'develop' into chore/sc-23725/livewire3
# Conflicts:
#	app/Livewire/LoginForm.php
#	package.json
#	resources/views/livewire/login-form.blade.php
2024-05-30 16:56:50 -07:00
snipe ee8931f886 Merge pull request #14799 from marcusmoore/chore/remove-unused-component
Removed unused Livewire component
2024-05-31 00:54:43 +01:00
Marcus Moore 1a1b891309 Remove unused Login Livewire component 2024-05-30 16:49:05 -07:00
Marcus Moore 2eaac3d381 Fix select2 re-renders 2024-05-30 16:20:04 -07:00
Marcus Moore f03249898a Update id syntax in custom fields component 2024-05-30 16:12:52 -07:00
snipe 0981cfa902 Built assets
Signed-off-by: snipe <snipe@snipe.net>
2024-05-30 20:22:50 +01:00
snipe 37fbcfa22b Merge pull request #14798 from Godmartinz/redirect_back_to_asset_fix
Fixed checkin option from appearing
2024-05-30 19:41:02 +01:00
Godfrey M 0ee441a976 adds hidden as well 2024-05-30 11:19:06 -07:00
Godfrey M cf8de3baa9 fix checkin option from appearing 2024-05-30 11:11:35 -07:00
bryanlopezinc 404ee238a3 Added test for setup page 2024-05-30 14:37:24 +01:00
snipe 5a5d171ba2 Put session facade back - derp
Signed-off-by: snipe <snipe@snipe.net>
2024-05-30 14:15:08 +01:00
snipe aadee068b3 Merge pull request #14740 from Godmartinz/redirect_back_to_asset
Added Redirect options to asset check in/out
2024-05-30 14:14:04 +01:00
snipe a46e2ebfd8 Small tweaks to user export, user view translations
Signed-off-by: snipe <snipe@snipe.net>
2024-05-30 13:59:00 +01:00
snipe f710b1aac3 Merge pull request #14614 from akemidx/feature/sc-19796
ADDED: Export User Permissions (Superuser & Admin)
2024-05-30 13:41:26 +01:00
snipe f6fe6e70b9 Merge branch 'develop' into redirect_back_to_asset 2024-05-30 13:38:11 +01:00
snipe bed8861179 Merge pull request #14796 from snipe/chore/sc-25715/axios
Upgraded axios
2024-05-30 13:17:23 +01:00
snipe 180d7b1b5b Upgraded axios
Signed-off-by: snipe <snipe@snipe.net>
2024-05-30 13:13:25 +01:00
snipe 386416ee5d Merge pull request #14795 from snipe/bug/sc-25687/papaparse
Upgraded papaparse
2024-05-30 13:04:00 +01:00
snipe 6b5aa91f3d Upgraded papaparse
Signed-off-by: snipe <snipe@snipe.net>
2024-05-30 13:00:57 +01:00
Marcus Moore e80b80f5d1 Remove manual livewire tags 2024-05-29 16:04:05 -07:00
Marcus Moore 9e35441281 Importer fixes 2024-05-29 15:50:42 -07:00
Godfrey M e28ad50bec fixes the color change 2024-05-29 15:34:08 -07:00
Scarzy f48c5ee252 Fix an error message 2024-05-29 22:32:45 +01:00
Scarzy 98a94dec29 Change some errors to be 404
The asset or file was not found, so 500 wasn't the best choice of error
code
2024-05-29 22:17:36 +01:00
Marcus Moore 7d95e7765d Add a few .prevents 2024-05-29 14:13:29 -07:00
Marcus Moore ee75b30683 Enable legacy_model_binding 2024-05-29 14:06:27 -07:00
Scarzy ca9d4e3155 Get the tests for download and delete working 2024-05-29 22:01:49 +01:00
Scarzy 633bcbb6c4 Get the file upload test working
Added the upload functionality to the get and delete tests, but I
currently don't seem to be able to reference the correct file ID
2024-05-29 22:01:49 +01:00
Scarzy 2d4af61e6c Begin to add some tests
There is currently only really a test for listing, and only for the
empty list response
2024-05-29 22:01:49 +01:00
Scarzy 45329912e6 Give a better response to listing no files on an asset
HTTP500 was never a good choice. Now it sends back an empty array
2024-05-29 22:01:49 +01:00
Scarzy b9d56a8ecc Fix some routes
Names of some of the routes overlapped with others in an incompatible
way. This makes the names more distinct
2024-05-29 22:01:48 +01:00
Scarzy 91c1e53e52 Fix the test file location 2024-05-29 22:01:48 +01:00
Scarzy 73a87a8ea8 Add the framework of a test 2024-05-29 22:01:48 +01:00
Scarzy bb0a614c39 Update some comments 2024-05-29 22:01:48 +01:00
Scarzy f11ea79406 Add some sanity checks that the asset actually exists 2024-05-29 22:01:48 +01:00
Scarzy e817b20840 Fix some responses to be more appropriate
Error/success was mixed up
2024-05-29 22:01:48 +01:00
Scarzy 516f766a44 Remove some debug code 2024-05-29 22:01:48 +01:00
Scarzy f5791c79a5 Change the returns to be API appropriate 2024-05-29 22:01:48 +01:00
Scarzy f6a1a76095 Add an endpoint for deleting a file 2024-05-29 22:01:48 +01:00
Scarzy bbb9145744 Add an API endpoint to download files 2024-05-29 22:01:48 +01:00
Scarzy 194853d860 Remove a redundant line 2024-05-29 22:01:48 +01:00
Scarzy 92670d5711 Add the ability to list files for an asset 2024-05-29 22:01:48 +01:00
Scarzy 8a2ea971e1 Add an API assets files controller
Based heavily on the Assets assets files controller.
Added errors related to to the files management.
Added the API endpoints for file upload and show, but only upload is
currently tested/works.
2024-05-29 22:01:48 +01:00
Marcus Moore 8d924b60d7 Replace references to @this in importer 2024-05-29 13:51:57 -07:00
Marcus Moore 34595c266d Update script tag 2024-05-29 13:16:30 -07:00
Marcus Moore 638ae9bdd5 Use new id method 2024-05-29 13:15:59 -07:00
Godfrey M 713ce7836f add some css in label field selector 2024-05-29 13:07:33 -07:00
Marcus Moore 093c6652a8 Update select2 snippet for Livewire 3 2024-05-29 12:58:24 -07:00
Marcus Moore 17f0ac1eae Set view correctly 2024-05-29 12:57:43 -07:00
Marcus Moore 43616d1874 Remove alpine reference from webpack 2024-05-29 12:30:20 -07:00
Marcus Moore 9dc4f2ca80 Migrate config 2024-05-29 12:24:17 -07:00
Marcus Moore 73e3ac7dd8 Migrate to $dispatch 2024-05-29 12:18:31 -07:00
Marcus Moore 8ff639913d Migrate away from dispatchBrowserEvent() 2024-05-29 12:17:36 -07:00
Marcus Moore 45419586fe Migrate away from wire:model.prevent 2024-05-29 12:11:33 -07:00
Marcus Moore d8a480b2a8 Migrate to wire:model.blur 2024-05-29 12:11:02 -07:00
Marcus Moore 29d87246a2 Migrate away from wire:model.defer 2024-05-29 12:10:46 -07:00
Marcus Moore 58e638d3cb Migrate to wire:model.live 2024-05-29 12:08:25 -07:00
Marcus Moore b52380f376 Migrate to new namespace 2024-05-29 12:07:48 -07:00
Marcus Moore 4ae74fb7f6 Remove alpinejs from package.json 2024-05-29 12:06:54 -07:00
Marcus Moore 7d1acd3d79 Update Livewire via composer 2024-05-29 12:04:06 -07:00
snipe 12e107a71b Merge pull request #13062 from ak-piracha/feature/snipe-12892-bulk-consumable-checkout
Bulk Consumable Checkout
2024-05-29 19:42:25 +01:00
snipe fba72e1e8d Merge pull request #14789 from snipe/fixes/14781_broken_wrench_icon
Fixed #14781 - Fixed broken wrench icon on some browsers in manufacturer section
2024-05-29 19:23:21 +01:00
snipe 7bbee053c6 Updated fa icon call
Signed-off-by: snipe <snipe@snipe.net>
2024-05-29 19:19:45 +01:00
snipe 6ea1a3bacf Merge pull request #14788 from snipe/security/Snyk-Upgrade-jquery-ui-from-1.13.2-to-1.13.3-#14735
Updated jquery-UI
2024-05-29 18:47:39 +01:00
snipe 603afe4466 Updated jquery-UI
Signed-off-by: snipe <snipe@snipe.net>
2024-05-29 18:44:39 +01:00
snipe 037ee8c07a Merge pull request #14787 from snipe/fixes/return_redirect_fixes_for_docblock
Fixes path for redirect response
2024-05-29 18:28:00 +01:00
snipe df1cef59d5 Fixes path for redirect response
Signed-off-by: snipe <snipe@snipe.net>
2024-05-29 18:01:40 +01:00
snipe 3fcd196c04 Merge pull request #14786 from snipe/security/upgrade_bs_tables
#14743 - Upgrade bootstrap-table from 1.22.3 to 1.22.5
2024-05-29 13:12:07 +01:00
snipe 8ee5e7cd0a #14743 - Upgrade bootstrap-table from 1.22.3 to 1.22.5
Signed-off-by: snipe <snipe@snipe.net>
2024-05-29 13:10:46 +01:00
snipe 1ec85063ee Merge pull request #14785 from snipe/fixes/updates_facade_paths
Fixed/updated facade paths
2024-05-29 13:03:13 +01:00
snipe 92ba889cae Updated/removed facades
Signed-off-by: snipe <snipe@snipe.net>
2024-05-29 12:53:51 +01:00
snipe f17162c2e2 Use artisan facade
Signed-off-by: snipe <snipe@snipe.net>
2024-05-29 12:40:05 +01:00
snipe fb233c0aa4 Cleaned up facade names and references
Signed-off-by: snipe <snipe@snipe.net>
2024-05-29 12:38:15 +01:00
snipe 369c819a27 Merge pull request #14754 from Godmartinz/footer_user_bug
Removed extra div from User Details.
2024-05-29 11:29:02 +01:00
snipe f1eb4bd3a5 Merge pull request #14349 from snipe/jerm/update-mailer-configs
Update mailer configurations for Symfony mailer
2024-05-29 11:25:55 +01:00
snipe 2f828683da Merge pull request #14783 from snipe/fixes/fixed_category_test_depreciation_warning
Fixed deprecation warning on category test
2024-05-29 11:19:31 +01:00
snipe 13db151297 Fixed deprecation warning on category test
Signed-off-by: snipe <snipe@snipe.net>
2024-05-29 11:06:51 +01:00
snipe bb95c231e5 Merge branch 'develop' of https://github.com/snipe/snipe-it into develop 2024-05-29 10:55:12 +01:00
snipe dcea14fb99 Merge pull request #14778 from uberbrady/fix_8_3_compat
Allows Snipe-ITv7 to install on PHPv8.1-8.3
2024-05-29 10:55:02 +01:00
snipe 282fed27da Add @bryanlopezinc as a contributor 2024-05-29 10:46:59 +01:00
snipe cf3ffe9c74 Merge pull request #14782 from bryanlopezinc/ReduceIDeErrors
Reduce IDE errors in App\Http\Controllers\SettingsController
2024-05-29 10:46:03 +01:00
bryanlopezinc 5d01a06245 Reduce IDE errors in App\Http\Controllers\SettingsController 2024-05-29 08:07:49 +01:00
snipe 02cdda56e2 Merge branch 'develop' of https://github.com/snipe/snipe-it into develop 2024-05-29 02:00:25 +01:00
snipe ffecd97665 Bumped laravel in readme
Signed-off-by: snipe <snipe@snipe.net>
2024-05-29 02:00:21 +01:00
snipe 779cf9418e Merge pull request #14780 from marcusmoore/fixes/sqlite-tests-in-gh
Fixed sqlite tests in GitHub Actions
2024-05-29 01:59:12 +01:00
Marcus Moore 34b4452645 Skip "migrating" and run passport:keys for sqlite testing in GH 2024-05-28 17:41:01 -07:00
snipe da1c4c23e6 Merge branch 'develop' of https://github.com/snipe/snipe-it into develop 2024-05-29 00:26:37 +01:00
snipe a5d0a21757 Fixed string path
Signed-off-by: snipe <snipe@snipe.net>
2024-05-29 00:26:33 +01:00
snipe 29454f7288 Merge pull request #14779 from marcusmoore/fixes/fix-group-create-endpoint
Fixed Array to string conversion exception in group create api endpoint
2024-05-28 23:26:34 +01:00
Brady Wetherington e271711c5b Added the clock-lts repo which allows use on php8.1-8.3 2024-05-28 22:50:09 +01:00
Marcus Moore 4c78da3bbf Re-add json encoding of permissions 2024-05-28 13:03:09 -07:00
Marcus Moore 71bab2c315 Improve test case 2024-05-28 13:02:44 -07:00
snipe fceba13b03 Merge pull request #14777 from snipe/fixes/reportscontroller_optimizations
Reports controller query optimizations
2024-05-28 18:08:27 +01:00
snipe 8ac3937bf4 Commented model loading on asset model
Signed-off-by: snipe <snipe@snipe.net>
2024-05-28 18:03:19 +01:00
snipe 1c1729854e Use statics for location, supplier, etc
Signed-off-by: snipe <snipe@snipe.net>
2024-05-28 18:02:22 +01:00
snipe 14c78d9065 Use static for custom fields
Signed-off-by: snipe <snipe@snipe.net>
2024-05-28 18:02:09 +01:00
snipe b1cb9259da Re-use total to avoid duplicate count
Signed-off-by: snipe <snipe@snipe.net>
2024-05-28 18:01:47 +01:00
snipe 7d2af61989 Merge pull request #14775 from snipe/bug/sc-25676/groups_api
Fixed #14771: improvements to groups API
2024-05-28 15:33:36 +01:00
snipe 03b5c2e246 Fixed bad translation string
Signed-off-by: snipe <snipe@snipe.net>
2024-05-28 15:21:28 +01:00
snipe 33d5d5e24f Added tests
Signed-off-by: snipe <snipe@snipe.net>
2024-05-28 15:21:13 +01:00
snipe 3df2a4a70b Removed debugging
Signed-off-by: snipe <snipe@snipe.net>
2024-05-28 15:16:44 +01:00
snipe 6b41970e97 Check that selected is an array
Signed-off-by: snipe <snipe@snipe.net>
2024-05-28 15:15:31 +01:00
snipe 92eb6eb1b6 Add unique constraint to name
Signed-off-by: snipe <snipe@snipe.net>
2024-05-28 15:09:31 +01:00
snipe 206238e83f Merge pull request #14773 from snipe/bug/sc-25674/location_currency_on_edit
Pass accessory's currency if set by location
2024-05-28 10:29:20 +01:00
snipe df882bbcbc Pass item’s currency if set by location
Signed-off-by: snipe <snipe@snipe.net>
2024-05-28 10:24:10 +01:00
snipe 6c1c3a99dd Bumped current_snipeit_version
Signed-off-by: snipe <snipe@snipe.net>
2024-05-27 19:22:24 +01:00
snipe 54067ec449 Fixed pre-version in version.php
Signed-off-by: snipe <snipe@snipe.net>
2024-05-27 18:21:46 +01:00
snipe 4c11e97922 Bumped version to dev, bumped hash
Signed-off-by: snipe <snipe@snipe.net>
2024-05-27 18:20:32 +01:00
Brady Wetherington 8df9007a8e Merge branch 'snipeit_v7_laravel10' into develop 2024-05-27 18:08:27 +01:00
snipe 702b944698 Merge remote-tracking branch 'origin/develop' 2024-05-27 15:46:07 +01:00
snipe 172d24fd3c Merge pull request #14770 from uberbrady/add_locations_parent_index
Add index to 'parent_id' for users with large number of locations
2024-05-27 15:43:49 +01:00
Brady Wetherington 28b450fd3c Add index to 'parent_id' for users with large number of locations 2024-05-27 15:38:42 +01:00
snipe 485caf1d92 Merge pull request #14755 from marcusmoore/chore/sc-25103/add-tests-around-asset-checkout
Added tests around asset checkout
2024-05-25 11:33:33 +01:00
snipe 29cd75a6d2 Merge pull request #14766 from snipe/chore/sc-25656/minus_icon_for_fieldsets
Changed icon, added translation
2024-05-25 11:19:56 +01:00
snipe b3fe10baa8 Merge branch 'snipeit_v7_laravel10' into chore/sc-25656/minus_icon_for_fieldsets 2024-05-25 11:19:43 +01:00
snipe 093cc9faf0 Merge pull request #14767 from snipe/chore/sc-25657/improved-translations
Improved translations
2024-05-25 11:19:14 +01:00
snipe be4e809254 Merge pull request #14762 from marcusmoore/chore/update-v7-test
Fixed test by removing non-existent trait
2024-05-25 11:18:54 +01:00
snipe dc5e15f919 Added translation for external link
Signed-off-by: snipe <snipe@snipe.net>
2024-05-25 11:02:07 +01:00
snipe ad7b291062 Added translations
Signed-off-by: snipe <snipe@snipe.net>
2024-05-25 10:55:48 +01:00
snipe b54c1caa74 Improved translation
Signed-off-by: snipe <snipe@snipe.net>
2024-05-25 10:43:28 +01:00
snipe c3cf123189 Better translation for custom fields
Signed-off-by: snipe <snipe@snipe.net>
2024-05-25 10:39:47 +01:00
snipe 3a2900621c Changed icon, added translation
Signed-off-by: snipe <snipe@snipe.net>
2024-05-25 10:20:52 +01:00
Godfrey M 442903ea5e trying to get link to work, fixed up markup and url 2024-05-23 16:08:18 -07:00
Marcus Moore 639cbf6d53 Remove passport:install command 2024-05-23 15:56:58 -07:00
Marcus Moore e03b5754a8 Combine steps 2024-05-23 15:54:32 -07:00
Marcus Moore 4ce86a061f Set DB_CONNECTION 2024-05-23 15:43:59 -07:00
Marcus Moore fa6e170feb Install passport 2024-05-23 14:01:06 -07:00
Marcus Moore 51f72daba1 Debugging step 2024-05-23 13:55:03 -07:00
spencerrlongg 8ce577db37 adds @snipe's rules for undeleted assigned targets 2024-05-23 15:51:26 -05:00
Godfrey M d3ab152d30 adds reminder notification constructor and updates markdown 2024-05-23 12:47:02 -07:00
Marcus Moore a130033480 Revert "Add Install Passport step"
This reverts commit ef95ede833.
2024-05-23 12:45:38 -07:00
Marcus Moore ef95ede833 Add Install Passport step 2024-05-23 12:32:34 -07:00
Spencer Long cdb1140f10 Merge branch 'develop' into bug/sc-24884 2024-05-23 13:53:00 -05:00
Marcus Moore d06e5f25b0 Remove old trait from test 2024-05-23 11:51:08 -07:00
U-H-T 2777ac96cc add logo support for Brother TZe24mm labels 2024-05-23 11:10:23 +02:00
snipe fd42f1ef24 Merge remote-tracking branch 'origin/develop' 2024-05-23 08:39:31 +01:00
snipe 8b3ff5a82d Handle potentially deleted admin users in license export
Signed-off-by: snipe <snipe@snipe.net>
2024-05-23 08:39:15 +01:00
Marcus Moore 482ebfbb68 Implement test 2024-05-22 17:21:29 -07:00
Marcus Moore 67c4fa2966 Improve event assertions 2024-05-22 17:14:10 -07:00
Marcus Moore a3389a31cd Update test name and add todo 2024-05-22 17:10:16 -07:00
Marcus Moore 8d74a976a1 Merge branch 'develop' into chore/sc-25103/add-tests-around-asset-checkout 2024-05-22 16:09:27 -07:00
Marcus Moore 6d104251b3 Remove todo 2024-05-22 15:40:54 -07:00
Marcus Moore f16c79bb9a Improve event assertions 2024-05-22 15:38:23 -07:00
Marcus Moore 1fe22e4b7b Re-order scenarios 2024-05-22 13:33:41 -07:00
Marcus Moore c7fa2c04ad Add scenario 2024-05-22 13:33:12 -07:00
Marcus Moore 8ca882d1c8 Complete a scenario 2024-05-22 13:23:49 -07:00
Marcus Moore 5d368990dc Fix assertion 2024-05-22 13:15:51 -07:00
Brady Wetherington 4adbd7af4c Merge branch 'develop' into snipeit_v7_laravel10 2024-05-22 21:02:11 +01:00
Marcus Moore 1935a4aca3 Improve scenario naming 2024-05-22 12:47:33 -07:00
Godfrey M c4d96f6ea3 removed extra div 2024-05-22 12:35:32 -07:00
snipe 986d5641f6 Merge remote-tracking branch 'origin/develop' 2024-05-22 18:39:25 +01:00
snipe e163d5cfc7 Merge pull request #14753 from snipe/chore/sc-24895/add_exif_to_upgrade_php_file
Added exif to required extensions
2024-05-22 18:31:47 +01:00
snipe b1e7c772ae Added exif to required extensions
Signed-off-by: snipe <snipe@snipe.net>
2024-05-22 18:27:52 +01:00
snipe dce1854ac4 Merge remote-tracking branch 'origin/develop' 2024-05-22 18:04:53 +01:00
snipe c4b4923ff8 Add @LeePorte as a contributor 2024-05-22 18:04:24 +01:00
snipe c20d10d4f2 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2024-05-22 17:50:14 +01:00
snipe b0479d543d Merge branch 'develop' of https://github.com/snipe/snipe-it into develop 2024-05-22 17:49:33 +01:00
snipe 81704c1d40 Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2024-05-22 17:49:29 +01:00
snipe d3798bf251 Merge pull request #14752 from snipe/fixes/better_handle_data_file_mismatch_in_user_files
Nicer handling of erroring when filename+log do not match
2024-05-22 17:47:39 +01:00
snipe 4bb7c1701f Fiddled with storage facade a little more
Signed-off-by: snipe <snipe@snipe.net>
2024-05-22 17:44:49 +01:00
snipe 5fd0f56258 Use proper storage facade for checking if the file exists
Signed-off-by: snipe <snipe@snipe.net>
2024-05-22 17:38:49 +01:00
snipe 37d7e89e93 Fixed error message
Signed-off-by: snipe <snipe@snipe.net>
2024-05-22 17:29:43 +01:00
snipe 3ab197075a Nicer handling of erroring when filename+log do not match
Signed-off-by: snipe <snipe@snipe.net>
2024-05-22 17:20:03 +01:00
Brady Wetherington 12e8ac8b41 Merge pull request #14751 from uberbrady/docker-permissions-fix-rebased
Fixed #12299: permissions on storage dir in Docker (rebased)
2024-05-22 16:57:35 +01:00
Lee Porte 6783dc1312 Fixed #12299: permissions on storage dir in Docker
Fixes #12299, where currently there is no recursive permissions set on
/var/www/html/storage/ during build time. As a result this requires
users to run an exec into the container and change the permissions
before they are able to initiate the setup. Without this a 500 error is
thrown and little is evident in the docker logs as to what the issue
is.
2024-05-22 16:54:07 +01:00
snipe b489c71fa2 Removed generated file
Signed-off-by: snipe <snipe@snipe.net>
2024-05-22 13:09:02 +01:00
snipe cf5f6f9b13 Created by OWASP Threat Dragon 2024-05-22 13:06:32 +01:00
snipe 860432acc5 Merge remote-tracking branch 'origin/develop' 2024-05-22 12:45:26 +01:00
snipe c9f7847fb3 Merge pull request #14745 from snipe/fixes/self_api_endpoint
Refactor group syncing on user edit API endpoint
2024-05-22 12:43:22 +01:00
snipe 6fad085a7d Removed debug in test
Signed-off-by: snipe <snipe@snipe.net>
2024-05-22 12:37:49 +01:00
snipe 4b23ef4021 Added new test
Signed-off-by: snipe <snipe@snipe.net>
2024-05-22 12:35:03 +01:00
snipe bb96a190fd Moved validator
Signed-off-by: snipe <snipe@snipe.net>
2024-05-22 12:34:48 +01:00
snipe e1eb457f3d Update tests/Feature/Api/Users/UpdateUserApiTest.php
Co-authored-by: Marcus Moore <contact@marcusmoore.io>
2024-05-22 11:03:46 +01:00
snipe 51025aad57 Update tests/Feature/Api/Users/UpdateUserApiTest.php
Co-authored-by: Marcus Moore <contact@marcusmoore.io>
2024-05-22 11:03:38 +01:00
snipe 14c4765be2 Update tests/Feature/Api/Users/UpdateUserApiTest.php
Co-authored-by: Marcus Moore <contact@marcusmoore.io>
2024-05-22 11:00:52 +01:00
snipe 3afe996755 Update tests/Feature/Api/Users/UpdateUserApiTest.php
Co-authored-by: Marcus Moore <contact@marcusmoore.io>
2024-05-22 11:00:47 +01:00
snipe 0891bd747a Update tests/Feature/Api/Users/UpdateUserApiTest.php
Co-authored-by: Marcus Moore <contact@marcusmoore.io>
2024-05-22 11:00:31 +01:00
Godfrey M f2693ee957 conditionally fixed redirect select option 2024-05-21 14:08:35 -07:00
Godfrey M 0327e71f0f made message the keys, cleaned up array 2024-05-21 13:26:29 -07:00
Godfrey M 69c2cf2c4f fixed assetcheckin test, created redirect option test 2024-05-21 13:13:25 -07:00
Godfrey M 9f02be0823 removed extra div 2024-05-21 10:15:18 -07:00
Godfrey M b5553af8ed rename variable 2024-05-21 10:11:53 -07:00
Godfrey M 4d6f4303f5 fixed partial up 2024-05-21 10:11:01 -07:00
Godfrey M 8a0afae90f fixed query, fixed no email logic, needs new markdown 2024-05-21 09:42:00 -07:00
snipe 34f1ea1c0e Re-order gating and refactor group syncing
Signed-off-by: snipe <snipe@snipe.net>
2024-05-21 10:00:49 +01:00
snipe e3561ad38e Added tests
Signed-off-by: snipe <snipe@snipe.net>
2024-05-21 09:56:57 +01:00
snipe a7ccf0efff Added translation
Signed-off-by: snipe <snipe@snipe.net>
2024-05-21 09:56:51 +01:00
snipe f422c2ecad Merge pull request #14741 from Godmartinz/footer-issue
removed extra div tags
2024-05-20 20:44:27 +01:00
Godfrey M db9c435ae0 removed extra div tags 2024-05-20 10:48:57 -07:00
Godfrey M a53f89cd2c remove license checkout changes p2 2024-05-20 10:26:45 -07:00
Godfrey M 280c03dcad remove license checkout changes 2024-05-20 10:25:59 -07:00
Godfrey M e70fb42f87 remove license redirects 2024-05-20 10:22:01 -07:00
Brady Wetherington f633dbba64 Merge branch 'develop' into snipeit_v7_laravel10 2024-05-20 12:55:29 +01:00
snipe cc0f2d7074 Merge remote-tracking branch 'origin/develop' 2024-05-20 11:22:34 +01:00
snipe a820f248c8 Merge pull request #14736 from snipe/fixes/small_translation_additions
Fixes/small translation additions
2024-05-20 11:21:47 +01:00
snipe 6a6272ace3 Translate no records found message
Signed-off-by: snipe <snipe@snipe.net>
2024-05-20 11:19:47 +01:00
snipe bcb747f886 Added string
Signed-off-by: snipe <snipe@snipe.net>
2024-05-20 11:19:37 +01:00
snipe 771c85e347 Translated account save message
Signed-off-by: snipe <snipe@snipe.net>
2024-05-20 11:19:31 +01:00
snipe e5c358a1fe Merge pull request #14731 from snipe/features/csp_env
Fixed #14664 - allow additional urls in env for CSP
2024-05-16 22:25:11 +01:00
snipe 52c906f6b8 Added to env.example
Signed-off-by: snipe <snipe@snipe.net>
2024-05-16 22:21:52 +01:00
snipe ca1555d962 Fixed #14664 - allow additional urls in env for CSP
Signed-off-by: snipe <snipe@snipe.net>
2024-05-16 22:19:18 +01:00
snipe 0d4f13219b Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2024-05-16 22:00:07 +01:00
snipe 7fdbbc846e Bumped hash
Signed-off-by: snipe <snipe@snipe.net>
2024-05-16 21:59:38 +01:00
snipe dbbbb103a0 Merge pull request #14730 from snipe/localizations/updated_strings
Updated translations
2024-05-16 21:58:24 +01:00
snipe 2182ea1ce8 Updated translations
Signed-off-by: snipe <snipe@snipe.net>
2024-05-16 21:57:19 +01:00
snipe f2cc9ec1dd Merge remote-tracking branch 'origin/develop' 2024-05-16 19:57:46 +01:00
snipe 54b24434e1 Set file name variable
Signed-off-by: snipe <snipe@snipe.net>
2024-05-16 19:56:58 +01:00
snipe 653ad562a4 Updated codacy link
Signed-off-by: snipe <snipe@snipe.net>
2024-05-16 18:56:44 +01:00
snipe 7743b03129 Merge remote-tracking branch 'origin/develop' 2024-05-16 18:51:27 +01:00
snipe 84a601f364 Merge pull request #14729 from snipe/fixes/attribute_for_purchase_date
Sets purchase date as date (versus datetime) in labels
2024-05-16 18:49:49 +01:00
snipe 88d131666c Sets purchase date as date (versus datetime) in labels
Signed-off-by: snipe <snipe@snipe.net>
2024-05-16 18:40:49 +01:00
snipe d691f3b315 Merge remote-tracking branch 'origin/develop' 2024-05-16 16:37:47 +01:00
snipe 00a9d5f33e Merge pull request #14719 from snipe/fixes/add_next_audit_date_to_assets_form
Added next audit date to assets form
2024-05-16 16:33:49 +01:00
snipe eb0fd2f519 Removed stricter validation :(
Signed-off-by: snipe <snipe@snipe.net>
2024-05-16 16:29:11 +01:00
snipe 81efaa7481 Merge branch 'develop' into fixes/add_next_audit_date_to_assets_form 2024-05-16 16:13:21 +01:00
snipe 2539c9e697 Updated assets
Signed-off-by: snipe <snipe@snipe.net>
2024-05-16 16:01:41 +01:00
snipe 3dfd471fa4 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/js/dist/all-defer.js
#	public/mix-manifest.json
2024-05-16 15:33:50 +01:00
snipe 4119526889 Merge pull request #14728 from snipe/fixes/smarter_decryption_in_activity
Only attempt to decrypt custom fields in activity log if the value is not empty
2024-05-16 15:31:18 +01:00
snipe 6b3346d90c Only attempt to decrypt if there is a value
Signed-off-by: snipe <snipe@snipe.net>
2024-05-16 15:28:25 +01:00
snipe 312ce51de6 Removed more debugging
Signed-off-by: snipe <snipe@snipe.net>
2024-05-16 15:25:57 +01:00
snipe 09914f508f Removed more debugging
Signed-off-by: snipe <snipe@snipe.net>
2024-05-16 15:16:52 +01:00
snipe 45eda0f611 Removed debug lines
Signed-off-by: snipe <snipe@snipe.net>
2024-05-16 15:09:27 +01:00
snipe de088d452f Merge pull request #14451 from Godmartinz/add_decline_note_to_acceptance
Adds a note text area to asset acceptances/declines
2024-05-16 15:06:05 +01:00
snipe 2f18430ce4 Merge pull request #14725 from snipe/features/added_security_dot_txt
Added security.txt file
2024-05-16 09:59:46 +01:00
snipe 8d67e02d63 Added security.txt file
Signed-off-by: snipe <snipe@snipe.net>
2024-05-16 09:56:11 +01:00
Phil 1b85eea28e added new compose and env files 2024-05-16 02:13:31 +02:00
Godfrey M fb9a5f928f removed license changes 2024-05-15 16:39:26 -07:00
Phil 4459483862 moved env. to own dev-file 2024-05-16 01:06:47 +02:00
Phil a0cf7ecc98 moved file to dev-specific naming-scheme 2024-05-16 00:05:59 +02:00
Godfrey M c658a0fcb4 fixes description 2024-05-15 13:20:05 -07:00
Godfrey M f40284c413 adds acceptance reminder command 2024-05-15 13:04:58 -07:00
snipe 8e35a56386 Updated dev assets
Signed-off-by: snipe <snipe@snipe.net>
2024-05-15 20:01:04 +01:00
snipe 30f738646e Merge pull request #14700 from marcusmoore/chore/sc-25471
Updated alpine to the latest version (3.13.10)
2024-05-15 19:59:51 +01:00
snipe 55281313d8 Merge pull request #14474 from Godmartinz/asset-location-update-bug
Fixed user assets not updating when a user changes location
2024-05-15 19:20:14 +01:00
Godfrey M 786799225c remove dd 2024-05-15 10:37:07 -07:00
snipe c137fafa97 Updated language
Signed-off-by: snipe <snipe@snipe.net>
2024-05-15 18:10:43 +01:00
snipe cb22a3d556 Updated comments again :-/
Signed-off-by: snipe <snipe@snipe.net>
2024-05-15 17:52:50 +01:00
snipe c7accb4599 Added comments
Signed-off-by: snipe <snipe@snipe.net>
2024-05-15 17:38:42 +01:00
snipe 72c85f93b6 Fixed test
Signed-off-by: snipe <snipe@snipe.net>
2024-05-15 16:47:45 +01:00
snipe c1d5b8713b Removed debugging
Signed-off-by: snipe <snipe@snipe.net>
2024-05-15 16:33:48 +01:00
snipe 8310b91e00 Use UploadFileRequest for audit files
Signed-off-by: snipe <snipe@snipe.net>
2024-05-15 16:33:48 +01:00
snipe 71b5bf2eef Added visual on the hardware view screen
Signed-off-by: snipe <snipe@snipe.net>
2024-05-15 16:33:48 +01:00
snipe ab8b40745e Added next audit date to create/edit asset screen
Signed-off-by: snipe <snipe@snipe.net>
2024-05-15 16:33:48 +01:00
snipe 16ec47573b Added help text to bulk edit blade
Signed-off-by: snipe <snipe@snipe.net>
2024-05-15 16:33:48 +01:00
snipe 556d0b44a3 Added asset
Signed-off-by: snipe <snipe@snipe.net>
2024-05-15 16:33:48 +01:00
snipe 0734d5b0b6 Added help text
Signed-off-by: snipe <snipe@snipe.net>
2024-05-15 16:33:48 +01:00
snipe f158a369a4 Added/updated string
Signed-off-by: snipe <snipe@snipe.net>
2024-05-15 16:33:47 +01:00
snipe bdbfb0f2a1 Added accessor and mutator for next_audit_date
Signed-off-by: snipe <snipe@snipe.net>
2024-05-15 16:33:47 +01:00
snipe e5653eaa93 Save new data
Signed-off-by: snipe <snipe@snipe.net>
2024-05-15 16:33:47 +01:00
snipe 3c4098038d Fail early if no tag
Signed-off-by: snipe <snipe@snipe.net>
2024-05-15 16:33:47 +01:00
snipe 8841e21dc9 Removed quickscan header
Signed-off-by: snipe <snipe@snipe.net>
2024-05-15 16:33:47 +01:00
snipe f5e03b264f Show additional help text if help text is given
Signed-off-by: snipe <snipe@snipe.net>
2024-05-15 16:33:47 +01:00
snipe eb09a99eb0 Merge pull request #14707 from spencerrlongg/bug/sc-24912
Bulk Edit Tests and Tweaks
2024-05-15 11:22:31 +01:00
Godfrey M dc418a7033 need to make variables names uniform 2024-05-14 14:09:54 -07:00
Godfrey M 15cc4345ab adds dynamic redirects to Assets 2024-05-14 13:25:52 -07:00
Godfrey Martinez 5272824d85 Merge branch 'develop' into asset-location-update-bug 2024-05-13 10:47:25 -07:00
snipe 9bce0f2ff7 Format fix
Signed-off-by: snipe <snipe@snipe.net>
2024-05-13 18:19:14 +01:00
snipe d2e7e11dca Removed debug line
Signed-off-by: snipe <snipe@snipe.net>
2024-05-13 12:48:28 +01:00
snipe 6823aabf92 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2024-05-13 10:53:07 +01:00
snipe f2dddc1226 Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2024-05-13 10:51:44 +01:00
snipe 957becabb9 Merge pull request #14715 from snipe/dependabot/github_actions/develop/codacy/codacy-analysis-cli-action-4.4.1
Bump codacy/codacy-analysis-cli-action from 4.4.0 to 4.4.1
2024-05-13 10:26:33 +01:00
dependabot[bot] 7df03722ee Bump codacy/codacy-analysis-cli-action from 4.4.0 to 4.4.1
Bumps [codacy/codacy-analysis-cli-action](https://github.com/codacy/codacy-analysis-cli-action) from 4.4.0 to 4.4.1.
- [Release notes](https://github.com/codacy/codacy-analysis-cli-action/releases)
- [Commits](https://github.com/codacy/codacy-analysis-cli-action/compare/v4.4.0...v4.4.1)

---
updated-dependencies:
- dependency-name: codacy/codacy-analysis-cli-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-13 08:53:06 +00:00
snipe 4642f50d6b Merge remote-tracking branch 'origin/develop' 2024-05-11 15:14:57 +01:00
snipe 2decc3d6d3 Merge pull request #14711 from snipe/jerm/fix-all-query-in-sidebar-middleware
Fix memory-hog query in AssetCountForSidebar middleware
2024-05-11 01:35:09 +01:00
Jeremy Price 2adc4ffa96 Fix memory-hog query in AssetCountForSidebar middleware
https://github.com/snipe/snipe-it/pull/14702/files introduced a bug
where instead of doing a quick `select count(*)` of assets, it did a `select *` of
assets, moving the count from the database to the PHP process.

This caused OOM issues in memory-constrained environments with lots of
assets, and also presented a speed issue even when memory limited were
increased.

Additionally, given this populates the sidebar, this was likely an issue
on every page load that included the sidebar.

The fix is simply removing the `all()->`, ending up with Asset::count(),
which yields the desired `select count(*)` DB query.
2024-05-10 12:54:40 -07:00
snipe c8fbf7640c 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-05-08 12:16:17 +01:00
snipe 46779ca865 Merge pull request #14697 from snipe/bug/sc-25502/disable_delete_if_not_deletable_user
Fixed UI where delete button was not disabled even if the user couldn't be deleted
2024-05-08 12:06:33 +01:00
snipe 86661e79d1 Merge pull request #14702 from Toreg87/fixes/total_asset_count
Fixes #14701 - wrong total asset count
2024-05-08 11:52:46 +01:00
Tobias Regnery b2a5d86e30 Fixes #14701 - wrong total asset count
The total asset count in the sidenav shows the ready to deploy count instead of the total count.
Fix this by adjusting the query to all assets. Also respect the setting for archived assets.
Add a default value for total assets, since we are now using the settings-variable, which is not available during the setup process.

While at it, move the block for total assets before the ready to deploy assets to match the ordering of the sidenav.

Signed-off-by: Tobias Regnery <tobias.regnery@gmail.com>
2024-05-08 09:34:35 +02:00
Marcus Moore d7f0ee49b7 Update Alpine to 3.13.10
Includes fix to new label engine.
2024-05-07 17:08:05 -07:00
spencerrlongg 5b86ee7291 a couple more tests 2024-05-07 17:19:00 -05:00
spencerrlongg ad2ba252ee two new test 2024-05-07 15:11:33 -05:00
spencerrlongg 17ef20ea92 alright, in a working place 2024-05-07 14:08:47 -05:00
snipe 8c327e6523 Handle user not found properly
Signed-off-by: snipe <snipe@snipe.net>
2024-05-07 19:16:56 +01:00
snipe 386b2839e8 Added tests
Signed-off-by: snipe <snipe@snipe.net>
2024-05-07 18:59:24 +01:00
snipe 934593e0b6 Updated icon
Signed-off-by: snipe <snipe@snipe.net>
2024-05-07 18:09:55 +01:00
snipe a7aa178f24 Used localized strings
Signed-off-by: snipe <snipe@snipe.net>
2024-05-07 17:56:07 +01:00
snipe 69122034e7 Fixed icon table headers
Signed-off-by: snipe <snipe@snipe.net>
2024-05-07 17:55:33 +01:00
snipe 1117f4289d Added string
Signed-off-by: snipe <snipe@snipe.net>
2024-05-07 17:55:10 +01:00
snipe 97bc4a092f Removed debugging
Signed-off-by: snipe <snipe@snipe.net>
2024-05-07 17:40:48 +01:00
snipe d942b8f1fb Fixed alias names
Signed-off-by: snipe <snipe@snipe.net>
2024-05-07 17:40:35 +01:00
snipe 49dc9767b6 Added debugging :(
Signed-off-by: snipe <snipe@snipe.net>
2024-05-07 15:54:43 +01:00
snipe 482965197d Added users, locations to presenter, transformer
Signed-off-by: snipe <snipe@snipe.net>
2024-05-07 12:07:41 +01:00
snipe 410b547f3c Added users and locatipon count to API
Signed-off-by: snipe <snipe@snipe.net>
2024-05-07 12:07:28 +01:00
snipe f769e8247f Added ManagedUsers method, additional checks in isDeletable()
Signed-off-by: snipe <snipe@snipe.net>
2024-05-07 12:07:15 +01:00
snipe 2b4a536f85 Added CSS for users, locations
Signed-off-by: snipe <snipe@snipe.net>
2024-05-07 12:06:54 +01:00
snipe 92ae069629 Disable button in UI if user cannot be deleted
Signed-off-by: snipe <snipe@snipe.net>
2024-05-07 12:06:35 +01:00
snipe 6f40b21986 Merge remote-tracking branch 'origin/develop' 2024-05-07 08:38:09 +01:00
snipe 3084521521 Merge pull request #14693 from snipe/fixes/14692_view_share_undefined
Fixes #14692 - set default variables for sidebar totals
2024-05-07 08:37:10 +01:00
snipe 4f12c86e74 Fixes #14692 - set default variables for sidebar totals
Signed-off-by: snipe <snipe@snipe.net>
2024-05-07 08:34:22 +01:00
snipe 204de99a64 Merge remote-tracking branch 'origin/develop' 2024-05-07 08:12:31 +01:00
snipe fd929f5dd9 Merge pull request #14690 from marcusmoore/import-settings-properly
Load settings in `SendUpcomingAuditReport` command
2024-05-07 07:42:34 +01:00
Marcus Moore 7e9c8ba290 Remove duplicate settings call 2024-05-06 17:08:16 -07:00
Marcus Moore 6f639f7bf0 Load settings properly in SendUpcomingAuditReport command 2024-05-06 16:44:14 -07:00
snipe 3594ed67d1 Removed back buttons on settings index
Signed-off-by: snipe <snipe@snipe.net>
2024-05-06 20:48:32 +01:00
snipe d36a06d8e1 Merge remote-tracking branch 'origin/develop' 2024-05-06 20:34:49 +01:00
snipe c816b960b5 Fixed stray closing paren
Signed-off-by: snipe <snipe@snipe.net>
2024-05-06 20:34:36 +01:00
Brady Wetherington 5b02a43957 Merge branch 'develop' into snipeit_v7_laravel10 2024-05-06 18:44:03 +01:00
snipe 4913e56086 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2024-05-06 18:43:48 +01:00
snipe 4d00bb98d1 Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2024-05-06 18:39:55 +01:00
snipe db2baae758 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/css/dist/all.css
#	public/js/dist/bootstrap-table.js
#	public/mix-manifest.json
2024-05-06 18:37:52 +01:00
snipe fdecdf4b15 Merge pull request #14689 from KorvinSzanto/develop
Capitalize `N` instead of `y` since no is default
2024-05-06 17:48:16 +01:00
Korvin Szanto 5c1d4aff23 Capitalize N instead of y since no is default 2024-05-06 09:00:33 -07:00
snipe bf0edcb92e docs: add @gitgrimbo as a contributor 2024-05-06 12:59:26 +01:00
snipe 39fa8ef3c0 docs: add @chandanchowdhury as a contributor 2024-05-06 12:55:47 +01:00
snipe 9e8a369bc8 docs: add @PP-JN-RL as a contributor 2024-05-06 12:54:35 +01:00
snipe 3f3fe8935f docs: add @jeffclay as a contributor 2024-05-06 12:54:20 +01:00
snipe 82387630c7 docs: add @squintfox as a contributor 2024-05-06 12:54:06 +01:00
snipe 16c5033514 docs: add @Q4kK as a contributor 2024-05-06 12:53:34 +01:00
snipe 46ffaee1e4 docs: add @franceslui as a contributor 2024-05-06 12:53:06 +01:00
snipe d936f92a7d docs: add @mustafa-online as a contributor 2024-05-06 12:52:46 +01:00
snipe b424ddf42d docs: add @koiakoia as a contributor 2024-05-06 12:51:40 +01:00
snipe b3d5a893fc Fixed text
via (@koiakoia )

Signed-off-by: snipe <snipe@snipe.net>
2024-05-06 12:49:54 +01:00
snipe 69ea6eebae Merge pull request #14688 from snipe/security/Upgrade-tableexport.jquery.plugin-from-1.28.0-to-1.30.0
[Snyk] Upgrade tableexport.jquery.plugin from 1.28.0 to 1.30.0 #14656
2024-05-06 12:47:01 +01:00
snipe 0892c34125 [Snyk] Upgrade tableexport.jquery.plugin from 1.28.0 to 1.30.0 #14656
Signed-off-by: snipe <snipe@snipe.net>
2024-05-06 12:45:33 +01:00
snipe 52e14d501f Merge pull request #14687 from snipe/security/upgrade_fontawesome_from-6.5.1-to-6.5.2
Upgrade fontawesome from 6.5.1 to 6.5.2
2024-05-06 12:22:50 +01:00
snipe 4d093160fc Upgrade @fortawesome/fontawesome-free from 6.5.1 to 6.5.2 #14647
Signed-off-by: snipe <snipe@snipe.net>
2024-05-06 12:21:34 +01:00
snipe 0bcca99573 Merge pull request #14686 from snipe/security/upgrade_alpine_to_3.13.8
[Snyk] Upgrade alpinejs from 3.13.5 to 3.13.8 #14646
2024-05-06 12:16:00 +01:00
snipe 63516c4a4f [Snyk] Upgrade alpinejs from 3.13.5 to 3.13.8 #14646
Signed-off-by: snipe <snipe@snipe.net>
2024-05-06 12:12:59 +01:00
snipe 19fb79ffff Merge pull request #14661 from ubc-cpsc/bugfix/CVE-2024-32489
Upgrade tecnickcom/tcpdf from version 6.7.4 to 6.7.5 to address the security vulnerability CVE-2024-22640
2024-05-06 11:58:31 +01:00
snipe 02835de13d Merge pull request #14679 from mustafa-online/develop
Improve RTL support
2024-05-04 15:47:14 +01:00
Mustafa Online 55b004d53d Improve RTL support 2024-05-04 13:32:42 +02:00
Mustafa Online c1b72a8ce6 Revert "Improve RTL support"
This reverts commit fa0bea87e6.
2024-05-04 13:31:52 +02:00
Mustafa Online fa0bea87e6 Improve RTL support
I'm starting to make some improvements to RTL support, more PR's to come to address other parts.
2024-05-04 13:17:48 +02:00
Godfrey M c94a7613ca dropdown redirect options, helper function and session variable added 2024-05-02 12:16:20 -07:00
snipe d146426dd8 Updated prod assets
Signed-off-by: snipe <snipe@snipe.net>
2024-05-02 14:02:53 +01:00
snipe 1e1782c232 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-05-02 14:02:36 +01:00
snipe dab5874fd7 Merge pull request #14391 from snipe/features/add_Brother_188mm_tape_label
Added Brother 18mm label type
2024-05-02 13:14:04 +01:00
snipe 4850227c04 Merge pull request #14655 from snipe/feature/sc-25381/simpler_overdue_endpoints
Refactored due/overdue for audit, added due/overdue for checkin API endpoint and GUI
2024-05-02 13:11:51 +01:00
snipe eb9a654cc3 Moved settings call higher
Signed-off-by: snipe <snipe@snipe.net>
2024-05-02 12:37:41 +01:00
snipe 4224bc0c43 Removed extra settings param
Signed-off-by: snipe <snipe@snipe.net>
2024-05-02 12:36:57 +01:00
snipe f893b23129 Refactored title blade areas
Signed-off-by: snipe <snipe@snipe.net>
2024-05-02 12:35:52 +01:00
snipe 8c65880504 Changed badge to span in default blade
Signed-off-by: snipe <snipe@snipe.net>
2024-05-02 12:35:41 +01:00
snipe 53cadf80fa Removed assertions for factories
Signed-off-by: snipe <snipe@snipe.net>
2024-05-02 12:24:31 +01: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
spencerrlongg e177993bcc notes and some playing around, push for eod 2024-05-01 16:57:11 -05:00
spencerrlongg 6a7f3ecc2e new test not quite working, almost there 2024-05-01 16:12:56 -05:00
spencerrlongg 39cc99c89b all initial attributes set in test 2024-04-30 22:22:59 -05:00
spencerrlongg 25480293dc change keys to values, add test 2024-04-30 18:03:26 -05: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
Frances Lui 8b3bfc6bc9 Fixes CVE-2024-32489 2024-04-29 16:33:00 -07:00
snipe 19cff25300 Merge pull request #14651 from marcusmoore/bug/sc-25402
Fixed `purchase_cost` not being allowed to be a string when creating asset via api
2024-04-27 03:39:10 +01:00
snipe 848e1fe1f6 Refactored audit alerts
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 21:26:00 +01:00
snipe fe147adec3 Refactor checkin alert
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 21:10:54 +01:00
snipe 103809b65f Removed debugging
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 21:01:43 +01:00
snipe a398496dd4 Added comments
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 21:01:27 +01:00
snipe 839db8ef44 Refactored due-or-overdue methods
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 20:59:27 +01:00
snipe bfd0530597 Fixed notification
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 20:59:13 +01:00
snipe 494ec5cd9c Added tests for due-or-overdue
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 20:59:04 +01:00
snipe fc61a4b88d Fixed badge HTML
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 19:50:58 +01:00
snipe 50d8b02f8b Removed unused scope
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 19:23:27 +01:00
snipe 860764a436 Use totals for sidebar
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 19:12:21 +01:00
snipe 52d6a8990a Check that the asset is not already checked in
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 19:06:46 +01:00
snipe 87de67e4a9 Fixed test for checkin
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 19:06:26 +01:00
snipe 8356b57fb4 Added translations
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 19:01:34 +01:00
snipe 3f04afee5c Removed unused method
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 19:01:26 +01:00
snipe 2117f61e8c More view sharing for sidebar
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 19:01:15 +01:00
snipe d40604b574 Removed debugging, added date cast
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 19:01:05 +01:00
snipe 76129e9011 Use trans_choice for title
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 18:59:13 +01:00
snipe 9c8411c7ff Added checkin due blade
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 18:58:56 +01:00
snipe c661d732b3 Refactored sidenav links for audit
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 18:58:44 +01:00
snipe fbe9daace6 Use pattern in API route
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 18:58:29 +01:00
snipe 651001bf6e Removed duplicate routes
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 18:58:15 +01:00
snipe 9167f8a3ba Cleaned up tests
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 18:57:07 +01:00
snipe 6dc9ccffcd Refactor api for handling audit/expected checkins
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 18:56:57 +01:00
snipe 4b4e3badb7 Removed hardware audit overdue blade
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 18:53:36 +01:00
snipe fe4dd23d39 Removed “all” text
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 15:49:12 +01:00
snipe de6d71cc3b Use plural api endpoints in blades
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 15:47:19 +01:00
snipe 9e44052709 Switch to plural route name for API endpoint
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 15:46:58 +01:00
snipe 2d112f227a Call the asset factory directly
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 15:44:37 +01:00
snipe bd8737d986 Changed sidenav badge class
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 15:44:21 +01:00
snipe 4b6d236eb7 Added class for sidebar menu badges
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 15:44:06 +01:00
snipe bf058bd5c6 Use updated scopes
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 14:02:56 +01:00
snipe dfaf01e8aa Updated asset counters
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 14:02:47 +01:00
snipe 2888dd6fd8 Added translation
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 14:02:37 +01:00
snipe 2e92ee8eee Switch to whereBetween so tests run on sqlite
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 14:02:23 +01:00
snipe 14b6a75507 Updated routes
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 14:01:38 +01:00
snipe 2484a9db2c Added tests
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 14:01:29 +01:00
snipe bfc30794c5 Updated badge styling
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 14:01:22 +01:00
snipe 27bc7a847b Updated routes
Signed-off-by: snipe <snipe@snipe.net>
2024-04-26 14:01:11 +01:00
Marcus Moore 2a71877bec Add additional condition 2024-04-25 17:04:07 -07:00
Marcus Moore 30bd920497 Add conditional 2024-04-25 16:24:12 -07:00
Marcus Moore 1d5b48b88d Add comment and improve method 2024-04-25 16:22:15 -07:00
spencerrlongg 97a6152ea9 update comment per @uberbrady 2024-04-25 17:47:55 -05:00
spencerrlongg 03f091a77f ammended note, got real rule in there 2024-04-25 17:17:42 -05:00
Marcus Moore 4295bad12f Separate test cases 2024-04-25 14:07:56 -07:00
Marcus Moore 3a2eeaea7a WIP: Future-proof rules being converted to array syntax 2024-04-24 17:40:40 -07:00
Marcus Moore 12418ae91b WIP: allow EU style purchase cost via api 2024-04-24 17:18:29 -07:00
Marcus Moore 783a24eb68 Add test for ParseCurrencyMethod 2024-04-24 17:17:42 -07:00
Brady Wetherington 3f5c5cbe82 Merge branch 'develop' into snipeit_v7_laravel10 2024-04-24 16:24:43 +01:00
snipe 2439758ef3 Merge pull request #14587 from Godmartinz/License-export-button
Added a License Export function and button
2024-04-24 04:42:56 +01:00
spencerrlongg 8696a423b0 another option 2024-04-23 17:38:40 -05:00
spencerrlongg 107f8db9bc another option 2024-04-23 17:35:33 -05:00
spencerrlongg b11c900a4c fix bracket, + overwrite required rulesets 2024-04-23 16:29:07 -05:00
akemidx ac4aa97103 develop reheading 2024-04-23 17:05:50 -04:00
akemidx 0bc93c6a1e space 2024-04-23 15:31:37 -04:00
Spencer Long 53ccd196d7 Merge branch 'develop' into bug/sc-24884 2024-04-23 13:57:59 -05:00
snipe 685f1cbfb8 Merge pull request #14499 from Godmartinz/remove_encrpyt_from_labels
Removed encrypted fields from label options
2024-04-23 13:31:38 +01:00
snipe e2d1e6b0c5 Merge pull request #14608 from akemidx/bug/sc-25232
Left Sidebar Was Not Respecting Theme
2024-04-23 12:32:48 +01:00
snipe 56cb9a0f4e Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
#	public/css/dist/skins/skin-black-dark.css
#	public/css/dist/skins/skin-black-dark.min.css
#	public/css/dist/skins/skin-blue-dark.css
#	public/css/dist/skins/skin-blue-dark.min.css
#	public/css/dist/skins/skin-green-dark.css
#	public/css/dist/skins/skin-green-dark.min.css
#	public/css/dist/skins/skin-orange-dark.css
#	public/css/dist/skins/skin-orange-dark.min.css
#	public/css/dist/skins/skin-purple-dark.css
#	public/css/dist/skins/skin-purple-dark.min.css
#	public/css/dist/skins/skin-red-dark.css
#	public/css/dist/skins/skin-red-dark.min.css
#	public/css/dist/skins/skin-yellow-dark.css
#	public/css/dist/skins/skin-yellow-dark.min.css
#	public/mix-manifest.json
2024-04-23 10:28:50 +01:00
snipe c8c81a360c Dev assets
Signed-off-by: snipe <snipe@snipe.net>
2024-04-23 10:26:43 +01:00
snipe bdd43b7134 Merge pull request #14602 from uberbrady/fix_saving_encrypted_custom_fields
Re-enabled updating encrypted custom fields via API [sc-41465]
2024-04-23 10:20:55 +01:00
snipe c50d5a678a Merge pull request #14616 from akemidx/bug/sc-25235
REMOVED: Dark Theme Button Text Coloring
2024-04-23 09:20:57 +01:00
Godfrey M 96b3af7cbc fixed view from sending all custom fields 2024-04-22 18:27:34 -07:00
Godfrey Martinez 9e7bbc968d Merge pull request #15 from Godmartinz/License-export-button_p2
adds licenses available, updated teranslations
2024-04-22 17:59:52 -07:00
Godfrey M 5fc6771543 adds licenses available, updated teranslations 2024-04-22 17:58:49 -07:00
akemidx 0d049a0be7 conflict resolution 2024-04-22 20:09:40 -04:00
akemidx 01c24ab4cd translating text 2024-04-22 19:16:14 -04:00
Marcus Moore 155f5f35cd Remove todo 2024-04-22 15:47:05 -07:00
snipe 7ad6caf30a Merge pull request #14632 from marcusmoore/bug/sc-25384
Added "select" option to top of data sources in new label engine
2024-04-22 20:40:31 +01:00
Marcus Moore ac8aab0043 Add default "select an option" to data source options 2024-04-22 12:22:10 -07:00
Godfrey M 14ddf36d46 removed two duplicate translations 2024-04-22 10:43:11 -07:00
Godfrey M 25f1167c9d adds company scoping to license export 2024-04-22 10:38:55 -07:00
Godfrey M 420225c2d5 Merge branch 'refs/heads/develop' into License-export-button 2024-04-22 10:33:30 -07:00
Marcus Moore 45f5eaac5b Extract CanSkipTests trait 2024-04-22 10:32:37 -07:00
snipe 5229dd65ce Merge remote-tracking branch 'origin/develop' 2024-04-22 15:02:51 +01:00
snipe cfe39afc11 Merge pull request #14630 from snipe/bug/sc-25377/double_encoding_assets_and_model_notes_on_upload
Removed escaping on notes for file uploads
2024-04-22 14:59:55 +01:00
snipe 2aa3ce15bd Removed escaping on notes for file uploads
Signed-off-by: snipe <snipe@snipe.net>
2024-04-22 14:55:02 +01:00
snipe c9873da732 Merge pull request #14628 from snipe/bug/sc-25375/icon_mimetype_validation_fix
Added `ico`, `image/x-icon`, `image/vnd.microsoft.icon` to favicon validation
2024-04-22 13:58:08 +01:00
snipe 8dd71f99cc Added ico, image/x-icon,image/vnd.microsoft.icon to favicon validation
Signed-off-by: snipe <snipe@snipe.net>
2024-04-22 13:54:19 +01:00
Brady Wetherington ab45975883 Mark custom fields tests as 'incomplete' if the DB is mysql 2024-04-22 13:11:36 +01:00
snipe 7f38ca239e 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-04-19 16:24:32 +01:00
snipe c3b982e759 Merge pull request #14622 from snipe/bug/sc-25363/z-index-bs-table-check-boxes-fix
Reeduced z-index of bs table override
2024-04-19 16:11:21 +01:00
snipe e330e80c46 Reeduced z-index of bs table override
Signed-off-by: snipe <snipe@snipe.net>
2024-04-19 16:06:43 +01:00
akemidx f0836d4d3a changes for button hover, removing text color changes. also added in a border for yellow and black themes 2024-04-18 19:36:35 -04:00
akemidx 1289920217 black button border 2024-04-18 19:29:56 -04:00
snipe a6a58094c9 Merge remote-tracking branch 'origin/develop' 2024-04-18 14:26:53 +01:00
snipe 424cbd3248 Removed noisy debug
Signed-off-by: snipe <snipe@snipe.net>
2024-04-18 14:25:54 +01:00
snipe e59b9627c7 Merge pull request #14511 from jeffclay/features/14508_pdo_ssl_verify
Fixed #14508: Added PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT options to database.php …
2024-04-18 14:23:00 +01:00
snipe f080c0cdcd Merge pull request #14578 from Q4kK/features/add_no_interactive
Feat: add no-interactive flag for `upgrade.php`
2024-04-18 14:19:38 +01:00
snipe 29bda2ef7d Merge pull request #14613 from marcusmoore/additional-test-cases
Added test cases around modifying user groups via api
2024-04-18 13:53:03 +01:00
akemidx e8d9701a26 array key existing 2024-04-17 19:16:25 -04:00
Marcus Moore 1d64692fd6 Add two test cases 2024-04-17 15:23:26 -07:00
snipe 6f195cb8ec Merge pull request #14591 from snipe/bug/sc-25258/naive_fix_for_user_scoping
First fix for user FMCS scoping
2024-04-17 21:49:53 +01:00
snipe 4c02a63acc Removed activated attribute on test users
Signed-off-by: snipe <snipe@snipe.net>
2024-04-17 20:29:51 +01:00
snipe 0fc9fc7516 Minor updates to tests
Signed-off-by: snipe <snipe@snipe.net>
2024-04-17 20:29:01 +01:00
snipe 4450351b75 Only sync groups if API user is superadmin
Signed-off-by: snipe <snipe@snipe.net>
2024-04-17 11:06:50 +01:00
snipe 9bb15aaf1b Added individual gates to keep response consistent with other company-ed things
Signed-off-by: snipe <snipe@snipe.net>
2024-04-17 10:57:49 +01:00
snipe 65dd729e19 Additional gates
Signed-off-by: snipe <snipe@snipe.net>
2024-04-17 10:57:20 +01:00
snipe c21142605d Added strings
Signed-off-by: snipe <snipe@snipe.net>
2024-04-17 10:47:56 +01:00
snipe 86e274faa3 Added API tests
Signed-off-by: snipe <snipe@snipe.net>
2024-04-17 10:47:48 +01:00
snipe 5e8c129c7f Revert accidental commit
Signed-off-by: snipe <snipe@snipe.net>
2024-04-17 09:26:50 +01:00
snipe ab3b5ca4ef Fixed tests
Signed-off-by: snipe <snipe@snipe.net>
2024-04-17 09:26:07 +01:00
Marcus Moore 60a5afd752 Merge branch 'factory-refactors' into fix_saving_encrypted_custom_fields 2024-04-16 17:15:22 -07:00
Marcus Moore 9d0ea857fe Import facade 2024-04-16 17:14:17 -07:00
Marcus Moore f763aea4fc Update tests to send post request 2024-04-16 17:13:18 -07:00
Marcus Moore e16c04250e Improve model factories 2024-04-16 16:58:28 -07:00
Marcus Moore ad99aa460b Remove unneeded imports 2024-04-16 15:09:49 -07:00
Marcus Moore e47f64f62d Separate test methods 2024-04-16 15:03:05 -07:00
Marcus Moore c6d9da1571 Remove unneeded fields in factory state 2024-04-16 12:36:41 -07:00
Marcus Moore ab561d1ce8 Simplify factory state 2024-04-16 12:36:13 -07:00
akemidx f39ba0136c errant carraige return 2024-04-16 14:26:18 -04:00
akemidx df60045bfe sidebar hover fix 2024-04-16 14:21:47 -04:00
akemidx 5e122f780f sidebar_hover_color 2024-04-16 14:00:20 -04:00
Marcus Moore eefe377159 Correct order of arguments 2024-04-16 10:51:33 -07:00
q4kK 20920c262d Feat: add no-interactive flag for upgrade.php
Having a no-interactive flag is useful because attempting
to automate snipe-it upgrades is currently extremely janky.
You have to either:
  a) read the prompts and pass in the input (the "correct" way)
  b) pipe in input, e.g. `yes` and hope no new prompts
  are added.

With the `no-interactive` flag, this can be fixed by both
allowing new prompts to be added without conflict
to user prompts, but also allowing automated upgrades (you could
choose to crash, or assign defaults).
2024-04-16 11:54:50 -05:00
Brady Wetherington 870612be1c Break 'update' API statements into its own test file. Split tests up 2024-04-16 15:34:28 +01:00
Brady Wetherington 266424ff0e Some simple renames for better readability as suggested by Marcus 2024-04-16 15:17:02 +01:00
snipe a8d48b758e Merge pull request #14594 from marcusmoore/bug/sc-25314/multiple-label-fields-on-one-row
Fixed label fields only showing first option
2024-04-15 18:53:03 +01:00
Brady Wetherington 67a8e0b5c6 This re-enables the ability to update encrypted custom fields via the API 2024-04-15 18:46:11 +01:00
snipe 7b7d424962 Merge pull request #13880 from Godmartinz/department-validation-bug
Fixed department validation to allow updates
2024-04-12 10:50:26 +01:00
Marcus Moore a4e959818a Add comment 2024-04-11 17:23:28 -07:00
Marcus Moore c3a71cc182 Improve variable names and add comment 2024-04-11 16:44:13 -07:00
Marcus Moore da03cfdbe5 Formatting 2024-04-11 16:39:29 -07:00
Marcus Moore 2b137d76fa Trim string to avoid leading whitespace if label is empty 2024-04-11 16:38:22 -07:00
Marcus Moore 81b8c111ca Allow multiple fields to be displayed in one row 2024-04-11 15:00:14 -07:00
snipe fce98b9ca4 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/css/dist/skins/skin-black-dark.css
#	public/css/dist/skins/skin-black-dark.min.css
#	public/css/dist/skins/skin-blue-dark.css
#	public/css/dist/skins/skin-blue-dark.min.css
#	public/css/dist/skins/skin-green-dark.css
#	public/css/dist/skins/skin-green-dark.min.css
#	public/css/dist/skins/skin-orange-dark.css
#	public/css/dist/skins/skin-orange-dark.min.css
#	public/css/dist/skins/skin-purple-dark.css
#	public/css/dist/skins/skin-purple-dark.min.css
#	public/css/dist/skins/skin-red-dark.css
#	public/css/dist/skins/skin-red-dark.min.css
#	public/css/dist/skins/skin-yellow-dark.css
#	public/css/dist/skins/skin-yellow-dark.min.css
#	public/mix-manifest.json
2024-04-11 18:58:50 +01:00
snipe c0dcae16f7 Updated dev assets
Signed-off-by: snipe <snipe@snipe.net>
2024-04-11 18:57:06 +01:00
snipe c604f08749 Small tweaks for troubleshooting :(
Signed-off-by: snipe <snipe@snipe.net>
2024-04-11 18:47:55 +01:00
snipe da21424416 Merge pull request #14581 from marcusmoore/bug/sc-25237
Fixed assigned to field in new label engine
2024-04-11 15:36:18 +01:00
snipe b5c83721ad Merge pull request #14577 from Godmartinz/signature_pad_upgrade
Upgraded Signature-pad.js  && Fixed Resizing Canvas on mobile
2024-04-11 15:35:47 +01:00
snipe 9b21fca1a0 Merge pull request #14558 from akemidx/bug/sc-25192
Fixed: Header Dropdown Menus had no hover coloring in dark themes
2024-04-11 15:35:33 +01:00
snipe af94b07771 Merge pull request #14582 from akemidx/feature/sc-25288
Reduce Extra Space in Header Dropdown
2024-04-11 15:35:11 +01:00
snipe 0d23d28a65 Added comments
Signed-off-by: snipe <snipe@snipe.net>
2024-04-11 15:15:56 +01:00
snipe 710370ac24 Added scoping for destroy
Signed-off-by: snipe <snipe@snipe.net>
2024-04-11 14:58:25 +01:00
snipe ed0a441e4d Refactor destroy method
Signed-off-by: snipe <snipe@snipe.net>
2024-04-11 14:52:03 +01:00
snipe 24e87cc0bb Updated comment
Signed-off-by: snipe <snipe@snipe.net>
2024-04-11 14:51:49 +01:00
snipe 460693c153 Added comment
Signed-off-by: snipe <snipe@snipe.net>
2024-04-11 14:40:13 +01:00
snipe f54a94bd4c Refactorered methods
Signed-off-by: snipe <snipe@snipe.net>
2024-04-11 14:40:00 +01:00
snipe a19b86add0 Re-ordered scoping for admins, added comments
Signed-off-by: snipe <snipe@snipe.net>
2024-04-11 14:39:37 +01:00
snipe 570944a48b Updated translation
Signed-off-by: snipe <snipe@snipe.net>
2024-04-11 14:38:52 +01:00
snipe 5829b02323 Added translation
Signed-off-by: snipe <snipe@snipe.net>
2024-04-11 14:38:47 +01:00
Marcus Moore 5567a1e9ac Formatting 2024-04-10 17:37:11 -07:00
Marcus Moore fa5016713f Implement test 2024-04-10 17:29:44 -07:00
Marcus Moore f28a82de71 Implement some tests, scaffold others 2024-04-10 17:27:07 -07:00
Marcus Moore 7c2fae7b9d Scaffold api test cases 2024-04-10 17:08:45 -07:00
Marcus Moore 70934e54cf Remove unneeded comment 2024-04-10 16:34:14 -07:00
Marcus Moore f6ad275030 Clean ups 2024-04-10 16:28:48 -07:00
Marcus Moore 6666a78936 Organization 2024-04-10 16:19:04 -07:00
Marcus Moore bbb2cdcceb Add note 2024-04-10 16:15:43 -07:00
Marcus Moore 6b6e18695f Account for null asset in factory state 2024-04-10 16:12:47 -07:00
Marcus Moore b63962e90b Add additional assertions 2024-04-10 16:01:15 -07:00
Marcus Moore 4434de6241 Add test case 2024-04-10 15:47:26 -07:00
Godfrey M a2bca0e358 fixed comments 2024-04-10 15:05:21 -07:00
Marcus Moore 6d572424ac Add validation around dates 2024-04-10 14:02:25 -07:00
Marcus Moore d371d14c1f Implement test 2024-04-10 13:49:07 -07:00
Marcus Moore 72eda1e909 Improve naming 2024-04-10 13:29:31 -07:00
Marcus Moore 7dbf8a8a8e Add tests for asset and location check out 2024-04-10 13:28:52 -07:00
Godfrey M 133fdd7a37 fix conditional 2024-04-10 12:31:04 -07:00
Godfrey M 0849262243 fixed notes 2024-04-10 12:19:34 -07:00
Godfrey M 17095feb33 fix typo 2024-04-10 12:15:48 -07:00
Godfrey M f42ae46338 exports all licenses 2024-04-10 12:14:44 -07:00
Marcus Moore 37ebf1827f Organization 2024-04-10 12:12:44 -07:00
Marcus Moore e65252725a Add simple test for LogListener 2024-04-10 11:52:59 -07:00
Marcus Moore 6f53f2ac64 Finish implementing test case 2024-04-10 11:43:50 -07:00
Godfrey M e2679852ce added export button, half the logic for export method 2024-04-10 11:31:30 -07:00
Marcus Moore deaba46e1c Merge branch 'develop' into chore/sc-25103/add-tests-around-asset-checkout 2024-04-10 11:01:35 -07:00
snipe 989dab6259 Moved company scoping methods to group them together
Signed-off-by: snipe <snipe@snipe.net>
2024-04-10 14:35:13 +01:00
snipe adacdc038d Apply company scoping for users
Signed-off-by: snipe <snipe@snipe.net>
2024-04-10 12:34:32 +01:00
akemidx f0aefaac42 padding fix 2024-04-09 17:51:42 -04:00
Marcus Moore 1aeaa0094a Fix assigned to in labels 2024-04-09 13:52:54 -07:00
akemidx 6d3fa12f37 white texty for dropdown lists 2024-04-09 14:52:43 -04:00
Godfrey M 052f1eedd0 fixes signature canvas refresh on mobile 2024-04-09 10:30:33 -07:00
Godfrey M 858da800be attempting to lock screen orientation 2024-04-09 09:40:39 -07:00
snipe 954cac3af7 Merge remote-tracking branch 'origin/develop' 2024-04-08 10:56:04 +01:00
snipe d0f171ebc6 Merge pull request #14567 from snipe/bug/sc-25257
Remove city as required field on location modal
2024-04-08 10:54:09 +01:00
snipe 90cf612ac7 Remove city as required field on location modal
Signed-off-by: snipe <snipe@snipe.net>
2024-04-08 10:50:52 +01:00
snipe 802b5863ab Merge remote-tracking branch 'origin/develop' 2024-04-08 08:49:54 +01:00
snipe 4baa949a99 Merge pull request #14557 from Godmartinz/add-audit-date-to-labels
Added audit dates to label options
2024-04-08 04:59:53 +01:00
snipe 3bed04a6d3 Merge pull request #14559 from Godmartinz/ldap_location_bug
Fixed  ldap location syncing incorrect locations for users.
2024-04-08 04:59:27 +01:00
spencerrlongg 99d7155729 translation strings 2024-04-07 19:50:53 -05:00
spencerrlongg f30439a544 small refactor, pretty much good to go now though 2024-04-07 17:07:46 -05:00
spencerrlongg 997eddfed1 cleanup + notes for monday 2024-04-04 18:23:03 -05:00
Godfrey M d548b800d5 nullifies location after ldap user sync 2024-04-04 15:43:33 -07:00
spencerrlongg 52340aca78 just about wrapped up 2024-04-04 17:41:10 -05:00
akemidx f7f199d929 black hover bg for dark yellow theme 2024-04-04 15:51:46 -04:00
akemidx 5519fddb78 new clean branch for color change 2024-04-04 15:50:30 -04:00
spencerrlongg e1fb446888 this is a pretty good start, need to know about other PR 2024-04-04 14:20:03 -05:00
Godfrey M a9ed748fb2 adds audit dates to label options 2024-04-04 11:39:49 -07:00
steve@degga.net 83443ad2b5 Sometimes I should just slow down. 2024-04-04 11:36:21 -04:00
steve@degga.net 3fcc067481 Removes accidental changes on two lines 2024-04-04 10:27:44 -04:00
snipe dcba2bfd25 Merge pull request #14529 from mauro-miatello/develop
Hide/Show encrypted values in hardware list
2024-04-04 15:07:58 +01:00
snipe 72c91ead8b 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-04-04 15:06:37 +01:00
snipe 774d0aa90c Updated dev assets
Signed-off-by: snipe <snipe@snipe.net>
2024-04-04 15:05:35 +01:00
snipe 2eea67ce34 Merge pull request #14547 from Godmartinz/user-dropdown-media-change
Fixed alignment of dropdown menu for user in nav bar
2024-04-04 15:04:36 +01:00
snipe db1c44f921 Merge pull request #14552 from snipe/bug/sc-25229/redirect_if_already_checked_in
Redirect on checkin if the asset is already checked in
2024-04-04 15:01:43 +01:00
snipe e11287ec25 Redirect on checkin if the asset is already checked in
Signed-off-by: snipe <snipe@snipe.net>
2024-04-04 15:00:55 +01:00
snipe 4f10adfb76 Merge remote-tracking branch 'origin/develop' 2024-04-04 14:27:35 +01:00
snipe f22803c59f Merge pull request #14551 from snipe/bug/sc-25221/ambiguous_id_in_custom_report
Fixed ambiguous id clause in custom report
2024-04-04 14:25:43 +01:00
snipe a72d4e5dc1 Fixed ambiguous id clause in custom report
Signed-off-by: snipe <snipe@snipe.net>
2024-04-04 14:23:58 +01:00
steve@degga.net 3e564eaf19 fixed accidentally forgot update a call to the old dynamicWarrantyUrl() method in hardware/view.blade.php 2024-04-03 20:09:37 -04:00
spencerrlongg 0a90df2b14 alright conflicts resolved 2024-04-03 14:40:14 -05:00
Spencer Long 4ab75c1c03 Merge branch 'develop' into bug/sc-24884 2024-04-03 14:08:41 -05:00
Godfrey M 08f9aae8ae adds note to log listener and checkout accept notif 2024-04-03 11:59:47 -07:00
Godfrey M 43c32fa1bf fix class name in migration 2024-04-03 11:47:08 -07:00
Godfrey M 5afe024644 changed translation on asset acceptancen blade 2024-04-03 11:40:48 -07:00
Godfrey M c01bdb42fc renamed migration 2024-04-03 11:39:17 -07:00
Godfrey M e3ef8d295f Merge remote-tracking branch 'origin/add_decline_note_to_acceptance' into add_decline_note_to_acceptance 2024-04-03 11:37:05 -07:00
Godfrey M ce1d677cdc adds note to acceptance 2024-04-03 11:36:03 -07:00
Godfrey M df5cacf8a2 removed front end if statement 2024-04-03 11:06:05 -07:00
Godfrey M bb2c73348d only grabs custom Fields that are not encrpyted 2024-04-03 11:03:58 -07:00
Godfrey M 4327653d70 remove db cleaner for encrypted selections 2024-04-03 10:57:41 -07:00
Godfrey M 5f7f4c9b91 aligns dropdown menu for user in nav 2024-04-03 10:41:50 -07:00
snipe d44202e55b 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-04-03 13:09:48 +01:00
snipe df95447ea4 New dev assets
Signed-off-by: snipe <snipe@snipe.net>
2024-04-03 13:08:08 +01:00
snipe 01852c7188 Merge pull request #14520 from Godmartinz/loading_overlap_bug
fixes z-index of table load
2024-04-03 13:07:14 +01:00
snipe 79c5697042 Fixed dev - take 2!
Signed-off-by: snipe <snipe@snipe.net>
2024-04-03 13:06:49 +01:00
Brady Wetherington 65e21faa3e Merge branch 'develop' into snipeit_v7_laravel10
Hopefully, last merge?
2024-04-02 20:34:04 +01:00
steve@degga.net bf10fd0cf0 Rename dynamicUrl() method 2024-03-31 22:37:41 -04:00
steve@degga.net 83ce04dc8d Fixes syntax error. 2024-03-31 22:31:06 -04:00
steve@degga.net f7bbec6be4 Makes all manufacturer URLs dynamic, not just warranty lookup. 2024-03-31 22:18:44 -04:00
MrM 658ba092e2 Hide encrypted values in hardware list
Encrypted values are now hidden also in hardware list, clicking on them show the decrypted value
2024-03-31 18:55:58 +02:00
MrM b221d99e7b Encrypted values enhancement
Show asterisks instead of the value, respecting the length of the field
2024-03-31 12:27:35 +02:00
snipe b7af049589 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2024-03-29 13:20:22 +00:00
snipe c2d863da99 Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2024-03-29 13:19:22 +00:00
snipe 6f9ba6ede4 Merge remote-tracking branch 'origin/develop' 2024-03-29 12:49:22 +00:00
snipe df4e6a0023 Fixed typo in Polish
I will fix this in CrowdIn shortly

Signed-off-by: snipe <snipe@snipe.net>
2024-03-29 12:47:43 +00:00
snipe d60fa65f85 Merge remote-tracking branch 'origin/develop' 2024-03-28 21:59:36 +00:00
snipe 8081a82fe4 Merge branch 'develop' of https://github.com/snipe/snipe-it into develop 2024-03-28 21:58:58 +00:00
snipe f42e5d5292 Reverting the store/update asset API responses for now
This currently breaks the Jamf integration - need a better longer term plan.

Signed-off-by: snipe <snipe@snipe.net>
2024-03-28 21:58:49 +00:00
snipe 5a3f5b03d0 Merge pull request #14456 from akemidx/feature/sc-25079/legacy-locations
Default Locale value changed to en-US
2024-03-28 21:47:40 +00:00
akemidx 721902c2d4 committed for later 2024-03-28 16:44:44 -04:00
Godfrey M a450530c74 fixes z-index of table load 2024-03-28 11:44:55 -07:00
snipe 2b4886f37f Commented out Heroic deploy for now 2024-03-28 17:43:18 +00:00
snipe b45de3e17f Update README.md
Added alert notations
2024-03-28 17:41:46 +00:00
snipe b2eea3e5a5 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/js/dist/all-defer.js
#	public/mix-manifest.json
2024-03-28 13:02:51 +00:00
snipe f411c0fdd8 Merge pull request #14518 from snipe/fixes/downgrade_alpine
Downgrade alpine to 3.13.5
2024-03-28 12:59:52 +00:00
snipe 74d8431d01 Downgrade alpine to 3.13.5
Signed-off-by: snipe <snipe@snipe.net>
2024-03-28 12:58:43 +00:00
snipe 3ea0cd75a5 Merge remote-tracking branch 'origin/develop' 2024-03-28 12:27:24 +00:00
snipe 5f6c746d25 Merge pull request #14517 from snipe/bug/sc-25186/label_index
Check that the array key exists in the label engine
2024-03-28 12:26:20 +00:00
snipe 1f2d30ebf4 Check that the array key exists
Signed-off-by: snipe <snipe@snipe.net>
2024-03-28 12:25:29 +00:00
akemidx e6b366020a lots of attempts and syntax, but no go 2024-03-27 19:05:59 -04:00
snipe 6dd6b45829 Merge remote-tracking branch 'origin/develop' 2024-03-27 20:43:34 +00:00
snipe e5800a2dac Merge pull request #14516 from snipe/fixes/fixed_sorting_on_last_checkin_assets_api
Fixes/fixed sorting on last checkin assets api
2024-03-27 20:39:12 +00:00
snipe 0d3d172108 Make last_checkin searchable and fillable
Signed-off-by: snipe <snipe@snipe.net>
2024-03-27 20:37:40 +00:00
snipe 86677b5f13 Make last_checkin sortable
Signed-off-by: snipe <snipe@snipe.net>
2024-03-27 20:37:25 +00:00
snipe 3f5b94f8ad Merge remote-tracking branch 'origin/develop' 2024-03-27 19:52:23 +00:00
snipe cf8cb8521b Merge pull request #14515 from squintfox/fixes-results-not-limited-by-api-params
Fixes #14289: /reports/activity API endpoint returns too many results due to orwhere
2024-03-27 19:51:58 +00:00
spencerrlongg cec84b857b fixed last audit date + test 2024-03-27 14:39:23 -05:00
Robert Spadaro ccd00caa70 Wrap where logic in additional where statement to protect appended params 2024-03-27 15:36:00 -04:00
spencerrlongg 1d4a7a7b02 added audit dates 2024-03-27 14:05:30 -05:00
snipe 57010b4c23 Merge pull request #14500 from Godmartinz/add-accessory-signature-to-print-all
Added signature to user print report for Accessories and Consumables
2024-03-27 19:02:59 +00:00
snipe 545a185614 Merge pull request #14262 from akemidx/bug/sc-24812
Last Checkin Date added to Hardware View and Index
2024-03-27 19:02:25 +00:00
snipe 1572e339f9 Merge pull request #14514 from snipe/localizations/new_translations_march_224
Updated translations
2024-03-27 19:01:23 +00:00
snipe 7782e5cc93 Updated translations
Signed-off-by: snipe <snipe@snipe.net>
2024-03-27 18:59:28 +00:00
Godfrey Martinez bcdda551b3 Merge pull request #12 from Godmartinz/remove_jquery
removes jquery and updates translation
2024-03-27 11:58:11 -07:00
Godfrey M bc66c0f223 removes jquery and updates translation 2024-03-27 11:56:47 -07:00
spencerrlongg 701411c1b9 get rid of a couple unnecessary changes 2024-03-27 13:53:57 -05:00
Spencer Long 013463aafc Merge branch 'develop' into bug/sc-24884 2024-03-27 12:45:45 -05:00
Jeff Clay 1b8c7ff4ec Added PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT options to database.php and updated .env files to provide value for the new option. 2024-03-27 11:38:13 -05:00
snipe 3bb81d1e4d Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/js/dist/all-defer.js
#	public/mix-manifest.json
2024-03-27 16:18:28 +00:00
snipe 756c44fcba Merge pull request #14510 from snipe/snyk/Upgrade-alpinejs-from-3.13.5-to-3.13.6
[Snyk] Upgrade alpinejs from 3.13.5 to 3.13.6
2024-03-27 16:14:53 +00:00
snipe befa4428d0 Merge pull request #14509 from snipe/feature/sc-25173/filter_assigned_user_assets_by_category_id
Added ability to filter in user's assigned assets by category ID and model ID
2024-03-27 16:13:51 +00:00
snipe 60c678680a [Snyk] Upgrade alpinejs from 3.13.5 to 3.13.6
Signed-off-by: snipe <snipe@snipe.net>
2024-03-27 16:12:57 +00:00
snipe 8bc9688d71 Added ability to filter on category ID and model ID from user’s asset API
Signed-off-by: snipe <snipe@snipe.net>
2024-03-27 16:04:00 +00:00
spencerrlongg 39c15b2868 reformat array 2024-03-27 10:35:25 -05:00
Godfrey M aa8af2220c trying to remove an encrypted field but not all fields 2024-03-26 16:10:08 -07:00
akemidx b124b9af4d adding in change to settings table 2024-03-26 16:50:39 -04:00
snipe ae403da8c1 Merge pull request #14502 from marcusmoore/bug/sc-25004/pwd_secure_complexity-validation
Added validation around `pwd_secure_complexity`
2024-03-26 20:05:04 +00:00
Marcus Moore b5b8777c94 Extract translation string 2024-03-26 12:23:57 -07:00
snipe 850f85ff59 Merge pull request #14369 from spencerrlongg/bug/sc-24343
Add new validator for custom field checkboxes and fix asset model default updates
2024-03-26 19:22:29 +00:00
Godfrey M 84cc88831d adds signature for components 2024-03-26 12:18:10 -07:00
Godfrey M f4f9b165a7 moves signature check inside of td 2024-03-26 11:24:34 -07:00
Godfrey M 3222d4c8df adds signature check 2024-03-26 09:18:34 -07:00
Godfrey M 3173ead2e7 adds accessory signature to user print report 2024-03-26 09:11:54 -07:00
Godfrey M 040f826c52 removes encrypted fields as a selectable option for labels 2024-03-26 08:57:18 -07:00
snipe 89d733d442 Merge remote-tracking branch 'origin/develop' 2024-03-26 14:53:24 +00:00
snipe df49e8350f Merge pull request #14498 from snipe/features/limit_report_by_admin
Fixed #14495 - Allow user_id to be passed to limit to only specific admins
2024-03-26 14:52:03 +00:00
snipe 3ced85080a Fixed #14495 - Allow user_id to be passed to limit to only specific admins
Signed-off-by: snipe <snipe@snipe.net>
2024-03-26 14:45:20 +00:00
snipe 0611ab9b4c Merge remote-tracking branch 'origin/develop' 2024-03-26 12:29:39 +00:00
snipe f450cafe3e Fixed missing div
Signed-off-by: snipe <snipe@snipe.net>
2024-03-26 12:29:25 +00:00
snipe 1f29eb1875 Merge pull request #14494 from snipe/features/add_supplier_address_to_licenses
Added supplier details to license view
2024-03-26 12:20:57 +00:00
snipe a4e5ae0938 Removed duplicates
Signed-off-by: snipe <snipe@snipe.net>
2024-03-26 12:20:27 +00:00
snipe 77dacfcc30 Show if deleted supplier
Signed-off-by: snipe <snipe@snipe.net>
2024-03-26 12:19:29 +00:00
snipe 0d9b6eaf71 Added supplier details to license view
Signed-off-by: snipe <snipe@snipe.net>
2024-03-26 12:18:04 +00:00
snipe 7060ffaf34 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
#	public/js/dist/bootstrap-table.js
#	public/mix-manifest.json
2024-03-26 11:17:07 +00:00
snipe 02a37e2f89 Bumped hash
Signed-off-by: snipe <snipe@snipe.net>
2024-03-26 10:16:46 +00:00
snipe 9c1b1bc2b5 Removed fre-order columns - it’s not currently used
Signed-off-by: snipe <snipe@snipe.net>
2024-03-26 10:15:46 +00:00
snipe b34156ca25 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/js/dist/bootstrap-table.js
#	public/mix-manifest.json
2024-03-26 09:58:35 +00:00
snipe 61bdb57b5d Merge pull request #14492 from snipe/feature/sc-25142/deeplink_search_urls
Fixed #14483 - adds deeplinking to search/sort/pagination
2024-03-26 09:55:50 +00:00
snipe 9df84e235c Check for config variable
Signed-off-by: snipe <snipe@snipe.net>
2024-03-26 09:54:40 +00:00
snipe 566ba4783e Fixed #14483 - adds deeplinking to search/sort/pagination
Signed-off-by: snipe <snipe@snipe.net>
2024-03-26 09:50:01 +00:00
snipe b41b4b1732 Merge remote-tracking branch 'origin/develop' 2024-03-26 08:48:44 +00:00
snipe ccf9457c45 Merge pull request #14491 from PP-JN-RL/patch-1
Added Dymo Labelwriter 1933081
2024-03-26 08:46:03 +00:00
snipe 53aabdab66 Merge remote-tracking branch 'origin/develop' 2024-03-26 08:33:40 +00:00
snipe 8ff85c952e Fixed labelwriter 2112283 namespace
Signed-off-by: snipe <snipe@snipe.net>
2024-03-26 08:33:30 +00:00
Phil J R afe1cb8234 Create LabelWriter_1933081.php
Added a longer version of the existing label (25 x 54mm vs. 25 x 89mm) due to better availability and to support longer asset names.
2024-03-26 08:29:47 +00:00
snipe bd42505799 Merge remote-tracking branch 'origin/develop' 2024-03-26 08:23:40 +00:00
snipe 6c735c97c6 Merge pull request #14490 from snipe/bug/sc-25141/bad_method_call_model_restore_from_view
Fixed #14482 - bad method call model restore from view
2024-03-26 08:21:27 +00:00
snipe 31a57cdf14 Fixed #14482 - bad method call on restore from view
Signed-off-by: snipe <snipe@snipe.net>
2024-03-26 08:18:59 +00:00
snipe 7ebbef25e7 Standardize button styling
Signed-off-by: snipe <snipe@snipe.net>
2024-03-26 08:18:36 +00:00
Phil J R f836342194 Rename Label_Writer_2112283.php to LabelWriter_2112283.php
Fix the name of LabelWWriter_2112283 to be consistent with the existing one.
2024-03-26 08:16:00 +00:00
spencerrlongg 5cf1a6c300 new validator for radio buttons 2024-03-25 21:03:13 -05:00
Marcus Moore bd506820b7 Display error message 2024-03-25 17:59:39 -07:00
Marcus Moore 5815607924 Add validation for pwd_secure_complexity 2024-03-25 17:45:41 -07:00
spencerrlongg 9b40c9788f rm commented tests 2024-03-25 18:58:49 -05:00
snipe 67b5e9093e Merge pull request #14488 from marcusmoore/bug/pass-last-audit-date-through-for-validation
Handle badly formatted `last_audit_date` in `StoreAssetRequest`
2024-03-25 20:57:20 +00:00
Marcus Moore 57d1c036ec Improve method name 2024-03-25 13:53:30 -07:00
Marcus Moore 71722b753d Little bit of clean up 2024-03-25 13:49:03 -07:00
Marcus Moore a2625c889a Improve comment 2024-03-25 13:48:32 -07:00
Marcus Moore c98b9da612 Pass last_audit_date through for model level validation if not a date 2024-03-25 13:47:24 -07:00
Marcus Moore 675717ff82 Add failing test 2024-03-25 13:46:22 -07:00
snipe 83ef7c6fe8 Merge pull request #14486 from marcusmoore/bug/sc-25139
Fixes `last_audit_date` not being stored via API correctly
2024-03-25 19:49:54 +00:00
Marcus Moore 5f4c964309 Account for last_audit_date not being provided 2024-03-25 12:45:11 -07:00
Marcus Moore 66ba96d531 Set last_audit_date to valid format in StoreAssetRequest 2024-03-25 12:38:12 -07:00
snipe d67b2da064 Merge pull request #14485 from PP-JN-RL/patch-1
Created Dymo LabelWriter Label 2112283
2024-03-25 16:50:10 +00:00
Phil J R e45fd4088f Created Dymo LabelWriter Label 2112283
I have added the layout for the Dymo LabelWriter 2112283 Labels.
They are: DYMO 2112283 DURABLE SMALL MULTI PURPOSE LABELS (160 LABELS) - 25 X 54MM
2024-03-25 16:31:20 +00:00
spencerrlongg 7e4a0eedf0 rm dumb note 2024-03-25 10:46:26 -05:00
snipe 3f812f696d Merge pull request #14472 from snipe/fixes/last_audit_date_via_api
Added validation for last_audit_date and next_audit_date
2024-03-25 14:35:42 +00:00
Godfrey M 633249b08a user assets get updated when a user changes location 2024-03-21 15:15:40 -07:00
Godfrey M 21c3b1fbd2 rename declined message to note, increased width of textarea 2024-03-21 14:03:25 -07:00
snipe e9e6f925bf Updated validation
Signed-off-by: snipe <snipe@snipe.net>
2024-03-21 18:34:39 +00:00
snipe 828b84084d Added validation for last_audit_date and next_audit_date
Signed-off-by: snipe <snipe@snipe.net>
2024-03-21 18:29:38 +00:00
snipe a6a0bfacc2 Merge remote-tracking branch 'origin/develop' 2024-03-21 18:03:19 +00:00
spencerrlongg 60ca634eff remove interactswithsettings 2024-03-21 12:04:53 -05:00
spencerrlongg be282dd038 resolve a couple issues 2024-03-21 09:26:45 -05:00
snipe c4b7e77498 Merge pull request #14089 from spencerrlongg/bug/escaped_quotes_in_listbox
Use `htmlentities()` instead of `htmlspecialcharacters()` on Custom Field Listbox Values
2024-03-21 12:55:25 +00:00
snipe 91c7180bfd Merge pull request #14469 from snipe/feature/sc-19515/2fa_reset_log
Added 2FA reset log entry
2024-03-21 12:52:22 +00:00
Marcus Moore b368acf941 Implement test case 2024-03-20 17:46:09 -07:00
snipe 7c39f516b9 Merge pull request #14421 from marcusmoore/fixes/add-minimal-validation-around-asset-tags
Adds a minimal amount of validation around asset_tags in AssetsController
2024-03-21 00:04:44 +00:00
snipe ce1ddcfcee Merge pull request #14438 from marcusmoore/chore/sc-25071
Removed the need to add `InteractsWithSettings` to each test case
2024-03-21 00:03:34 +00:00
snipe 945e8b402f Only offer the 2FA reset if the user already has 2FA set up
Signed-off-by: snipe <snipe@snipe.net>
2024-03-20 23:52:51 +00:00
snipe 5ed2bd0fb7 Skip the normal edit observer
Signed-off-by: snipe <snipe@snipe.net>
2024-03-20 23:52:22 +00:00
snipe bc908b854d Added icon
Signed-off-by: snipe <snipe@snipe.net>
2024-03-20 23:44:47 +00:00
snipe 2067b1138a Added the log item
Signed-off-by: snipe <snipe@snipe.net>
2024-03-20 23:43:58 +00:00
snipe 1ffbdee156 Updated 2FA text to not be google authenticator specific
Signed-off-by: snipe <snipe@snipe.net>
2024-03-20 23:43:30 +00:00
snipe bd2812cac1 Added new string
Signed-off-by: snipe <snipe@snipe.net>
2024-03-20 23:43:12 +00:00
snipe f2a5eac256 Tightened up 2FA text
Signed-off-by: snipe <snipe@snipe.net>
2024-03-20 23:43:05 +00:00
snipe b4e647dbd1 Merge remote-tracking branch 'origin/develop' 2024-03-20 21:31:04 +00:00
Marcus Moore 530291f81c Implement some tests 2024-03-20 14:28:27 -07:00
snipe de18e449a6 Merge pull request #14464 from snipe/features/toggle_all_columns
Added "toggle all" to column selector
2024-03-20 21:26:23 +00:00
snipe dce19e0bea Set names and actions to switchable = false
Signed-off-by: snipe <snipe@snipe.net>
2024-03-20 21:25:50 +00:00
snipe 1f586d3102 Removed data-show-columns-toggle-all data attribute
Signed-off-by: snipe <snipe@snipe.net>
2024-03-20 21:25:16 +00:00
snipe e5d01170d2 Fixed locale, added showColumnsToggleAll and minimumCountColumns
Signed-off-by: snipe <snipe@snipe.net>
2024-03-20 21:24:59 +00:00
Marcus Moore 393dc51167 Add assertions around the event dispatch 2024-03-20 13:44:26 -07:00
spencerrlongg 8cc1397ace rm a couple unnecessary 2024-03-20 15:36:53 -05:00
Marcus Moore 984cc7a4f2 Scaffold tests around asset checkout via web 2024-03-20 13:29:25 -07:00
spencerrlongg e7b9903341 delete some extra lines 2024-03-20 15:29:06 -05:00
spencerrlongg e3e01e07b1 final cleanup 2024-03-20 15:23:45 -05:00
spencerrlongg d18aa1db98 some more cleanup + tests 2024-03-20 15:18:15 -05:00
snipe 0f11963127 Merge remote-tracking branch 'origin/develop' 2024-03-20 19:01:03 +00:00
snipe d8378f2a10 Merge pull request #14468 from snipe/features/added_default_location_to_print_all_assigned
Added default location to print all assigned
2024-03-20 18:57:01 +00:00
snipe a0a5480c97 Added default location to print all assigned
Signed-off-by: snipe <snipe@snipe.net>
2024-03-20 18:55:47 +00:00
spencerrlongg c155e4a7c9 new test for not found assets 2024-03-20 13:52:22 -05:00
spencerrlongg fdf0be09db all tests passing 2024-03-20 13:43:01 -05:00
spencerrlongg e1addc5aef oops, typo from conflict resolve 2024-03-20 13:16:36 -05:00
Spencer Long b4b4927370 Merge branch 'develop' into bug/sc-24884 2024-03-20 12:36:39 -05:00
snipe 3391108551 Merge remote-tracking branch 'origin/develop' 2024-03-20 12:57:30 +00:00
snipe 52551dad0f Merge pull request #14465 from snipe/features/14460_add_avif_format
Added #14460 add avif format
2024-03-20 12:39:14 +00:00
snipe 321414f6e3 Updated comment
Signed-off-by: snipe <snipe@snipe.net>
2024-03-20 12:38:48 +00:00
snipe 7787fe42c8 Added avif to helpers
Signed-off-by: snipe <snipe@snipe.net>
2024-03-20 12:30:28 +00:00
snipe 3b66912742 Fixed #14460 - added support for avif
Signed-off-by: snipe <snipe@snipe.net>
2024-03-20 12:25:02 +00:00
snipe 278a25c63b Added toggle all to column selector
Signed-off-by: snipe <snipe@snipe.net>
2024-03-20 12:14:41 +00:00
snipe 0d124bb5a1 Fixed indent
Signed-off-by: snipe <snipe@snipe.net>
2024-03-20 12:08:35 +00:00
snipe 417caae589 Added translation
Signed-off-by: snipe <snipe@snipe.net>
2024-03-20 12:07:18 +00:00
snipe 3d306aacc5 Fixed mismatched HTML tag
Signed-off-by: snipe <snipe@snipe.net>
2024-03-20 11:52:51 +00:00
snipe ea4ecaea03 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/css/dist/all.css
#	public/css/dist/bootstrap-table.css
#	public/js/dist/bootstrap-table.js
#	public/mix-manifest.json
2024-03-20 11:04:34 +00:00
snipe 6c90f9e395 Merge pull request #14462 from snipe/fixes/small_ui_tweaks_for_country_dropdown
Wider country dropdown
2024-03-20 11:01:39 +00:00
snipe ddf81ba135 Wider country dropdown
Signed-off-by: snipe <snipe@snipe.net>
2024-03-20 11:00:06 +00:00
snipe 8ebb41caa6 Merge pull request #14461 from snipe/security/update_bs_tables
[Snyk] Upgrade bootstrap-table from 1.22.2 to 1.22.3 #14455
2024-03-20 10:39:05 +00:00
snipe faf48b1684 [Snyk] Upgrade bootstrap-table from 1.22.2 to 1.22.3 #14455
Signed-off-by: snipe <snipe@snipe.net>
2024-03-20 10:37:53 +00:00
snipe b8232d205b Merge pull request #14457 from Godmartinz/bulk_delete_locations_bug
Fixed Bulk delete locations bug
2024-03-20 10:35:45 +00:00
spencerrlongg 0ffceb9691 some notes and a little progress 2024-03-20 00:07:52 -05:00
spencerrlongg 1e810d2426 most tests now passing, still one broken 2024-03-19 19:47:26 -05:00
spencerrlongg c0110e7f29 some more tests and refinement 2024-03-19 19:27:35 -05:00
Godfrey M 62745923cf fixes API location delete 2024-03-19 15:25:28 -07:00
Godfrey M 090466123f add withCount to query instead 2024-03-19 15:18:18 -07:00
Godfrey M 38a3e36cd6 fixes translation usage 2024-03-19 14:32:21 -07:00
Godfrey M e8dc634a40 fixes translation usage 2024-03-19 14:30:53 -07:00
Godfrey M 0d0984a400 Bulk Delete Locations does not work [sc-25100] 2024-03-19 14:26:40 -07:00
spencerrlongg 86ab880c90 buncha progress 2024-03-19 15:34:59 -05:00
akemidx 8640cad033 was using lcoations and not locale. fixed 2024-03-19 16:11:32 -04:00
akemidx dc29717623 fixing default 2024-03-19 15:51:05 -04:00
snipe 814914924f Merge remote-tracking branch 'origin/develop' 2024-03-19 15:51:07 +00:00
snipe c7083488b2 Merge pull request #14447 from snipe/feature/sc-25020_better_print_view
Add additional options to print all assigned view
2024-03-19 15:01:50 +00:00
snipe 4b4d383509 Removed - it’s for another PR
Signed-off-by: snipe <snipe@snipe.net>
2024-03-19 15:00:26 +00:00
Godfrey M b9986033cc removed abbr. of variable, changed variable types in migration 2024-03-18 16:03:40 -07:00
akemidx 3680e04817 migration to set legacy locations to an standardized format 2024-03-18 18:29:59 -04:00
snipe 21e23baa37 Fixed ternary
Signed-off-by: snipe <snipe@snipe.net>
2024-03-18 21:28:46 +00:00
snipe fcd130ae15 Layout improvements
Signed-off-by: snipe <snipe@snipe.net>
2024-03-18 21:17:46 +00:00
Godfrey M 8b52d5da85 fixed typos, reordered jquery, fixed migrations 2024-03-18 12:36:54 -07:00
Marcus Moore d1dffb84dc Remove InteractsWithSettings trait for remaining tests 2024-03-18 12:33:45 -07:00
Marcus Moore 541350916d Merge branch 'develop' into chore/sc-25071
# Conflicts:
#	tests/Feature/Api/Users/UpdateUserApiTest.php
#	tests/Feature/Notifications/AccessoryWebhookTest.php
#	tests/Feature/Notifications/AssetWebhookTest.php
#	tests/Feature/Notifications/ComponentWebhookTest.php
#	tests/Feature/Notifications/ConsumableWebhookTest.php
#	tests/Feature/Notifications/LicenseWebhookTest.php
2024-03-18 12:33:31 -07:00
Godfrey M 01afa9a749 declined notes are reflected in the action logs 2024-03-18 10:50:15 -07:00
Godfrey M 57f5d4a570 deleted_msg saves to db 2024-03-18 10:45:47 -07:00
Godfrey M 4588393b76 adds declined msg to mail notif, updates lang files and checkout acceptance controller 2024-03-18 10:25:55 -07:00
Godfrey M 0fd99d410e adds a text field and jquery to show/hide text field 2024-03-18 09:36:09 -07:00
snipe 002fd4ce30 Nicer formatting for signoff
Signed-off-by: snipe <snipe@snipe.net>
2024-03-18 13:44:51 +00:00
snipe 7b4ecb275f Use trans choice for language
Signed-off-by: snipe <snipe@snipe.net>
2024-03-18 13:29:01 +00:00
snipe 2df5d3a8ff Fixed column selector
Signed-off-by: snipe <snipe@snipe.net>
2024-03-18 13:06:08 +00:00
snipe 7070bad53b 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-03-18 12:32:22 +00:00
snipe da62d6af26 Merge pull request #14445 from snipe/fixes/check_for_valid_license_category_on_view_assets
Make sure the category is still valid before displaying on view assets
2024-03-18 12:30:15 +00:00
snipe d0d4d14787 Make sure the category is still valid before displaying on view assets
Signed-off-by: snipe <snipe@snipe.net>
2024-03-18 12:29:00 +00:00
snipe 09d69b214b Merge pull request #14436 from marcusmoore/chore/sc-24901
Organized notification test cases
2024-03-18 12:20:23 +00:00
snipe 0e2aaebda4 Merge pull request #14406 from mauro-miatello/develop
Hide/Show ecnrypted values when click on the lock icon
2024-03-18 12:19:54 +00:00
snipe ec2c58163f Merge pull request #14437 from marcusmoore/chore/sc-25070
Removed dead test code
2024-03-18 12:19:35 +00:00
Marcus Moore a28bee86ba Extract method 2024-03-14 16:33:49 -07:00
Marcus Moore fb64892971 Re-order 2024-03-14 16:26:27 -07:00
Marcus Moore 95ff692b14 Improve InteractsWithSettings name 2024-03-14 15:06:52 -07:00
Marcus Moore 8003615b1f Move InteractsWithSettings to TestCase 2024-03-14 14:15:11 -07:00
Marcus Moore 948dc3c974 Remove duplicate trait 2024-03-14 13:11:53 -07:00
Marcus Moore 1afb724606 Remove commented (and old) test cases 2024-03-14 13:11:43 -07:00
Marcus Moore 451281d833 Delete test cases with only commented code 2024-03-14 13:11:27 -07:00
Marcus Moore 485f11c945 Move trait usage to parent TestCase 2024-03-14 12:56:49 -07:00
Marcus Moore dbc79655b0 Cleanup 2024-03-14 12:02:56 -07:00
Marcus Moore 02f6aa6161 Add group tag for new test case 2024-03-14 11:19:36 -07:00
Marcus Moore 07c5264b41 Organize email check in notifications test 2024-03-14 11:17:47 -07:00
Marcus Moore 7c178a6a78 Merge branch 'develop' into chore/sc-24901
# Conflicts:
#	tests/Feature/Notifications/AssetWebhookTest.php
2024-03-14 11:13:14 -07:00
snipe f56d53d7c1 Prod assets
Signed-off-by: snipe <snipe@snipe.net>
2024-03-14 17:14:33 +00:00
snipe 4cd4a936d8 Updated dev assets
Signed-off-by: snipe <snipe@snipe.net>
2024-03-14 15:43:47 +00:00
snipe 7bae4c39c6 Merge pull request #14401 from uberbrady/fix_locale_warning
Fix [sc-25008] - correct and improve legacy language warnings
2024-03-14 15:42:28 +00:00
snipe d55d95bbea Merge pull request #14415 from Godmartinz/date_picker_z_order
Fixed z-index of date-picker
2024-03-14 15:39:11 +00:00
snipe 5e48d56561 Merge pull request #14427 from marcusmoore/bug/sc-25014
Removes the unused `mediconesystems/livewire-datatables` package
2024-03-14 15:35:53 +00:00
snipe 6a5098fb0c Merge remote-tracking branch 'origin/develop' 2024-03-14 13:26:38 +00:00
snipe 4e835e1772 Merge pull request #14430 from snipe/bug/sc-25066/fixed_requestable_search
Move requestable scope below sorting, etc
2024-03-14 13:25:44 +00:00
snipe cce8cb4f5e Move requestable scope below sorting, etc
Signed-off-by: snipe <snipe@snipe.net>
2024-03-14 13:24:22 +00:00
Marcus Moore 8aed26aab1 Remove unneeded test cases 2024-03-13 16:56:54 -07:00
Marcus Moore 01d5d4c2c8 Improve data provider name 2024-03-13 16:37:50 -07:00
spencerrlongg f6ab0f8f46 lots of cleanup to do, but this DOES work 2024-03-13 15:57:10 -05:00
spencerrlongg f01b205486 some changes 2024-03-13 15:10:51 -05:00
Marcus Moore 592385cb07 Remove mediconesystems/livewire-datatables package 2024-03-13 11:58:03 -07:00
spencerrlongg 8962ced038 push to switch branches 2024-03-13 10:40:50 -05:00
snipe 85123b3e66 Rework print page
Still seeing a weird error tho, not done yet

Signed-off-by: snipe <snipe@snipe.net>
2024-03-13 12:36:17 +00:00
spencerrlongg 04d7884af8 some more testing stuff 2024-03-12 23:17:40 -05:00
spencerrlongg 6732b6601e some cool progress, but something with unique not working 2024-03-12 18:33:59 -05:00
Marcus Moore 0fcf223960 Add minimal validation for asset_tags 2024-03-12 12:00:10 -07:00
Godfrey M bf0bd06f20 put important back 2024-03-11 15:56:53 -07:00
Godfrey M f07b0b6bd7 removed important 2024-03-11 15:54:59 -07:00
Godfrey M 717b26c834 fixes z-index of date-picker 2024-03-11 15:53:59 -07:00
snipe 8bb8eab69b Merge remote-tracking branch 'origin/develop' 2024-03-11 15:00:38 +00:00
snipe 693d1c9452 Merge pull request #14413 from snipe/fixes/deprecation_on_strtoupper
Fixed deprecation warning on `strtoupper()`
2024-03-11 14:59:55 +00:00
snipe b049bb1d5c Check for null on select
Signed-off-by: snipe <snipe@snipe.net>
2024-03-11 14:55:49 +00:00
snipe c5c6b3bbc6 Starting the revised print page
Signed-off-by: snipe <snipe@snipe.net>
2024-03-11 14:23:25 +00:00
snipe 1df56a7cab Merge pull request #14407 from snipe/bug/sc-25019_added_created_at_pivot
Added created_at to license pivot
2024-03-10 16:40:56 +00:00
snipe 3f5cc2507d Used updated_at instead
Signed-off-by: snipe <snipe@snipe.net>
2024-03-10 16:39:49 +00:00
snipe 5a85424295 Added created_at to license pivot
Signed-off-by: snipe <snipe@snipe.net>
2024-03-10 16:33:04 +00:00
snipe a53a8cca74 Merge remote-tracking branch 'origin/develop' 2024-03-10 14:40:41 +00:00
snipe 3fdee881f9 Merge pull request #14404 from snipe/fixes/Uninitialized-string-offset-0-in-labels
Fixed uninitialized offset in labels in new label engine
2024-03-10 14:40:12 +00:00
snipe a289dfaf88 Cleanup
Signed-off-by: snipe <snipe@snipe.net>
2024-03-10 14:33:53 +00:00
MrM 8abd359b5b Script to hide / show encrypted values in web ui
added a function to show/hide encrypted values with a simple trick because ClipboardJS can't copy display:none element's value
2024-03-10 15:18:54 +01:00
MrM 9359809b4f Hide / Show encrypted values in web ui
added a span element to hide encrypted values
2024-03-10 15:09:46 +01:00
snipe cde5502f94 Handle blank labels on asset label fields
Signed-off-by: snipe <snipe@snipe.net>
2024-03-10 14:03:21 +00:00
spencerrlongg eb8f1dd553 some cleanup 2024-03-09 12:29:26 -06:00
spencerrlongg c8341d9dc4 aha, got it working. 2024-03-08 19:48:47 -06:00
spencerrlongg b239b3a4db some good progress, lots of testing needs to be done on the new inclusion of SubstituteBindings 2024-03-08 18:24:41 -06:00
spencerrlongg 04e0a9d4a5 commented tests for now 2024-03-08 13:14:59 -06:00
snipe 28ec0b8ebb Removed debugging console lines
Signed-off-by: snipe <snipe@snipe.net>
2024-03-08 17:19:31 +00:00
snipe 37dfecf098 Fixed uninitialized offset in labels
Signed-off-by: snipe <snipe@snipe.net>
2024-03-08 16:46:56 +00:00
snipe 9d8ce872a4 Merge remote-tracking branch 'origin/develop' 2024-03-08 14:56:21 +00:00
snipe 07880dfe50 Merge pull request #14400 from snipe/localizations/updated_strings
Updated language strings, added Somali
2024-03-08 14:07:32 +00:00
snipe 7eed9f8542 Added Somali
Signed-off-by: snipe <snipe@snipe.net>
2024-03-08 14:06:21 +00:00
Brady Wetherington a2e70dd6b2 Fix [sc-25008] - correct and improve legacy language warnings
The legacy language warning was misfiring when a user's language
didn't match the APP_LOCALE from .env.

Additionally, we weren't properly warning when the legacy-language
came from Settings or from the user themselves. Both of which should
be impossible but still probably not a bad idea to warn on it, anyways
2024-03-08 14:04:21 +00:00
snipe b9aeded957 Updated strings
Signed-off-by: snipe <snipe@snipe.net>
2024-03-08 14:01:34 +00:00
snipe 7939c691f7 Added Brother 18mm label type
Signed-off-by: snipe <snipe@snipe.net>
2024-03-07 22:04:12 +00:00
spencerrlongg 3a0a13d06d tests written but something not working... 2024-03-05 16:35:06 -06:00
spencerrlongg a251e61d73 rm commented code and add comment 2024-03-05 13:40:44 -06:00
spencerrlongg af06b1cd06 hide encryption option for checkbox and radio 2024-03-05 13:37:30 -06:00
Brady Wetherington 5b9120ba6c Merge branch 'develop' into snipeit_v7_laravel10 2024-03-05 19:22:37 +00:00
spencerrlongg ad0f873ece rm validation stuff 2024-03-05 11:58:00 -06:00
spencerrlongg eac01868ca not all working, but pushing to work on something else 2024-03-05 11:02:55 -06:00
Jeremy Price 8ace30ee23 Update mailer configurations for Symfony mailer
Newer Laravel uses Symfony mailer instead of SwiftMailer, and that means
that some configs and functionality have changed

In this change, we update config/mail.php with the new config layout and
name/functionality changes

of note:

* New configuration layout supporting lots of new/different mailers
* MAIL_DRIVER has become MAIL_MAILER, though we'll support both
* MAIL_ENCRYPTION is mostly useless, and we mark it as such -- symfony
  mailer detects which type of encryption to use automagically.
* MAIL_TLS_VERIFY_PEER is now available in case of self-signed
  certificates on the mail server, of if you want to access it by a
  different name, or by IP

Accordingly, we also update the .env examples, docker configs, and
the .env builder in the snipeit.sh installation script with the above
changes
2024-02-28 23:37:52 -08:00
akemidx eb0657c953 Merge branch 'develop' into bug/sc-24812 2024-02-28 17:22:16 -05:00
Marcus Moore 551354b1bb Add group annotation for tests 2024-02-27 18:05:18 -08:00
Marcus Moore 03b7891edc Remove unneeded factory states 2024-02-27 18:03:53 -08:00
Marcus Moore 8978dff054 Consolidate helpers into trait 2024-02-27 18:01:08 -08:00
Marcus Moore d20844fefa Improve readability by extracting additional helpers 2024-02-27 17:57:12 -08:00
Marcus Moore cd579a04dd Improve readability by extracting fireCheckOutEvent method 2024-02-27 17:52:18 -08:00
Marcus Moore 15b8140bff Fix test helper 2024-02-27 17:48:17 -08:00
Marcus Moore 9a93ad2e06 Remove unneeded factory state 2024-02-27 17:46:27 -08:00
Marcus Moore bd4d3aa52b Improve readability by extracting additional helpers 2024-02-27 17:44:19 -08:00
Marcus Moore bf32ab177f Improve readability by extracting fireCheckInEvent method 2024-02-27 17:37:07 -08:00
Marcus Moore 2ea883aa15 Move Notification::fake() to setUp method 2024-02-27 17:23:30 -08:00
Marcus Moore 43cc296582 Consolidate additional tests 2024-02-27 17:14:35 -08:00
Marcus Moore 4c1aadd74e Improve naming and inline helper 2024-02-27 17:09:22 -08:00
Marcus Moore 7d3719bf70 Consolidate some slack notification tests 2024-02-27 17:07:40 -08:00
Marcus Moore c08164d864 Update test names 2024-02-27 16:48:17 -08:00
Marcus Moore b156aa74a5 Update helper name 2024-02-27 16:45:49 -08:00
akemidx 5ffade663a unstash 2024-02-26 18:41:58 -05:00
spencerrlongg c025e25839 just the basics and notes, pushing to keep track 2024-02-26 14:32:50 -06:00
spencerrlongg b6fa6cba22 note before switching tasks 2024-02-22 15:01:14 -06:00
spencerrlongg 14358651e4 pushing to test other branches 2024-02-22 13:28:23 -06:00
spencerrlongg 20dbacd22f store good, update needs work 2024-02-21 21:33:34 -06:00
Brady Wetherington 8f2843bfcf Merge branch 'develop' into snipeit_v7_laravel10
Had to re-generate composer.lock, and re-do package.json and rebuild assets as well.
2024-02-21 20:22:28 +00:00
akemidx 9397372f87 permissions, but they are now all in their own column because reasons??? 2024-02-20 18:48:17 -05:00
akemidx 8bbf6da052 user block, trying to pick out ONLY permissions we wanna see 2024-02-20 18:25:41 -05:00
spencerrlongg d67ff54f4b temporary decrypt, almost there 2024-02-20 16:20:03 -06:00
spencerrlongg 26728a85ad this seems to work for patches 2024-02-20 13:18:40 -06:00
spencerrlongg c6d85a1b0b allows arrays on checkbox values 2024-02-20 12:23:24 -06:00
spencerrlongg 115e0fc119 implode submitted arrays to save 2024-02-14 13:15:23 -06:00
spencerrlongg 1ceb703129 rm var 2024-02-14 12:44:09 -06:00
spencerrlongg fb28882f65 trim potential spaces 2024-02-14 11:59:14 -06:00
spencerrlongg d9c61fdb02 validation msg 2024-02-14 11:52:25 -06:00
spencerrlongg 72c118a70f cleanup 2024-02-14 11:41:46 -06:00
spencerrlongg 25241542d2 progress, going to sleep 2024-02-14 02:12:31 -06:00
spencerrlongg 57a75e68b9 maybe i do the inverse here? 2024-02-14 00:52:50 -06:00
spencerrlongg dcf2168454 initial stuff, need to switch branches 2024-02-13 19:35:37 -06:00
akemidx c5e8d1c276 custom report tinker 2024-02-13 17:09:51 -05:00
akemidx 4093327b7f adding in Last Checkin Date to Hardware view and index 2024-02-13 16:52:12 -05:00
spencerrlongg d55358652b cleanup for pr 2024-02-13 13:45:56 -06:00
akemidx f7d0cecdac permissions query starto 2024-02-12 19:01:06 -05:00
spencerrlongg bcfa913450 condition makes this work, needs more testing 2024-02-07 20:03:37 -06:00
spencerrlongg 43d8474caa a note to remember this tomorrow 2024-02-06 17:45:46 -06:00
Brady Wetherington 8a2f3405d5 Merge branch 'develop' into snipeit_v7_laravel10
A lot of changes here, but hopefully this works?
2024-01-29 22:12:58 +00:00
spencerrlongg 1248260df3 i don't think the output needs to separately escaped, the entire statement is already wrapped in {{}} 2024-01-26 12:33:35 -06:00
spencerrlongg 4cb804cf03 get rid of e() on store and update 2024-01-26 11:56:02 -06:00
spencerrlongg 2b0dd8851c probably needs more testing... but should work 2024-01-26 11:47:09 -06:00
snipe 25db35e41e Merge pull request #14128 from snipe/jerm/upgrade-dot-php
Add remote requirements checking to upgrade.php
2024-01-24 13:23:10 +00:00
snipe 99000fada1 Merge pull request #14127 from snipe/jerm/upgrade-deps-file
Add php version requirements file for future-proofing upgrades
2024-01-17 13:15:56 +00:00
Jeremy Price 58b2f8ca17 typo 2024-01-11 19:12:24 -08:00
Jeremy Price 8be3c1aaf2 Quit the script when we hit hard errors
a found a few other points where we talk about exiting and re-running
the script once fixed, but never actually exit. So i'm adding-in the
missing exits, and updating any existing exits to make sure we return a
failing return code to the shell
2024-01-11 18:20:09 -08:00
Jeremy Price 2ee8639eaf Check to make sure there's a .env file
While i was testing this, i noticed that it ran right by the .env check,
even though i don't have a .env file at all. The script checks for a
_bad_ .env, but not a missing one.

Now it does
2024-01-11 18:18:41 -08:00
Jeremy Price 32605578dd Add remote requirements checking to upgrade.php
quoted from https://github.com/snipe/snipe-it/pull/14127
    There is a race condition in the upgrade.php file where it can't
    currently know the hard requirements for the version it's upgrading to
    until it does a git pull. By that time, it will have pulled new source
    code that possibly relies on an incompatible version of php, leaving you
    with a broken installation.

    Example: You're running v6.2.x on PHP 7.4, which is fine. v7 requires
    PHP 8.1 or 8.2, but we couldn't know that when we released v6. or v5 for
    that matter. We could change the requirements in the most-recent v6
    version of upgrade.php, but that doesn't help anyone who doesn't upgrade
    first to the most recent v6.

With this change, we implement fetching and incorporating the
requirements data from the remote file.

It's just fetching/decoding a couple of json values that replace the
hard-coded version requirements.

We move the branch checking higher than the php version checking so that
we can use the defined/overridden $branch to decide what branch to pull
the requirements from.
2024-01-11 18:13:59 -08:00
Jeremy Price fe0bba6df6 rename upgrade requirements file and add snipeit version differentiation
the latter mostly for testing and san checking.. but it doesn't really
matter because it's just json.. if we don't use it we don't use it
2024-01-11 16:52:39 -08:00
Jeremy Price 5fdcd6298f rename php_max_major, because it's not.. it's major_minor, even if it sounds ridiculous 2024-01-11 16:50:16 -08:00
Jeremy Price 55943dbff6 add comments and php_max_wontwork because that's what we use rigth now and MVP, dammit 2024-01-11 16:47:47 -08:00
Jeremy Price d12e571b20 undoing versioning.. doesn't make sense 2024-01-11 16:32:17 -08:00
Jeremy Price 0c15f05316 Initial upgrade_requirements.json file
for fetching before upgrades, to check major prereqs -- mainly php -- before
pulling down new, possibly breaking, code.
2024-01-11 16:27:03 -08:00
Jermops 25c9f8e038 Merge pull request #14105 from snipe/jerm/snipeit-sh
Update snipeit.sh for v7 Requirements
2024-01-08 11:48:21 -08:00
Jeremy Price a3811371cc remove removal of installation scripts 2024-01-08 11:41:30 -08:00
Brady Wetherington f734e196e5 Merge branch 'develop' into snipeit_v7_laravel10 2024-01-08 18:57:55 +00:00
Jeremy Price 6129f4722f Oops! Don't checkout my custom branch
using master until we make the switch to main. As master will keep
working after we switch branches, main will _not_ work _until_ we switch, and if
for some reason we have to delay the branch migration, this will remain
broken until we fix it.
2024-01-08 10:08:52 -08:00
Jeremy Price 585d7d0b87 replace some tabs with spaces. don't @ me 2024-01-05 12:09:03 -08:00
Jeremy Price cdfc198f28 update changelog 2024-01-05 00:09:06 -08:00
Jeremy Price 6fcb3d3d5e re-add missing progress bar to ensure correct command ordering 2024-01-05 00:09:06 -08:00
Jeremy Price 358d9ec06d fix enterprise linux version in remi repo for v9 distros 2024-01-05 00:09:06 -08:00
Jeremy Price 322c8c1cf3 install php-sodium on al2. fix snipeit database name 2024-01-05 00:09:06 -08:00
Jeremy Price 47eb0c34a2 remove fedora surpport, add amazon and alma 2024-01-05 00:09:06 -08:00
Jeremy Price 4a290a85e6 awsl2 support, php8.2 support in centos/alma, new mysql user creation code 2024-01-05 00:09:06 -08:00
Jeremy Price 5489c50cc0 remove remaining 8.2 references in Ubuntu 23* block
different vim config confusion made my regex misbehave :-/
2024-01-05 00:09:06 -08:00
Jeremy Price 066e40dada update Ubuntu versions comment in code block 2024-01-05 00:09:06 -08:00
Jeremy Price 123d04ff7b split-out ubuntu 23* versions
since 2023 didn't produce and LTS ubuntu versions

the Ondrej repo we use for installing arbitrary PHP versions doesn't
(easily) support non-LTS versions of ubuntu, which means that 23.04 and
23.10 are problematic using the repo

However, these versions ship with  php8.1 and php8.2 (respectively), so
we don't even need the Ondrej repo for these, so we'll remove it

In general, we'll only support LTS Ubuntu repos because of this, but if
they happen to ship with our preferred PHP versions and otherwise work
w/o heroics, we'll include nominal support in the script
2024-01-05 00:09:06 -08:00
Jeremy Price d5881736cf stop quoting run_as_app_user args
because "$@" splits positional parameters, but quoting the args makes
them one arg, which doesn't work
2024-01-05 00:09:06 -08:00
Jeremy Price 5e539da3da Debian 12 2024-01-05 00:09:06 -08:00
Jeremy Price ba58ca9d5c fix up ondrej repo 2024-01-05 00:09:06 -08:00
Jeremy Price 117007dfa1 add new ubuntu/debian versions, change php to 8.2 2024-01-05 00:09:06 -08:00
snipe d29b3633d1 Merge pull request #14063 from marcusmoore/chore/sc-24353
Removed unused files in assets directory
2024-01-04 22:41:49 +00:00
spencerrlongg 41e0275c95 htmlentities() 2024-01-03 12:42:36 -06:00
Marcus Moore 7cf4baa92a Remove unused vendor less from resources directory 2023-12-18 17:58:47 -08:00
Marcus Moore 6c3dfdfe6d Remove unused vendor css files 2023-12-18 17:48:52 -08:00
Marcus Moore 149d159c05 Remove unused bootstrap resources 2023-12-18 11:49:52 -08:00
Marcus Moore c0ad16f497 Remove unused vendor js files 2023-12-18 11:48:28 -08:00
snipe 9edb631d52 Merge pull request #14024 from spencerrlongg/chore/last_vue_component
Last Vue Components
2023-12-13 04:35:35 +00:00
spencerrlongg 58d2f0a41e quick note 2023-12-12 15:49:57 -06:00
spencerrlongg 255d9427b6 make edit a button 2023-12-12 15:41:29 -06:00
spencerrlongg d29f4489de fix 2023-12-12 14:09:12 -06:00
spencerrlongg 4367fc54bf remove vue from webpack steps 2023-12-12 13:43:05 -06:00
spencerrlongg b89116eb55 submit on enter for edit 2023-12-12 13:33:51 -06:00
spencerrlongg 9430e9c8e2 autofocus, package-lock.json 2023-12-12 13:28:04 -06:00
spencerrlongg b01d53a247 one more 2023-12-11 18:43:46 -06:00
spencerrlongg 65cbba3c2e completely kill vue 2023-12-11 18:09:22 -06:00
spencerrlongg f93e7b91ff that's all folks 2023-12-06 16:20:30 -06:00
spencerrlongg 04069bab82 remove comment 2023-12-05 20:50:07 -06:00
spencerrlongg 3106035ef9 delete, comment 2023-12-05 20:41:34 -06:00
spencerrlongg 18720b3302 safety stuff 2023-12-05 20:36:59 -06:00
spencerrlongg 12e546e63a everything working, cleanup 2023-12-05 20:22:20 -06:00
spencerrlongg c28936fefb almost there... problem with update button 2023-12-05 17:39:35 -06:00
spencerrlongg 080d196138 buttons work now after style tags removed 2023-12-05 16:41:25 -06:00
spencerrlongg d3967b37cd this is a start, buttons not working? 2023-12-05 14:52:14 -06:00
snipe 0089ea2321 Merge pull request #13882 from marcusmoore/fixes/jquery-validation
Fix client side validation in the v7 branch
2023-12-05 17:26:48 +00:00
snipe 3f35124838 Merge pull request #13888 from spencerrlongg/chore/sc-16907
Convert Vue Personal Access Tokens to Livewire
2023-12-05 16:45:16 +00:00
spencerrlongg 6ca5fb6b20 remove token scope html 2023-12-05 09:44:03 -06:00
Marcus Moore a3b0273445 Remove comment 2023-12-04 15:21:04 -08:00
akemidx 2a54797dce permission level proof of formatting 2023-11-28 17:58:37 -05:00
akemidx 9770016eec beginning of permission groups export 2023-11-28 17:47:36 -05:00
Brady Wetherington 6210716199 Merge branch 'develop' into snipeit_v7_laravel10 2023-11-27 13:04:39 +00:00
akemidx 697595d963 Merge branch 'develop' into eol_date_range_for_reports 2023-11-21 16:07:26 -05:00
snipe e41a16dbf3 Merge pull request #13879 from Godmartinz/location_search_bug
added user location scope
2023-11-19 07:01:59 +00:00
Godfrey M 01f4aa018f fixed query 2023-11-16 11:20:14 -08:00
Godfrey M f9baeefbaf allows to search full name 2023-11-16 11:14:42 -08:00
spencerrlongg af3417d6cc add return type 2023-11-16 11:42:37 -06:00
spencerrlongg 17bf8d0124 fix string 2023-11-16 11:31:00 -06:00
spencerrlongg c3e02286d3 i can't blame this on livewire - animations or something? 2023-11-16 11:24:54 -06:00
spencerrlongg a9d82bf157 enter working 2023-11-16 10:54:32 -06:00
spencerrlongg e097df912e a little cleanup 2023-11-15 22:35:20 -06:00
spencerrlongg 477bb6165f rm log 2023-11-15 20:45:04 -06:00
Spencer Long 19850e8c5a Merge branch 'snipeit_v7_laravel10' into chore/sc-16907 2023-11-15 20:37:15 -06:00
spencerrlongg 12dcf76da9 more cleanup 2023-11-15 20:33:44 -06:00
spencerrlongg 36aac328e4 delete vue component 2023-11-15 20:32:22 -06:00
spencerrlongg 9cf81c7ad4 cleanup, validation 2023-11-15 20:29:14 -06:00
spencerrlongg 6c6417e595 ok, maybe i do like livewire 2023-11-15 20:19:03 -06:00
spencerrlongg efa8ba5965 nice, just need frontend work now 2023-11-15 17:24:54 -06:00
spencerrlongg fd02385c22 deleted components i've already rebuilt in livewire 2023-11-15 17:14:09 -06:00
spencerrlongg 713b21de14 note 2023-11-15 16:56:08 -06:00
spencerrlongg af144a5184 cleanup 2023-11-15 16:55:21 -06:00
spencerrlongg 9b31ae3146 create mostly working 2023-11-15 16:51:09 -06:00
spencerrlongg 4cb0012872 cleanup 2023-11-15 16:33:16 -06:00
spencerrlongg eaa68327f7 SINGLE QUOTES 2023-11-15 16:27:01 -06:00
Marcus Moore 68ef618028 Run validation on blur 2023-11-14 16:30:29 -08:00
Marcus Moore 3ecdafa685 Add class to error placement check 2023-11-14 16:12:47 -08:00
Marcus Moore 20ae9dea19 Fix placement of error message 2023-11-14 15:55:15 -08:00
Godfrey M c9d46856a3 added name back 2023-11-14 15:00:11 -08:00
Godfrey M 6d65f6646f allows validation to ignore self and update 2023-11-14 14:55:51 -08:00
Marcus Moore 34cd106357 Apply validation 2023-11-14 12:25:18 -08:00
Marcus Moore 714fce7e59 Add site name validation test 2023-11-14 12:23:58 -08:00
Marcus Moore 08e4ea384e Update additional partials for validation 2023-11-14 12:23:46 -08:00
Marcus Moore fe0f9743d3 Update additional partials for validation 2023-11-14 12:07:37 -08:00
Godfrey M 57019e170f adds user location scope, still needs fine tuning 2023-11-14 11:49:00 -08:00
spencerrlongg 9f303cc116 playing around with livewire 2023-11-14 11:50:27 -06:00
spencerrlongg e504b20235 couple small changes 2023-11-14 11:01:38 -06:00
Brady Wetherington f64b0d3818 Merge branch 'develop' into snipeit_v7_laravel10 2023-11-14 16:00:29 +00:00
Marcus Moore 1a26ea0911 Update a couple more fields for new validation 2023-11-13 19:18:04 -08:00
Marcus Moore 7098ab6509 Match styling of existing error messages 2023-11-13 18:54:51 -08:00
Marcus Moore 0d3589ca24 Update create asset page to use new validation library 2023-11-13 18:17:39 -08:00
Marcus Moore f02ff62a08 Install jquery-validation package 2023-11-13 18:15:18 -08:00
spencerrlongg fbfc817c5f just some cleanup 2023-11-13 19:47:03 -06:00
snipe 13601031cb Merge pull request #13764 from Godmartinz/expiring-alerts-fix
Fixed the `getExpiringLicenses` query
2023-11-13 20:39:29 +00:00
snipe 442cad69a7 Merge pull request #13864 from marcusmoore/chore/sc-24012
Fixed GitHub Action tests for v7
2023-11-13 16:34:35 +00:00
Marcus Moore be6545a366 Merge Laravel setup steps 2023-11-09 15:55:04 -08:00
Marcus Moore 32fdd36802 Run migrations 2023-11-09 15:51:30 -08:00
Marcus Moore fbc54526ed Set variables for Passport install step 2023-11-09 15:47:52 -08:00
Marcus Moore a3306e4a81 Install Passport during test setup process specifying the environment 2023-11-09 15:41:22 -08:00
Marcus Moore 3d858b21fa Revert "Install Passport during test setup process"
This reverts commit 690a5119f4.
2023-11-09 15:29:31 -08:00
Marcus Moore 62b557f82c Revert "Add database migration step"
This reverts commit 65e3696029.
2023-11-09 15:29:19 -08:00
Marcus Moore 158c82ff5f Revert "Be explicit about database host"
This reverts commit fd410c0281.
2023-11-09 15:26:50 -08:00
Marcus Moore fd410c0281 Be explicit about database host 2023-11-09 15:20:41 -08:00
Marcus Moore 65e3696029 Add database migration step 2023-11-09 14:56:32 -08:00
Marcus Moore 690a5119f4 Install Passport during test setup process 2023-11-09 14:49:56 -08:00
Marcus Moore cc0653c68a Update GitHub test action to run on PHP 8.1 and 8.2 2023-11-09 14:42:47 -08:00
Marcus Moore 042a15d294 Set minimum PHP version to 8.1 2023-11-09 14:41:13 -08:00
spencerrlongg 8e4c0f60a1 return format 2023-11-08 17:36:54 -06:00
spencerrlongg 5615fc09e6 add view modal 2023-11-08 16:55:29 -06:00
spencerrlongg d68f1e4cfa initial display work done 2023-11-08 16:48:20 -06:00
spencerrlongg 0c4901487d delete component class (for now) 2023-11-08 16:12:01 -06:00
spencerrlongg 7f4b2d6e42 modal and initial stuff working 2023-11-08 16:10:09 -06:00
spencerrlongg 715a49d9fe update php in composer.json 2023-11-08 14:29:06 -06:00
Godfrey M b98c1a0627 fixes getExpiringLicenses query 2023-10-18 13:25:34 -07:00
snipe da30292d84 Merge pull request #13763 from Godmartinz/snipeit_v7_laravel10
fixed the bulk edit button on Asset tab
2023-10-18 18:51:41 +01:00
Godfrey M 7bda5c06de fixes the bulk edit button on Asset tab 2023-10-18 10:46:47 -07:00
Brady Wetherington 3d5847f4b3 Merge branch 'develop' into snipeit_v7_laravel10 2023-10-16 23:37:13 +01:00
Brady Wetherington db400dffb5 Merge branch 'develop' into snipeit_v7_laravel10
Rebuild assets and re-install from npm
2023-10-16 20:13:59 +01:00
snipe 199cdf6899 Commented out noisy debugging
Signed-off-by: snipe <snipe@snipe.net>
2023-10-16 20:05:11 +01:00
snipe 752171d5b8 Use singleton for offset
Signed-off-by: snipe <snipe@snipe.net>
2023-10-16 20:05:11 +01:00
Brady Wetherington 7a5714cc85 Merge branch 'develop' into snipeit_v7_laravel10 2023-10-03 20:37:17 +01:00
Brady Wetherington c77f5eee8c Merge branch 'develop' into snipeit_v7_laravel10 2023-09-12 12:04:42 +01:00
Brady Wetherington aacfed40f8 Switch back to our fork of laravel-scim-server 2023-09-07 20:16:03 +01:00
Brady Wetherington ec1059e74c Merge branch 'develop' into snipeit_v7_laravel10 2023-09-07 20:11:41 +01:00
Brady Wetherington 3500217f94 Merge branch 'develop' into snipeit_v7_laravel10 2023-08-31 13:07:06 +01:00
Brady Wetherington 427f8b1522 Merge branch 'develop' into snipeit_v7_laravel10
Upgraded composer due to lockfile conflicts
2023-08-28 16:04:21 +01:00
Brady Wetherington 8b52bad16f Merge branch 'develop' into snipeit_v7_laravel10 2023-08-15 21:25:16 +01:00
akemidx 0bdd8a5917 fixing key names 2023-08-02 16:40:38 -04:00
Brady Wetherington daed0b60bc Merge branch 'develop' into snipeit_v7_laravel10 2023-07-31 19:40:56 +01:00
Brady Wetherington 4654f7aa37 Porting Snipe-IT v7 to Laravel v10 2023-07-31 14:07:12 +01:00
Brady Wetherington 70e87dad1c Merge branch 'develop' into snipeit_v7 2023-07-27 16:21:31 +01: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
Brady Wetherington ba8d8a6f05 Merge branch 'develop' into snipeit_v7 2023-07-20 17:16:04 +01:00
Brady Wetherington 605d267fe8 Merge branch 'develop' into snipeit_v7 2023-07-19 11:47:51 +01: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
Brady Wetherington 8f2a17585e Merge branch 'develop' into snipeit_v7
Had to do a lot of conflict work here, so this could get ugly :(
2023-07-10 16:53:35 +01:00
Brady Wetherington 51424d01a9 Merge branch 'develop' into snipeit_v7 2023-06-28 14:25:33 +01:00
Brady Wetherington f5ff9b2208 Merge branch 'develop' into snipeit_v7 - 2023-06-12 2023-06-12 16:56:23 +01:00
ak-piracha 457f4c410a add check for default consumable qty 2023-05-21 23:11:03 +09:30
ak-piracha bb013d5c3c Bulk Consumable Checkout 2023-05-21 22:49:00 +09:30
Brady Wetherington a9c7dbd17a Shift PHP version requiremeents for Snipe-IT v7 to be php 8.0-8.2 2023-05-17 17:51:02 -07:00
Brady Wetherington 09fdc946a0 Merge branch 'develop' into snipeit_v7
Had to do some asset rebuilds, and a composer update
2023-05-17 17:37:10 -07:00
snipe 31f1bce16b Merge pull request #12958 from uberbrady/snipeit_v7_merge_develop_05_01_2022
Snipeit v7 merge develop 05 01 2022
2023-05-03 10:40:18 -07:00
Brady Wetherington 2f3ddaec20 Merge branch 'develop' into snipeit_v7 2023-05-01 18:09:12 -07:00
snipe 7cd37e6e95 Merge pull request #12957 from uberbrady/fix_webpack_for_v7
Fix webpack for v7
2023-05-01 18:08:46 -07:00
Brady Wetherington a938009074 Rebuilt assets with new Node and node_modules and package.json 2023-05-01 18:06:51 -07:00
Brady Wetherington 21d08ff742 Whoops! Forgot to commit this before 2023-05-01 18:05:06 -07:00
snipe da8b41b12a Merge pull request #12956 from uberbrady/upgrade_node_and_packages_for_v7
Updated Node version, and various packages to more recent
2023-05-01 17:33:20 -07:00
Brady Wetherington 6e031727fa Updated Node version, and various packages to more recent 2023-05-01 17:05:10 -07:00
Brady Wetherington 381890b578 Merge branch 'develop' into laravel_v9 2023-04-27 13:56:04 -07:00
Brady Wetherington 71fa6d765f Update to Latest Livewire files 2023-04-18 11:05:35 -07:00
Brady Wetherington 9793130f6c Merge branch 'develop' into laravel_v9 2023-04-18 11:01:00 -07:00
Brady Wetherington aadfa9aa9c Back out Laravel Vite stuff - we're so far away from that right now 2023-02-21 19:54:14 -08:00
Brady Wetherington 645bba96cd WIP: First stabs at getting Laravel Vite to work; no luck so far :(
Probably going to back out all the 'vite' stuff anyways :/
2023-02-21 19:35:37 -08:00
3601 changed files with 379442 additions and 145935 deletions
+199
View File
@@ -3018,6 +3018,205 @@
"contributions": [
"code"
]
},
{
"login": "koiakoia",
"name": "koiakoia",
"avatar_url": "https://avatars.githubusercontent.com/u/60405354?v=4",
"profile": "https://github.com/koiakoia",
"contributions": [
"code"
]
},
{
"login": "mustafa-online",
"name": "Mustafa Online",
"avatar_url": "https://avatars.githubusercontent.com/u/5323832?v=4",
"profile": "https://github.com/mustafa-online",
"contributions": [
"code"
]
},
{
"login": "franceslui",
"name": "franceslui",
"avatar_url": "https://avatars.githubusercontent.com/u/104601439?v=4",
"profile": "https://github.com/franceslui",
"contributions": [
"code"
]
},
{
"login": "Q4kK",
"name": "Q4kK",
"avatar_url": "https://avatars.githubusercontent.com/u/125313163?v=4",
"profile": "https://github.com/Q4kK",
"contributions": [
"code"
]
},
{
"login": "squintfox",
"name": "squintfox",
"avatar_url": "https://avatars.githubusercontent.com/u/55590532?v=4",
"profile": "https://github.com/squintfox",
"contributions": [
"code"
]
},
{
"login": "jeffclay",
"name": "Jeff Clay",
"avatar_url": "https://avatars.githubusercontent.com/u/1380084?v=4",
"profile": "https://github.com/jeffclay",
"contributions": [
"code"
]
},
{
"login": "PP-JN-RL",
"name": "Phil J R",
"avatar_url": "https://avatars.githubusercontent.com/u/52716446?v=4",
"profile": "https://github.com/PP-JN-RL",
"contributions": [
"code"
]
},
{
"login": "chandanchowdhury",
"name": "i_virus",
"avatar_url": "https://avatars.githubusercontent.com/u/1496725?v=4",
"profile": "https://www.corelight.com/",
"contributions": [
"code"
]
},
{
"login": "gitgrimbo",
"name": "Paul Grime",
"avatar_url": "https://avatars.githubusercontent.com/u/1020541?v=4",
"profile": "https://github.com/gitgrimbo",
"contributions": [
"code"
]
},
{
"login": "LeePorte",
"name": "Lee Porte",
"avatar_url": "https://avatars.githubusercontent.com/u/922815?v=4",
"profile": "https://leeporte.co.uk",
"contributions": [
"code"
]
},
{
"login": "bryanlopezinc",
"name": "BRYAN ",
"avatar_url": "https://avatars.githubusercontent.com/u/23613427?v=4",
"profile": "https://github.com/bryanlopezinc",
"contributions": [
"code",
"test"
]
},
{
"login": "U-H-T",
"name": "U-H-T",
"avatar_url": "https://avatars.githubusercontent.com/u/64061710?v=4",
"profile": "https://github.com/U-H-T",
"contributions": [
"code"
]
},
{
"login": "Tyree",
"name": "Matt Tyree",
"avatar_url": "https://avatars.githubusercontent.com/u/5395363?v=4",
"profile": "https://github.com/Tyree",
"contributions": [
"doc"
]
},
{
"login": "FlorentDotMe",
"name": "Florent Bervas",
"avatar_url": "https://avatars.githubusercontent.com/u/292081?v=4",
"profile": "http://spoontux.net",
"contributions": [
"code"
]
},
{
"login": "dbakan",
"name": "Daniel Albertsen",
"avatar_url": "https://avatars.githubusercontent.com/u/4498077?v=4",
"profile": "https://ditscheri.com",
"contributions": [
"code"
]
},
{
"login": "r-xyz",
"name": "r-xyz",
"avatar_url": "https://avatars.githubusercontent.com/u/100710244?v=4",
"profile": "https://github.com/r-xyz",
"contributions": [
"code"
]
},
{
"login": "DrekiDegga",
"name": "Steven Mainor",
"avatar_url": "https://avatars.githubusercontent.com/u/47491036?v=4",
"profile": "https://github.com/DrekiDegga",
"contributions": [
"code"
]
},
{
"login": "arne-kroeger",
"name": "arne-kroeger",
"avatar_url": "https://avatars.githubusercontent.com/u/65785975?v=4",
"profile": "https://github.com/arne-kroeger",
"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"
]
}
]
}
+168
View File
@@ -0,0 +1,168 @@
# --------------------------------------------
# REQUIRED: DB SETUP
# --------------------------------------------
# https://mariadb.com/kb/en/mariadb-server-docker-official-image-environment-variables/
MYSQL_DATABASE=snipeit
MYSQL_USER=snipeit
MYSQL_PASSWORD=changeme1234
MYSQL_ROOT_PASSWORD=changeme1234
# --------------------------------------------
# REQUIRED: BASIC APP SETTINGS
# --------------------------------------------
APP_ENV=develop
APP_DEBUG=false
# please regenerate the APP_KEY value by calling `docker-compose run --rm snipeit bash` and then `php artisan key:generate --show` and then copy paste the value here
APP_KEY=base64:3ilviXqB9u6DX1NRcyWGJ+sjySF+H18CPDGb3+IVwMQ=
APP_URL=http://localhost:8000
APP_TIMEZONE='UTC'
APP_LOCALE=en
MAX_RESULTS=500
# --------------------------------------------
# REQUIRED: UPLOADED FILE STORAGE SETTINGS
# --------------------------------------------
PRIVATE_FILESYSTEM_DISK=local
PUBLIC_FILESYSTEM_DISK=local_public
# --------------------------------------------
# REQUIRED: DATABASE SETTINGS
# --------------------------------------------
DB_CONNECTION=mysql
DB_HOST=mariadb
DB_DATABASE=snipeit
DB_USERNAME=snipeit
DB_PASSWORD=changeme1234
DB_PREFIX=null
DB_DUMP_PATH='/usr/bin'
DB_CHARSET=utf8mb4
DB_COLLATION=utf8mb4_unicode_ci
# --------------------------------------------
# OPTIONAL: SSL DATABASE SETTINGS
# --------------------------------------------
DB_SSL=false
DB_SSL_IS_PAAS=false
DB_SSL_KEY_PATH=null
DB_SSL_CERT_PATH=null
DB_SSL_CA_PATH=null
DB_SSL_CIPHER=null
DB_SSL_VERIFY_SERVER=null
# --------------------------------------------
# REQUIRED: OUTGOING MAIL SERVER SETTINGS
# --------------------------------------------
MAIL_DRIVER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDR=you@example.com
MAIL_FROM_NAME='Snipe-IT'
MAIL_REPLYTO_ADDR=you@example.com
MAIL_REPLYTO_NAME='Snipe-IT'
MAIL_AUTO_EMBED_METHOD='attachment'
# --------------------------------------------
# REQUIRED: IMAGE LIBRARY
# This should be gd or imagick
# --------------------------------------------
IMAGE_LIB=gd
# --------------------------------------------
# OPTIONAL: BACKUP SETTINGS
# --------------------------------------------
MAIL_BACKUP_NOTIFICATION_DRIVER=null
MAIL_BACKUP_NOTIFICATION_ADDRESS=null
BACKUP_ENV=true
# --------------------------------------------
# OPTIONAL: SESSION SETTINGS
# --------------------------------------------
SESSION_LIFETIME=12000
EXPIRE_ON_CLOSE=false
ENCRYPT=false
COOKIE_NAME=snipeit_session
COOKIE_DOMAIN=null
SECURE_COOKIES=false
API_TOKEN_EXPIRATION_YEARS=40
# --------------------------------------------
# OPTIONAL: SECURITY HEADER SETTINGS
# --------------------------------------------
APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1
ALLOW_IFRAMING=false
REFERRER_POLICY=same-origin
ENABLE_CSP=false
CORS_ALLOWED_ORIGINS=null
ENABLE_HSTS=false
# --------------------------------------------
# OPTIONAL: CACHE SETTINGS
# --------------------------------------------
CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync
CACHE_PREFIX=snipeit
# --------------------------------------------
# OPTIONAL: REDIS SETTINGS
# --------------------------------------------
REDIS_HOST=redis
REDIS_PASSWORD=null
REDIS_PORT=6379
# --------------------------------------------
# OPTIONAL: MEMCACHED SETTINGS
# --------------------------------------------
MEMCACHED_HOST=null
MEMCACHED_PORT=null
# --------------------------------------------
# OPTIONAL: PUBLIC S3 Settings
# --------------------------------------------
PUBLIC_AWS_SECRET_ACCESS_KEY=null
PUBLIC_AWS_ACCESS_KEY_ID=null
PUBLIC_AWS_DEFAULT_REGION=null
PUBLIC_AWS_BUCKET=null
PUBLIC_AWS_URL=null
PUBLIC_AWS_BUCKET_ROOT=null
# --------------------------------------------
# OPTIONAL: PRIVATE S3 Settings
# --------------------------------------------
PRIVATE_AWS_ACCESS_KEY_ID=null
PRIVATE_AWS_SECRET_ACCESS_KEY=null
PRIVATE_AWS_DEFAULT_REGION=null
PRIVATE_AWS_BUCKET=null
PRIVATE_AWS_URL=null
PRIVATE_AWS_BUCKET_ROOT=null
# --------------------------------------------
# OPTIONAL: AWS Settings
# --------------------------------------------
AWS_ACCESS_KEY_ID=null
AWS_SECRET_ACCESS_KEY=null
AWS_DEFAULT_REGION=null
# --------------------------------------------
# OPTIONAL: LOGIN THROTTLING
# --------------------------------------------
LOGIN_MAX_ATTEMPTS=5
LOGIN_LOCKOUT_DURATION=60
RESET_PASSWORD_LINK_EXPIRES=900
# --------------------------------------------
# OPTIONAL: MISC
# --------------------------------------------
LOG_CHANNEL=stderr
LOG_MAX_DAYS=10
APP_LOCKED=false
APP_CIPHER=AES-256-CBC
APP_FORCE_TLS=false
GOOGLE_MAPS_API=
LDAP_MEM_LIM=500M
LDAP_TIME_LIM=600
+22 -15
View File
@@ -1,20 +1,20 @@
# --------------------------------------------
# REQUIRED: DB SETUP
# REQUIRED: DOCKER SPECIFIC SETTINGS
# --------------------------------------------
MYSQL_DATABASE=snipeit
MYSQL_USER=snipeit
MYSQL_PASSWORD=changeme1234
MYSQL_ROOT_PASSWORD=changeme1234
APP_VERSION=v6.4.1
APP_PORT=8000
# --------------------------------------------
# REQUIRED: BASIC APP SETTINGS
# --------------------------------------------
APP_ENV=develop
APP_ENV=production
APP_DEBUG=false
# please regenerate the APP_KEY value by calling `docker-compose run --rm snipeit bash` and then `php artisan key:generate --show` and then copy paste the value here
# Please regenerate the APP_KEY value by calling `docker compose run --rm snipeit php artisan key:generate --show`. Copy paste the value here
APP_KEY=base64:3ilviXqB9u6DX1NRcyWGJ+sjySF+H18CPDGb3+IVwMQ=
APP_URL=http://localhost:8000
# https://en.wikipedia.org/wiki/List_of_tz_database_time_zones - TZ identifier
APP_TIMEZONE='UTC'
APP_LOCALE=en
APP_LOCALE=en-US
MAX_RESULTS=500
# --------------------------------------------
@@ -27,10 +27,12 @@ PUBLIC_FILESYSTEM_DISK=local_public
# REQUIRED: DATABASE SETTINGS
# --------------------------------------------
DB_CONNECTION=mysql
DB_HOST=mariadb
DB_HOST=db
DB_PORT='3306'
DB_DATABASE=snipeit
DB_USERNAME=snipeit
DB_PASSWORD=changeme1234
MYSQL_ROOT_PASSWORD=changeme1234
DB_PREFIX=null
DB_DUMP_PATH='/usr/bin'
DB_CHARSET=utf8mb4
@@ -45,29 +47,35 @@ DB_SSL_KEY_PATH=null
DB_SSL_CERT_PATH=null
DB_SSL_CA_PATH=null
DB_SSL_CIPHER=null
DB_SSL_VERIFY_SERVER=null
# --------------------------------------------
# REQUIRED: OUTGOING MAIL SERVER SETTINGS
# --------------------------------------------
MAIL_DRIVER=smtp
MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_TLS_VERIFY_PEER=true
MAIL_FROM_ADDR=you@example.com
MAIL_FROM_NAME='Snipe-IT'
MAIL_REPLYTO_ADDR=you@example.com
MAIL_REPLYTO_NAME='Snipe-IT'
MAIL_AUTO_EMBED_METHOD='attachment'
# --------------------------------------------
# REQUIRED: DATA PROTECTION
# --------------------------------------------
ALLOW_BACKUP_DELETE=false
ALLOW_DATA_PURGE=false
# --------------------------------------------
# REQUIRED: IMAGE LIBRARY
# This should be gd or imagick
# --------------------------------------------
IMAGE_LIB=gd
# --------------------------------------------
# OPTIONAL: BACKUP SETTINGS
# --------------------------------------------
@@ -75,7 +83,6 @@ MAIL_BACKUP_NOTIFICATION_DRIVER=null
MAIL_BACKUP_NOTIFICATION_ADDRESS=null
BACKUP_ENV=true
# --------------------------------------------
# OPTIONAL: SESSION SETTINGS
# --------------------------------------------
@@ -90,7 +97,7 @@ API_TOKEN_EXPIRATION_YEARS=40
# --------------------------------------------
# OPTIONAL: SECURITY HEADER SETTINGS
# --------------------------------------------
APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1
APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1,172.16.0.0/12
ALLOW_IFRAMING=false
REFERRER_POLICY=same-origin
ENABLE_CSP=false
@@ -108,7 +115,7 @@ CACHE_PREFIX=snipeit
# --------------------------------------------
# OPTIONAL: REDIS SETTINGS
# --------------------------------------------
REDIS_HOST=redis
REDIS_HOST=null
REDIS_PASSWORD=null
REDIS_PORT=6379
+3 -2
View File
@@ -6,7 +6,7 @@ APP_DEBUG=false
APP_KEY=base64:hTUIUh9CP6dQx+6EjSlfWTgbaMaaRvlpEwk45vp+xmk=
APP_URL=http://127.0.0.1:8000
APP_TIMEZONE='US/Eastern'
APP_LOCALE=en
APP_LOCALE=en-US
APP_LOCKED=false
MAX_RESULTS=200
@@ -36,11 +36,12 @@ DB_SSL_KEY_PATH=null
DB_SSL_CERT_PATH=null
DB_SSL_CA_PATH=null
DB_SSL_CIPHER=null
DB_SSL_VERIFY_SERVER=null
# --------------------------------------------
# REQUIRED: OUTGOING MAIL SERVER SETTINGS
# --------------------------------------------
MAIL_DRIVER="log"
MAIL_MAILER="log"
# --------------------------------------------
+14 -3
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
@@ -42,21 +44,26 @@ DB_SSL_KEY_PATH=null
DB_SSL_CERT_PATH=null
DB_SSL_CA_PATH=null
DB_SSL_CIPHER=null
DB_SSL_VERIFY_SERVER=null
# --------------------------------------------
# REQUIRED: OUTGOING MAIL SERVER SETTINGS
# --------------------------------------------
MAIL_DRIVER=smtp
MAIL_MAILER=smtp
MAIL_HOST=email-smtp.us-west-2.amazonaws.com
MAIL_PORT=587
MAIL_USERNAME=YOURUSERNAME
MAIL_PASSWORD=YOURPASSWORD
MAIL_ENCRYPTION=null
MAIL_FROM_ADDR=you@example.com
MAIL_FROM_NAME='Snipe-IT'
MAIL_REPLYTO_ADDR=you@example.com
MAIL_REPLYTO_NAME='Snipe-IT'
MAIL_AUTO_EMBED_METHOD='attachment'
MAIL_TLS_VERIFY_PEER=true
# MAIL_ENCRYPTION is no longer supported. SymfonyMailer will use tls if it's
# advertised, and won't if it's not. If you want to use your mail server's IP but it's failing
# because of certificate errors, set MAIL_TLS_VERIFY_PEER-true
# --------------------------------------------
# REQUIRED: IMAGE LIBRARY
@@ -82,10 +89,12 @@ SESSION_LIFETIME=12000
EXPIRE_ON_CLOSE=false
ENCRYPT=false
COOKIE_NAME=snipeit_session
PASSPORT_COOKIE_NAME='snipeit_passport_token'
COOKIE_DOMAIN=null
SECURE_COOKIES=false
API_TOKEN_EXPIRATION_YEARS=15
BS_TABLE_STORAGE=cookieStorage
BS_TABLE_DEEPLINK=true
# --------------------------------------------
# OPTIONAL: SECURITY HEADER SETTINGS
@@ -94,6 +103,7 @@ APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1
ALLOW_IFRAMING=false
REFERRER_POLICY=same-origin
ENABLE_CSP=false
ADDITIONAL_CSP_URLS=null
CORS_ALLOWED_ORIGINS=null
ENABLE_HSTS=false
@@ -176,6 +186,7 @@ REPORT_TIME_LIMIT=12000
REQUIRE_SAML=false
API_THROTTLE_PER_MINUTE=120
CSV_ESCAPE_FORMULAS=true
LIVEWIRE_URL_PREFIX=null
# --------------------------------------------
# OPTIONAL: HASHING
@@ -190,4 +201,4 @@ ARGON_TIME=2
# OPTIONAL: SCIM
# --------------------------------------------
SCIM_TRACE=false
SCIM_STANDARDS_COMPLIANCE=false
SCIM_STANDARDS_COMPLIANCE=false
+1 -1
View File
@@ -22,7 +22,7 @@ DB_PASSWORD=null
# --------------------------------------------
# REQUIRED: OUTGOING MAIL SERVER SETTINGS
# --------------------------------------------
MAIL_DRIVER=log
MAIL_MAILER=log
# --------------------------------------------
+1 -1
View File
@@ -18,6 +18,6 @@ APP_KEY=base64:tu9NRh/a6+dCXBDGvg0Gv/0TcABnFsbT4AKxrr8mwQo=
LOGIN_MAX_ATTEMPTS=1000000
LOGIN_LOCKOUT_DURATION=100000000
MAIL_DRIVER=log
MAIL_MAILER=log
MAIL_FROM_ADDR=you@example.com
MAIL_FROM_NAME=Snipe-IT
+1 -1
View File
@@ -15,6 +15,6 @@ APP_KEY=base64:tu9NRh/a6+dCXBDGvg0Gv/0TcABnFsbT4AKxrr8mwQo=
LOGIN_MAX_ATTEMPTS=1000000
LOGIN_LOCKOUT_DURATION=100000000
MAIL_DRIVER=log
MAIL_MAILER=log
MAIL_FROM_ADDR=you@example.com
MAIL_FROM_NAME=Snipe-IT
-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.
+1 -1
View File
@@ -36,7 +36,7 @@ jobs:
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
- name: Run Codacy Analysis CLI
uses: codacy/codacy-analysis-cli-action@v4.4.0
uses: codacy/codacy-analysis-cli-action@v4.4.5
with:
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
# You can also omit the token and run the tools that support default configurations
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
uses: actions/checkout@v4
- name: Crowdin push
uses: crowdin/github-action@v1
uses: crowdin/github-action@v2
with:
upload_sources: true
upload_translations: false
+1 -1
View File
@@ -73,7 +73,7 @@ jobs:
# https://github.com/docker/build-push-action
- name: Build and push 'snipe-it' image
id: docker_build
uses: docker/build-push-action@v5
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile.alpine
+1 -1
View File
@@ -73,7 +73,7 @@ jobs:
# https://github.com/docker/build-push-action
- name: Build and push 'snipe-it' image
id: docker_build
uses: docker/build-push-action@v5
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
+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
+15 -9
View File
@@ -25,9 +25,9 @@ jobs:
fail-fast: false
matrix:
php-version:
- "7.4"
- "8.0"
- "8.1.1"
- "8.1"
- "8.2"
- "8.3"
name: PHP ${{ matrix.php-version }}
@@ -58,11 +58,17 @@ jobs:
- name: Install Dependencies
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
- name: Generate key
run: php artisan key:generate
- name: Directory Permissions
run: chmod -R 777 storage bootstrap/cache
- name: Setup Laravel
env:
DB_CONNECTION: mysql
DB_DATABASE: snipeit
DB_PORT: ${{ job.services.mysql.ports[3306] }}
DB_USERNAME: root
run: |
php artisan key:generate
php artisan migrate --force
php artisan passport:install
chmod -R 777 storage bootstrap/cache
- name: Execute tests (Unit and Feature tests) via PHPUnit
env:
@@ -70,4 +76,4 @@ jobs:
DB_DATABASE: snipeit
DB_PORT: ${{ job.services.mysql.ports[3306] }}
DB_USERNAME: root
run: php artisan test --parallel
run: php artisan test
+77
View File
@@ -0,0 +1,77 @@
name: Tests in Postgres
on: workflow_dispatch
jobs:
tests:
runs-on: ubuntu-latest
services:
postgresql:
image: postgres
env:
POSTGRES_DB: snipeit
POSTGRES_USER: snipeit
POSTGRES_PASSWORD: password
ports:
- 5432:5432
options: --health-cmd=pg_isready --health-interval=10s --health-timeout=5s --health-retries=3
strategy:
fail-fast: false
matrix:
php-version:
- "8.1"
- "8.2"
- "8.3"
name: PHP ${{ matrix.php-version }}
steps:
- uses: shivammathur/setup-php@v2
with:
php-version: "${{ matrix.php-version }}"
coverage: none
- uses: actions/checkout@v4
- name: Get Composer Cache Directory
id: composer-cache
run: |
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-${{ matrix.php-version }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-composer-
- name: Copy .env
run: |
cp -v .env.testing.example .env
cp -v .env.testing.example .env.testing
- name: Install Dependencies
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
- name: Setup Laravel
env:
DB_CONNECTION: pgsql
DB_DATABASE: snipeit
DB_PORT: ${{ job.services.postgresql.ports[5432] }}
DB_USERNAME: snipeit
DB_PASSWORD: password
run: |
php artisan key:generate
php artisan migrate --force
php artisan passport:install
chmod -R 777 storage bootstrap/cache
- name: Execute tests (Unit and Feature tests) via PHPUnit
env:
DB_CONNECTION: pgsql
DB_DATABASE: snipeit
DB_PORT: ${{ job.services.postgresql.ports[5432] }}
DB_USERNAME: snipeit
DB_PASSWORD: password
run: php artisan test
+4 -1
View File
@@ -49,10 +49,13 @@ jobs:
- name: Generate key
run: php artisan key:generate
- name: Setup Passport
run: php artisan passport:keys
- name: Directory Permissions
run: chmod -R 777 storage bootstrap/cache
- name: Execute tests (Unit and Feature tests) via PHPUnit
env:
DB_CONNECTION: sqlite_testing
run: php artisan test --parallel
run: php artisan test
+4
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
@@ -67,3 +68,6 @@ _ide_helper_models.php
/.phplint-cache
storage/ldap_client_tls.cert
storage/ldap_client_tls.key
/storage/framework/testing
/.phpunit.cache
+1 -1
View File
@@ -1 +1 @@
v12.22.1
v18.16.0
+4 -4
View File
@@ -3,8 +3,8 @@
"DOC2": "In other words, what you see locally are the requirements for your _current_ install",
"DOC3": "Please don't rely on these versions for planning upgrades unless you've fetched the most recent version",
"DOC4": "You should really just ignore it and run upgrade.php. Really",
"php_min_version": "7.4.0",
"php_max_major_minor": "8.1",
"php_max_wontwork": "8.2.0",
"current_snipeit_version": "6.3"
"php_min_version": "8.1.0",
"php_max_major_minor": "8.3",
"php_max_wontwork": "8.4.0",
"current_snipeit_version": "7.0"
}
+52 -438
View File
@@ -1,444 +1,58 @@
Thanks goes to all of these wonderful people ([emoji key](https://github.com/kentcdodds/all-contributors#emoji-key)) who have helped Snipe-IT get this far:
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
<tbody>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://www.snipe.net"><img src="https://avatars3.githubusercontent.com/u/197404?v=3?s=110" width="110px;" alt="snipe"/><br /><sub><b>snipe</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=snipe" title="Code">💻</a> <a href="#infra-snipe" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/snipe/snipe-it/commits?author=snipe" title="Documentation">📖</a> <a href="https://github.com/snipe/snipe-it/commits?author=snipe" title="Tests">⚠️</a> <a href="https://github.com/snipe/snipe-it/issues?q=author%3Asnipe" title="Bug reports">🐛</a> <a href="#design-snipe" title="Design">🎨</a> <a href="https://github.com/snipe/snipe-it/pulls?q=is%3Apr+reviewed-by%3Asnipe" title="Reviewed Pull Requests">👀</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.uberbrady.com"><img src="https://avatars0.githubusercontent.com/u/36335?v=3?s=110" width="110px;" alt="Brady Wetherington"/><br /><sub><b>Brady Wetherington</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=uberbrady" title="Code">💻</a> <a href="https://github.com/snipe/snipe-it/commits?author=uberbrady" title="Documentation">📖</a> <a href="#infra-uberbrady" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/snipe/snipe-it/pulls?q=is%3Apr+reviewed-by%3Auberbrady" title="Reviewed Pull Requests">👀</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/dmeltzer"><img src="https://avatars0.githubusercontent.com/u/3803132?v=3?s=110" width="110px;" alt="Daniel Meltzer"/><br /><sub><b>Daniel Meltzer</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=dmeltzer" title="Code">💻</a> <a href="https://github.com/snipe/snipe-it/commits?author=dmeltzer" title="Tests">⚠️</a> <a href="https://github.com/snipe/snipe-it/commits?author=dmeltzer" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.tuckertechonline.com"><img src="https://avatars0.githubusercontent.com/u/1609106?v=3?s=110" width="110px;" alt="Michael T"/><br /><sub><b>Michael T</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=mtucker6784" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/madd15"><img src="https://avatars2.githubusercontent.com/u/3274937?v=3?s=110" width="110px;" alt="madd15"/><br /><sub><b>madd15</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=madd15" title="Documentation">📖</a> <a href="#question-madd15" title="Answering Questions">💬</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/vsposato"><img src="https://avatars2.githubusercontent.com/u/894126?v=3?s=110" width="110px;" alt="Vincent Sposato"/><br /><sub><b>Vincent Sposato</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=vsposato" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/vjandrea"><img src="https://avatars0.githubusercontent.com/u/1639757?v=3?s=110" width="110px;" alt="Andrea Bergamasco"/><br /><sub><b>Andrea Bergamasco</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=vjandrea" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/kpawelski"><img src="https://avatars0.githubusercontent.com/u/10640152?v=3?s=110" width="110px;" alt="Karol"/><br /><sub><b>Karol</b></sub></a><br /><a href="#translation-kpawelski" title="Translation">🌍</a> <a href="https://github.com/snipe/snipe-it/commits?author=kpawelski" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://blog.morph027.de/"><img src="https://avatars3.githubusercontent.com/u/600106?v=3?s=110" width="110px;" alt="morph027"/><br /><sub><b>morph027</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=morph027" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fvleminckx"><img src="https://avatars3.githubusercontent.com/u/22935755?v=3?s=110" width="110px;" alt="fvleminckx"/><br /><sub><b>fvleminckx</b></sub></a><br /><a href="#infra-fvleminckx" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/itsupportcmsukorg"><img src="https://avatars2.githubusercontent.com/u/15633547?v=3?s=110" width="110px;" alt="itsupportcmsukorg"/><br /><sub><b>itsupportcmsukorg</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=itsupportcmsukorg" title="Code">💻</a> <a href="https://github.com/snipe/snipe-it/issues?q=author%3Aitsupportcmsukorg" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://override.io"><img src="https://avatars3.githubusercontent.com/u/12373799?v=3?s=110" width="110px;" alt="Frank"/><br /><sub><b>Frank</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=base-zero" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ghost"><img src="https://avatars0.githubusercontent.com/u/10137?v=3?s=110" width="110px;" alt="Deleted user"/><br /><sub><b>Deleted user</b></sub></a><br /><a href="#translation-ghost" title="Translation">🌍</a> <a href="https://github.com/snipe/snipe-it/commits?author=ghost" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tiagom62"><img src="https://avatars1.githubusercontent.com/u/10802313?v=3?s=110" width="110px;" alt="tiagom62"/><br /><sub><b>tiagom62</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=tiagom62" title="Code">💻</a> <a href="#infra-tiagom62" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/rystaf"><img src="https://avatars3.githubusercontent.com/u/2389047?v=3?s=110" width="110px;" alt="Ryan Stafford"/><br /><sub><b>Ryan Stafford</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=rystaf" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ehanlon"><img src="https://avatars2.githubusercontent.com/u/10345935?v=3?s=110" width="110px;" alt="Eammon Hanlon"/><br /><sub><b>Eammon Hanlon</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=ehanlon" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zjean"><img src="https://avatars0.githubusercontent.com/u/441924?v=3?s=110" width="110px;" alt="zjean"/><br /><sub><b>zjean</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=zjean" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.frei.media"><img src="https://avatars0.githubusercontent.com/u/12660103?v=3?s=110" width="110px;" alt="Matthias Frei"/><br /><sub><b>Matthias Frei</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=FREImedia" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/opsydev"><img src="https://avatars0.githubusercontent.com/u/3767518?v=3?s=110" width="110px;" alt="opsydev"/><br /><sub><b>opsydev</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=opsydev" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.ddreier.com"><img src="https://avatars1.githubusercontent.com/u/82290?v=3?s=110" width="110px;" alt="Daniel Dreier"/><br /><sub><b>Daniel Dreier</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=ddreier" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://rassie.org"><img src="https://avatars0.githubusercontent.com/u/23448?v=3?s=110" width="110px;" alt="Nikolai Prokoschenko"/><br /><sub><b>Nikolai Prokoschenko</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=rassie" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/YetAnotherCodeMonkey"><img src="https://avatars0.githubusercontent.com/u/13452757?v=3?s=110" width="110px;" alt="Drew"/><br /><sub><b>Drew</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=YetAnotherCodeMonkey" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/merid14"><img src="https://avatars0.githubusercontent.com/u/1342320?v=3?s=110" width="110px;" alt="Walter"/><br /><sub><b>Walter</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=merid14" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/balous"><img src="https://avatars3.githubusercontent.com/u/11254614?v=3?s=110" width="110px;" alt="Petr Baloun"/><br /><sub><b>Petr Baloun</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=balous" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/reidblomquist"><img src="https://avatars0.githubusercontent.com/u/6117660?v=3?s=110" width="110px;" alt="reidblomquist"/><br /><sub><b>reidblomquist</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=reidblomquist" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mathieuk"><img src="https://avatars0.githubusercontent.com/u/539914?v=3?s=110" width="110px;" alt="Mathieu Kooiman"/><br /><sub><b>Mathieu Kooiman</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=mathieuk" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/csayre"><img src="https://avatars3.githubusercontent.com/u/6606421?v=3?s=110" width="110px;" alt="csayre"/><br /><sub><b>csayre</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=csayre" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/adamdunson"><img src="https://avatars1.githubusercontent.com/u/768488?v=3?s=110" width="110px;" alt="Adam Dunson"/><br /><sub><b>Adam Dunson</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=adamdunson" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/thehereward"><img src="https://avatars0.githubusercontent.com/u/5547470?v=3?s=110" width="110px;" alt="Hereward"/><br /><sub><b>Hereward</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=thehereward" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/swoopdk"><img src="https://avatars0.githubusercontent.com/u/5802977?v=3?s=110" width="110px;" alt="swoopdk"/><br /><sub><b>swoopdk</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=swoopdk" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://linkedin.com/in/ahimta"><img src="https://avatars1.githubusercontent.com/u/3470403?v=3?s=110" width="110px;" alt="Abdullah Alansari"/><br /><sub><b>Abdullah Alansari</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=Ahimta" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MicaelRodrigues"><img src="https://avatars0.githubusercontent.com/u/796443?v=3?s=110" width="110px;" alt="Micael Rodrigues"/><br /><sub><b>Micael Rodrigues</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=MicaelRodrigues" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://macadmincorner.com"><img src="https://avatars0.githubusercontent.com/u/614564?v=3?s=110" width="110px;" alt="Patrick Gallagher"/><br /><sub><b>Patrick Gallagher</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=patgmac" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Miliamber"><img src="https://avatars3.githubusercontent.com/u/7165922?v=3?s=110" width="110px;" alt="Miliamber"/><br /><sub><b>Miliamber</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=Miliamber" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hawk554"><img src="https://avatars3.githubusercontent.com/u/861766?v=3?s=110" width="110px;" alt="hawk554"/><br /><sub><b>hawk554</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=hawk554" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://jbirdkerr.net"><img src="https://avatars1.githubusercontent.com/u/1695622?v=3?s=110" width="110px;" alt="Justin Kerr"/><br /><sub><b>Justin Kerr</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=jbirdkerr" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.irasnyder.com/devel/"><img src="https://avatars3.githubusercontent.com/u/11426176?v=3?s=110" width="110px;" alt="Ira W. Snyder"/><br /><sub><b>Ira W. Snyder</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=irasnyd" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/aalaily"><img src="https://avatars2.githubusercontent.com/u/2475759?v=3?s=110" width="110px;" alt="Aladin Alaily"/><br /><sub><b>Aladin Alaily</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=aalaily" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/kobie-chasehansen"><img src="https://avatars0.githubusercontent.com/u/10247644?v=3?s=110" width="110px;" alt="Chase Hansen"/><br /><sub><b>Chase Hansen</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=kobie-chasehansen" title="Code">💻</a> <a href="#question-kobie-chasehansen" title="Answering Questions">💬</a> <a href="https://github.com/snipe/snipe-it/issues?q=author%3Akobie-chasehansen" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/IDM-Helpdesk"><img src="https://avatars2.githubusercontent.com/u/13545400?v=3?s=110" width="110px;" alt="IDM Helpdesk"/><br /><sub><b>IDM Helpdesk</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=IDM-Helpdesk" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://balticer.de"><img src="https://avatars2.githubusercontent.com/u/614439?v=3?s=110" width="110px;" alt="Kai"/><br /><sub><b>Kai</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=balticer" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.michaeldaniels.me"><img src="https://avatars1.githubusercontent.com/u/8762511?v=3?s=110" width="110px;" alt="Michael Daniels"/><br /><sub><b>Michael Daniels</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=mdaniels5757" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://tomcastleman.me"><img src="https://avatars3.githubusercontent.com/u/1532660?v=3?s=110" width="110px;" alt="Tom Castleman"/><br /><sub><b>Tom Castleman</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=tomcastleman" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DanielNemanic"><img src="https://avatars3.githubusercontent.com/u/10723243?v=3?s=110" width="110px;" alt="Daniel Nemanic"/><br /><sub><b>Daniel Nemanic</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=DanielNemanic" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/southwolf"><img src="https://avatars0.githubusercontent.com/u/150648?v=3?s=110" width="110px;" alt="SouthWolf"/><br /><sub><b>SouthWolf</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=southwolf" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ivarne"><img src="https://avatars2.githubusercontent.com/u/131616?v=3?s=110" width="110px;" alt="Ivar Nesje"/><br /><sub><b>Ivar Nesje</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=ivarne" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.j0k3r.net"><img src="https://avatars1.githubusercontent.com/u/62333?v=3?s=110" width="110px;" alt="Jérémy Benoist"/><br /><sub><b>Jérémy Benoist</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=j0k3r" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/cleathley"><img src="https://avatars2.githubusercontent.com/u/724344?v=3?s=110" width="110px;" alt="Chris Leathley"/><br /><sub><b>Chris Leathley</b></sub></a><br /><a href="#infra-cleathley" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/splaer"><img src="https://avatars0.githubusercontent.com/u/972498?v=3?s=110" width="110px;" alt="splaer"/><br /><sub><b>splaer</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/issues?q=author%3Asplaer" title="Bug reports">🐛</a> <a href="https://github.com/snipe/snipe-it/commits?author=splaer" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://www.joeferguson.me"><img src="https://avatars1.githubusercontent.com/u/967362?v=3?s=110" width="110px;" alt="Joe Ferguson"/><br /><sub><b>Joe Ferguson</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=svpernova09" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/diwanicki"><img src="https://avatars3.githubusercontent.com/u/6108682?v=3?s=110" width="110px;" alt="diwanicki"/><br /><sub><b>diwanicki</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=diwanicki" title="Code">💻</a> <a href="https://github.com/snipe/snipe-it/commits?author=diwanicki" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/pakkua80"><img src="https://avatars3.githubusercontent.com/u/2527115?v=3?s=110" width="110px;" alt="Lee Thoong Ching"/><br /><sub><b>Lee Thoong Ching</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=pakkua80" title="Documentation">📖</a> <a href="https://github.com/snipe/snipe-it/commits?author=pakkua80" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://shu.io"><img src="https://avatars1.githubusercontent.com/u/461491?v=3?s=110" width="110px;" alt="Marek Šuppa"/><br /><sub><b>Marek Šuppa</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=mrshu" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mizar1616"><img src="https://avatars1.githubusercontent.com/u/8693762?v=3?s=110" width="110px;" alt="Juan J. Martinez"/><br /><sub><b>Juan J. Martinez</b></sub></a><br /><a href="#translation-mizar1616" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/rrdial"><img src="https://avatars1.githubusercontent.com/u/1458388?v=3?s=110" width="110px;" alt="R Ryan Dial"/><br /><sub><b>R Ryan Dial</b></sub></a><br /><a href="#translation-rrdial" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/burlito"><img src="https://avatars2.githubusercontent.com/u/2871745?v=3?s=110" width="110px;" alt="Andrej Manduch"/><br /><sub><b>Andrej Manduch</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=burlito" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://www.cordeos.com"><img src="https://avatars0.githubusercontent.com/u/8341172?v=3?s=110" width="110px;" alt="Jay Richards"/><br /><sub><b>Jay Richards</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=technogenus" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://necurity.co.uk"><img src="https://avatars2.githubusercontent.com/u/7295127?v=3?s=110" width="110px;" alt="Alexander Innes"/><br /><sub><b>Alexander Innes</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=leostat" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://buzzedword.codes"><img src="https://avatars2.githubusercontent.com/u/334485?v=3?s=110" width="110px;" alt="Danny Garcia"/><br /><sub><b>Danny Garcia</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=buzzedword" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/archpoint"><img src="https://avatars2.githubusercontent.com/u/366855?v=3?s=110" width="110px;" alt="archpoint"/><br /><sub><b>archpoint</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=archpoint" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.jakemcgraw.com"><img src="https://avatars1.githubusercontent.com/u/67991?v=3?s=110" width="110px;" alt="Jake McGraw"/><br /><sub><b>Jake McGraw</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=jakemcgraw" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FleischKarussel"><img src="https://avatars1.githubusercontent.com/u/1714374?v=3?s=110" width="110px;" alt="FleischKarussel"/><br /><sub><b>FleischKarussel</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=FleischKarussel" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/feeva"><img src="https://avatars3.githubusercontent.com/u/319644?v=3?s=110" width="110px;" alt="Dylan Yi"/><br /><sub><b>Dylan Yi</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=feeva" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://FlashingCursor.com"><img src="https://avatars2.githubusercontent.com/u/857740?v=3?s=110" width="110px;" alt="Gil Rutkowski"/><br /><sub><b>Gil Rutkowski</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=flashingcursor" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.desmondmorris.com"><img src="https://avatars3.githubusercontent.com/u/129360?v=3?s=110" width="110px;" alt="Desmond Morris"/><br /><sub><b>Desmond Morris</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=desmondmorris" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://peelman.us"><img src="https://avatars2.githubusercontent.com/u/52936?v=3?s=110" width="110px;" alt="Nick Peelman"/><br /><sub><b>Nick Peelman</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=peelman" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://abrahamvegh.com"><img src="https://avatars0.githubusercontent.com/u/53161?v=3?s=110" width="110px;" alt="Abraham Vegh"/><br /><sub><b>Abraham Vegh</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=abrahamvegh" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/rashivkp"><img src="https://avatars0.githubusercontent.com/u/2818680?v=3?s=110" width="110px;" alt="Mohamed Rashid"/><br /><sub><b>Mohamed Rashid</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=rashivkp" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://hinchk.github.io"><img src="https://avatars3.githubusercontent.com/u/1509456?v=3?s=110" width="110px;" alt="Kasey"/><br /><sub><b>Kasey</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=HinchK" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/BrettFagerlund"><img src="https://avatars2.githubusercontent.com/u/10522541?v=3?s=110" width="110px;" alt="Brett"/><br /><sub><b>Brett</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=BrettFagerlund" title="Tests">⚠️</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://jasonspriggs.com"><img src="https://avatars2.githubusercontent.com/u/16108587?v=3?s=110" width="110px;" alt="Jason Spriggs"/><br /><sub><b>Jason Spriggs</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=jasonspriggs" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://n8felton.wordpress.com"><img src="https://avatars2.githubusercontent.com/u/1134568?v=3?s=110" width="110px;" alt="Nate Felton"/><br /><sub><b>Nate Felton</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=n8felton" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://homepages.dcc.ufmg.br/~manassesferreira"><img src="https://avatars2.githubusercontent.com/u/14036694?v=3?s=110" width="110px;" alt="Manasses Ferreira"/><br /><sub><b>Manasses Ferreira</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=manassesferreira" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/steveelwood"><img src="https://avatars0.githubusercontent.com/u/15913949?v=3?s=110" width="110px;" alt="Steve"/><br /><sub><b>Steve</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=steveelwood" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://twitter.com/matc"><img src="https://avatars1.githubusercontent.com/u/3361683?v=3?s=110" width="110px;" alt="matc"/><br /><sub><b>matc</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=matc" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.davisracingteam.com"><img src="https://avatars3.githubusercontent.com/u/7405702?v=3?s=110" width="110px;" alt="Cole R. Davis"/><br /><sub><b>Cole R. Davis</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=VanillaNinjaD" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/gibsonjoshua55"><img src="https://avatars2.githubusercontent.com/u/10167681?v=3?s=110" width="110px;" alt="gibsonjoshua55"/><br /><sub><b>gibsonjoshua55</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=gibsonjoshua55" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zwerch"><img src="https://avatars2.githubusercontent.com/u/2809241?v=4?s=110" width="110px;" alt="Robin Temme"/><br /><sub><b>Robin Temme</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=zwerch" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/imanghafoori1"><img src="https://avatars0.githubusercontent.com/u/6961695?v=4?s=110" width="110px;" alt="Iman"/><br /><sub><b>Iman</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=imanghafoori1" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/richardhofman6"><img src="https://avatars1.githubusercontent.com/u/6551003?v=4?s=110" width="110px;" alt="Richard Hofman"/><br /><sub><b>Richard Hofman</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=richardhofman6" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/gizzmojr"><img src="https://avatars0.githubusercontent.com/u/3697569?v=4?s=110" width="110px;" alt="gizzmojr"/><br /><sub><b>gizzmojr</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=gizzmojr" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/imjennyli"><img src="https://avatars3.githubusercontent.com/u/404729?v=4?s=110" width="110px;" alt="Jenny Li"/><br /><sub><b>Jenny Li</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=imjennyli" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/GeoffYoung"><img src="https://avatars0.githubusercontent.com/u/869227?v=4?s=110" width="110px;" alt="Geoff Young"/><br /><sub><b>Geoff Young</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=GeoffYoung" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.elliotblackburn.com"><img src="https://avatars3.githubusercontent.com/u/1068477?v=4?s=110" width="110px;" alt="Elliot Blackburn"/><br /><sub><b>Elliot Blackburn</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=BlueHatbRit" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://andmemasin.eu"><img src="https://avatars1.githubusercontent.com/u/6357451?v=4?s=110" width="110px;" alt="Tõnis Ormisson"/><br /><sub><b>Tõnis Ormisson</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=TonisOrmisson" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.nicolai-essig.de"><img src="https://avatars0.githubusercontent.com/u/449411?v=4?s=110" width="110px;" alt="Nicolai Essig"/><br /><sub><b>Nicolai Essig</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=thakilla" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/techincolor"><img src="https://avatars1.githubusercontent.com/u/14809698?v=4?s=110" width="110px;" alt="Danielle"/><br /><sub><b>Danielle</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=techincolor" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/TheVakman"><img src="https://avatars1.githubusercontent.com/u/18545156?v=4?s=110" width="110px;" alt="Lawrence"/><br /><sub><b>Lawrence</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=TheVakman" title="Tests">⚠️</a> <a href="https://github.com/snipe/snipe-it/issues?q=author%3ATheVakman" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/uknzaeinozpas"><img src="https://avatars1.githubusercontent.com/u/22473767?v=4?s=110" width="110px;" alt="uknzaeinozpas"/><br /><sub><b>uknzaeinozpas</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=uknzaeinozpas" title="Tests">⚠️</a> <a href="https://github.com/snipe/snipe-it/commits?author=uknzaeinozpas" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Gelob"><img src="https://avatars3.githubusercontent.com/u/422752?v=4?s=110" width="110px;" alt="Ryan"/><br /><sub><b>Ryan</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=Gelob" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/vcordes79"><img src="https://avatars1.githubusercontent.com/u/10672546?v=4?s=110" width="110px;" alt="vcordes79"/><br /><sub><b>vcordes79</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=vcordes79" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fordster78"><img src="https://avatars3.githubusercontent.com/u/27958330?v=4?s=110" width="110px;" alt="fordster78"/><br /><sub><b>fordster78</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=fordster78" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/CronKz"><img src="https://avatars0.githubusercontent.com/u/34064225?v=4?s=110" width="110px;" alt="CronKz"/><br /><sub><b>CronKz</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=CronKz" title="Code">💻</a> <a href="#translation-CronKz" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tdb"><img src="https://avatars1.githubusercontent.com/u/585486?v=4?s=110" width="110px;" alt="Tim Bishop"/><br /><sub><b>Tim Bishop</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=tdb" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.seanmcilvenna.com"><img src="https://avatars2.githubusercontent.com/u/5384694?v=4?s=110" width="110px;" alt="Sean McIlvenna"/><br /><sub><b>Sean McIlvenna</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=seanmcilvenna" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/cepacs"><img src="https://avatars3.githubusercontent.com/u/36515590?v=4?s=110" width="110px;" alt="cepacs"/><br /><sub><b>cepacs</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/issues?q=author%3Acepacs" title="Bug reports">🐛</a> <a href="https://github.com/snipe/snipe-it/commits?author=cepacs" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lea-mink"><img src="https://avatars2.githubusercontent.com/u/37537300?v=4?s=110" width="110px;" alt="lea-mink"/><br /><sub><b>lea-mink</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=lea-mink" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hannahtinkler"><img src="https://avatars0.githubusercontent.com/u/7140719?v=4?s=110" width="110px;" alt="Hannah Tinkler"/><br /><sub><b>Hannah Tinkler</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=hannahtinkler" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/doekman"><img src="https://avatars1.githubusercontent.com/u/1086388?v=4?s=110" width="110px;" alt="Doeke Zanstra"/><br /><sub><b>Doeke Zanstra</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=doekman" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.sdhd.nl/"><img src="https://avatars1.githubusercontent.com/u/4325936?v=4?s=110" width="110px;" alt="Djamon Staal"/><br /><sub><b>Djamon Staal</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=SjamonDaal" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/EarlRamirez"><img src="https://avatars3.githubusercontent.com/u/12306859?v=4?s=110" width="110px;" alt="Earl Ramirez"/><br /><sub><b>Earl Ramirez</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=EarlRamirez" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/RichardRay"><img src="https://avatars2.githubusercontent.com/u/8671456?v=4?s=110" width="110px;" alt="Richard Ray Thomas"/><br /><sub><b>Richard Ray Thomas</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=RichardRay" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.taisun.io/"><img src="https://avatars3.githubusercontent.com/u/1852688?v=4?s=110" width="110px;" alt="Ryan Kuba"/><br /><sub><b>Ryan Kuba</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=thelamer" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ParadoxGuitarist"><img src="https://avatars1.githubusercontent.com/u/6751928?v=4?s=110" width="110px;" alt="Brian Monroe"/><br /><sub><b>Brian Monroe</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=ParadoxGuitarist" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/plexorama"><img src="https://avatars1.githubusercontent.com/u/605167?v=4?s=110" width="110px;" alt="plexorama"/><br /><sub><b>plexorama</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=plexorama" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://tilldeeke.de"><img src="https://avatars2.githubusercontent.com/u/1795149?v=4?s=110" width="110px;" alt="Till Deeke"/><br /><sub><b>Till Deeke</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=tilldeeke" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/5quirrel"><img src="https://avatars0.githubusercontent.com/u/12634129?v=4?s=110" width="110px;" alt="5quirrel"/><br /><sub><b>5quirrel</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=5quirrel" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jasonlshelton"><img src="https://avatars1.githubusercontent.com/u/13071957?v=4?s=110" width="110px;" alt="Jason"/><br /><sub><b>Jason</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=jasonlshelton" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/chemfy"><img src="https://avatars3.githubusercontent.com/u/7128321?v=4?s=110" width="110px;" alt="Antti"/><br /><sub><b>Antti</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=chemfy" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DeusMaximus"><img src="https://avatars3.githubusercontent.com/u/10080364?v=4?s=110" width="110px;" alt="DeusMaximus"/><br /><sub><b>DeusMaximus</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=DeusMaximus" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/A-ROYAL"><img src="https://avatars2.githubusercontent.com/u/16384611?v=4?s=110" width="110px;" alt="a-royal"/><br /><sub><b>a-royal</b></sub></a><br /><a href="#translation-A-ROYAL" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/albertoaldrigo"><img src="https://avatars0.githubusercontent.com/u/5358208?v=4?s=110" width="110px;" alt="Alberto Aldrigo"/><br /><sub><b>Alberto Aldrigo</b></sub></a><br /><a href="#translation-albertoaldrigo" title="Translation">🌍</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://alex.stanev.org/blog"><img src="https://avatars0.githubusercontent.com/u/1412342?v=4?s=110" width="110px;" alt="Alex Stanev"/><br /><sub><b>Alex Stanev</b></sub></a><br /><a href="#translation-RealEnder" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://devel.itsolution2.de"><img src="https://avatars0.githubusercontent.com/u/177295?v=4?s=110" width="110px;" alt="Andreas Rehm"/><br /><sub><b>Andreas Rehm</b></sub></a><br /><a href="#translation-sirrus" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xelan"><img src="https://avatars0.githubusercontent.com/u/5080535?v=4?s=110" width="110px;" alt="Andreas Erhard"/><br /><sub><b>Andreas Erhard</b></sub></a><br /><a href="#translation-xelan" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/angeldeejay"><img src="https://avatars2.githubusercontent.com/u/142350?v=4?s=110" width="110px;" alt="Andrés Vanegas Jiménez"/><br /><sub><b>Andrés Vanegas Jiménez</b></sub></a><br /><a href="#translation-angeldeejay" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/aschiavon91"><img src="https://avatars0.githubusercontent.com/u/3910403?v=4?s=110" width="110px;" alt="Antonio Schiavon"/><br /><sub><b>Antonio Schiavon</b></sub></a><br /><a href="#translation-aschiavon91" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/benunter"><img src="https://avatars0.githubusercontent.com/u/10464547?v=4?s=110" width="110px;" alt="benunter"/><br /><sub><b>benunter</b></sub></a><br /><a href="#translation-benunter" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://catweb24.pl"><img src="https://avatars1.githubusercontent.com/u/5038647?v=4?s=110" width="110px;" alt="Borys Żmuda"/><br /><sub><b>Borys Żmuda</b></sub></a><br /><a href="#translation-rudashi" title="Translation">🌍</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/chibacityblues"><img src="https://avatars0.githubusercontent.com/u/5539359?v=4?s=110" width="110px;" alt="chibacityblues"/><br /><sub><b>chibacityblues</b></sub></a><br /><a href="#translation-chibacityblues" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/cwlin0416"><img src="https://avatars1.githubusercontent.com/u/1954830?v=4?s=110" width="110px;" alt="Chien Wei Lin"/><br /><sub><b>Chien Wei Lin</b></sub></a><br /><a href="#translation-cwlin0416" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Againstreality"><img src="https://avatars3.githubusercontent.com/u/11700533?v=4?s=110" width="110px;" alt="Christian Schuster"/><br /><sub><b>Christian Schuster</b></sub></a><br /><a href="#translation-Againstreality" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://chriss.webhostid.com"><img src="https://avatars1.githubusercontent.com/u/4308704?v=4?s=110" width="110px;" alt="Christian Stefanus"/><br /><sub><b>Christian Stefanus</b></sub></a><br /><a href="#translation-kopi-item" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://wxcafe.net"><img src="https://avatars3.githubusercontent.com/u/3009327?v=4?s=110" width="110px;" alt="wxcafé"/><br /><sub><b>wxcafé</b></sub></a><br /><a href="#translation-wxcafe" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/dpyroc"><img src="https://avatars3.githubusercontent.com/u/35761525?v=4?s=110" width="110px;" alt="dpyroc"/><br /><sub><b>dpyroc</b></sub></a><br /><a href="#translation-dpyroc" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.friedlmaier.net"><img src="https://avatars1.githubusercontent.com/u/2153639?v=4?s=110" width="110px;" alt="Daniel Friedlmaier"/><br /><sub><b>Daniel Friedlmaier</b></sub></a><br /><a href="#translation-da-friedl" title="Translation">🌍</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/danielheene"><img src="https://avatars1.githubusercontent.com/u/2947640?v=4?s=110" width="110px;" alt="Daniel Heene"/><br /><sub><b>Daniel Heene</b></sub></a><br /><a href="#translation-danielheene" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/danielcb"><img src="https://avatars3.githubusercontent.com/u/319022?v=4?s=110" width="110px;" alt="danielcb"/><br /><sub><b>danielcb</b></sub></a><br /><a href="#translation-danielcb" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/dominiksenti"><img src="https://avatars3.githubusercontent.com/u/15846537?v=4?s=110" width="110px;" alt="Dominik Senti"/><br /><sub><b>Dominik Senti</b></sub></a><br /><a href="#translation-dominiksenti" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.konectik.com"><img src="https://avatars0.githubusercontent.com/u/25570954?v=4?s=110" width="110px;" alt="Eric Gautheron"/><br /><sub><b>Eric Gautheron</b></sub></a><br /><a href="#translation-EpixFr" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://erlpil.com"><img src="https://avatars1.githubusercontent.com/u/5732623?v=4?s=110" width="110px;" alt="Erlend Pilø"/><br /><sub><b>Erlend Pilø</b></sub></a><br /><a href="#translation-Erlpil" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://fabio.technology"><img src="https://avatars0.githubusercontent.com/u/541832?v=4?s=110" width="110px;" alt="Fabio Rapposelli"/><br /><sub><b>Fabio Rapposelli</b></sub></a><br /><a href="#translation-frapposelli" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fgbs"><img src="https://avatars2.githubusercontent.com/u/3605240?v=4?s=110" width="110px;" alt="Felipe Barros"/><br /><sub><b>Felipe Barros</b></sub></a><br /><a href="#translation-fgbs" title="Translation">🌍</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/possebon"><img src="https://avatars0.githubusercontent.com/u/257745?v=4?s=110" width="110px;" alt="Fernando Possebon"/><br /><sub><b>Fernando Possebon</b></sub></a><br /><a href="#translation-possebon" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/gdraque"><img src="https://avatars3.githubusercontent.com/u/2540832?v=4?s=110" width="110px;" alt="gdraque"/><br /><sub><b>gdraque</b></sub></a><br /><a href="#translation-gdraque" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/georgwallisch"><img src="https://avatars0.githubusercontent.com/u/23440381?v=4?s=110" width="110px;" alt="Georg Wallisch"/><br /><sub><b>Georg Wallisch</b></sub></a><br /><a href="#translation-georgwallisch" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jgroblesr85"><img src="https://avatars1.githubusercontent.com/u/9852832?v=4?s=110" width="110px;" alt="Gerardo Robles"/><br /><sub><b>Gerardo Robles</b></sub></a><br /><a href="#translation-jgroblesr85" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://t.me/Gluek"><img src="https://avatars2.githubusercontent.com/u/11082640?v=4?s=110" width="110px;" alt="Gluek"/><br /><sub><b>Gluek</b></sub></a><br /><a href="#translation-mrgluek" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/AdnanAbuShahad"><img src="https://avatars0.githubusercontent.com/u/6847946?v=4?s=110" width="110px;" alt="AdnanAbuShahad"/><br /><sub><b>AdnanAbuShahad</b></sub></a><br /><a href="#translation-AdnanAbuShahad" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://hafidzi.my"><img src="https://avatars1.githubusercontent.com/u/3580608?v=4?s=110" width="110px;" alt="Hafidzi My"/><br /><sub><b>Hafidzi My</b></sub></a><br /><a href="#translation-hafidzi" title="Translation">🌍</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fofwisdom"><img src="https://avatars2.githubusercontent.com/u/205521?v=4?s=110" width="110px;" alt="Harim Park"/><br /><sub><b>Harim Park</b></sub></a><br /><a href="#translation-fofwisdom" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.kentsson.se"><img src="https://avatars2.githubusercontent.com/u/3333841?v=4?s=110" width="110px;" alt="Henrik Kentsson"/><br /><sub><b>Henrik Kentsson</b></sub></a><br /><a href="#translation-Kentsson" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/husnulyaqien"><img src="https://avatars0.githubusercontent.com/u/36551034?v=4?s=110" width="110px;" alt="Husnul Yaqien"/><br /><sub><b>Husnul Yaqien</b></sub></a><br /><a href="#translation-husnulyaqien" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://abaalkhail.org"><img src="https://avatars1.githubusercontent.com/u/2372747?v=4?s=110" width="110px;" alt="Ibrahim"/><br /><sub><b>Ibrahim</b></sub></a><br /><a href="#translation-abaalkh" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/igolman"><img src="https://avatars0.githubusercontent.com/u/1389334?v=4?s=110" width="110px;" alt="igolman"/><br /><sub><b>igolman</b></sub></a><br /><a href="#translation-igolman" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/itangiang"><img src="https://avatars1.githubusercontent.com/u/3257070?v=4?s=110" width="110px;" alt="itangiang"/><br /><sub><b>itangiang</b></sub></a><br /><a href="#translation-itangiang" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jarby1211"><img src="https://avatars2.githubusercontent.com/u/14814254?v=4?s=110" width="110px;" alt="jarby1211"/><br /><sub><b>jarby1211</b></sub></a><br /><a href="#translation-jarby1211" title="Translation">🌍</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://jwillker.com"><img src="https://avatars3.githubusercontent.com/u/6719357?v=4?s=110" width="110px;" alt="Jhonn Willker"/><br /><sub><b>Jhonn Willker</b></sub></a><br /><a href="#translation-JohnWillker" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/joxelito94"><img src="https://avatars2.githubusercontent.com/u/10983635?v=4?s=110" width="110px;" alt="Jose"/><br /><sub><b>Jose</b></sub></a><br /><a href="#translation-joxelito94" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/laopangzi"><img src="https://avatars0.githubusercontent.com/u/5206122?v=4?s=110" width="110px;" alt="laopangzi"/><br /><sub><b>laopangzi</b></sub></a><br /><a href="#translation-laopangzi" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://usrportage.de"><img src="https://avatars2.githubusercontent.com/u/79707?v=4?s=110" width="110px;" alt="Lars Strojny"/><br /><sub><b>Lars Strojny</b></sub></a><br /><a href="#translation-lstrojny" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://twitter.com/marcosbl"><img src="https://avatars0.githubusercontent.com/u/389801?v=4?s=110" width="110px;" alt="MarcosBL"/><br /><sub><b>MarcosBL</b></sub></a><br /><a href="#translation-MarcosBL" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mariejoyacajes"><img src="https://avatars3.githubusercontent.com/u/35664606?v=4?s=110" width="110px;" alt="marie joy cajes"/><br /><sub><b>marie joy cajes</b></sub></a><br /><a href="#translation-mariejoyacajes" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.markjohansen.dk"><img src="https://avatars2.githubusercontent.com/u/3052816?v=4?s=110" width="110px;" alt="Mark S. Johansen"/><br /><sub><b>Mark S. Johansen</b></sub></a><br /><a href="#translation-msjohansen" title="Translation">🌍</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://martinstub.dk"><img src="https://avatars2.githubusercontent.com/u/982885?v=4?s=110" width="110px;" alt="Martin Stub"/><br /><sub><b>Martin Stub</b></sub></a><br /><a href="#translation-stubben" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/meyerf99"><img src="https://avatars2.githubusercontent.com/u/28959963?v=4?s=110" width="110px;" alt="Meyer Flavio"/><br /><sub><b>Meyer Flavio</b></sub></a><br /><a href="#translation-meyerf99" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MicaelRodrigues"><img src="https://avatars3.githubusercontent.com/u/796443?v=4?s=110" width="110px;" alt="Micael Rodrigues"/><br /><sub><b>Micael Rodrigues</b></sub></a><br /><a href="#translation-MicaelRodrigues" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://rubixy.com/"><img src="https://avatars0.githubusercontent.com/u/10481331?v=4?s=110" width="110px;" alt="Mikael Rasmussen"/><br /><sub><b>Mikael Rasmussen</b></sub></a><br /><a href="#translation-mikaelssen" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/IxFail"><img src="https://avatars1.githubusercontent.com/u/1544552?v=4?s=110" width="110px;" alt="IxFail"/><br /><sub><b>IxFail</b></sub></a><br /><a href="#translation-IxFail" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.mohammedfota.com"><img src="https://avatars3.githubusercontent.com/u/18483118?v=4?s=110" width="110px;" alt="Mohammed Fota"/><br /><sub><b>Mohammed Fota</b></sub></a><br /><a href="#translation-MohammedFota" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/omego"><img src="https://avatars0.githubusercontent.com/u/227080?v=4?s=110" width="110px;" alt="Moayad Alserihi"/><br /><sub><b>Moayad Alserihi</b></sub></a><br /><a href="#translation-omego" title="Translation">🌍</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/saymd"><img src="https://avatars0.githubusercontent.com/u/1680266?v=4?s=110" width="110px;" alt="saymd"/><br /><sub><b>saymd</b></sub></a><br /><a href="#translation-saymd" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://nordsken.se"><img src="https://avatars0.githubusercontent.com/u/1826808?v=4?s=110" width="110px;" alt="Patrik Larsson"/><br /><sub><b>Patrik Larsson</b></sub></a><br /><a href="#translation-pooot" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/drcryo"><img src="https://avatars1.githubusercontent.com/u/20584746?v=4?s=110" width="110px;" alt="drcryo"/><br /><sub><b>drcryo</b></sub></a><br /><a href="#translation-drcryo" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/pawel1615"><img src="https://avatars1.githubusercontent.com/u/19408004?v=4?s=110" width="110px;" alt="pawel1615"/><br /><sub><b>pawel1615</b></sub></a><br /><a href="#translation-pawel1615" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bodrovics"><img src="https://avatars2.githubusercontent.com/u/23340468?v=4?s=110" width="110px;" alt="bodrovics"/><br /><sub><b>bodrovics</b></sub></a><br /><a href="#translation-bodrovics" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/priatna"><img src="https://avatars0.githubusercontent.com/u/3257654?v=4?s=110" width="110px;" alt="priatna"/><br /><sub><b>priatna</b></sub></a><br /><a href="#translation-priatna" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://amayume.net"><img src="https://avatars1.githubusercontent.com/u/5358374?v=4?s=110" width="110px;" alt="Fan Jiang"/><br /><sub><b>Fan Jiang</b></sub></a><br /><a href="#translation-ProfFan" title="Translation">🌍</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ragnarcx"><img src="https://avatars1.githubusercontent.com/u/22555451?v=4?s=110" width="110px;" alt="ragnarcx"/><br /><sub><b>ragnarcx</b></sub></a><br /><a href="#translation-ragnarcx" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.reinvanhaaren.nl/"><img src="https://avatars2.githubusercontent.com/u/18654582?v=4?s=110" width="110px;" alt="Rein van Haaren"/><br /><sub><b>Rein van Haaren</b></sub></a><br /><a href="#translation-reinvanhaaren" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://dheche.songolimo.net"><img src="https://avatars1.githubusercontent.com/u/386672?v=4?s=110" width="110px;" alt="Teguh Dwicaksana"/><br /><sub><b>Teguh Dwicaksana</b></sub></a><br /><a href="#translation-dheche" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FRaccie"><img src="https://avatars2.githubusercontent.com/u/2572552?v=4?s=110" width="110px;" alt="fraccie"/><br /><sub><b>fraccie</b></sub></a><br /><a href="#translation-FRaccie" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/vinzruzell"><img src="https://avatars0.githubusercontent.com/u/35182720?v=4?s=110" width="110px;" alt="vinzruzell"/><br /><sub><b>vinzruzell</b></sub></a><br /><a href="#translation-vinzruzell" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://kevinaustin.com"><img src="https://avatars1.githubusercontent.com/u/7883603?v=4?s=110" width="110px;" alt="Kevin Austin"/><br /><sub><b>Kevin Austin</b></sub></a><br /><a href="#translation-vipsystem" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://azuraweb.xyz"><img src="https://avatars3.githubusercontent.com/u/3861828?v=4?s=110" width="110px;" alt="Wira Sandy"/><br /><sub><b>Wira Sandy</b></sub></a><br /><a href="#translation-wira-sandy" title="Translation">🌍</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/GrayHoax"><img src="https://avatars2.githubusercontent.com/u/8663789?v=4?s=110" width="110px;" alt="Илья"/><br /><sub><b>Илья</b></sub></a><br /><a href="#translation-GrayHoax" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/godusevpn"><img src="https://avatars3.githubusercontent.com/u/30119111?v=4?s=110" width="110px;" alt="GodUseVPN"/><br /><sub><b>GodUseVPN</b></sub></a><br /><a href="#translation-godusevpn" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/EngrZhou"><img src="https://avatars1.githubusercontent.com/u/745576?v=4?s=110" width="110px;" alt="周周"/><br /><sub><b>周周</b></sub></a><br /><a href="#translation-EngrZhou" title="Translation">🌍</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/takuy"><img src="https://avatars3.githubusercontent.com/u/1631095?v=4?s=110" width="110px;" alt="Sam"/><br /><sub><b>Sam</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=takuy" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.illisian.com.au"><img src="https://avatars1.githubusercontent.com/u/264022?v=4?s=110" width="110px;" alt="Azerothian"/><br /><sub><b>Azerothian</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=Azerothian" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://macfoo.wordpress.com/"><img src="https://avatars1.githubusercontent.com/u/4930051?v=4?s=110" width="110px;" alt="Wes Hulette"/><br /><sub><b>Wes Hulette</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=jwhulette" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/patrict"><img src="https://avatars0.githubusercontent.com/u/8134591?v=4?s=110" width="110px;" alt="patrict"/><br /><sub><b>patrict</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=patrict" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/VELIKII-DIVAN"><img src="https://avatars3.githubusercontent.com/u/2611616?v=4?s=110" width="110px;" alt="Dmitriy Minaev"/><br /><sub><b>Dmitriy Minaev</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=VELIKII-DIVAN" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/liquidhorse"><img src="https://avatars0.githubusercontent.com/u/5132245?v=4?s=110" width="110px;" alt="liquidhorse"/><br /><sub><b>liquidhorse</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=liquidhorse" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://seld.be/"><img src="https://avatars1.githubusercontent.com/u/183678?v=4?s=110" width="110px;" alt="Jordi Boggiano"/><br /><sub><b>Jordi Boggiano</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=Seldaek" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/inietov"><img src="https://avatars0.githubusercontent.com/u/653557?v=4?s=110" width="110px;" alt="Ivan Nieto"/><br /><sub><b>Ivan Nieto</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=inietov" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/benrubson"><img src="https://avatars2.githubusercontent.com/u/6764151?v=4?s=110" width="110px;" alt="Ben RUBSON"/><br /><sub><b>Ben RUBSON</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=benrubson" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/NMathar"><img src="https://avatars2.githubusercontent.com/u/8554558?v=4?s=110" width="110px;" alt="NMathar"/><br /><sub><b>NMathar</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=NMathar" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/smb"><img src="https://avatars1.githubusercontent.com/u/139566?v=4?s=110" width="110px;" alt="Steffen"/><br /><sub><b>Steffen</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=smb" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Sxderp"><img src="https://avatars0.githubusercontent.com/u/6609453?v=4?s=110" width="110px;" alt="Sxderp"/><br /><sub><b>Sxderp</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=Sxderp" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fanta8897"><img src="https://avatars1.githubusercontent.com/u/4807843?v=4?s=110" width="110px;" alt="fanta8897"/><br /><sub><b>fanta8897</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=fanta8897" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://andreybolonin.com/phpconsulting/"><img src="https://avatars2.githubusercontent.com/u/2576509?v=4?s=110" width="110px;" alt="Andrey Bolonin"/><br /><sub><b>Andrey Bolonin</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=andreybolonin" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.shinayoshi.net/"><img src="https://avatars3.githubusercontent.com/u/2173307?v=4?s=110" width="110px;" alt="shinayoshi"/><br /><sub><b>shinayoshi</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=shinayoshi" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/reuser"><img src="https://avatars3.githubusercontent.com/u/2130159?v=4?s=110" width="110px;" alt="Hubert"/><br /><sub><b>Hubert</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=reuser" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://brashear.me"><img src="https://avatars0.githubusercontent.com/u/6865789?v=4?s=110" width="110px;" alt="KeenRivals"/><br /><sub><b>KeenRivals</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=KeenRivals" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/omyno"><img src="https://avatars3.githubusercontent.com/u/2902513?v=4?s=110" width="110px;" alt="omyno"/><br /><sub><b>omyno</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=omyno" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jackka"><img src="https://avatars1.githubusercontent.com/u/6271335?v=4?s=110" width="110px;" alt="Evgeny"/><br /><sub><b>Evgeny</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=jackka" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://digitalist.se"><img src="https://avatars2.githubusercontent.com/u/1169963?v=4?s=110" width="110px;" alt="Colin Campbell"/><br /><sub><b>Colin Campbell</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=colin-campbell" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lubo"><img src="https://avatars3.githubusercontent.com/u/2872098?v=4?s=110" width="110px;" alt="Ľubomír Kučera"/><br /><sub><b>Ľubomír Kučera</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=lubo" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.sourceguru.net"><img src="https://avatars3.githubusercontent.com/u/570639?v=4?s=110" width="110px;" alt="Martin Meredith"/><br /><sub><b>Martin Meredith</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=Mezzle" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/timothyfarmer"><img src="https://avatars1.githubusercontent.com/u/7632599?v=4?s=110" width="110px;" alt="Tim Farmer"/><br /><sub><b>Tim Farmer</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=timothyfarmer" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mskrip"><img src="https://avatars0.githubusercontent.com/u/17459600?v=4?s=110" width="110px;" alt="Marián Skrip"/><br /><sub><b>Marián Skrip</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=mskrip" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Godmartinz"><img src="https://avatars2.githubusercontent.com/u/47435081?v=4?s=110" width="110px;" alt="Godfrey Martinez"/><br /><sub><b>Godfrey Martinez</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=Godmartinz" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bigtreeEdo"><img src="https://avatars1.githubusercontent.com/u/2075128?v=4?s=110" width="110px;" alt="bigtreeEdo"/><br /><sub><b>bigtreeEdo</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=bigtreeEdo" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://colinmcneil.me/"><img src="https://avatars0.githubusercontent.com/u/5000430?v=4?s=110" width="110px;" alt="Colin McNeil"/><br /><sub><b>Colin McNeil</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=ColinMcNeil" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/JoKneeMo"><img src="https://avatars0.githubusercontent.com/u/421625?v=4?s=110" width="110px;" alt="JoKneeMo"/><br /><sub><b>JoKneeMo</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=JoKneeMo" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.redbridge.se"><img src="https://avatars0.githubusercontent.com/u/54849013?v=4?s=110" width="110px;" alt="Joshi"/><br /><sub><b>Joshi</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=joshi-redbridge" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/anthonypburns"><img src="https://avatars2.githubusercontent.com/u/15731458?v=4?s=110" width="110px;" alt="Anthony Burns"/><br /><sub><b>Anthony Burns</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=anthonypburns" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/johnson-yi"><img src="https://avatars1.githubusercontent.com/u/63399474?v=4?s=110" width="110px;" alt="johnson-yi"/><br /><sub><b>johnson-yi</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=johnson-yi" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://tangentmc.net"><img src="https://avatars1.githubusercontent.com/u/1862720?v=4?s=110" width="110px;" alt="Sanjay Govind"/><br /><sub><b>Sanjay Govind</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=sanjay900" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://peter.upfold.org.uk/"><img src="https://avatars0.githubusercontent.com/u/1255375?v=4?s=110" width="110px;" alt="Peter Upfold"/><br /><sub><b>Peter Upfold</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=PeterUpfold" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jbiel"><img src="https://avatars2.githubusercontent.com/u/961717?v=4?s=110" width="110px;" alt="Jared Biel"/><br /><sub><b>Jared Biel</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=jbiel" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/dampfklon"><img src="https://avatars1.githubusercontent.com/u/1733625?v=4?s=110" width="110px;" alt="Dampfklon"/><br /><sub><b>Dampfklon</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=dampfklon" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://communityclosing.com"><img src="https://avatars2.githubusercontent.com/u/52973156?v=4?s=110" width="110px;" alt="Charles Hamilton"/><br /><sub><b>Charles Hamilton</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=chamilton-ccn" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/giannello"><img src="https://avatars.githubusercontent.com/u/551789?v=4?s=110" width="110px;" alt="Giuseppe Iannello"/><br /><sub><b>Giuseppe Iannello</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=giannello" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.peterdavehello.org/"><img src="https://avatars.githubusercontent.com/u/3691490?v=4?s=110" width="110px;" alt="Peter Dave Hello"/><br /><sub><b>Peter Dave Hello</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=PeterDaveHello" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sigmoidal"><img src="https://avatars.githubusercontent.com/u/6106332?v=4?s=110" width="110px;" alt="sigmoidal"/><br /><sub><b>sigmoidal</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=sigmoidal" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/phenixdotnet"><img src="https://avatars.githubusercontent.com/u/2082554?v=4?s=110" width="110px;" alt="Vincent Lainé"/><br /><sub><b>Vincent Lainé</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=phenixdotnet" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.lucas-pless.com"><img src="https://avatars.githubusercontent.com/u/1943040?v=4?s=110" width="110px;" alt="Lucas Pleß"/><br /><sub><b>Lucas Pleß</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=derlucas" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://twitter.com/iansltx"><img src="https://avatars.githubusercontent.com/u/472804?v=4?s=110" width="110px;" alt="Ian Littman"/><br /><sub><b>Ian Littman</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=iansltx" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/PauloLuna"><img src="https://avatars.githubusercontent.com/u/3519029?v=4?s=110" width="110px;" alt="João Paulo"/><br /><sub><b>João Paulo</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=PauloLuna" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ThoBur"><img src="https://avatars.githubusercontent.com/u/70443365?v=4?s=110" width="110px;" alt="ThoBur"/><br /><sub><b>ThoBur</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=ThoBur" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://phpprofi.ru/"><img src="https://avatars.githubusercontent.com/u/1972329?v=4?s=110" width="110px;" alt="Alexander Chibrikin"/><br /><sub><b>Alexander Chibrikin</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=alek13" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/winstan"><img src="https://avatars.githubusercontent.com/u/438332?v=4?s=110" width="110px;" alt="Anthony Winstanley"/><br /><sub><b>Anthony Winstanley</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=winstan" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fashberg"><img src="https://avatars.githubusercontent.com/u/3075214?v=4?s=110" width="110px;" alt="Folke"/><br /><sub><b>Folke</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=fashberg" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/benwa"><img src="https://avatars.githubusercontent.com/u/1351571?v=4?s=110" width="110px;" alt="Bennett Blodinger"/><br /><sub><b>Bennett Blodinger</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=benwa" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://nmc.dev"><img src="https://avatars.githubusercontent.com/u/2974631?v=4?s=110" width="110px;" alt="NMC"/><br /><sub><b>NMC</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=ncareau" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/andres-baller"><img src="https://avatars.githubusercontent.com/u/52182449?v=4?s=110" width="110px;" alt="andres-baller"/><br /><sub><b>andres-baller</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=andres-baller" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sean-borg"><img src="https://avatars.githubusercontent.com/u/67109348?v=4?s=110" width="110px;" alt="sean-borg"/><br /><sub><b>sean-borg</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=sean-borg" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/EDVLeer"><img src="https://avatars.githubusercontent.com/u/32170051?v=4?s=110" width="110px;" alt="EDVLeer"/><br /><sub><b>EDVLeer</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=EDVLeer" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Kurokat"><img src="https://avatars.githubusercontent.com/u/23075196?v=4?s=110" width="110px;" alt="Kurokat"/><br /><sub><b>Kurokat</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=Kurokat" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://www.kevinkoellmann.de"><img src="https://avatars.githubusercontent.com/u/915514?v=4?s=110" width="110px;" alt="Kevin Köllmann"/><br /><sub><b>Kevin Köllmann</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=koelle25" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sw-mreyes"><img src="https://avatars.githubusercontent.com/u/49025941?v=4?s=110" width="110px;" alt="sw-mreyes"/><br /><sub><b>sw-mreyes</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=sw-mreyes" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://pittet.ca"><img src="https://avatars.githubusercontent.com/u/70129?v=4?s=110" width="110px;" alt="Joel Pittet"/><br /><sub><b>Joel Pittet</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=joelpittet" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://elyscape.com"><img src="https://avatars.githubusercontent.com/u/792695?v=4?s=110" width="110px;" alt="Eli Young"/><br /><sub><b>Eli Young</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=elyscape" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/raelldottin"><img src="https://avatars.githubusercontent.com/u/317015?v=4?s=110" width="110px;" alt="Raell Dottin"/><br /><sub><b>Raell Dottin</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=raelldottin" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/misilot"><img src="https://avatars.githubusercontent.com/u/1446856?v=4?s=110" width="110px;" alt="Tom Misilo"/><br /><sub><b>Tom Misilo</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=misilot" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://david.davenne.be"><img src="https://avatars.githubusercontent.com/u/4496300?v=4?s=110" width="110px;" alt="David Davenne"/><br /><sub><b>David Davenne</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=JuustoMestari" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://markstenglein.com"><img src="https://avatars.githubusercontent.com/u/9255772?v=4?s=110" width="110px;" alt="Mark Stenglein"/><br /><sub><b>Mark Stenglein</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=ocelotsloth" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ajsy"><img src="https://avatars.githubusercontent.com/u/35658596?v=4?s=110" width="110px;" alt="ajsy"/><br /><sub><b>ajsy</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=ajsy" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/t3easy"><img src="https://avatars.githubusercontent.com/u/3628035?v=4?s=110" width="110px;" alt="Jan Kiesewetter"/><br /><sub><b>Jan Kiesewetter</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=t3easy" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Tetrachloromethane250"><img src="https://avatars.githubusercontent.com/u/79449630?v=4?s=110" width="110px;" alt="Tetrachloromethane250"/><br /><sub><b>Tetrachloromethane250</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=Tetrachloromethane250" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.kajes.se/"><img src="https://avatars.githubusercontent.com/u/22004482?v=4?s=110" width="110px;" alt="Lars Kajes"/><br /><sub><b>Lars Kajes</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=kajes" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Joly0"><img src="https://avatars.githubusercontent.com/u/13993216?v=4?s=110" width="110px;" alt="Joly0"/><br /><sub><b>Joly0</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=Joly0" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/limeless"><img src="https://avatars.githubusercontent.com/u/1501022?v=4?s=110" width="110px;" alt="theburger"/><br /><sub><b>theburger</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=limeless" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/deivishome"><img src="https://avatars.githubusercontent.com/u/36065681?v=4?s=110" width="110px;" alt="David Valin Alonso"/><br /><sub><b>David Valin Alonso</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=deivishome" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/andreaci"><img src="https://avatars.githubusercontent.com/u/8290389?v=4?s=110" width="110px;" alt="andreaci"/><br /><sub><b>andreaci</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=andreaci" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.jellesebreghts.be"><img src="https://avatars.githubusercontent.com/u/1828542?v=4?s=110" width="110px;" alt="Jelle Sebreghts"/><br /><sub><b>Jelle Sebreghts</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=Jelle-S" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Skywalker-11"><img src="https://avatars.githubusercontent.com/u/11180862?v=4?s=110" width="110px;" alt="Michael Pietsch"/><br /><sub><b>Michael Pietsch</b></sub></a><br /></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sh1hab"><img src="https://avatars.githubusercontent.com/u/22068886?v=4?s=110" width="110px;" alt="Masudul Haque Shihab"/><br /><sub><b>Masudul Haque Shihab</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=sh1hab" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.freedomdive.com/"><img src="https://avatars.githubusercontent.com/u/16099942?v=4?s=110" width="110px;" alt="Supapong Areeprasertkul"/><br /><sub><b>Supapong Areeprasertkul</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=zybersup" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/psarossy"><img src="https://avatars.githubusercontent.com/u/207358?v=4?s=110" width="110px;" alt="Peter Sarossy"/><br /><sub><b>Peter Sarossy</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=psarossy" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/nepella"><img src="https://avatars.githubusercontent.com/u/11823649?v=4?s=110" width="110px;" alt="Renee Margaret McConahy"/><br /><sub><b>Renee Margaret McConahy</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=nepella" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/JohnnyPicnic"><img src="https://avatars.githubusercontent.com/u/5553884?v=4?s=110" width="110px;" alt="JohnnyPicnic"/><br /><sub><b>JohnnyPicnic</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=JohnnyPicnic" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/markbrule"><img src="https://avatars.githubusercontent.com/u/8799594?v=4?s=110" width="110px;" alt="markbrule"/><br /><sub><b>markbrule</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=markbrule" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mikecmpbll"><img src="https://avatars.githubusercontent.com/u/1962801?v=4?s=110" width="110px;" alt="Mike Campbell"/><br /><sub><b>Mike Campbell</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=mikecmpbll" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tbrconnect"><img src="https://avatars.githubusercontent.com/u/11973217?v=4?s=110" width="110px;" alt="tbrconnect"/><br /><sub><b>tbrconnect</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=tbrconnect" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/kcoyo"><img src="https://avatars.githubusercontent.com/u/12447225?v=4?s=110" width="110px;" alt="kcoyo"/><br /><sub><b>kcoyo</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=kcoyo" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://travismiller.com/"><img src="https://avatars.githubusercontent.com/u/494017?v=4?s=110" width="110px;" alt="Travis Miller"/><br /><sub><b>Travis Miller</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=travismiller" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Delta5"><img src="https://avatars.githubusercontent.com/u/1975640?v=4?s=110" width="110px;" alt="Evan Taylor"/><br /><sub><b>Evan Taylor</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=Delta5" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/PetriAsi"><img src="https://avatars.githubusercontent.com/u/8735148?v=4?s=110" width="110px;" alt="Petri Asikainen"/><br /><sub><b>Petri Asikainen</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=PetriAsi" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/derdeagle"><img src="https://avatars.githubusercontent.com/u/11424540?v=4?s=110" width="110px;" alt="derdeagle"/><br /><sub><b>derdeagle</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=derdeagle" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://wh0rd.org/"><img src="https://avatars.githubusercontent.com/u/176950?v=4?s=110" width="110px;" alt="Mike Frysinger"/><br /><sub><b>Mike Frysinger</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=vapier" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/AL4AL"><img src="https://avatars.githubusercontent.com/u/22044358?v=4?s=110" width="110px;" alt="ALPHA"/><br /><sub><b>ALPHA</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=AL4AL" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.ifern.de"><img src="https://avatars.githubusercontent.com/u/1042587?v=4?s=110" width="110px;" alt="FliegenKLATSCH"/><br /><sub><b>FliegenKLATSCH</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=FliegenKLATSCH" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jerm"><img src="https://avatars.githubusercontent.com/u/442138?v=4?s=110" width="110px;" alt="Jeremy Price"/><br /><sub><b>Jeremy Price</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=jerm" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Toreg87"><img src="https://avatars.githubusercontent.com/u/84392209?v=4?s=110" width="110px;" alt="Toreg87"/><br /><sub><b>Toreg87</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=Toreg87" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Computroniks"><img src="https://avatars.githubusercontent.com/u/67638596?v=4?s=110" width="110px;" alt="Matthew Nickson"/><br /><sub><b>Matthew Nickson</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=Computroniks" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://jethron.id.au"><img src="https://avatars.githubusercontent.com/u/1646397?v=4?s=110" width="110px;" alt="Jethro Nederhof"/><br /><sub><b>Jethro Nederhof</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=jethron" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/01ste02"><img src="https://avatars.githubusercontent.com/u/23289826?v=4?s=110" width="110px;" alt="Oskar Stenberg"/><br /><sub><b>Oskar Stenberg</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=01ste02" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Robert-Azelis"><img src="https://avatars.githubusercontent.com/u/82208283?v=4?s=110" width="110px;" alt="Robert-Azelis"/><br /><sub><b>Robert-Azelis</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=Robert-Azelis" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/alwism"><img src="https://avatars.githubusercontent.com/u/60648387?v=4?s=110" width="110px;" alt="Alexander William Smith"/><br /><sub><b>Alexander William Smith</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=alwism" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.leitwerk.de/"><img src="https://avatars.githubusercontent.com/u/24418301?v=4?s=110" width="110px;" alt="LEITWERK AG"/><br /><sub><b>LEITWERK AG</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=leitwerk-ag" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://www.aboutcher.co.uk"><img src="https://avatars.githubusercontent.com/u/1911435?v=4?s=110" width="110px;" alt="Adam"/><br /><sub><b>Adam</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=adamboutcher" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://snksrv.com"><img src="https://avatars.githubusercontent.com/u/16104273?v=4?s=110" width="110px;" alt="Ian"/><br /><sub><b>Ian</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=sneak-it" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://blog.bestlong.idv.tw/"><img src="https://avatars.githubusercontent.com/u/4023909?v=4?s=110" width="110px;" alt="Shao Yu-Lung (Allen)"/><br /><sub><b>Shao Yu-Lung (Allen)</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=bestlong" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Haxatron"><img src="https://avatars.githubusercontent.com/u/76475453?v=4?s=110" width="110px;" alt="Haxatron"/><br /><sub><b>Haxatron</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=Haxatron" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/PlaneNuts"><img src="https://avatars.githubusercontent.com/u/88776392?v=4?s=110" width="110px;" alt="PlaneNuts"/><br /><sub><b>PlaneNuts</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=PlaneNuts" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://bjcpgd.cias.rit.edu"><img src="https://avatars.githubusercontent.com/u/3842948?v=4?s=110" width="110px;" alt="Bradley Coudriet"/><br /><sub><b>Bradley Coudriet</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=exula" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://daltondur.st"><img src="https://avatars.githubusercontent.com/u/21966173?v=4?s=110" width="110px;" alt="Dalton Durst"/><br /><sub><b>Dalton Durst</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=UniversalSuperBox" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://adagiohealth.org"><img src="https://avatars.githubusercontent.com/u/38761237?v=4?s=110" width="110px;" alt="Alex Janes"/><br /><sub><b>Alex Janes</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=adagioajanes" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/nuraeil"><img src="https://avatars.githubusercontent.com/u/32387849?v=4?s=110" width="110px;" alt="Nuraeil"/><br /><sub><b>Nuraeil</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=nuraeil" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/TenOfTens"><img src="https://avatars.githubusercontent.com/u/48162670?v=4?s=110" width="110px;" alt="TenOfTens"/><br /><sub><b>TenOfTens</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=TenOfTens" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://ditisjens.be/"><img src="https://avatars.githubusercontent.com/u/9415391?v=4?s=110" width="110px;" alt="waffle"/><br /><sub><b>waffle</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=insert-waffle" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/QveenSi"><img src="https://avatars.githubusercontent.com/u/19945501?v=4?s=110" width="110px;" alt="Yevhenii Huzii"/><br /><sub><b>Yevhenii Huzii</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=QveenSi" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/veenone"><img src="https://avatars.githubusercontent.com/u/3839381?v=4?s=110" width="110px;" alt="Achmad Fienan Rahardianto"/><br /><sub><b>Achmad Fienan Rahardianto</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=veenone" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/QveenSi"><img src="https://avatars.githubusercontent.com/u/19945501?v=4?s=110" width="110px;" alt="Yevhenii Huzii"/><br /><sub><b>Yevhenii Huzii</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=QveenSi" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/chrisweirich"><img src="https://avatars.githubusercontent.com/u/97299851?v=4?s=110" width="110px;" alt="Christian Weirich"/><br /><sub><b>Christian Weirich</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=chrisweirich" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/denzfarid"><img src="https://avatars.githubusercontent.com/u/1294403?v=4?s=110" width="110px;" alt="denzfarid"/><br /><sub><b>denzfarid</b></sub></a><br /></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ntbutler-nbcs"><img src="https://avatars.githubusercontent.com/u/94018771?v=4?s=110" width="110px;" alt="ntbutler-nbcs"/><br /><sub><b>ntbutler-nbcs</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=ntbutler-nbcs" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://naveensrinivasan.dev"><img src="https://avatars.githubusercontent.com/u/172697?v=4?s=110" width="110px;" alt="Naveen"/><br /><sub><b>Naveen</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=naveensrinivasan" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mikeroq"><img src="https://avatars.githubusercontent.com/u/55674383?v=4?s=110" width="110px;" alt="Mike Roquemore"/><br /><sub><b>Mike Roquemore</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=mikeroq" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/reederda"><img src="https://avatars.githubusercontent.com/u/7991086?v=4?s=110" width="110px;" alt="Daniel Reeder"/><br /><sub><b>Daniel Reeder</b></sub></a><br /><a href="#translation-reederda" title="Translation">🌍</a> <a href="#translation-reederda" title="Translation">🌍</a> <a href="https://github.com/snipe/snipe-it/commits?author=reederda" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/vickyjaura183"><img src="https://avatars.githubusercontent.com/u/109422491?v=4?s=110" width="110px;" alt="vickyjaura183"/><br /><sub><b>vickyjaura183</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=vickyjaura183" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/julian-piehl"><img src="https://avatars.githubusercontent.com/u/32363424?v=4?s=110" width="110px;" alt="Peace"/><br /><sub><b>Peace</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=julian-piehl" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/kylegordon"><img src="https://avatars.githubusercontent.com/u/231528?v=4?s=110" width="110px;" alt="Kyle Gordon"/><br /><sub><b>Kyle Gordon</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=kylegordon" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.bfh.ch"><img src="https://avatars.githubusercontent.com/u/53009155?v=4?s=110" width="110px;" alt="Katharina Drexel"/><br /><sub><b>Katharina Drexel</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=sunflowerbofh" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://david.sferruzza.fr/"><img src="https://avatars.githubusercontent.com/u/1931963?v=4?s=110" width="110px;" alt="David Sferruzza"/><br /><sub><b>David Sferruzza</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=dsferruzza" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/rnelsonee"><img src="https://avatars.githubusercontent.com/u/19511639?v=4?s=110" width="110px;" alt="Rick Nelson"/><br /><sub><b>Rick Nelson</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=rnelsonee" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/BasO12"><img src="https://avatars.githubusercontent.com/u/94169344?v=4?s=110" width="110px;" alt="BasO12"/><br /><sub><b>BasO12</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=BasO12" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Vautia"><img src="https://avatars.githubusercontent.com/u/111710123?v=4?s=110" width="110px;" alt="Vautia"/><br /><sub><b>Vautia</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=Vautia" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://www.littlehart.net/atthekeyboard"><img src="https://avatars.githubusercontent.com/u/28321?v=4?s=110" width="110px;" alt="Chris Hartjes"/><br /><sub><b>Chris Hartjes</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=chartjes" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/geo-chen"><img src="https://avatars.githubusercontent.com/u/2404584?v=4?s=110" width="110px;" alt="geo-chen"/><br /><sub><b>geo-chen</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=geo-chen" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/nh314"><img src="https://avatars.githubusercontent.com/u/6006620?v=4?s=110" width="110px;" alt="Phan Nguyen"/><br /><sub><b>Phan Nguyen</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=nh314" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/StarlessNights"><img src="https://avatars.githubusercontent.com/u/115993812?v=4?s=110" width="110px;" alt="Iisakki Jaakkola"/><br /><sub><b>Iisakki Jaakkola</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=StarlessNights" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://bandism.net/"><img src="https://avatars.githubusercontent.com/u/22633385?v=4?s=110" width="110px;" alt="Ikko Ashimine"/><br /><sub><b>Ikko Ashimine</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=eltociear" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lukasfehling"><img src="https://avatars.githubusercontent.com/u/56871540?v=4?s=110" width="110px;" alt="Lukas Fehling"/><br /><sub><b>Lukas Fehling</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=lukasfehling" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fernando-almeida"><img src="https://avatars.githubusercontent.com/u/1975990?v=4?s=110" width="110px;" alt="Fernando Almeida"/><br /><sub><b>Fernando Almeida</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=fernando-almeida" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/akemidx"><img src="https://avatars.githubusercontent.com/u/116301219?v=4?s=110" width="110px;" alt="akemidx"/><br /><sub><b>akemidx</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=akemidx" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://oguz.site"><img src="https://avatars.githubusercontent.com/u/144778?v=4?s=110" width="110px;" alt="Oguz Bilgic"/><br /><sub><b>Oguz Bilgic</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=oguzbilgic" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/scoo73r"><img src="https://avatars.githubusercontent.com/u/9262438?v=4?s=110" width="110px;" alt="Scooter Crawford"/><br /><sub><b>Scooter Crawford</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=scoo73r" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/subdriven"><img src="https://avatars.githubusercontent.com/u/5957345?v=4?s=110" width="110px;" alt="subdriven"/><br /><sub><b>subdriven</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=subdriven" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/AndrewSav"><img src="https://avatars.githubusercontent.com/u/658865?v=4?s=110" width="110px;" alt="Andrew Savinykh"/><br /><sub><b>Andrew Savinykh</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=AndrewSav" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://kenchan0130.github.io"><img src="https://avatars.githubusercontent.com/u/1155067?v=4?s=110" width="110px;" alt="Tadayuki Onishi"/><br /><sub><b>Tadayuki Onishi</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=kenchan0130" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/floschoepfer"><img src="https://avatars.githubusercontent.com/u/112496896?v=4?s=110" width="110px;" alt="Florian"/><br /><sub><b>Florian</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=floschoepfer" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://spencerlong.com"><img src="https://avatars.githubusercontent.com/u/7305753?v=4?s=110" width="110px;" alt="Spencer Long"/><br /><sub><b>Spencer Long</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=spencerrlongg" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/marcusmoore"><img src="https://avatars.githubusercontent.com/u/1141514?v=4?s=110" width="110px;" alt="Marcus Moore"/><br /><sub><b>Marcus Moore</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=marcusmoore" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Mezzle"><img src="https://avatars.githubusercontent.com/u/570639?v=4?s=110" width="110px;" alt="Martin Meredith"/><br /><sub><b>Martin Meredith</b></sub></a><br /></td>
<td align="center" valign="top" width="14.28%"><a href="http://dboth.de"><img src="https://avatars.githubusercontent.com/u/5731963?v=4?s=110" width="110px;" alt="dboth"/><br /><sub><b>dboth</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=dboth" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zacharyfleck"><img src="https://avatars.githubusercontent.com/u/87536651?v=4?s=110" width="110px;" alt="Zachary Fleck"/><br /><sub><b>Zachary Fleck</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=zacharyfleck" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/vikaas-cyper"><img src="https://avatars.githubusercontent.com/u/74609912?v=4?s=110" width="110px;" alt="VIKAAS-A"/><br /><sub><b>VIKAAS-A</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=vikaas-cyper" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ak-piracha"><img src="https://avatars.githubusercontent.com/u/88882041?v=4?s=110" width="110px;" alt="Abdul Kareem"/><br /><sub><b>Abdul Kareem</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=ak-piracha" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/NojoudAlshehri"><img src="https://avatars.githubusercontent.com/u/111287779?v=4?s=110" width="110px;" alt="NojoudAlshehri"/><br /><sub><b>NojoudAlshehri</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=NojoudAlshehri" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/stefanstidlffg"><img src="https://avatars.githubusercontent.com/u/54367449?v=4?s=110" width="110px;" alt="Stefan Stidl"/><br /><sub><b>Stefan Stidl</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=stefanstidlffg" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/qay21"><img src="https://avatars.githubusercontent.com/u/87803479?v=4?s=110" width="110px;" alt="Quentin Aymard"/><br /><sub><b>Quentin Aymard</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=qay21" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/cram42"><img src="https://avatars.githubusercontent.com/u/5396871?v=4?s=110" width="110px;" alt="Grant Le Roux"/><br /><sub><b>Grant Le Roux</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=cram42" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://@singrity"><img src="https://avatars.githubusercontent.com/u/58479551?v=4?s=110" width="110px;" alt="Bogdan"/><br /><sub><b>Bogdan</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=Singrity" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mmanjos"><img src="https://avatars.githubusercontent.com/u/3483684?v=4?s=110" width="110px;" alt="mmanjos"/><br /><sub><b>mmanjos</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=mmanjos" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://azooz2014.github.io/"><img src="https://avatars.githubusercontent.com/u/7429229?v=4?s=110" width="110px;" alt="Abdelaziz Faki"/><br /><sub><b>Abdelaziz Faki</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=Azooz2014" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bilias"><img src="https://avatars.githubusercontent.com/u/47315739?v=4?s=110" width="110px;" alt="bilias"/><br /><sub><b>bilias</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=bilias" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/coach1988"><img src="https://avatars.githubusercontent.com/u/2565989?v=4?s=110" width="110px;" alt="coach1988"/><br /><sub><b>coach1988</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=coach1988" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mauro-miatello"><img src="https://avatars.githubusercontent.com/u/11910225?v=4?s=110" width="110px;" alt="MrM"/><br /><sub><b>MrM</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=mauro-miatello" title="Code">💻</a></td>
</tr>
</tbody>
</table>
<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->
| [<img src="https://avatars3.githubusercontent.com/u/197404?v=3" width="110px;"/><br /><sub>snipe</sub>](http://www.snipe.net)<br />[💻](https://github.com/snipe/snipe-it/commits?author=snipe "Code") [🚇](#infra-snipe "Infrastructure (Hosting, Build-Tools, etc)") [📖](https://github.com/snipe/snipe-it/commits?author=snipe "Documentation") [⚠️](https://github.com/snipe/snipe-it/commits?author=snipe "Tests") [🐛](https://github.com/snipe/snipe-it/issues?q=author%3Asnipe "Bug reports") [🎨](#design-snipe "Design") [👀](#review-snipe "Reviewed Pull Requests") | [<img src="https://avatars0.githubusercontent.com/u/36335?v=3" width="110px;"/><br /><sub>Brady Wetherington</sub>](http://www.uberbrady.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=uberbrady "Code") [📖](https://github.com/snipe/snipe-it/commits?author=uberbrady "Documentation") [🚇](#infra-uberbrady "Infrastructure (Hosting, Build-Tools, etc)") [👀](#review-uberbrady "Reviewed Pull Requests") | [<img src="https://avatars0.githubusercontent.com/u/3803132?v=3" width="110px;"/><br /><sub>Daniel Meltzer</sub>](https://github.com/dmeltzer)<br />[💻](https://github.com/snipe/snipe-it/commits?author=dmeltzer "Code") [⚠️](https://github.com/snipe/snipe-it/commits?author=dmeltzer "Tests") [📖](https://github.com/snipe/snipe-it/commits?author=dmeltzer "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/1609106?v=3" width="110px;"/><br /><sub>Michael T</sub>](http://www.tuckertechonline.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mtucker6784 "Code") | [<img src="https://avatars2.githubusercontent.com/u/3274937?v=3" width="110px;"/><br /><sub>madd15</sub>](https://github.com/madd15)<br />[📖](https://github.com/snipe/snipe-it/commits?author=madd15 "Documentation") [💬](#question-madd15 "Answering Questions") | [<img src="https://avatars2.githubusercontent.com/u/894126?v=3" width="110px;"/><br /><sub>Vincent Sposato</sub>](https://github.com/vsposato)<br />[💻](https://github.com/snipe/snipe-it/commits?author=vsposato "Code") | [<img src="https://avatars0.githubusercontent.com/u/1639757?v=3" width="110px;"/><br /><sub>Andrea Bergamasco</sub>](https://github.com/vjandrea)<br />[💻](https://github.com/snipe/snipe-it/commits?author=vjandrea "Code") |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| [<img src="https://avatars0.githubusercontent.com/u/10640152?v=3" width="110px;"/><br /><sub>Karol</sub>](https://github.com/kpawelski)<br />[🌍](#translation-kpawelski "Translation") [💻](https://github.com/snipe/snipe-it/commits?author=kpawelski "Code") | [<img src="https://avatars3.githubusercontent.com/u/600106?v=3" width="110px;"/><br /><sub>morph027</sub>](http://blog.morph027.de/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=morph027 "Code") | [<img src="https://avatars3.githubusercontent.com/u/22935755?v=3" width="110px;"/><br /><sub>fvleminckx</sub>](https://github.com/fvleminckx)<br />[🚇](#infra-fvleminckx "Infrastructure (Hosting, Build-Tools, etc)") | [<img src="https://avatars2.githubusercontent.com/u/15633547?v=3" width="110px;"/><br /><sub>itsupportcmsukorg</sub>](https://github.com/itsupportcmsukorg)<br />[💻](https://github.com/snipe/snipe-it/commits?author=itsupportcmsukorg "Code") [🐛](https://github.com/snipe/snipe-it/issues?q=author%3Aitsupportcmsukorg "Bug reports") | [<img src="https://avatars3.githubusercontent.com/u/12373799?v=3" width="110px;"/><br /><sub>Frank</sub>](https://override.io)<br />[💻](https://github.com/snipe/snipe-it/commits?author=base-zero "Code") | [<img src="https://avatars0.githubusercontent.com/u/10137?v=3" width="110px;"/><br /><sub>Deleted user</sub>](https://github.com/ghost)<br />[🌍](#translation-ghost "Translation") [💻](https://github.com/snipe/snipe-it/commits?author=ghost "Code") | [<img src="https://avatars1.githubusercontent.com/u/10802313?v=3" width="110px;"/><br /><sub>tiagom62</sub>](https://github.com/tiagom62)<br />[💻](https://github.com/snipe/snipe-it/commits?author=tiagom62 "Code") [🚇](#infra-tiagom62 "Infrastructure (Hosting, Build-Tools, etc)") |
| [<img src="https://avatars3.githubusercontent.com/u/2389047?v=3" width="110px;"/><br /><sub>Ryan Stafford</sub>](https://github.com/rystaf)<br />[💻](https://github.com/snipe/snipe-it/commits?author=rystaf "Code") | [<img src="https://avatars2.githubusercontent.com/u/10345935?v=3" width="110px;"/><br /><sub>Eammon Hanlon</sub>](https://github.com/ehanlon)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ehanlon "Code") | [<img src="https://avatars0.githubusercontent.com/u/441924?v=3" width="110px;"/><br /><sub>zjean</sub>](https://github.com/zjean)<br />[💻](https://github.com/snipe/snipe-it/commits?author=zjean "Code") | [<img src="https://avatars0.githubusercontent.com/u/12660103?v=3" width="110px;"/><br /><sub>Matthias Frei</sub>](http://www.frei.media)<br />[💻](https://github.com/snipe/snipe-it/commits?author=FREImedia "Code") | [<img src="https://avatars0.githubusercontent.com/u/3767518?v=3" width="110px;"/><br /><sub>opsydev</sub>](https://github.com/opsydev)<br />[💻](https://github.com/snipe/snipe-it/commits?author=opsydev "Code") | [<img src="https://avatars1.githubusercontent.com/u/82290?v=3" width="110px;"/><br /><sub>Daniel Dreier</sub>](http://www.ddreier.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ddreier "Code") | [<img src="https://avatars0.githubusercontent.com/u/23448?v=3" width="110px;"/><br /><sub>Nikolai Prokoschenko</sub>](http://rassie.org)<br />[💻](https://github.com/snipe/snipe-it/commits?author=rassie "Code") |
| [<img src="https://avatars0.githubusercontent.com/u/13452757?v=3" width="110px;"/><br /><sub>Drew</sub>](https://github.com/YetAnotherCodeMonkey)<br />[💻](https://github.com/snipe/snipe-it/commits?author=YetAnotherCodeMonkey "Code") | [<img src="https://avatars0.githubusercontent.com/u/1342320?v=3" width="110px;"/><br /><sub>Walter</sub>](https://github.com/merid14)<br />[💻](https://github.com/snipe/snipe-it/commits?author=merid14 "Code") | [<img src="https://avatars3.githubusercontent.com/u/11254614?v=3" width="110px;"/><br /><sub>Petr Baloun</sub>](https://github.com/balous)<br />[💻](https://github.com/snipe/snipe-it/commits?author=balous "Code") | [<img src="https://avatars0.githubusercontent.com/u/6117660?v=3" width="110px;"/><br /><sub>reidblomquist</sub>](https://github.com/reidblomquist)<br />[📖](https://github.com/snipe/snipe-it/commits?author=reidblomquist "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/539914?v=3" width="110px;"/><br /><sub>Mathieu Kooiman</sub>](https://github.com/mathieuk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mathieuk "Code") | [<img src="https://avatars3.githubusercontent.com/u/6606421?v=3" width="110px;"/><br /><sub>csayre</sub>](https://github.com/csayre)<br />[📖](https://github.com/snipe/snipe-it/commits?author=csayre "Documentation") | [<img src="https://avatars1.githubusercontent.com/u/768488?v=3" width="110px;"/><br /><sub>Adam Dunson</sub>](https://github.com/adamdunson)<br />[💻](https://github.com/snipe/snipe-it/commits?author=adamdunson "Code") |
| [<img src="https://avatars0.githubusercontent.com/u/5547470?v=3" width="110px;"/><br /><sub>Hereward</sub>](https://github.com/thehereward)<br />[💻](https://github.com/snipe/snipe-it/commits?author=thehereward "Code") | [<img src="https://avatars0.githubusercontent.com/u/5802977?v=3" width="110px;"/><br /><sub>swoopdk</sub>](https://github.com/swoopdk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=swoopdk "Code") | [<img src="https://avatars1.githubusercontent.com/u/3470403?v=3" width="110px;"/><br /><sub>Abdullah Alansari</sub>](https://linkedin.com/in/ahimta)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Ahimta "Code") | [<img src="https://avatars0.githubusercontent.com/u/796443?v=3" width="110px;"/><br /><sub>Micael Rodrigues</sub>](https://github.com/MicaelRodrigues)<br />[💻](https://github.com/snipe/snipe-it/commits?author=MicaelRodrigues "Code") | [<img src="https://avatars0.githubusercontent.com/u/614564?v=3" width="110px;"/><br /><sub>Patrick Gallagher</sub>](http://macadmincorner.com)<br />[📖](https://github.com/snipe/snipe-it/commits?author=patgmac "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/7165922?v=3" width="110px;"/><br /><sub>Miliamber</sub>](https://github.com/Miliamber)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Miliamber "Code") | [<img src="https://avatars3.githubusercontent.com/u/861766?v=3" width="110px;"/><br /><sub>hawk554</sub>](https://github.com/hawk554)<br />[💻](https://github.com/snipe/snipe-it/commits?author=hawk554 "Code") |
| [<img src="https://avatars1.githubusercontent.com/u/1695622?v=3" width="110px;"/><br /><sub>Justin Kerr</sub>](http://jbirdkerr.net)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jbirdkerr "Code") | [<img src="https://avatars3.githubusercontent.com/u/11426176?v=3" width="110px;"/><br /><sub>Ira W. Snyder</sub>](http://www.irasnyder.com/devel/)<br />[📖](https://github.com/snipe/snipe-it/commits?author=irasnyd "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/2475759?v=3" width="110px;"/><br /><sub>Aladin Alaily</sub>](https://github.com/aalaily)<br />[💻](https://github.com/snipe/snipe-it/commits?author=aalaily "Code") | [<img src="https://avatars0.githubusercontent.com/u/10247644?v=3" width="110px;"/><br /><sub>Chase Hansen</sub>](https://github.com/kobie-chasehansen)<br />[💻](https://github.com/snipe/snipe-it/commits?author=kobie-chasehansen "Code") [💬](#question-kobie-chasehansen "Answering Questions") [🐛](https://github.com/snipe/snipe-it/issues?q=author%3Akobie-chasehansen "Bug reports") | [<img src="https://avatars2.githubusercontent.com/u/13545400?v=3" width="110px;"/><br /><sub>IDM Helpdesk</sub>](https://github.com/IDM-Helpdesk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=IDM-Helpdesk "Code") | [<img src="https://avatars2.githubusercontent.com/u/614439?v=3" width="110px;"/><br /><sub>Kai</sub>](http://balticer.de)<br />[💻](https://github.com/snipe/snipe-it/commits?author=balticer "Code") | [<img src="https://avatars1.githubusercontent.com/u/8762511?v=3" width="110px;"/><br /><sub>Michael Daniels</sub>](http://www.michaeldaniels.me)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mdaniels5757 "Code") |
| [<img src="https://avatars3.githubusercontent.com/u/1532660?v=3" width="110px;"/><br /><sub>Tom Castleman</sub>](http://tomcastleman.me)<br />[💻](https://github.com/snipe/snipe-it/commits?author=tomcastleman "Code") | [<img src="https://avatars3.githubusercontent.com/u/10723243?v=3" width="110px;"/><br /><sub>Daniel Nemanic</sub>](https://github.com/DanielNemanic)<br />[💻](https://github.com/snipe/snipe-it/commits?author=DanielNemanic "Code") | [<img src="https://avatars0.githubusercontent.com/u/150648?v=3" width="110px;"/><br /><sub>SouthWolf</sub>](https://github.com/southwolf)<br />[💻](https://github.com/snipe/snipe-it/commits?author=southwolf "Code") | [<img src="https://avatars2.githubusercontent.com/u/131616?v=3" width="110px;"/><br /><sub>Ivar Nesje</sub>](https://github.com/ivarne)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ivarne "Code") | [<img src="https://avatars1.githubusercontent.com/u/62333?v=3" width="110px;"/><br /><sub>Jérémy Benoist</sub>](http://www.j0k3r.net)<br />[📖](https://github.com/snipe/snipe-it/commits?author=j0k3r "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/724344?v=3" width="110px;"/><br /><sub>Chris Leathley</sub>](https://github.com/cleathley)<br />[🚇](#infra-cleathley "Infrastructure (Hosting, Build-Tools, etc)") | [<img src="https://avatars0.githubusercontent.com/u/972498?v=3" width="110px;"/><br /><sub>splaer</sub>](https://github.com/splaer)<br />[🐛](https://github.com/snipe/snipe-it/issues?q=author%3Asplaer "Bug reports") [💻](https://github.com/snipe/snipe-it/commits?author=splaer "Code") |
| [<img src="https://avatars1.githubusercontent.com/u/967362?v=3" width="110px;"/><br /><sub>Joe Ferguson</sub>](http://www.joeferguson.me)<br />[💻](https://github.com/snipe/snipe-it/commits?author=svpernova09 "Code") | [<img src="https://avatars3.githubusercontent.com/u/6108682?v=3" width="110px;"/><br /><sub>diwanicki</sub>](https://github.com/diwanicki)<br />[💻](https://github.com/snipe/snipe-it/commits?author=diwanicki "Code") [📖](https://github.com/snipe/snipe-it/commits?author=diwanicki "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/2527115?v=3" width="110px;"/><br /><sub>Lee Thoong Ching</sub>](https://github.com/pakkua80)<br />[📖](https://github.com/snipe/snipe-it/commits?author=pakkua80 "Documentation") [💻](https://github.com/snipe/snipe-it/commits?author=pakkua80 "Code") | [<img src="https://avatars1.githubusercontent.com/u/461491?v=3" width="110px;"/><br /><sub>Marek Šuppa</sub>](http://shu.io)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mrshu "Code") | [<img src="https://avatars1.githubusercontent.com/u/8693762?v=3" width="110px;"/><br /><sub>Juan J. Martinez</sub>](https://github.com/mizar1616)<br />[🌍](#translation-mizar1616 "Translation") | [<img src="https://avatars1.githubusercontent.com/u/1458388?v=3" width="110px;"/><br /><sub>R Ryan Dial</sub>](https://github.com/rrdial)<br />[🌍](#translation-rrdial "Translation") | [<img src="https://avatars2.githubusercontent.com/u/2871745?v=3" width="110px;"/><br /><sub>Andrej Manduch</sub>](https://github.com/burlito)<br />[📖](https://github.com/snipe/snipe-it/commits?author=burlito "Documentation") |
| [<img src="https://avatars0.githubusercontent.com/u/8341172?v=3" width="110px;"/><br /><sub>Jay Richards</sub>](http://www.cordeos.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=technogenus "Code") | [<img src="https://avatars2.githubusercontent.com/u/7295127?v=3" width="110px;"/><br /><sub>Alexander Innes</sub>](https://necurity.co.uk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=leostat "Code") | [<img src="https://avatars2.githubusercontent.com/u/334485?v=3" width="110px;"/><br /><sub>Danny Garcia</sub>](https://buzzedword.codes)<br />[💻](https://github.com/snipe/snipe-it/commits?author=buzzedword "Code") | [<img src="https://avatars2.githubusercontent.com/u/366855?v=3" width="110px;"/><br /><sub>archpoint</sub>](https://github.com/archpoint)<br />[💻](https://github.com/snipe/snipe-it/commits?author=archpoint "Code") | [<img src="https://avatars1.githubusercontent.com/u/67991?v=3" width="110px;"/><br /><sub>Jake McGraw</sub>](http://www.jakemcgraw.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jakemcgraw "Code") | [<img src="https://avatars1.githubusercontent.com/u/1714374?v=3" width="110px;"/><br /><sub>FleischKarussel</sub>](https://github.com/FleischKarussel)<br />[📖](https://github.com/snipe/snipe-it/commits?author=FleischKarussel "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/319644?v=3" width="110px;"/><br /><sub>Dylan Yi</sub>](https://github.com/feeva)<br />[💻](https://github.com/snipe/snipe-it/commits?author=feeva "Code") |
| [<img src="https://avatars2.githubusercontent.com/u/857740?v=3" width="110px;"/><br /><sub>Gil Rutkowski</sub>](http://FlashingCursor.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=flashingcursor "Code") | [<img src="https://avatars3.githubusercontent.com/u/129360?v=3" width="110px;"/><br /><sub>Desmond Morris</sub>](http://www.desmondmorris.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=desmondmorris "Code") | [<img src="https://avatars2.githubusercontent.com/u/52936?v=3" width="110px;"/><br /><sub>Nick Peelman</sub>](http://peelman.us)<br />[💻](https://github.com/snipe/snipe-it/commits?author=peelman "Code") | [<img src="https://avatars0.githubusercontent.com/u/53161?v=3" width="110px;"/><br /><sub>Abraham Vegh</sub>](https://abrahamvegh.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=abrahamvegh "Code") | [<img src="https://avatars0.githubusercontent.com/u/2818680?v=3" width="110px;"/><br /><sub>Mohamed Rashid</sub>](https://github.com/rashivkp)<br />[📖](https://github.com/snipe/snipe-it/commits?author=rashivkp "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/1509456?v=3" width="110px;"/><br /><sub>Kasey</sub>](http://hinchk.github.io)<br />[💻](https://github.com/snipe/snipe-it/commits?author=HinchK "Code") | [<img src="https://avatars2.githubusercontent.com/u/10522541?v=3" width="110px;"/><br /><sub>Brett</sub>](https://github.com/BrettFagerlund)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=BrettFagerlund "Tests") |
| [<img src="https://avatars2.githubusercontent.com/u/16108587?v=3" width="110px;"/><br /><sub>Jason Spriggs</sub>](http://jasonspriggs.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jasonspriggs "Code") | [<img src="https://avatars2.githubusercontent.com/u/1134568?v=3" width="110px;"/><br /><sub>Nate Felton</sub>](http://n8felton.wordpress.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=n8felton "Code") | [<img src="https://avatars2.githubusercontent.com/u/14036694?v=3" width="110px;"/><br /><sub>Manasses Ferreira</sub>](http://homepages.dcc.ufmg.br/~manassesferreira)<br />[💻](https://github.com/snipe/snipe-it/commits?author=manassesferreira "Code") | [<img src="https://avatars0.githubusercontent.com/u/15913949?v=3" width="110px;"/><br /><sub>Steve</sub>](https://github.com/steveelwood)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=steveelwood "Tests") | [<img src="https://avatars1.githubusercontent.com/u/3361683?v=3" width="110px;"/><br /><sub>matc</sub>](http://twitter.com/matc)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=matc "Tests") | [<img src="https://avatars3.githubusercontent.com/u/7405702?v=3" width="110px;"/><br /><sub>Cole R. Davis</sub>](http://www.davisracingteam.com)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=VanillaNinjaD "Tests") | [<img src="https://avatars2.githubusercontent.com/u/10167681?v=3" width="110px;"/><br /><sub>gibsonjoshua55</sub>](https://github.com/gibsonjoshua55)<br />[💻](https://github.com/snipe/snipe-it/commits?author=gibsonjoshua55 "Code") |
| [<img src="https://avatars2.githubusercontent.com/u/2809241?v=4" width="110px;"/><br /><sub>Robin Temme</sub>](https://github.com/zwerch)<br />[💻](https://github.com/snipe/snipe-it/commits?author=zwerch "Code") | [<img src="https://avatars0.githubusercontent.com/u/6961695?v=4" width="110px;"/><br /><sub>Iman</sub>](https://github.com/imanghafoori1)<br />[💻](https://github.com/snipe/snipe-it/commits?author=imanghafoori1 "Code") | [<img src="https://avatars1.githubusercontent.com/u/6551003?v=4" width="110px;"/><br /><sub>Richard Hofman</sub>](https://github.com/richardhofman6)<br />[💻](https://github.com/snipe/snipe-it/commits?author=richardhofman6 "Code") | [<img src="https://avatars0.githubusercontent.com/u/3697569?v=4" width="110px;"/><br /><sub>gizzmojr</sub>](https://github.com/gizzmojr)<br />[💻](https://github.com/snipe/snipe-it/commits?author=gizzmojr "Code") | [<img src="https://avatars3.githubusercontent.com/u/404729?v=4" width="110px;"/><br /><sub>Jenny Li</sub>](https://github.com/imjennyli)<br />[📖](https://github.com/snipe/snipe-it/commits?author=imjennyli "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/869227?v=4" width="110px;"/><br /><sub>Geoff Young</sub>](https://github.com/GeoffYoung)<br />[💻](https://github.com/snipe/snipe-it/commits?author=GeoffYoung "Code") | [<img src="https://avatars3.githubusercontent.com/u/1068477?v=4" width="110px;"/><br /><sub>Elliot Blackburn</sub>](http://www.elliotblackburn.com)<br />[📖](https://github.com/snipe/snipe-it/commits?author=BlueHatbRit "Documentation") |
| [<img src="https://avatars1.githubusercontent.com/u/6357451?v=4" width="110px;"/><br /><sub>Tõnis Ormisson</sub>](http://andmemasin.eu)<br />[💻](https://github.com/snipe/snipe-it/commits?author=TonisOrmisson "Code") | [<img src="https://avatars0.githubusercontent.com/u/449411?v=4" width="110px;"/><br /><sub>Nicolai Essig</sub>](http://www.nicolai-essig.de)<br />[💻](https://github.com/snipe/snipe-it/commits?author=thakilla "Code") | [<img src="https://avatars1.githubusercontent.com/u/14809698?v=4" width="110px;"/><br /><sub>Danielle</sub>](https://github.com/techincolor)<br />[📖](https://github.com/snipe/snipe-it/commits?author=techincolor "Documentation") | [<img src="https://avatars1.githubusercontent.com/u/18545156?v=4" width="110px;"/><br /><sub>Lawrence</sub>](https://github.com/TheVakman)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=TheVakman "Tests") [🐛](https://github.com/snipe/snipe-it/issues?q=author%3ATheVakman "Bug reports") | [<img src="https://avatars1.githubusercontent.com/u/22473767?v=4" width="110px;"/><br /><sub>uknzaeinozpas</sub>](https://github.com/uknzaeinozpas)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=uknzaeinozpas "Tests") [💻](https://github.com/snipe/snipe-it/commits?author=uknzaeinozpas "Code") | [<img src="https://avatars3.githubusercontent.com/u/422752?v=4" width="110px;"/><br /><sub>Ryan</sub>](https://github.com/Gelob)<br />[📖](https://github.com/snipe/snipe-it/commits?author=Gelob "Documentation") | [<img src="https://avatars1.githubusercontent.com/u/10672546?v=4" width="110px;"/><br /><sub>vcordes79</sub>](https://github.com/vcordes79)<br />[💻](https://github.com/snipe/snipe-it/commits?author=vcordes79 "Code") |
| [<img src="https://avatars3.githubusercontent.com/u/27958330?v=4" width="110px;"/><br /><sub>fordster78</sub>](https://github.com/fordster78)<br />[💻](https://github.com/snipe/snipe-it/commits?author=fordster78 "Code") | [<img src="https://avatars0.githubusercontent.com/u/34064225?v=4" width="110px;"/><br /><sub>CronKz</sub>](https://github.com/CronKz)<br />[💻](https://github.com/snipe/snipe-it/commits?author=CronKz "Code") [🌍](#translation-CronKz "Translation") | [<img src="https://avatars1.githubusercontent.com/u/585486?v=4" width="110px;"/><br /><sub>Tim Bishop</sub>](https://github.com/tdb)<br />[💻](https://github.com/snipe/snipe-it/commits?author=tdb "Code") | [<img src="https://avatars2.githubusercontent.com/u/5384694?v=4" width="110px;"/><br /><sub>Sean McIlvenna</sub>](https://www.seanmcilvenna.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=seanmcilvenna "Code") | [<img src="https://avatars3.githubusercontent.com/u/36515590?v=4" width="110px;"/><br /><sub>cepacs</sub>](https://github.com/cepacs)<br />[🐛](https://github.com/snipe/snipe-it/issues?q=author%3Acepacs "Bug reports") [📖](https://github.com/snipe/snipe-it/commits?author=cepacs "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/37537300?v=4" width="110px;"/><br /><sub>lea-mink</sub>](https://github.com/lea-mink)<br />[💻](https://github.com/snipe/snipe-it/commits?author=lea-mink "Code") | [<img src="https://avatars0.githubusercontent.com/u/7140719?v=4" width="110px;"/><br /><sub>Hannah Tinkler</sub>](https://github.com/hannahtinkler)<br />[💻](https://github.com/snipe/snipe-it/commits?author=hannahtinkler "Code") |
| [<img src="https://avatars1.githubusercontent.com/u/1086388?v=4" width="110px;"/><br /><sub>Doeke Zanstra</sub>](https://github.com/doekman)<br />[💻](https://github.com/snipe/snipe-it/commits?author=doekman "Code") | [<img src="https://avatars1.githubusercontent.com/u/4325936?v=4" width="110px;"/><br /><sub>Djamon Staal</sub>](https://www.sdhd.nl/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=SjamonDaal "Code") | [<img src="https://avatars3.githubusercontent.com/u/12306859?v=4" width="110px;"/><br /><sub>Earl Ramirez</sub>](https://github.com/EarlRamirez)<br />[💻](https://github.com/snipe/snipe-it/commits?author=EarlRamirez "Code") | [<img src="https://avatars2.githubusercontent.com/u/8671456?v=4" width="110px;"/><br /><sub>Richard Ray Thomas</sub>](https://github.com/RichardRay)<br />[💻](https://github.com/snipe/snipe-it/commits?author=RichardRay "Code") | [<img src="https://avatars3.githubusercontent.com/u/1852688?v=4" width="110px;"/><br /><sub>Ryan Kuba</sub>](https://www.taisun.io/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=thelamer "Code") | [<img src="https://avatars1.githubusercontent.com/u/6751928?v=4" width="110px;"/><br /><sub>Brian Monroe</sub>](https://github.com/ParadoxGuitarist)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ParadoxGuitarist "Code") | [<img src="https://avatars1.githubusercontent.com/u/605167?v=4" width="110px;"/><br /><sub>plexorama</sub>](https://github.com/plexorama)<br />[💻](https://github.com/snipe/snipe-it/commits?author=plexorama "Code") |
| [<img src="https://avatars2.githubusercontent.com/u/1795149?v=4" width="110px;"/><br /><sub>Till Deeke</sub>](https://tilldeeke.de)<br />[💻](https://github.com/snipe/snipe-it/commits?author=tilldeeke "Code") | [<img src="https://avatars0.githubusercontent.com/u/12634129?v=4" width="110px;"/><br /><sub>5quirrel</sub>](https://github.com/5quirrel)<br />[💻](https://github.com/snipe/snipe-it/commits?author=5quirrel "Code") | [<img src="https://avatars1.githubusercontent.com/u/13071957?v=4" width="110px;"/><br /><sub>Jason</sub>](https://github.com/jasonlshelton)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jasonlshelton "Code") | [<img src="https://avatars3.githubusercontent.com/u/7128321?v=4" width="110px;"/><br /><sub>Antti</sub>](https://github.com/chemfy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=chemfy "Code") | [<img src="https://avatars3.githubusercontent.com/u/10080364?v=4" width="110px;"/><br /><sub>DeusMaximus</sub>](https://github.com/DeusMaximus)<br />[💻](https://github.com/snipe/snipe-it/commits?author=DeusMaximus "Code") | [<img src="https://avatars2.githubusercontent.com/u/16384611?v=4" width="110px;"/><br /><sub>a-royal</sub>](https://github.com/A-ROYAL)<br />[🌍](#translation-A-ROYAL "Translation") | [<img src="https://avatars0.githubusercontent.com/u/5358208?v=4" width="110px;"/><br /><sub>Alberto Aldrigo</sub>](https://github.com/albertoaldrigo)<br />[🌍](#translation-albertoaldrigo "Translation") |
| [<img src="https://avatars0.githubusercontent.com/u/1412342?v=4" width="110px;"/><br /><sub>Alex Stanev</sub>](http://alex.stanev.org/blog)<br />[🌍](#translation-RealEnder "Translation") | [<img src="https://avatars0.githubusercontent.com/u/177295?v=4" width="110px;"/><br /><sub>Andreas Rehm</sub>](http://devel.itsolution2.de)<br />[🌍](#translation-sirrus "Translation") | [<img src="https://avatars0.githubusercontent.com/u/5080535?v=4" width="110px;"/><br /><sub>Andreas Erhard</sub>](https://github.com/xelan)<br />[🌍](#translation-xelan "Translation") | [<img src="https://avatars2.githubusercontent.com/u/142350?v=4" width="110px;"/><br /><sub>Andrés Vanegas Jiménez</sub>](https://github.com/angeldeejay)<br />[🌍](#translation-angeldeejay "Translation") | [<img src="https://avatars0.githubusercontent.com/u/3910403?v=4" width="110px;"/><br /><sub>Antonio Schiavon</sub>](https://github.com/aschiavon91)<br />[🌍](#translation-aschiavon91 "Translation") | [<img src="https://avatars0.githubusercontent.com/u/10464547?v=4" width="110px;"/><br /><sub>benunter</sub>](https://github.com/benunter)<br />[🌍](#translation-benunter "Translation") | [<img src="https://avatars1.githubusercontent.com/u/5038647?v=4" width="110px;"/><br /><sub>Borys Żmuda</sub>](http://catweb24.pl)<br />[🌍](#translation-rudashi "Translation") |
| [<img src="https://avatars0.githubusercontent.com/u/5539359?v=4" width="110px;"/><br /><sub>chibacityblues</sub>](https://github.com/chibacityblues)<br />[🌍](#translation-chibacityblues "Translation") | [<img src="https://avatars1.githubusercontent.com/u/1954830?v=4" width="110px;"/><br /><sub>Chien Wei Lin</sub>](https://github.com/cwlin0416)<br />[🌍](#translation-cwlin0416 "Translation") | [<img src="https://avatars3.githubusercontent.com/u/11700533?v=4" width="110px;"/><br /><sub>Christian Schuster</sub>](https://github.com/Againstreality)<br />[🌍](#translation-Againstreality "Translation") | [<img src="https://avatars1.githubusercontent.com/u/4308704?v=4" width="110px;"/><br /><sub>Christian Stefanus</sub>](http://chriss.webhostid.com)<br />[🌍](#translation-kopi-item "Translation") | [<img src="https://avatars3.githubusercontent.com/u/3009327?v=4" width="110px;"/><br /><sub>wxcafé</sub>](http://wxcafe.net)<br />[🌍](#translation-wxcafe "Translation") | [<img src="https://avatars3.githubusercontent.com/u/35761525?v=4" width="110px;"/><br /><sub>dpyroc</sub>](https://github.com/dpyroc)<br />[🌍](#translation-dpyroc "Translation") | [<img src="https://avatars1.githubusercontent.com/u/2153639?v=4" width="110px;"/><br /><sub>Daniel Friedlmaier</sub>](http://www.friedlmaier.net)<br />[🌍](#translation-da-friedl "Translation") |
| [<img src="https://avatars1.githubusercontent.com/u/2947640?v=4" width="110px;"/><br /><sub>Daniel Heene</sub>](https://github.com/danielheene)<br />[🌍](#translation-danielheene "Translation") | [<img src="https://avatars3.githubusercontent.com/u/319022?v=4" width="110px;"/><br /><sub>danielcb</sub>](https://github.com/danielcb)<br />[🌍](#translation-danielcb "Translation") | [<img src="https://avatars3.githubusercontent.com/u/15846537?v=4" width="110px;"/><br /><sub>Dominik Senti</sub>](https://github.com/dominiksenti)<br />[🌍](#translation-dominiksenti "Translation") | [<img src="https://avatars0.githubusercontent.com/u/25570954?v=4" width="110px;"/><br /><sub>Eric Gautheron</sub>](http://www.konectik.com)<br />[🌍](#translation-EpixFr "Translation") | [<img src="https://avatars1.githubusercontent.com/u/5732623?v=4" width="110px;"/><br /><sub>Erlend Pilø</sub>](https://erlpil.com)<br />[🌍](#translation-Erlpil "Translation") | [<img src="https://avatars0.githubusercontent.com/u/541832?v=4" width="110px;"/><br /><sub>Fabio Rapposelli</sub>](http://fabio.technology)<br />[🌍](#translation-frapposelli "Translation") | [<img src="https://avatars2.githubusercontent.com/u/3605240?v=4" width="110px;"/><br /><sub>Felipe Barros</sub>](https://github.com/fgbs)<br />[🌍](#translation-fgbs "Translation") |
| [<img src="https://avatars0.githubusercontent.com/u/257745?v=4" width="110px;"/><br /><sub>Fernando Possebon</sub>](https://github.com/possebon)<br />[🌍](#translation-possebon "Translation") | [<img src="https://avatars3.githubusercontent.com/u/2540832?v=4" width="110px;"/><br /><sub>gdraque</sub>](https://github.com/gdraque)<br />[🌍](#translation-gdraque "Translation") | [<img src="https://avatars0.githubusercontent.com/u/23440381?v=4" width="110px;"/><br /><sub>Georg Wallisch</sub>](https://github.com/georgwallisch)<br />[🌍](#translation-georgwallisch "Translation") | [<img src="https://avatars1.githubusercontent.com/u/9852832?v=4" width="110px;"/><br /><sub>Gerardo Robles</sub>](https://github.com/jgroblesr85)<br />[🌍](#translation-jgroblesr85 "Translation") | [<img src="https://avatars2.githubusercontent.com/u/11082640?v=4" width="110px;"/><br /><sub>Gluek</sub>](https://t.me/Gluek)<br />[🌍](#translation-mrgluek "Translation") | [<img src="https://avatars0.githubusercontent.com/u/6847946?v=4" width="110px;"/><br /><sub>AdnanAbuShahad</sub>](https://github.com/AdnanAbuShahad)<br />[🌍](#translation-AdnanAbuShahad "Translation") | [<img src="https://avatars1.githubusercontent.com/u/3580608?v=4" width="110px;"/><br /><sub>Hafidzi My</sub>](https://hafidzi.my)<br />[🌍](#translation-hafidzi "Translation") |
| [<img src="https://avatars2.githubusercontent.com/u/205521?v=4" width="110px;"/><br /><sub>Harim Park</sub>](https://github.com/fofwisdom)<br />[🌍](#translation-fofwisdom "Translation") | [<img src="https://avatars2.githubusercontent.com/u/3333841?v=4" width="110px;"/><br /><sub>Henrik Kentsson</sub>](http://www.kentsson.se)<br />[🌍](#translation-Kentsson "Translation") | [<img src="https://avatars0.githubusercontent.com/u/36551034?v=4" width="110px;"/><br /><sub>Husnul Yaqien</sub>](https://github.com/husnulyaqien)<br />[🌍](#translation-husnulyaqien "Translation") | [<img src="https://avatars1.githubusercontent.com/u/2372747?v=4" width="110px;"/><br /><sub>Ibrahim</sub>](http://abaalkhail.org)<br />[🌍](#translation-abaalkh "Translation") | [<img src="https://avatars0.githubusercontent.com/u/1389334?v=4" width="110px;"/><br /><sub>igolman</sub>](https://github.com/igolman)<br />[🌍](#translation-igolman "Translation") | [<img src="https://avatars1.githubusercontent.com/u/3257070?v=4" width="110px;"/><br /><sub>itangiang</sub>](https://github.com/itangiang)<br />[🌍](#translation-itangiang "Translation") | [<img src="https://avatars2.githubusercontent.com/u/14814254?v=4" width="110px;"/><br /><sub>jarby1211</sub>](https://github.com/jarby1211)<br />[🌍](#translation-jarby1211 "Translation") |
| [<img src="https://avatars3.githubusercontent.com/u/6719357?v=4" width="110px;"/><br /><sub>Jhonn Willker</sub>](http://jwillker.com)<br />[🌍](#translation-JohnWillker "Translation") | [<img src="https://avatars2.githubusercontent.com/u/10983635?v=4" width="110px;"/><br /><sub>Jose</sub>](https://github.com/joxelito94)<br />[🌍](#translation-joxelito94 "Translation") | [<img src="https://avatars0.githubusercontent.com/u/5206122?v=4" width="110px;"/><br /><sub>laopangzi</sub>](https://github.com/laopangzi)<br />[🌍](#translation-laopangzi "Translation") | [<img src="https://avatars2.githubusercontent.com/u/79707?v=4" width="110px;"/><br /><sub>Lars Strojny</sub>](http://usrportage.de)<br />[🌍](#translation-lstrojny "Translation") | [<img src="https://avatars0.githubusercontent.com/u/389801?v=4" width="110px;"/><br /><sub>MarcosBL</sub>](http://twitter.com/marcosbl)<br />[🌍](#translation-MarcosBL "Translation") | [<img src="https://avatars3.githubusercontent.com/u/35664606?v=4" width="110px;"/><br /><sub>marie joy cajes</sub>](https://github.com/mariejoyacajes)<br />[🌍](#translation-mariejoyacajes "Translation") | [<img src="https://avatars2.githubusercontent.com/u/3052816?v=4" width="110px;"/><br /><sub>Mark S. Johansen</sub>](http://www.markjohansen.dk)<br />[🌍](#translation-msjohansen "Translation") |
| [<img src="https://avatars2.githubusercontent.com/u/982885?v=4" width="110px;"/><br /><sub>Martin Stub</sub>](http://martinstub.dk)<br />[🌍](#translation-stubben "Translation") | [<img src="https://avatars2.githubusercontent.com/u/28959963?v=4" width="110px;"/><br /><sub>Meyer Flavio</sub>](https://github.com/meyerf99)<br />[🌍](#translation-meyerf99 "Translation") | [<img src="https://avatars3.githubusercontent.com/u/796443?v=4" width="110px;"/><br /><sub>Micael Rodrigues</sub>](https://github.com/MicaelRodrigues)<br />[🌍](#translation-MicaelRodrigues "Translation") | [<img src="https://avatars0.githubusercontent.com/u/10481331?v=4" width="110px;"/><br /><sub>Mikael Rasmussen</sub>](http://rubixy.com/)<br />[🌍](#translation-mikaelssen "Translation") | [<img src="https://avatars1.githubusercontent.com/u/1544552?v=4" width="110px;"/><br /><sub>IxFail</sub>](https://github.com/IxFail)<br />[🌍](#translation-IxFail "Translation") | [<img src="https://avatars3.githubusercontent.com/u/18483118?v=4" width="110px;"/><br /><sub>Mohammed Fota</sub>](http://www.mohammedfota.com)<br />[🌍](#translation-MohammedFota "Translation") | [<img src="https://avatars0.githubusercontent.com/u/227080?v=4" width="110px;"/><br /><sub>Moayad Alserihi</sub>](https://github.com/omego)<br />[🌍](#translation-omego "Translation") |
| [<img src="https://avatars0.githubusercontent.com/u/1680266?v=4" width="110px;"/><br /><sub>saymd</sub>](https://github.com/saymd)<br />[🌍](#translation-saymd "Translation") | [<img src="https://avatars0.githubusercontent.com/u/1826808?v=4" width="110px;"/><br /><sub>Patrik Larsson</sub>](https://nordsken.se)<br />[🌍](#translation-pooot "Translation") | [<img src="https://avatars1.githubusercontent.com/u/20584746?v=4" width="110px;"/><br /><sub>drcryo</sub>](https://github.com/drcryo)<br />[🌍](#translation-drcryo "Translation") | [<img src="https://avatars1.githubusercontent.com/u/19408004?v=4" width="110px;"/><br /><sub>pawel1615</sub>](https://github.com/pawel1615)<br />[🌍](#translation-pawel1615 "Translation") | [<img src="https://avatars2.githubusercontent.com/u/23340468?v=4" width="110px;"/><br /><sub>bodrovics</sub>](https://github.com/bodrovics)<br />[🌍](#translation-bodrovics "Translation") | [<img src="https://avatars0.githubusercontent.com/u/3257654?v=4" width="110px;"/><br /><sub>priatna</sub>](https://github.com/priatna)<br />[🌍](#translation-priatna "Translation") | [<img src="https://avatars1.githubusercontent.com/u/5358374?v=4" width="110px;"/><br /><sub>Fan Jiang</sub>](https://amayume.net)<br />[🌍](#translation-ProfFan "Translation") |
| [<img src="https://avatars1.githubusercontent.com/u/22555451?v=4" width="110px;"/><br /><sub>ragnarcx</sub>](https://github.com/ragnarcx)<br />[🌍](#translation-ragnarcx "Translation") | [<img src="https://avatars2.githubusercontent.com/u/18654582?v=4" width="110px;"/><br /><sub>Rein van Haaren</sub>](http://www.reinvanhaaren.nl/)<br />[🌍](#translation-reinvanhaaren "Translation") | [<img src="https://avatars1.githubusercontent.com/u/386672?v=4" width="110px;"/><br /><sub>Teguh Dwicaksana</sub>](http://dheche.songolimo.net)<br />[🌍](#translation-dheche "Translation") | [<img src="https://avatars2.githubusercontent.com/u/2572552?v=4" width="110px;"/><br /><sub>fraccie</sub>](https://github.com/FRaccie)<br />[🌍](#translation-FRaccie "Translation") | [<img src="https://avatars0.githubusercontent.com/u/35182720?v=4" width="110px;"/><br /><sub>vinzruzell</sub>](https://github.com/vinzruzell)<br />[🌍](#translation-vinzruzell "Translation") | [<img src="https://avatars1.githubusercontent.com/u/7883603?v=4" width="110px;"/><br /><sub>Kevin Austin</sub>](http://kevinaustin.com)<br />[🌍](#translation-vipsystem "Translation") | [<img src="https://avatars3.githubusercontent.com/u/3861828?v=4" width="110px;"/><br /><sub>Wira Sandy</sub>](http://azuraweb.xyz)<br />[🌍](#translation-wira-sandy "Translation") |
| [<img src="https://avatars2.githubusercontent.com/u/8663789?v=4" width="110px;"/><br /><sub>Илья</sub>](https://github.com/GrayHoax)<br />[🌍](#translation-GrayHoax "Translation") | [<img src="https://avatars3.githubusercontent.com/u/30119111?v=4" width="110px;"/><br /><sub>GodUseVPN</sub>](https://github.com/godusevpn)<br />[🌍](#translation-godusevpn "Translation") | [<img src="https://avatars1.githubusercontent.com/u/745576?v=4" width="110px;"/><br /><sub>周周</sub>](https://github.com/EngrZhou)<br />[🌍](#translation-EngrZhou "Translation") | [<img src="https://avatars3.githubusercontent.com/u/1631095?v=4" width="110px;"/><br /><sub>Sam</sub>](https://github.com/takuy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=takuy "Code") | [<img src="https://avatars1.githubusercontent.com/u/264022?v=4" width="110px;"/><br /><sub>Azerothian</sub>](https://www.illisian.com.au)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Azerothian "Code") | [<img src="https://avatars1.githubusercontent.com/u/4930051?v=4" width="110px;"/><br /><sub>Wes Hulette</sub>](http://macfoo.wordpress.com/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jwhulette "Code") | [<img src="https://avatars0.githubusercontent.com/u/8134591?v=4" width="110px;"/><br /><sub>patrict</sub>](https://github.com/patrict)<br />[💻](https://github.com/snipe/snipe-it/commits?author=patrict "Code") |
| [<img src="https://avatars3.githubusercontent.com/u/2611616?v=4" width="110px;"/><br /><sub>Dmitriy Minaev</sub>](https://github.com/VELIKII-DIVAN)<br />[💻](https://github.com/snipe/snipe-it/commits?author=VELIKII-DIVAN "Code") | [<img src="https://avatars0.githubusercontent.com/u/5132245?v=4" width="110px;"/><br /><sub>liquidhorse</sub>](https://github.com/liquidhorse)<br />[💻](https://github.com/snipe/snipe-it/commits?author=liquidhorse "Code") | [<img src="https://avatars1.githubusercontent.com/u/183678?v=4" width="110px;"/><br /><sub>Jordi Boggiano</sub>](https://seld.be/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Seldaek "Code") | [<img src="https://avatars0.githubusercontent.com/u/653557?v=4" width="110px;"/><br /><sub>Ivan Nieto</sub>](https://github.com/inietov)<br />[💻](https://github.com/snipe/snipe-it/commits?author=inietov "Code") | [<img src="https://avatars2.githubusercontent.com/u/6764151?v=4" width="110px;"/><br /><sub>Ben RUBSON</sub>](https://github.com/benrubson)<br />[💻](https://github.com/snipe/snipe-it/commits?author=benrubson "Code") | [<img src="https://avatars2.githubusercontent.com/u/8554558?v=4" width="110px;"/><br /><sub>NMathar</sub>](https://github.com/NMathar)<br />[💻](https://github.com/snipe/snipe-it/commits?author=NMathar "Code") | [<img src="https://avatars1.githubusercontent.com/u/139566?v=4" width="110px;"/><br /><sub>Steffen</sub>](https://github.com/smb)<br />[💻](https://github.com/snipe/snipe-it/commits?author=smb "Code") |
| [<img src="https://avatars0.githubusercontent.com/u/6609453?v=4" width="110px;"/><br /><sub>Sxderp</sub>](https://github.com/Sxderp)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Sxderp "Code") | [<img src="https://avatars1.githubusercontent.com/u/4807843?v=4" width="110px;"/><br /><sub>fanta8897</sub>](https://github.com/fanta8897)<br />[💻](https://github.com/snipe/snipe-it/commits?author=fanta8897 "Code") | [<img src="https://avatars2.githubusercontent.com/u/2576509?v=4" width="110px;"/><br /><sub>Andrey Bolonin</sub>](https://andreybolonin.com/phpconsulting/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=andreybolonin "Code") | [<img src="https://avatars3.githubusercontent.com/u/2173307?v=4" width="110px;"/><br /><sub>shinayoshi</sub>](http://www.shinayoshi.net/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=shinayoshi "Code") | [<img src="https://avatars3.githubusercontent.com/u/2130159?v=4" width="110px;"/><br /><sub>Hubert</sub>](https://github.com/reuser)<br />[💻](https://github.com/snipe/snipe-it/commits?author=reuser "Code") | [<img src="https://avatars0.githubusercontent.com/u/6865789?v=4" width="110px;"/><br /><sub>KeenRivals</sub>](https://brashear.me)<br />[💻](https://github.com/snipe/snipe-it/commits?author=KeenRivals "Code") | [<img src="https://avatars3.githubusercontent.com/u/2902513?v=4" width="110px;"/><br /><sub>omyno</sub>](https://github.com/omyno)<br />[💻](https://github.com/snipe/snipe-it/commits?author=omyno "Code") |
| [<img src="https://avatars1.githubusercontent.com/u/6271335?v=4" width="110px;"/><br /><sub>Evgeny</sub>](https://github.com/jackka)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jackka "Code") | [<img src="https://avatars2.githubusercontent.com/u/1169963?v=4" width="110px;"/><br /><sub>Colin Campbell</sub>](https://digitalist.se)<br />[💻](https://github.com/snipe/snipe-it/commits?author=colin-campbell "Code") | [<img src="https://avatars3.githubusercontent.com/u/2872098?v=4" width="110px;"/><br /><sub>Ľubomír Kučera</sub>](https://github.com/lubo)<br />[💻](https://github.com/snipe/snipe-it/commits?author=lubo "Code") | [<img src="https://avatars3.githubusercontent.com/u/570639?v=4" width="110px;"/><br /><sub>Martin Meredith</sub>](https://www.sourceguru.net)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Mezzle "Code") | [<img src="https://avatars1.githubusercontent.com/u/7632599?v=4" width="110px;"/><br /><sub>Tim Farmer</sub>](https://github.com/timothyfarmer)<br />[💻](https://github.com/snipe/snipe-it/commits?author=timothyfarmer "Code") | [<img src="https://avatars0.githubusercontent.com/u/17459600?v=4" width="110px;"/><br /><sub>Marián Skrip</sub>](https://github.com/mskrip)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mskrip "Code") | [<img src="https://avatars2.githubusercontent.com/u/47435081?v=4" width="110px;"/><br /><sub>Godfrey Martinez</sub>](https://github.com/Godmartinz)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Godmartinz "Code") |
| [<img src="https://avatars1.githubusercontent.com/u/2075128?v=4" width="110px;"/><br /><sub>bigtreeEdo</sub>](https://github.com/bigtreeEdo)<br />[💻](https://github.com/snipe/snipe-it/commits?author=bigtreeEdo "Code") | [<img src="https://avatars0.githubusercontent.com/u/5000430?v=4" width="110px;"/><br /><sub>Colin McNeil</sub>](https://colinmcneil.me/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ColinMcNeil "Code") | [<img src="https://avatars0.githubusercontent.com/u/421625?v=4" width="110px;"/><br /><sub>JoKneeMo</sub>](https://github.com/JoKneeMo)<br />[💻](https://github.com/snipe/snipe-it/commits?author=JoKneeMo "Code") | [<img src="https://avatars0.githubusercontent.com/u/54849013?v=4" width="110px;"/><br /><sub>Joshi</sub>](http://www.redbridge.se)<br />[💻](https://github.com/snipe/snipe-it/commits?author=joshi-redbridge "Code") | [<img src="https://avatars2.githubusercontent.com/u/15731458?v=4" width="110px;"/><br /><sub>Anthony Burns</sub>](https://github.com/anthonypburns)<br />[💻](https://github.com/snipe/snipe-it/commits?author=anthonypburns "Code") | [<img src="https://avatars1.githubusercontent.com/u/63399474?v=4" width="110px;"/><br /><sub>johnson-yi</sub>](https://github.com/johnson-yi)<br />[💻](https://github.com/snipe/snipe-it/commits?author=johnson-yi "Code") | [<img src="https://avatars1.githubusercontent.com/u/1862720?v=4" width="110px;"/><br /><sub>Sanjay Govind</sub>](https://tangentmc.net)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sanjay900 "Code") |
| [<img src="https://avatars0.githubusercontent.com/u/1255375?v=4" width="110px;"/><br /><sub>Peter Upfold</sub>](https://peter.upfold.org.uk/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=PeterUpfold "Code") | [<img src="https://avatars2.githubusercontent.com/u/961717?v=4" width="110px;"/><br /><sub>Jared Biel</sub>](https://github.com/jbiel)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jbiel "Code") | [<img src="https://avatars1.githubusercontent.com/u/1733625?v=4" width="110px;"/><br /><sub>Dampfklon</sub>](https://github.com/dampfklon)<br />[💻](https://github.com/snipe/snipe-it/commits?author=dampfklon "Code") | [<img src="https://avatars2.githubusercontent.com/u/52973156?v=4" width="110px;"/><br /><sub>Charles Hamilton</sub>](https://communityclosing.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=chamilton-ccn "Code") | [<img src="https://avatars.githubusercontent.com/u/551789?v=4" width="110px;"/><br /><sub>Giuseppe Iannello</sub>](https://github.com/giannello)<br />[💻](https://github.com/snipe/snipe-it/commits?author=giannello "Code") | [<img src="https://avatars.githubusercontent.com/u/3691490?v=4" width="110px;"/><br /><sub>Peter Dave Hello</sub>](https://www.peterdavehello.org/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=PeterDaveHello "Code") | [<img src="https://avatars.githubusercontent.com/u/6106332?v=4" width="110px;"/><br /><sub>sigmoidal</sub>](https://github.com/sigmoidal)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sigmoidal "Code") |
| [<img src="https://avatars.githubusercontent.com/u/2082554?v=4" width="110px;"/><br /><sub>Vincent Lainé</sub>](https://github.com/phenixdotnet)<br />[💻](https://github.com/snipe/snipe-it/commits?author=phenixdotnet "Code") | [<img src="https://avatars.githubusercontent.com/u/1943040?v=4" width="110px;"/><br /><sub>Lucas Pleß</sub>](http://www.lucas-pless.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=derlucas "Code") | [<img src="https://avatars.githubusercontent.com/u/472804?v=4" width="110px;"/><br /><sub>Ian Littman</sub>](http://twitter.com/iansltx)<br />[💻](https://github.com/snipe/snipe-it/commits?author=iansltx "Code") | [<img src="https://avatars.githubusercontent.com/u/3519029?v=4" width="110px;"/><br /><sub>João Paulo</sub>](https://github.com/PauloLuna)<br />[💻](https://github.com/snipe/snipe-it/commits?author=PauloLuna "Code") | [<img src="https://avatars.githubusercontent.com/u/70443365?v=4" width="110px;"/><br /><sub>ThoBur</sub>](https://github.com/ThoBur)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ThoBur "Code") | [<img src="https://avatars.githubusercontent.com/u/1972329?v=4" width="110px;"/><br /><sub>Alexander Chibrikin</sub>](http://phpprofi.ru/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=alek13 "Code") | [<img src="https://avatars.githubusercontent.com/u/438332?v=4" width="110px;"/><br /><sub>Anthony Winstanley</sub>](https://github.com/winstan)<br />[💻](https://github.com/snipe/snipe-it/commits?author=winstan "Code") |
| [<img src="https://avatars.githubusercontent.com/u/3075214?v=4" width="110px;"/><br /><sub>Folke</sub>](https://github.com/fashberg)<br />[💻](https://github.com/snipe/snipe-it/commits?author=fashberg "Code") | [<img src="https://avatars.githubusercontent.com/u/1351571?v=4" width="110px;"/><br /><sub>Bennett Blodinger</sub>](https://github.com/benwa)<br />[💻](https://github.com/snipe/snipe-it/commits?author=benwa "Code") | [<img src="https://avatars.githubusercontent.com/u/2974631?v=4" width="110px;"/><br /><sub>NMC</sub>](https://nmc.dev)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ncareau "Code") | [<img src="https://avatars.githubusercontent.com/u/52182449?v=4" width="110px;"/><br /><sub>andres-baller</sub>](https://github.com/andres-baller)<br />[💻](https://github.com/snipe/snipe-it/commits?author=andres-baller "Code") | [<img src="https://avatars.githubusercontent.com/u/67109348?v=4" width="110px;"/><br /><sub>sean-borg</sub>](https://github.com/sean-borg)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sean-borg "Code") | [<img src="https://avatars.githubusercontent.com/u/32170051?v=4" width="110px;"/><br /><sub>EDVLeer</sub>](https://github.com/EDVLeer)<br />[💻](https://github.com/snipe/snipe-it/commits?author=EDVLeer "Code") | [<img src="https://avatars.githubusercontent.com/u/23075196?v=4" width="110px;"/><br /><sub>Kurokat</sub>](https://github.com/Kurokat)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Kurokat "Code") |
| [<img src="https://avatars.githubusercontent.com/u/915514?v=4" width="110px;"/><br /><sub>Kevin Köllmann</sub>](https://www.kevinkoellmann.de)<br />[💻](https://github.com/snipe/snipe-it/commits?author=koelle25 "Code") | [<img src="https://avatars.githubusercontent.com/u/49025941?v=4" width="110px;"/><br /><sub>sw-mreyes</sub>](https://github.com/sw-mreyes)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sw-mreyes "Code") | [<img src="https://avatars.githubusercontent.com/u/70129?v=4" width="110px;"/><br /><sub>Joel Pittet</sub>](https://pittet.ca)<br />[💻](https://github.com/snipe/snipe-it/commits?author=joelpittet "Code") | [<img src="https://avatars.githubusercontent.com/u/792695?v=4" width="110px;"/><br /><sub>Eli Young</sub>](https://elyscape.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=elyscape "Code") | [<img src="https://avatars.githubusercontent.com/u/317015?v=4" width="110px;"/><br /><sub>Raell Dottin</sub>](https://github.com/raelldottin)<br />[💻](https://github.com/snipe/snipe-it/commits?author=raelldottin "Code") | [<img src="https://avatars.githubusercontent.com/u/1446856?v=4" width="110px;"/><br /><sub>Tom Misilo</sub>](https://github.com/misilot)<br />[💻](https://github.com/snipe/snipe-it/commits?author=misilot "Code") | [<img src="https://avatars.githubusercontent.com/u/4496300?v=4" width="110px;"/><br /><sub>David Davenne</sub>](http://david.davenne.be)<br />[💻](https://github.com/snipe/snipe-it/commits?author=JuustoMestari "Code") |
| [<img src="https://avatars.githubusercontent.com/u/9255772?v=4" width="110px;"/><br /><sub>Mark Stenglein</sub>](https://markstenglein.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ocelotsloth "Code") | [<img src="https://avatars.githubusercontent.com/u/35658596?v=4" width="110px;"/><br /><sub>ajsy</sub>](https://github.com/ajsy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ajsy "Code") | [<img src="https://avatars.githubusercontent.com/u/3628035?v=4" width="110px;"/><br /><sub>Jan Kiesewetter</sub>](https://github.com/t3easy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=t3easy "Code") | [<img src="https://avatars.githubusercontent.com/u/79449630?v=4" width="110px;"/><br /><sub>Tetrachloromethane250</sub>](https://github.com/Tetrachloromethane250)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Tetrachloromethane250 "Code") | [<img src="https://avatars.githubusercontent.com/u/22004482?v=4" width="110px;"/><br /><sub>Lars Kajes</sub>](https://www.kajes.se/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=kajes "Code") | [<img src="https://avatars.githubusercontent.com/u/13993216?v=4" width="110px;"/><br /><sub>Joly0</sub>](https://github.com/Joly0)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Joly0 "Code") | [<img src="https://avatars.githubusercontent.com/u/1501022?v=4" width="110px;"/><br /><sub>theburger</sub>](https://github.com/limeless)<br />[💻](https://github.com/snipe/snipe-it/commits?author=limeless "Code") |
| [<img src="https://avatars.githubusercontent.com/u/36065681?v=4" width="110px;"/><br /><sub>David Valin Alonso</sub>](https://github.com/deivishome)<br />[💻](https://github.com/snipe/snipe-it/commits?author=deivishome "Code") | [<img src="https://avatars.githubusercontent.com/u/8290389?v=4" width="110px;"/><br /><sub>andreaci</sub>](https://github.com/andreaci)<br />[💻](https://github.com/snipe/snipe-it/commits?author=andreaci "Code") | [<img src="https://avatars.githubusercontent.com/u/1828542?v=4" width="110px;"/><br /><sub>Jelle Sebreghts</sub>](http://www.jellesebreghts.be)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Jelle-S "Code") | [<img src="https://avatars.githubusercontent.com/u/11180862?v=4" width="110px;"/><br /><sub>Michael Pietsch</sub>](https://github.com/Skywalker-11)<br /> | [<img src="https://avatars.githubusercontent.com/u/22068886?v=4" width="110px;"/><br /><sub>Masudul Haque Shihab</sub>](https://github.com/sh1hab)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sh1hab "Code") | [<img src="https://avatars.githubusercontent.com/u/16099942?v=4" width="110px;"/><br /><sub>Supapong Areeprasertkul</sub>](http://www.freedomdive.com/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=zybersup "Code") | [<img src="https://avatars.githubusercontent.com/u/207358?v=4" width="110px;"/><br /><sub>Peter Sarossy</sub>](https://github.com/psarossy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=psarossy "Code") |
| [<img src="https://avatars.githubusercontent.com/u/11823649?v=4" width="110px;"/><br /><sub>Renee Margaret McConahy</sub>](https://github.com/nepella)<br />[💻](https://github.com/snipe/snipe-it/commits?author=nepella "Code") | [<img src="https://avatars.githubusercontent.com/u/5553884?v=4" width="110px;"/><br /><sub>JohnnyPicnic</sub>](https://github.com/JohnnyPicnic)<br />[💻](https://github.com/snipe/snipe-it/commits?author=JohnnyPicnic "Code") | [<img src="https://avatars.githubusercontent.com/u/8799594?v=4" width="110px;"/><br /><sub>markbrule</sub>](https://github.com/markbrule)<br />[💻](https://github.com/snipe/snipe-it/commits?author=markbrule "Code") | [<img src="https://avatars.githubusercontent.com/u/1962801?v=4" width="110px;"/><br /><sub>Mike Campbell</sub>](https://github.com/mikecmpbll)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mikecmpbll "Code") | [<img src="https://avatars.githubusercontent.com/u/11973217?v=4" width="110px;"/><br /><sub>tbrconnect</sub>](https://github.com/tbrconnect)<br />[💻](https://github.com/snipe/snipe-it/commits?author=tbrconnect "Code") | [<img src="https://avatars.githubusercontent.com/u/12447225?v=4" width="110px;"/><br /><sub>kcoyo</sub>](https://github.com/kcoyo)<br />[💻](https://github.com/snipe/snipe-it/commits?author=kcoyo "Code") | [<img src="https://avatars.githubusercontent.com/u/494017?v=4" width="110px;"/><br /><sub>Travis Miller</sub>](https://travismiller.com/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=travismiller "Code") |
| [<img src="https://avatars.githubusercontent.com/u/1975640?v=4" width="110px;"/><br /><sub>Evan Taylor</sub>](https://github.com/Delta5)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Delta5 "Code") | [<img src="https://avatars.githubusercontent.com/u/8735148?v=4" width="110px;"/><br /><sub>Petri Asikainen</sub>](https://github.com/PetriAsi)<br />[💻](https://github.com/snipe/snipe-it/commits?author=PetriAsi "Code") | [<img src="https://avatars.githubusercontent.com/u/11424540?v=4" width="110px;"/><br /><sub>derdeagle</sub>](https://github.com/derdeagle)<br />[💻](https://github.com/snipe/snipe-it/commits?author=derdeagle "Code") | [<img src="https://avatars.githubusercontent.com/u/176950?v=4" width="110px;"/><br /><sub>Mike Frysinger</sub>](https://wh0rd.org/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=vapier "Code") | [<img src="https://avatars.githubusercontent.com/u/22044358?v=4" width="110px;"/><br /><sub>ALPHA</sub>](https://github.com/AL4AL)<br />[💻](https://github.com/snipe/snipe-it/commits?author=AL4AL "Code") | [<img src="https://avatars.githubusercontent.com/u/1042587?v=4" width="110px;"/><br /><sub>FliegenKLATSCH</sub>](https://www.ifern.de)<br />[💻](https://github.com/snipe/snipe-it/commits?author=FliegenKLATSCH "Code") | [<img src="https://avatars.githubusercontent.com/u/442138?v=4" width="110px;"/><br /><sub>Jeremy Price</sub>](https://github.com/jerm)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jerm "Code") |
| [<img src="https://avatars.githubusercontent.com/u/84392209?v=4" width="110px;"/><br /><sub>Toreg87</sub>](https://github.com/Toreg87)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Toreg87 "Code") | [<img src="https://avatars.githubusercontent.com/u/67638596?v=4" width="110px;"/><br /><sub>Matthew Nickson</sub>](https://github.com/Computroniks)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Computroniks "Code") | [<img src="https://avatars.githubusercontent.com/u/1646397?v=4" width="110px;"/><br /><sub>Jethro Nederhof</sub>](https://jethron.id.au)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jethron "Code") | [<img src="https://avatars.githubusercontent.com/u/23289826?v=4" width="110px;"/><br /><sub>Oskar Stenberg</sub>](https://github.com/01ste02)<br />[💻](https://github.com/snipe/snipe-it/commits?author=01ste02 "Code") | [<img src="https://avatars.githubusercontent.com/u/82208283?v=4" width="110px;"/><br /><sub>Robert-Azelis</sub>](https://github.com/Robert-Azelis)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Robert-Azelis "Code") | [<img src="https://avatars.githubusercontent.com/u/60648387?v=4" width="110px;"/><br /><sub>Alexander William Smith</sub>](https://github.com/alwism)<br />[💻](https://github.com/snipe/snipe-it/commits?author=alwism "Code") | [<img src="https://avatars.githubusercontent.com/u/24418301?v=4" width="110px;"/><br /><sub>LEITWERK AG</sub>](https://www.leitwerk.de/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=leitwerk-ag "Code") |
| [<img src="https://avatars.githubusercontent.com/u/1911435?v=4" width="110px;"/><br /><sub>Adam</sub>](http://www.aboutcher.co.uk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=adamboutcher "Code") | [<img src="https://avatars.githubusercontent.com/u/16104273?v=4" width="110px;"/><br /><sub>Ian</sub>](https://snksrv.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sneak-it "Code") | [<img src="https://avatars.githubusercontent.com/u/4023909?v=4" width="110px;"/><br /><sub>Shao Yu-Lung (Allen)</sub>](http://blog.bestlong.idv.tw/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=bestlong "Code") | [<img src="https://avatars.githubusercontent.com/u/76475453?v=4" width="110px;"/><br /><sub>Haxatron</sub>](https://github.com/Haxatron)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Haxatron "Code") | [<img src="https://avatars.githubusercontent.com/u/88776392?v=4" width="110px;"/><br /><sub>PlaneNuts</sub>](https://github.com/PlaneNuts)<br />[💻](https://github.com/snipe/snipe-it/commits?author=PlaneNuts "Code") | [<img src="https://avatars.githubusercontent.com/u/3842948?v=4" width="110px;"/><br /><sub>Bradley Coudriet</sub>](http://bjcpgd.cias.rit.edu)<br />[💻](https://github.com/snipe/snipe-it/commits?author=exula "Code") | [<img src="https://avatars.githubusercontent.com/u/21966173?v=4" width="110px;"/><br /><sub>Dalton Durst</sub>](https://daltondur.st)<br />[💻](https://github.com/snipe/snipe-it/commits?author=UniversalSuperBox "Code") |
| [<img src="https://avatars.githubusercontent.com/u/38761237?v=4" width="110px;"/><br /><sub>Alex Janes</sub>](https://adagiohealth.org)<br />[💻](https://github.com/snipe/snipe-it/commits?author=adagioajanes "Code") | [<img src="https://avatars.githubusercontent.com/u/32387849?v=4" width="110px;"/><br /><sub>Nuraeil</sub>](https://github.com/nuraeil)<br />[💻](https://github.com/snipe/snipe-it/commits?author=nuraeil "Code") | [<img src="https://avatars.githubusercontent.com/u/48162670?v=4" width="110px;"/><br /><sub>TenOfTens</sub>](https://github.com/TenOfTens)<br />[💻](https://github.com/snipe/snipe-it/commits?author=TenOfTens "Code") | [<img src="https://avatars.githubusercontent.com/u/9415391?v=4" width="110px;"/><br /><sub>waffle</sub>](https://ditisjens.be/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=insert-waffle "Code") | [<img src="https://avatars.githubusercontent.com/u/19945501?v=4" width="110px;"/><br /><sub>Yevhenii Huzii</sub>](https://github.com/QveenSi)<br />[💻](https://github.com/snipe/snipe-it/commits?author=QveenSi "Code") | [<img src="https://avatars.githubusercontent.com/u/3839381?v=4" width="110px;"/><br /><sub>Achmad Fienan Rahardianto</sub>](https://github.com/veenone)<br />[💻](https://github.com/snipe/snipe-it/commits?author=veenone "Code") | [<img src="https://avatars.githubusercontent.com/u/19945501?v=4" width="110px;"/><br /><sub>Yevhenii Huzii</sub>](https://github.com/QveenSi)<br />[💻](https://github.com/snipe/snipe-it/commits?author=QveenSi "Code") |
| [<img src="https://avatars.githubusercontent.com/u/97299851?v=4" width="110px;"/><br /><sub>Christian Weirich</sub>](https://github.com/chrisweirich)<br />[💻](https://github.com/snipe/snipe-it/commits?author=chrisweirich "Code") | [<img src="https://avatars.githubusercontent.com/u/1294403?v=4" width="110px;"/><br /><sub>denzfarid</sub>](https://github.com/denzfarid)<br /> | [<img src="https://avatars.githubusercontent.com/u/94018771?v=4" width="110px;"/><br /><sub>ntbutler-nbcs</sub>](https://github.com/ntbutler-nbcs)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ntbutler-nbcs "Code") | [<img src="https://avatars.githubusercontent.com/u/172697?v=4" width="110px;"/><br /><sub>Naveen</sub>](https://naveensrinivasan.dev)<br />[💻](https://github.com/snipe/snipe-it/commits?author=naveensrinivasan "Code") | [<img src="https://avatars.githubusercontent.com/u/55674383?v=4" width="110px;"/><br /><sub>Mike Roquemore</sub>](https://github.com/mikeroq)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mikeroq "Code") | [<img src="https://avatars.githubusercontent.com/u/7991086?v=4" width="110px;"/><br /><sub>Daniel Reeder</sub>](https://github.com/reederda)<br />[🌍](#translation-reederda "Translation") [🌍](#translation-reederda "Translation") [💻](https://github.com/snipe/snipe-it/commits?author=reederda "Code") | [<img src="https://avatars.githubusercontent.com/u/109422491?v=4" width="110px;"/><br /><sub>vickyjaura183</sub>](https://github.com/vickyjaura183)<br />[💻](https://github.com/snipe/snipe-it/commits?author=vickyjaura183 "Code") |
| [<img src="https://avatars.githubusercontent.com/u/32363424?v=4" width="110px;"/><br /><sub>Peace</sub>](https://github.com/julian-piehl)<br />[💻](https://github.com/snipe/snipe-it/commits?author=julian-piehl "Code") | [<img src="https://avatars.githubusercontent.com/u/231528?v=4" width="110px;"/><br /><sub>Kyle Gordon</sub>](https://github.com/kylegordon)<br />[💻](https://github.com/snipe/snipe-it/commits?author=kylegordon "Code") | [<img src="https://avatars.githubusercontent.com/u/53009155?v=4" width="110px;"/><br /><sub>Katharina Drexel</sub>](http://www.bfh.ch)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sunflowerbofh "Code") | [<img src="https://avatars.githubusercontent.com/u/1931963?v=4" width="110px;"/><br /><sub>David Sferruzza</sub>](https://david.sferruzza.fr/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=dsferruzza "Code") | [<img src="https://avatars.githubusercontent.com/u/19511639?v=4" width="110px;"/><br /><sub>Rick Nelson</sub>](https://github.com/rnelsonee)<br />[💻](https://github.com/snipe/snipe-it/commits?author=rnelsonee "Code") | [<img src="https://avatars.githubusercontent.com/u/94169344?v=4" width="110px;"/><br /><sub>BasO12</sub>](https://github.com/BasO12)<br />[💻](https://github.com/snipe/snipe-it/commits?author=BasO12 "Code") | [<img src="https://avatars.githubusercontent.com/u/111710123?v=4" width="110px;"/><br /><sub>Vautia</sub>](https://github.com/Vautia)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Vautia "Code") |
| [<img src="https://avatars.githubusercontent.com/u/28321?v=4" width="110px;"/><br /><sub>Chris Hartjes</sub>](http://www.littlehart.net/atthekeyboard)<br />[💻](https://github.com/snipe/snipe-it/commits?author=chartjes "Code") | [<img src="https://avatars.githubusercontent.com/u/2404584?v=4" width="110px;"/><br /><sub>geo-chen</sub>](https://github.com/geo-chen)<br />[💻](https://github.com/snipe/snipe-it/commits?author=geo-chen "Code") | [<img src="https://avatars.githubusercontent.com/u/6006620?v=4" width="110px;"/><br /><sub>Phan Nguyen</sub>](https://github.com/nh314)<br />[💻](https://github.com/snipe/snipe-it/commits?author=nh314 "Code") | [<img src="https://avatars.githubusercontent.com/u/115993812?v=4" width="110px;"/><br /><sub>Iisakki Jaakkola</sub>](https://github.com/StarlessNights)<br />[💻](https://github.com/snipe/snipe-it/commits?author=StarlessNights "Code") | [<img src="https://avatars.githubusercontent.com/u/22633385?v=4" width="110px;"/><br /><sub>Ikko Ashimine</sub>](https://bandism.net/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=eltociear "Code") | [<img src="https://avatars.githubusercontent.com/u/56871540?v=4" width="110px;"/><br /><sub>Lukas Fehling</sub>](https://github.com/lukasfehling)<br />[💻](https://github.com/snipe/snipe-it/commits?author=lukasfehling "Code") | [<img src="https://avatars.githubusercontent.com/u/1975990?v=4" width="110px;"/><br /><sub>Fernando Almeida</sub>](https://github.com/fernando-almeida)<br />[💻](https://github.com/snipe/snipe-it/commits?author=fernando-almeida "Code") |
| [<img src="https://avatars.githubusercontent.com/u/116301219?v=4" width="110px;"/><br /><sub>akemidx</sub>](https://github.com/akemidx)<br />[💻](https://github.com/snipe/snipe-it/commits?author=akemidx "Code") | [<img src="https://avatars.githubusercontent.com/u/144778?v=4" width="110px;"/><br /><sub>Oguz Bilgic</sub>](http://oguz.site)<br />[💻](https://github.com/snipe/snipe-it/commits?author=oguzbilgic "Code") | [<img src="https://avatars.githubusercontent.com/u/9262438?v=4" width="110px;"/><br /><sub>Scooter Crawford</sub>](https://github.com/scoo73r)<br />[💻](https://github.com/snipe/snipe-it/commits?author=scoo73r "Code") | [<img src="https://avatars.githubusercontent.com/u/5957345?v=4" width="110px;"/><br /><sub>subdriven</sub>](https://github.com/subdriven)<br />[💻](https://github.com/snipe/snipe-it/commits?author=subdriven "Code") | [<img src="https://avatars.githubusercontent.com/u/658865?v=4" width="110px;"/><br /><sub>Andrew Savinykh</sub>](https://github.com/AndrewSav)<br />[💻](https://github.com/snipe/snipe-it/commits?author=AndrewSav "Code") | [<img src="https://avatars.githubusercontent.com/u/1155067?v=4" width="110px;"/><br /><sub>Tadayuki Onishi</sub>](https://kenchan0130.github.io)<br />[💻](https://github.com/snipe/snipe-it/commits?author=kenchan0130 "Code") | [<img src="https://avatars.githubusercontent.com/u/112496896?v=4" width="110px;"/><br /><sub>Florian</sub>](https://github.com/floschoepfer)<br />[💻](https://github.com/snipe/snipe-it/commits?author=floschoepfer "Code") |
| [<img src="https://avatars.githubusercontent.com/u/7305753?v=4" width="110px;"/><br /><sub>Spencer Long</sub>](http://spencerlong.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=spencerrlongg "Code") | [<img src="https://avatars.githubusercontent.com/u/1141514?v=4" width="110px;"/><br /><sub>Marcus Moore</sub>](https://github.com/marcusmoore)<br />[💻](https://github.com/snipe/snipe-it/commits?author=marcusmoore "Code") | [<img src="https://avatars.githubusercontent.com/u/570639?v=4" width="110px;"/><br /><sub>Martin Meredith</sub>](https://github.com/Mezzle)<br /> | [<img src="https://avatars.githubusercontent.com/u/5731963?v=4" width="110px;"/><br /><sub>dboth</sub>](http://dboth.de)<br />[💻](https://github.com/snipe/snipe-it/commits?author=dboth "Code") | [<img src="https://avatars.githubusercontent.com/u/87536651?v=4" width="110px;"/><br /><sub>Zachary Fleck</sub>](https://github.com/zacharyfleck)<br />[💻](https://github.com/snipe/snipe-it/commits?author=zacharyfleck "Code") | [<img src="https://avatars.githubusercontent.com/u/74609912?v=4" width="110px;"/><br /><sub>VIKAAS-A</sub>](https://github.com/vikaas-cyper)<br />[💻](https://github.com/snipe/snipe-it/commits?author=vikaas-cyper "Code") | [<img src="https://avatars.githubusercontent.com/u/88882041?v=4" width="110px;"/><br /><sub>Abdul Kareem</sub>](https://github.com/ak-piracha)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ak-piracha "Code") |
| [<img src="https://avatars.githubusercontent.com/u/111287779?v=4" width="110px;"/><br /><sub>NojoudAlshehri</sub>](https://github.com/NojoudAlshehri)<br />[💻](https://github.com/snipe/snipe-it/commits?author=NojoudAlshehri "Code") | [<img src="https://avatars.githubusercontent.com/u/54367449?v=4" width="110px;"/><br /><sub>Stefan Stidl</sub>](https://github.com/stefanstidlffg)<br />[💻](https://github.com/snipe/snipe-it/commits?author=stefanstidlffg "Code") | [<img src="https://avatars.githubusercontent.com/u/87803479?v=4" width="110px;"/><br /><sub>Quentin Aymard</sub>](https://github.com/qay21)<br />[💻](https://github.com/snipe/snipe-it/commits?author=qay21 "Code") | [<img src="https://avatars.githubusercontent.com/u/5396871?v=4" width="110px;"/><br /><sub>Grant Le Roux</sub>](https://github.com/cram42)<br />[💻](https://github.com/snipe/snipe-it/commits?author=cram42 "Code") | [<img src="https://avatars.githubusercontent.com/u/58479551?v=4" width="110px;"/><br /><sub>Bogdan</sub>](http://@singrity)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Singrity "Code") | [<img src="https://avatars.githubusercontent.com/u/3483684?v=4" width="110px;"/><br /><sub>mmanjos</sub>](https://github.com/mmanjos)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mmanjos "Code") | [<img src="https://avatars.githubusercontent.com/u/7429229?v=4" width="110px;"/><br /><sub>Abdelaziz Faki</sub>](https://azooz2014.github.io/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Azooz2014 "Code") |
| [<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!
+1 -1
View File
@@ -105,7 +105,7 @@ RUN \
&& ln -fs "/var/lib/snipeit/keys/ldap_client_tls.cert" "/var/www/html/storage/ldap_client_tls.cert" \
&& ln -fs "/var/lib/snipeit/keys/ldap_client_tls.key" "/var/www/html/storage/ldap_client_tls.key" \
&& chown docker "/var/lib/snipeit/keys/" \
&& chown -h docker "/var/www/html/storage/" \
&& chown -Rh docker "/var/www/html/storage/" \
&& chmod +x /var/www/html/artisan \
&& echo "Finished setting up application in /var/www/html"
+34 -34
View File
@@ -1,35 +1,35 @@
FROM alpine:3.18.6
FROM alpine:3.19
# Apache + PHP
RUN apk add --no-cache \
apache2 \
php81 \
php81-common \
php81-apache2 \
php81-curl \
php81-ldap \
php81-mysqli \
php81-gd \
php81-xml \
php81-mbstring \
php81-zip \
php81-ctype \
php81-tokenizer \
php81-pdo_mysql \
php81-openssl \
php81-bcmath \
php81-phar \
php81-json \
php81-iconv \
php81-fileinfo \
php81-simplexml \
php81-session \
php81-dom \
php81-xmlwriter \
php81-xmlreader \
php81-sodium \
php81-redis \
php81-pecl-memcached \
php81-exif \
php82 \
php82-common \
php82-apache2 \
php82-curl \
php82-ldap \
php82-mysqli \
php82-gd \
php82-xml \
php82-mbstring \
php82-zip \
php82-ctype \
php82-tokenizer \
php82-pdo_mysql \
php82-openssl \
php82-bcmath \
php82-phar \
php82-json \
php82-iconv \
php82-fileinfo \
php82-simplexml \
php82-session \
php82-dom \
php82-xmlwriter \
php82-xmlreader \
php82-sodium \
php82-redis \
php82-pecl-memcached \
php82-exif \
curl \
wget \
vim \
@@ -42,7 +42,7 @@ COPY docker/column-statistics.cnf /etc/mysql/conf.d/column-statistics.cnf
# Where apache's PID lives
RUN mkdir -p /run/apache2 && chown apache:apache /run/apache2
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php81/php.ini
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php82/php.ini
COPY docker/000-default-2.4.conf /etc/apache2/conf.d/default.conf
# Enable mod_rewrite
@@ -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" ]
+22 -13
View File
@@ -1,17 +1,18 @@
![snipe-it-by-grok](https://github.com/snipe/snipe-it/assets/197404/b515673b-c7c8-4d9a-80f5-9fa58829a602)
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/snipe-it/localized.svg)](https://crowdin.com/project/snipe-it) [![Docker Pulls](https://img.shields.io/docker/pulls/snipe/snipe-it.svg)](https://hub.docker.com/r/snipe/snipe-it/) [![Twitter Follow](https://img.shields.io/twitter/follow/snipeitapp.svg?style=social)](https://twitter.com/snipeitapp) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/553ce52037fc43ea99149785afcfe641)](https://www.codacy.com/app/snipe/snipe-it?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=snipe/snipe-it&amp;utm_campaign=Badge_Grade) [![Tests](https://github.com/snipe/snipe-it/actions/workflows/tests.yml/badge.svg)](https://github.com/snipe/snipe-it/actions/workflows/tests.yml)
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/snipe-it/localized.svg)](https://crowdin.com/project/snipe-it) [![Docker Pulls](https://img.shields.io/docker/pulls/snipe/snipe-it.svg)](https://hub.docker.com/r/snipe/snipe-it/) [![Twitter Follow](https://img.shields.io/twitter/follow/snipeitapp.svg?style=social)](https://twitter.com/snipeitapp) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/553ce52037fc43ea99149785afcfe641)](https://app.codacy.com/gh/snipe/snipe-it/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) [![Tests](https://github.com/snipe/snipe-it/actions/workflows/tests.yml/badge.svg)](https://github.com/snipe/snipe-it/actions/workflows/tests.yml)
[![All Contributors](https://img.shields.io/badge/all_contributors-331-orange.svg?style=flat-square)](#contributing) [![Discord](https://badgen.net/badge/icon/discord?icon=discord&label)](https://discord.gg/yZFtShAcKk)
## Snipe-IT - Open Source Asset Management System
This is a FOSS project for asset management in IT Operations. Knowing who has which laptop, when it was purchased in order to depreciate it correctly, handling software licenses, etc.
It is built on [Laravel 8](http://laravel.com).
It is built on [Laravel 10](http://laravel.com).
Snipe-IT is actively developed and we [release quite frequently](https://github.com/snipe/snipe-it/releases). ([Check out the live demo here](https://snipeitapp.com/demo/).)
__This is web-based software__. This means there is no executable file (aka no .exe files), and it must be run on a web server and accessed through a web browser. It runs on any Mac OSX, flavor of Linux, as well as Windows, and we have a [Docker image](https://snipe-it.readme.io/docs/docker) available if that's what you're into.
> [!TIP]
> __This is web-based software__. This means there is no executable file (aka no .exe files), and it must be run on a web server and accessed through a web browser. It runs on any Mac OSX, any flavor of Linux, as well as Windows, and we have a [Docker image](https://snipe-it.readme.io/docs/docker) available if that's what you're into.
-----
@@ -21,7 +22,7 @@ For instructions on installing and configuring Snipe-IT on your server, check ou
If you're having trouble with the installation, please check the [Common Issues](https://snipe-it.readme.io/docs/common-issues) and [Getting Help](https://snipe-it.readme.io/docs/getting-help) documentation, and search this repository's open *and* closed issues for help.
[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)
<!-- [![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy) -->
-----
### User's Manual
@@ -32,8 +33,9 @@ For help using Snipe-IT, check out the [user's manual](https://snipe-it.readme.i
Feel free to check out the [GitHub Issues for this project](https://github.com/snipe/snipe-it/issues) to open a bug report or see what open issues you can help with. Please search through existing issues (open *and* closed) to see if your question has already been answered before opening a new issue.
**PLEASE see the [Getting Help Guidelines](https://snipe-it.readme.io/docs/getting-help) and [Common Issues](https://snipe-it.readme.io/docs/common-issues) before opening a ticket, and be sure to complete all of the questions in the Github Issue template to help us to help you as quickly as possible.**
> [!IMPORTANT]
> **PLEASE see the [Getting Help Guidelines](https://snipe-it.readme.io/docs/getting-help) and [Common Issues](https://snipe-it.readme.io/docs/common-issues) before opening a ticket, and be sure to complete all of the questions in the Github Issue template to help us to help you as quickly as possible.**
>
-----
### Upgrading
@@ -57,6 +59,9 @@ Please see the [translations documentation](https://snipe-it.readme.io/docs/tran
Since the release of the JSON REST API, several third-party developers have been developing modules and libraries to work with Snipe-IT.
> [!NOTE]
> As these were created by third-parties, Snipe-IT cannot provide support for these project, and you should contact the developers directly if you need assistance. Additionally, Snipe-IT makes no guarantees as to the reliability, accuracy or maintainability of these libraries. Use at your own risk. :)
- [Python Module](https://github.com/jbloomer/SnipeIT-PythonAPI) by [@jbloomer](https://github.com/jbloomer)
- [SnipeSharp - .NET module in C#](https://github.com/barrycarey/SnipeSharp) by [@barrycarey](https://github.com/barrycarey)
- [InQRy -unmaintained-](https://github.com/Microsoft/InQRy) by [@Microsoft](https://github.com/Microsoft)
@@ -67,20 +72,23 @@ 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
As these were created by third-parties, Snipe-IT cannot provide support for these project, and you should contact the developers directly if you need assistance. Additionally, Snipe-IT makes no guarantees as to the reliability, accuracy or maintainability of these libraries. Use at your own risk. :)
- [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.
-----
### Contributing
Please see the documentation on [contributing and developing for Snipe-IT](https://snipe-it.readme.io/docs/contributing-overview).
Please refrain from submitting issues or pull requests generated by fully-automated tools. Maintainers reserve the right, at their sole discretion, to close such submissions and to block any account responsible for them.
Ideally, contributions should follow from a human-to-human discussion in the form of an issue.
Please see the complete documentation on [contributing and developing for Snipe-IT](https://snipe-it.readme.io/docs/contributing-overview).
Please note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.
@@ -92,4 +100,5 @@ The ERD is available [online here](https://drawsql.app/templates/snipe-it).
### Security
To report a security vulnerability, please email security@snipeitapp.com instead of using the issue tracker.
> [!IMPORTANT]
> **To report a security vulnerability, please email security@snipeitapp.com instead of using the issue tracker.**
+1 -1
View File
@@ -20,7 +20,7 @@ APP_DEBUG=true
APP_KEY=base64:glJpcM7BYwWiBggp3SQ/+NlRkqsBQMaGEOjemXqJzOU=
APP_URL=http://localhost:8000
APP_TIMEZONE='UTC'
APP_LOCALE=en
APP_LOCALE=en-US
# --------------------------------------------
# REQUIRED: DATABASE SETTINGS
+4 -4
View File
@@ -38,7 +38,7 @@
"description": "The maximum number of search results that can be returned at one time.",
"value": "500"
},
"MAIL_DRIVER": {
"MAIL_MAILER": {
"description": "Mail driver - Generally SMTP on Heroku - https://snipe-it.readme.io/docs/configuration#required-outgoing-mail-settings",
"value": "smtp"
},
@@ -58,9 +58,9 @@
"description": "SMTP Server Password",
"value": "YOURPASSWORD"
},
"MAIL_ENCRYPTION": {
"description": "Encryption protocol for email sending.",
"value": "null"
"MAIL_TLS_VERIFY_PEER": {
"description": "Ensure validity of TLS certificate on remote mail server",
"value": true
},
"MAIL_FROM_ADDR": {
"description": "Email from address",
@@ -0,0 +1,66 @@
<?php
namespace App\Console\Commands;
use App\Models\Asset;
use Illuminate\Console\Command;
class FixupAssignedToWithoutAssignedType extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'snipeit:assigned-to-fixup
{--debug : Display debugging output}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Fixes up assets that have an assigned_to but no assigned_type';
/**
* Execute the console command.
*/
public function handle()
{
$assets = Asset::whereNull("assigned_type")->whereNotNull("assigned_to")->withTrashed();
$this->withProgressBar($assets->get(), function (Asset $asset) {
//now check each action log, from the most recent backwards, to find the last checkin or checkout
foreach($asset->log()->orderBy("id","desc")->get() as $action_log) {
if($this->option("debug")) {
$this->info("Asset id: " . $asset->id . " action log, action type is: " . $action_log->action_type);
}
switch($action_log->action_type) {
case 'checkin from':
if($this->option("debug")) {
$this->info("Doing a checkin for ".$asset->id);
}
$asset->assigned_to = null;
// if you have a required custom field, we still want to save, and we *don't* want an action_log
$asset->saveQuietly();
return;
case 'checkout':
if($this->option("debug")) {
$this->info("Doing a checkout for " . $asset->id . " picking target type: " . $action_log->target_type);
}
if($asset->assigned_to != $action_log->target_id) {
$this->error("Asset's assigned_to does *NOT* match Action Log's target_id. \$asset->assigned_to=".$asset->assigned_to." vs. \$action_log->target_id=".$action_log->target_id);
//FIXME - do we abort here? Do we try to keep looking? I don't know, this means your data is *really* messed up...
}
$asset->assigned_type = $action_log->target_type;
$asset->saveQuietly(); // see above
return;
}
}
$asset->assigned_to = null; //asset was never checked in or out in its lifetime - it stays 'checked in'
$asset->saveQuietly(); //see above
});
$this->newLine();
$this->info("Assets assigned_type are fixed");
}
}
@@ -7,7 +7,7 @@ use Illuminate\Console\Command;
use App\Models\User;
use Laravel\Passport\TokenRepository;
use Illuminate\Contracts\Validation\Factory as ValidationFactory;
use DB;
use Illuminate\Support\Facades\DB;
class GeneratePersonalAccessToken extends Command
{
+149 -132
View File
@@ -9,7 +9,7 @@ use App\Models\Setting;
use App\Models\Ldap;
use App\Models\User;
use App\Models\Location;
use Log;
use Illuminate\Support\Facades\Log;
class LdapSync extends Command
{
@@ -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' => []];
@@ -126,23 +137,24 @@ class LdapSync extends Command
}
/* Determine which location to assign users to by default. */
$location = null; // TODO - this would be better called "$default_location", which is more explicit about its purpose
$default_location = null;
if ($this->option('location') != '') {
if ($location = Location::where('name', '=', $this->option('location'))->first()) {
if ($default_location = Location::where('name', '=', $this->option('location'))->first()) {
Log::debug('Location name ' . $this->option('location') . ' passed');
Log::debug('Importing to ' . $location->name . ' (' . $location->id . ')');
Log::debug('Importing to '.$default_location->name.' ('.$default_location->id.')');
}
} elseif ($this->option('location_id')) {
//TODO - figure out how or why this is an array?
foreach($this->option('location_id') as $location_id) {
if ($location = Location::where('id', '=', $location_id)->first()) {
if ($default_location = Location::where('id', '=', $location_id)->first()) {
Log::debug('Location ID ' . $location_id . ' passed');
Log::debug('Importing to ' . $location->name . ' (' . $location->id . ')');
Log::debug('Importing to '.$default_location->name.' ('.$default_location->id.')');
}
}
}
if (! isset($location)) {
if (!isset($default_location)) {
Log::debug('That location is invalid or a location was not provided, so no location will be assigned by default.');
}
@@ -183,17 +195,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]);
}
}
@@ -218,76 +230,78 @@ 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['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 = [];
$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_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] ?? '';
$location = $default_location; //initially, set '$location' to the default_location (which may just be `null`)
// ONLY if you are using the "ldap_location" option *AND* you have an actual result
if ($ldap_result_location && $item['location']) {
$location = Location::firstOrCreate([
'name' => $item['location'],
]);
}
$department = Department::firstOrCreate([
'name' => $item['department'],
// ONLY if you are using the "ldap_location" option *AND* you have an actual result
if ($ldap_map["location"] && $item['location']) {
$location = Location::firstOrCreate([
'name' => $item['location'],
]);
}
$department = Department::firstOrCreate([
'name' => $item['department'],
]);
$user = User::where('username', $item['username'])->first();
if ($user) {
// Updating an existing user.
$item['createorupdate'] = 'updated';
} else {
// Creating a new user.
$user = new User;
$user->password = $user->noPassword();
$user->activated = 1; // newly created users can log in by default, unless AD's UAC is in use, or an active flag is set (below)
$item['createorupdate'] = 'created';
}
$user = User::where('username', $item['username'])->first();
if ($user) {
// Updating an existing user.
$item['createorupdate'] = 'updated';
} else {
// Creating a new user.
$user = new User;
$user->password = $user->noPassword();
$user->locale = app()->getLocale();
$user->activated = 1; // newly created users can log in by default, unless AD's UAC is in use, or an active flag is set (below)
$item['createorupdate'] = 'created';
}
//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){
$user->location_id = $location ? $location->id : null;
if($ldap_map["location"] != null){
$user->location_id = $location?->id;
}
if($ldap_result_manager != null){
if($ldap_map["manager"] != null){
if($item['manager'] != null) {
// Check Cache first
if (isset($manager_cache[$item['manager']])) {
@@ -298,13 +312,13 @@ class LdapSync extends Command
try {
$ldap_manager = Ldap::findLdapUsers($item['manager'], -1, $this->option('filter'));
} catch (\Exception $e) {
\Log::warning("Manager lookup caused an exception: " . $e->getMessage() . ". Falling back to direct username lookup");
Log::warning("Manager lookup caused an exception: " . $e->getMessage() . ". Falling back to direct username lookup");
// Hail-mary for Okta manager 'shortnames' - will only work if
// Okta configuration is using full email-address-style usernames
$ldap_manager = [
"count" => 1,
0 => [
$ldap_result_username => [$item['manager']]
$ldap_map["username"] => [$item['manager']]
]
];
}
@@ -313,7 +327,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();
@@ -329,38 +343,38 @@ class LdapSync extends Command
}
}
// Sync activated state for Active Directory.
if ( !empty($ldap_result_active_flag)) { // IF we have an 'active' flag set....
// ....then *most* things that are truthy will activate the user. Anything falsey will deactivate them.
// (Specifically, we don't handle a value of '0.0' correctly)
$raw_value = @$results[$i][$ldap_result_active_flag][0];
$filter_var = filter_var($raw_value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
$boolean_cast = (bool)$raw_value;
// Sync activated state for Active Directory.
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_map["active_flag"]][0];
$filter_var = filter_var($raw_value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
$boolean_cast = (bool) $raw_value;
$user->activated = $filter_var ?? $boolean_cast; // if filter_var() was true or false, use that. If it's null, use the $boolean_cast
$user->activated = $filter_var ?? $boolean_cast; // if filter_var() was true or false, use that. If it's null, use the $boolean_cast
} elseif (array_key_exists('useraccountcontrol', $results[$i]) ) {
// ....otherwise, (ie if no 'active' LDAP flag is defined), IF the UAC setting exists,
// ....then use the UAC setting on the account to determine can-log-in vs. cannot-log-in
} elseif (array_key_exists('useraccountcontrol', $results[$i])) {
// ....otherwise, (ie if no 'active' LDAP flag is defined), IF the UAC setting exists,
// ....then use the UAC setting on the account to determine can-log-in vs. cannot-log-in
/* The following is _probably_ the correct logic, but we can't use it because
some users may have been dependent upon the previous behavior, and this
could cause additional access to be available to users they don't want
to allow to log in.
/* The following is _probably_ the correct logic, but we can't use it because
some users may have been dependent upon the previous behavior, and this
could cause additional access to be available to users they don't want
to allow to log in.
$useraccountcontrol = $results[$i]['useraccountcontrol'][0];
if(
// based on MS docs at: https://support.microsoft.com/en-us/help/305144/how-to-use-useraccountcontrol-to-manipulate-user-account-properties
($useraccountcontrol & 0x200) && // is a NORMAL_ACCOUNT
!($useraccountcontrol & 0x02) && // *and* _not_ ACCOUNTDISABLE
!($useraccountcontrol & 0x10) // *and* _not_ LOCKOUT
) {
$user->activated = 1;
} else {
$user->activated = 0;
} */
$enabled_accounts = [
$useraccountcontrol = $results[$i]['useraccountcontrol'][0];
if(
// based on MS docs at: https://support.microsoft.com/en-us/help/305144/how-to-use-useraccountcontrol-to-manipulate-user-account-properties
($useraccountcontrol & 0x200) && // is a NORMAL_ACCOUNT
!($useraccountcontrol & 0x02) && // *and* _not_ ACCOUNTDISABLE
!($useraccountcontrol & 0x10) // *and* _not_ LOCKOUT
) {
$user->activated = 1;
} else {
$user->activated = 0;
} */
$enabled_accounts = [
'512', // 0x200 NORMAL_ACCOUNT
'544', // 0x220 NORMAL_ACCOUNT, PASSWD_NOTREQD
'66048', // 0x10200 NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD
@@ -373,44 +387,47 @@ class LdapSync extends Command
'4260352', // 0x410200 NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD, DONT_REQ_PREAUTH
'1049088', // 0x100200 NORMAL_ACCOUNT, NOT_DELEGATED
'1114624', // 0x110200 NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD, NOT_DELEGATED,
];
$user->activated = (in_array($results[$i]['useraccountcontrol'][0], $enabled_accounts)) ? 1 : 0;
];
$user->activated = (in_array($results[$i]['useraccountcontrol'][0], $enabled_accounts)) ? 1 : 0;
// If we're not using AD, and there isn't an activated flag set, activate all users
} /* implied 'else' here - leave the $user->activated flag alone. Newly-created accounts will be active.
already-existing accounts will be however the administrator has set them */
} /* implied 'else' here - leave the $user->activated flag alone. Newly-created accounts will be active.
already-existing accounts will be however the administrator has set them */
if ($item['ldap_location_override'] == true) {
$user->location_id = $item['location_id'];
} elseif ((isset($location)) && (! empty($location))) {
if ((is_array($location)) && (array_key_exists('id', $location))) {
$user->location_id = $location['id'];
} elseif (is_object($location)) {
$user->location_id = $location->id;
}
if ($item['ldap_location_override'] == true) {
$user->location_id = $item['location_id'];
} elseif ((isset($location)) && (!empty($location))) {
if ((is_array($location)) && (array_key_exists('id', $location))) {
$user->location_id = $location['id'];
} elseif (is_object($location)) {
$user->location_id = $location->id; //THIS is the magic line, this should do it.
}
}
// TODO - should we be NULLING locations if $location is really `null`, and that's what we came up with?
// will that conflict with any overriding setting that the user set? Like, if they moved someone from
// the 'null' location to somewhere, we wouldn't want to try to override that, right?
$location = null;
$user->ldap_import = 1;
$errors = '';
if ($user->save()) {
$item['note'] = $item['createorupdate'];
$item['status'] = 'success';
if ($item['createorupdate'] === 'created' && $ldap_default_group) {
$user->groups()->attach($ldap_default_group);
}
$user->ldap_import = 1;
$errors = '';
if ($user->save()) {
$item['note'] = $item['createorupdate'];
$item['status'] = 'success';
if ( $item['createorupdate'] === 'created' && $ldap_default_group) {
$user->groups()->attach($ldap_default_group);
}
} else {
foreach ($user->getErrors()->getMessages() as $key => $err) {
$errors .= $err[0];
}
$item['note'] = $errors;
$item['status'] = 'error';
} else {
foreach ($user->getErrors()->getMessages() as $key => $err) {
$errors .= $err[0];
}
$item['note'] = $errors;
$item['status'] = 'error';
}
array_push($summary, $item);
array_push($summary, $item);
}
if ($this->option('summary')) {
+2 -2
View File
@@ -5,7 +5,7 @@ namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\Setting;
use Exception;
use Crypt;
use Illuminate\Support\Facades\Crypt;
/**
* Check if a given ip is in a network
@@ -160,7 +160,7 @@ class LdapTroubleshooter extends Command
$output[] = "-x";
$output[] = "-b ".escapeshellarg($settings->ldap_basedn);
$output[] = "-D ".escapeshellarg($settings->ldap_uname);
$output[] = "-w ".escapeshellarg(\Crypt::Decrypt($settings->ldap_pword));
$output[] = "-w ".escapeshellarg(Crypt::Decrypt($settings->ldap_pword));
$output[] = escapeshellarg(parenthesized_filter($settings->ldap_filter));
if($settings->ldap_tls) {
$this->line("# adding STARTTLS option");
+18 -1
View File
@@ -2,6 +2,7 @@
namespace App\Console\Commands;
use App\Events\UserMerged;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Console\Command;
@@ -51,7 +52,7 @@ class MergeUsersByUsername extends Command
$bad_users = User::where('username', '=', trim($parts[0]))
->whereNull('deleted_at')
->with('assets', 'manager', 'userlog', 'licenses', 'consumables', 'accessories', 'managedLocations')
->with('assets', 'manager', 'userlog', 'licenses', 'consumables', 'accessories', 'managedLocations','uploads', 'acceptances')
->get();
@@ -105,10 +106,26 @@ class MergeUsersByUsername extends Command
$managedLocation->save();
}
foreach ($bad_user->uploads as $upload) {
$this->info('Updating upload log record '.$upload->id.' to user '.$user->id);
$upload->item_id = $user->id;
$upload->save();
}
foreach ($bad_user->acceptances as $acceptance) {
$this->info('Updating acceptance log record '.$acceptance->id.' to user '.$user->id);
$acceptance->item_id = $user->id;
$acceptance->save();
}
// Mark the user as deleted
$this->info('Marking the user as deleted');
$bad_user->deleted_at = Carbon::now()->timestamp;
$bad_user->save();
event(new UserMerged($bad_user, $user, null));
}
}
}
@@ -4,6 +4,7 @@ namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Log;
class MoveUploadsToNewDisk extends Command
{
@@ -74,7 +75,7 @@ class MoveUploadsToNewDisk extends Command
$new_url = Storage::disk('public')->url('uploads/'.$public_type.'/'.$filename, $filename);
$this->info($type_count.'. PUBLIC: '.$filename.' was copied to '.$new_url);
} catch (\Exception $e) {
\Log::debug($e);
Log::debug($e);
$this->error($e);
}
}
@@ -116,7 +117,7 @@ class MoveUploadsToNewDisk extends Command
$new_url = Storage::url($private_type . '/' . $filename, $filename);
$this->info($type_count . '. PRIVATE: ' . $filename . ' was copied to ' . $new_url);
} catch (\Exception $e) {
\Log::debug($e);
Log::debug($e);
$this->error($e);
}
}
@@ -140,7 +141,7 @@ class MoveUploadsToNewDisk extends Command
unlink($filename);
$public_delete_count++;
} catch (\Exception $e) {
\Log::debug($e);
Log::debug($e);
$this->error($e);
}
}
@@ -153,7 +154,7 @@ class MoveUploadsToNewDisk extends Command
unlink($filename);
$private_delete_count++;
} catch (\Exception $e) {
\Log::debug($e);
Log::debug($e);
$this->error($e);
}
}
+21 -35
View File
@@ -5,6 +5,8 @@ namespace App\Console\Commands;
use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Illuminate\Support\Facades\Log;
use Symfony\Component\Console\Helper\ProgressIndicator;
ini_set('max_execution_time', env('IMPORT_TIME_LIMIT', 600)); //600 seconds = 10 minutes
ini_set('memory_limit', env('IMPORT_MEMORY_LIMIT', '500M'));
@@ -28,6 +30,11 @@ class ObjectImportCommand extends Command
*/
protected $description = 'Import Items from CSV';
/**
* The progress indicator instance.
*/
protected ProgressIndicator $progressIndicator;
/**
* Create a new command instance.
*
@@ -38,8 +45,6 @@ class ObjectImportCommand extends Command
parent::__construct();
}
private $bar;
/**
* Execute the console command.
*
@@ -47,6 +52,8 @@ class ObjectImportCommand extends Command
*/
public function handle()
{
$this->progressIndicator = new ProgressIndicator($this->output);
$filename = $this->argument('filename');
$class = title_case($this->option('item-type'));
$classString = "App\\Importer\\{$class}Importer";
@@ -59,47 +66,26 @@ class ObjectImportCommand extends Command
// This $logFile/useFiles() bit is currently broken, so commenting it out for now
// $logFile = $this->option('logfile');
// \Log::useFiles($logFile);
$this->comment('======= Importing Items from '.$filename.' =========');
// Log::useFiles($logFile);
$this->progressIndicator->start('======= Importing Items from '.$filename.' =========');
$importer->import();
$this->bar = null;
if (! empty($this->errors)) {
$this->comment('The following Errors were encountered.');
foreach ($this->errors as $asset => $error) {
$this->comment('Error: Item: '.$asset.' failed validation: '.json_encode($error));
}
} else {
$this->comment('All Items imported successfully!');
}
$this->comment('');
$this->progressIndicator->finish('Import finished.');
}
public function errorCallback($item, $field, $errorString)
public function errorCallback($item, $field, $error)
{
$this->errors[$item->name][$field] = $errorString;
$this->output->write("\x0D\x1B[2K");
$this->warn('Error: Item: '.$item->name.' failed validation: '.json_encode($error));
}
public function progress($count)
public function progress($importedItemsCount)
{
if (! $this->bar) {
$this->bar = $this->output->createProgressBar($count);
}
static $index = 0;
$index++;
if ($index < $count) {
$this->bar->advance();
} else {
$this->bar->finish();
}
$this->progressIndicator->advance();
}
// Tracks the current item for error messages
private $updating;
// An array of errors encountered while parsing
private $errors;
/**
* Log a message to file, configurable by the --log-file parameter.
* If a warning message is passed, we'll spit it to the console as well.
@@ -112,10 +98,10 @@ class ObjectImportCommand extends Command
public function log($string, $level = 'info')
{
if ($level === 'warning') {
\Log::warning($string);
Log::warning($string);
$this->comment($string);
} else {
\Log::Info($string);
Log::Info($string);
if ($this->option('verbose')) {
$this->comment($string);
}
+1 -1
View File
@@ -5,7 +5,7 @@ namespace App\Console\Commands;
use App\Models\Asset;
use App\Models\CustomField;
use Schema;
use DB;
use Illuminate\Support\Facades\DB;
use Illuminate\Console\Command;
class PaveIt extends Command
+17
View File
@@ -3,6 +3,7 @@
namespace App\Console\Commands;
use App\Models\Accessory;
use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\AssetModel;
use App\Models\Category;
@@ -15,6 +16,8 @@ use App\Models\Statuslabel;
use App\Models\Supplier;
use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
class Purge extends Command
{
@@ -141,6 +144,20 @@ class Purge extends Command
$this->info($users->count().' users purged.');
$user_assoc = 0;
foreach ($users as $user) {
$rel_path = 'private_uploads/users';
$filenames = Actionlog::where('action_type', 'uploaded')
->where('item_id', $user->id)
->pluck('filename');
foreach($filenames as $filename) {
try {
if (Storage::exists($rel_path . '/' . $filename)) {
Storage::delete($rel_path . '/' . $filename);
}
} catch (\Exception $e) {
Log::info('An error occurred while deleting files: ' . $e->getMessage());
}
}
$this->info('- User "'.$user->username.'" deleted.');
$user_assoc += $user->userlog()->count();
$user->userlog()->forceDelete();
+2 -2
View File
@@ -103,7 +103,7 @@ class RecryptFromMcrypt extends Command
$this->comment('INFO: No LDAP password found. Skipping... ');
} else {
$decrypted_ldap_pword = $mcrypter->decrypt($settings->ldap_pword);
$settings->ldap_pword = \Crypt::encrypt($decrypted_ldap_pword);
$settings->ldap_pword = Crypt::encrypt($decrypted_ldap_pword);
$settings->save();
}
/** @var CustomField[] $custom_fields */
@@ -132,7 +132,7 @@ class RecryptFromMcrypt extends Command
// Try to decrypt the payload using the legacy app key
try {
$decrypted_field = $mcrypter->decrypt($asset->{$columnName});
$asset->{$columnName} = \Crypt::encrypt($decrypted_field);
$asset->{$columnName} = Crypt::encrypt($decrypted_field);
$this->comment($decrypted_field);
} catch (\Exception $e) {
$errors[] = ' - ERROR: Could not decrypt field ['.$encrypted_field->name.']: '.$e->getMessage();
+1 -1
View File
@@ -4,7 +4,7 @@ namespace App\Console\Commands;
use App\Models\Asset;
use App\Models\Setting;
use Artisan;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Console\Command;
class RegenerateAssetTags extends Command
@@ -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');
}
}
@@ -73,6 +73,7 @@ class ResetDemoSettings extends Command
$settings->saml_forcelogin = '0';
$settings->saml_slo = null;
$settings->saml_custom_settings = null;
$settings->default_avatar = 'default.png';
$settings->save();
+2 -2
View File
@@ -6,8 +6,8 @@ use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\License;
use App\Models\User;
use Artisan;
use DB;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB;
use Illuminate\Console\Command;
class RestoreDeletedUsers extends Command
+34 -13
View File
@@ -4,6 +4,7 @@ namespace App\Console\Commands;
use Illuminate\Console\Command;
use ZipArchive;
use Illuminate\Support\Facades\Log;
class SQLStreamer {
private $input;
@@ -29,8 +30,11 @@ class SQLStreamer {
public function parse_sql(string $line): string {
// take into account the 'start of line or not' setting as an instance variable?
// 'continuation' lines for a permitted statement are PERMITTED.
// remove *only* line-feeds & carriage-returns; helpful for regexes against lines from
// Windows dumps
$line = trim($line, "\r\n");
if($this->statement_is_permitted && $line[0] === ' ') {
return $line;
return $line . "\n"; //re-add the newline
}
$table_regex = '`?([a-zA-Z0-9_]+)`?';
@@ -41,8 +45,12 @@ class SQLStreamer {
"/^(INSERT INTO )$table_regex(.*)$/" => false,
"/^UNLOCK TABLES/" => false,
// "/^\\) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;/" => false, // FIXME not sure what to do here?
"/^\\)[a-zA-Z0-9_= ]*;$/" => false
// ^^^^^^ that bit should *exit* the 'perimitted' black
"/^\\)[a-zA-Z0-9_= ]*;$/" => false,
// ^^^^^^ that bit should *exit* the 'permitted' block
"/^\\(.*\\)[,;]$/" => false, //older MySQL dump style with one set of values per line
/* we *could* have made the ^INSERT INTO blah VALUES$ turn on the capturing state, and closed it with
a ^(blahblah);$ but it's cleaner to not have to manage the state machine. We're just going to
assume that (blahblah), or (blahblah); are values for INSERT and are always acceptable. */
];
foreach($allowed_statements as $statement => $statechange) {
@@ -66,7 +74,7 @@ class SQLStreamer {
}
//how do we *replace* the tablename?
// print "RETURNING LINE: $line";
return $line;
return $line . "\n"; //re-add newline
}
}
// all that is not allowed is denied.
@@ -84,7 +92,7 @@ class SQLStreamer {
$parser->line_aware_piping(); // <----- THIS is doing the heavy lifting!
$check_tables = ['settings' => null, 'migrations' => null /* 'assets' => null */]; //TODO - move to statics?
//can't use 'users' because the 'accessories_users' table?
//can't use 'users' because the 'accessories_checkout' table?
// can't use 'assets' because 'ver1_components_assets'
foreach($check_tables as $check_table => $_ignore) {
foreach ($parser->tablenames as $tablename => $_count) {
@@ -125,7 +133,7 @@ class SQLStreamer {
while (($buffer = fgets($this->input, SQLStreamer::$buffer_size)) !== false) {
$bytes_read += strlen($buffer);
if ($this->reading_beginning_of_line) {
// \Log::debug("Buffer is: '$buffer'");
// Log::debug("Buffer is: '$buffer'");
$cleaned_buffer = $this->parse_sql($buffer);
if ($this->output) {
$bytes_written = fwrite($this->output, $cleaned_buffer);
@@ -163,7 +171,8 @@ class RestoreFromBackup extends Command
{filename : The zip file to be migrated}
{--no-progress : Don\'t show a progress bar}
{--sanitize-guess-prefix : Guess and output the table-prefix needed to "sanitize" the SQL}
{--sanitize-with-prefix= : "Sanitize" the SQL, using the passed-in table prefix (can be learned from --sanitize-guess-prefix). Pass as just \'--sanitize-with-prefix=\' to use no prefix}';
{--sanitize-with-prefix= : "Sanitize" the SQL, using the passed-in table prefix (can be learned from --sanitize-guess-prefix). Pass as just \'--sanitize-with-prefix=\' to use no prefix}
{--sql-stdout-only : ONLY "Sanitize" the SQL and print it to stdout - useful for debugging - probably requires --sanitize-with-prefix= }';
/**
* The console command description.
@@ -191,7 +200,7 @@ class RestoreFromBackup extends Command
{
$dir = getcwd();
if( $dir != base_path() ) { // usually only the case when running via webserver, not via command-line
\Log::debug("Current working directory is: $dir, changing directory to: ".base_path());
Log::debug("Current working directory is: $dir, changing directory to: ".base_path());
chdir(base_path()); // TODO - is this *safe* to change on a running script?!
}
//
@@ -297,7 +306,7 @@ class RestoreFromBackup extends Command
continue;
}
if (@pathinfo($raw_path, PATHINFO_EXTENSION) == 'sql') {
\Log::debug("Found a sql file!");
Log::debug("Found a sql file!");
$sqlfiles[] = $raw_path;
$sqlfile_indices[] = $i;
continue;
@@ -364,6 +373,15 @@ class RestoreFromBackup extends Command
return $this->info("Re-run this command with '--sanitize-with-prefix=".$prefix."' to see an attempt to sanitze your SQL.");
}
// If we're doing --sql-stdout-only, handle that now so we don't have to open pipes to mysql and all of that silliness
if ($this->option('sql-stdout-only')) {
$sql_importer = new SQLStreamer($sql_contents, STDOUT, $this->option('sanitize-with-prefix'));
$bytes_read = $sql_importer->line_aware_piping();
return $this->warn("$bytes_read total bytes read");
//TODO - it'd be nice to dump this message to STDERR so that STDOUT is just pure SQL,
// which would be good for redirecting to a file, and not having to trim the last line off of it
}
//how to invoke the restore?
$pipes = [];
@@ -413,7 +431,7 @@ class RestoreFromBackup extends Command
$bytes_read = 0;
while (($buffer = fgets($sql_contents, SQLStreamer::$buffer_size)) !== false) {
$bytes_read += strlen($buffer);
// \Log::debug("Buffer is: '$buffer'");
// Log::debug("Buffer is: '$buffer'");
$bytes_written = fwrite($pipes[0], $buffer);
if ($bytes_written === false) {
@@ -425,13 +443,13 @@ class RestoreFromBackup extends Command
$bytes_read = $sql_importer->line_aware_piping();
}
} catch (\Exception $e) {
\Log::error("Error during restore!!!! ".$e->getMessage());
Log::error("Error during restore!!!! ".$e->getMessage());
// FIXME - put these back and/or put them in the right places?!
$err_out = fgets($pipes[1]);
$err_err = fgets($pipes[2]);
\Log::error("Error OUTPUT: ".$err_out);
Log::error("Error OUTPUT: ".$err_out);
$this->info($err_out);
\Log::error("Error ERROR : ".$err_err);
Log::error("Error ERROR : ".$err_err);
$this->error($err_err);
throw $e;
}
@@ -465,6 +483,9 @@ class RestoreFromBackup extends Command
$ugly_file_name = $za->statIndex($file_details['index'])['name'];
$fp = $za->getStream($ugly_file_name);
//$this->info("Weird problem, here are file details? ".print_r($file_details,true));
if (!is_dir($file_details['dest'])) {
mkdir($file_details['dest'], 0755, true); //0755 is what Laravel uses, so we do that
}
$migrated_file = fopen($file_details['dest'].'/'.basename($pretty_file_name), 'w');
while (($buffer = fgets($fp, SQLStreamer::$buffer_size)) !== false) {
fwrite($migrated_file, $buffer);
+1 -1
View File
@@ -5,7 +5,7 @@ namespace App\Console\Commands;
use App\Models\Asset;
use App\Models\CustomField;
use App\Models\Setting;
use Artisan;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Console\Command;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Encryption\Encrypter;
@@ -0,0 +1,106 @@
<?php
namespace App\Console\Commands;
use App\Models\Asset;
use App\Models\CheckoutAcceptance;
use App\Models\Setting;
use App\Models\User;
use App\Notifications\CheckoutAssetNotification;
use App\Notifications\CurrentInventory;
use App\Notifications\UnacceptedAssetReminderNotification;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Notification;
class SendAcceptanceReminder extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'snipeit:acceptance-reminder';
/**
* The console command description.
*
* @var string
*/
protected $description = 'This will resend users with unaccepted assets a reminder to accept or decline them.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$pending = CheckoutAcceptance::pending()->where('checkoutable_type', 'App\Models\Asset')
->whereHas('checkoutable', function($query) {
$query->where('accepted_at', null)
->where('declined_at', null);
})
->with(['assignedTo', 'checkoutable.assignedTo', 'checkoutable.model', 'checkoutable.adminuser'])
->get();
$count = 0;
$unacceptedAssetGroups = $pending
->filter(function($acceptance) {
return $acceptance->checkoutable_type == 'App\Models\Asset';
})
->map(function($acceptance) {
return ['assetItem' => $acceptance->checkoutable, 'acceptance' => $acceptance];
})
->groupBy(function($item) {
return $item['acceptance']->assignedTo ? $item['acceptance']->assignedTo->id : '';
});
$no_mail_address = [];
foreach($unacceptedAssetGroups as $unacceptedAssetGroup) {
$item_count = $unacceptedAssetGroup->count();
foreach ($unacceptedAssetGroup as $unacceptedAsset) {
// if ($unacceptedAsset['acceptance']->assignedTo->email == ''){
// $no_mail_address[] = $unacceptedAsset['checkoutable']->assignedTo->present()->fullName;
// }
if ($unacceptedAsset['acceptance']->assignedTo) {
if (!$unacceptedAsset['acceptance']->assignedTo->locale) {
Notification::locale(Setting::getSettings()->locale)->send(
$unacceptedAsset['acceptance']->assignedTo,
new UnacceptedAssetReminderNotification($unacceptedAsset['assetItem'], $count)
);
} else {
Notification::send(
$unacceptedAsset['acceptance']->assignedTo,
new UnacceptedAssetReminderNotification($unacceptedAsset, $item_count)
);
}
$count++;
}
}
}
if (!empty($no_mail_address)) {
foreach($no_mail_address as $user) {
return $user.' has no email.';
}
}
$this->info($count.' users notified.');
}
}
@@ -43,7 +43,7 @@ class SendCurrentInventoryToUsers extends Command
$count = 0;
foreach ($users as $user) {
if (($user->assets->count() > 0) || ($user->accessories->count() > 0) || ($user->licenses->count() > 0)) {
if (($user->assets->count() > 0) || ($user->accessories->count() > 0) || ($user->licenses->count() > 0) || ($user->consumables->count() > 0)) {
$count++;
$user->notify((new CurrentInventory($user)));
}
@@ -9,7 +9,6 @@ use App\Notifications\ExpectedCheckinAdminNotification;
use App\Notifications\ExpectedCheckinNotification;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
class SendExpectedCheckinAlerts extends Command
{
@@ -43,25 +42,31 @@ class SendExpectedCheckinAlerts extends Command
public function handle()
{
$settings = Setting::getSettings();
$whenNotify = Carbon::now();
$assets = Asset::with('assignedTo')->whereNotNull('assigned_to')->whereNotNull('expected_checkin')->where('expected_checkin', '<=', $whenNotify)->get();
$interval = $settings->audit_warning_days ?? 0;
$today = Carbon::now();
$interval_date = $today->copy()->addDays($interval);
$assets = Asset::whereNull('deleted_at')->DueOrOverdueForCheckin($settings)->orderBy('assets.expected_checkin', 'desc')->get();
$this->info($assets->count().' assets must be checked in on or before '.$interval_date.' is deadline');
$this->info($whenNotify.' is deadline');
$this->info($assets->count().' assets');
foreach ($assets as $asset) {
if ($asset->assigned && $asset->checkedOutToUser()) {
Log::info('Sending ExpectedCheckinNotification to ' . $asset->assigned->email);
$asset->assigned->notify((new ExpectedCheckinNotification($asset)));
if ($asset->assignedTo && (isset($asset->assignedTo->email)) && ($asset->assignedTo->email!='') && $asset->checkedOutToUser()) {
$this->info('Sending User ExpectedCheckinNotification to: '.$asset->assignedTo->email);
$asset->assignedTo->notify((new ExpectedCheckinNotification($asset)));
}
}
if (($assets) && ($assets->count() > 0) && ($settings->alert_email != '')) {
// Send a rollup to the admin, if settings dictate
$recipients = collect(explode(',', $settings->alert_email))->map(function ($item, $key) {
$recipients = collect(explode(',', $settings->alert_email))->map(function ($item) {
return new AlertRecipient($item);
});
$this->info('Sending Admin ExpectedCheckinNotification to: '.$settings->alert_email);
\Notification::send($recipients, new ExpectedCheckinAdminNotification($assets));
}
}
}
@@ -3,13 +3,11 @@
namespace App\Console\Commands;
use App\Models\Asset;
use App\Models\License;
use App\Models\Recipients;
use App\Models\Recipients\AlertRecipient;
use App\Models\Setting;
use App\Notifications\ExpiringAssetsNotification;
use App\Notifications\SendUpcomingAuditNotification;
use Carbon\Carbon;
use DB;
use Illuminate\Support\Facades\DB;
use Illuminate\Console\Command;
class SendUpcomingAuditReport extends Command
@@ -46,39 +44,24 @@ class SendUpcomingAuditReport extends Command
public function handle()
{
$settings = Setting::getSettings();
$interval = $settings->audit_warning_days ?? 0;
$today = Carbon::now();
$interval_date = $today->copy()->addDays($interval);
if (($settings->alert_email != '') && ($settings->audit_warning_days) && ($settings->alerts_enabled == 1)) {
$assets = Asset::whereNull('deleted_at')->DueOrOverdueForAudit($settings)->orderBy('assets.next_audit_date', 'desc')->get();
$this->info($assets->count().' assets must be audited in on or before '.$interval_date.' is deadline');
if (($assets) && ($assets->count() > 0) && ($settings->alert_email != '')) {
// Send a rollup to the admin, if settings dictate
$recipients = collect(explode(',', $settings->alert_email))->map(function ($item, $key) {
return new \App\Models\Recipients\AlertRecipient($item);
$recipients = collect(explode(',', $settings->alert_email))->map(function ($item) {
return new AlertRecipient($item);
});
// Assets due for auditing
$this->info('Sending Admin SendUpcomingAuditNotification to: '.$settings->alert_email);
\Notification::send($recipients, new SendUpcomingAuditNotification($assets, $settings->audit_warning_days));
$assets = Asset::whereNotNull('next_audit_date')
->DueOrOverdueForAudit($settings)
->orderBy('last_audit_date', 'asc')->get();
if ($assets->count() > 0) {
$this->info(trans_choice('mail.upcoming-audits', $assets->count(),
['count' => $assets->count(), 'threshold' => $settings->audit_warning_days]));
\Notification::send($recipients, new SendUpcomingAuditNotification($assets, $settings->audit_warning_days));
$this->info('Audit report sent to '.$settings->alert_email);
} else {
$this->info('No assets to be audited. No report sent.');
}
} elseif ($settings->alert_email == '') {
$this->error('Could not send email. No alert email configured in settings');
} elseif (! $settings->audit_warning_days) {
$this->error('No audit warning days set in Admin Notifications. No mail will be sent.');
} elseif ($settings->alerts_enabled != 1) {
$this->info('Alerts are disabled in the settings. No mail will be sent');
} else {
$this->error('Something went wrong. :( ');
$this->error('Admin Notifications Email Setting: '.$settings->alert_email);
$this->error('Admin Audit Warning Setting: '.$settings->audit_warning_days);
$this->error('Admin Alerts Emnabled: '.$settings->alerts_enabled);
}
}
}
+2 -1
View File
@@ -4,6 +4,7 @@ namespace App\Console\Commands;
use App\Models\Asset;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
class SyncAssetCounters extends Command
{
@@ -58,7 +59,7 @@ class SyncAssetCounters extends Command
$asset->save();
$bar->advance();
\Log::debug('Asset: '.$asset->id.' has '.$asset->checkin_counter.' checkins, '.$asset->checkout_counter.' checkouts, and '.$asset->requests_counter.' requests');
Log::debug('Asset: '.$asset->id.' has '.$asset->checkin_counter.' checkins, '.$asset->checkout_counter.' checkouts, and '.$asset->requests_counter.' requests');
}
+1 -1
View File
@@ -15,7 +15,7 @@ class UserMerged
*
* @return void
*/
public function __construct(User $from_user, User $to_user, User $admin)
public function __construct(User $from_user, User $to_user, ?User $admin)
{
$this->merged_from = $from_user;
$this->merged_to = $to_user;
+3 -3
View File
@@ -7,7 +7,7 @@ use App\Helpers\Helper;
use Illuminate\Validation\ValidationException;
use Illuminate\Auth\AuthenticationException;
use ArieTimmerman\Laravel\SCIMServer\Exceptions\SCIMException;
use Log;
use Illuminate\Support\Facades\Log;
use Throwable;
use JsonException;
use Carbon\Exceptions\InvalidFormatException;
@@ -44,8 +44,8 @@ class Handler extends ExceptionHandler
public function report(Throwable $exception)
{
if ($this->shouldReport($exception)) {
if (class_exists(\Log::class)) {
\Log::error($exception);
if (class_exists(Log::class)) {
Log::error($exception);
}
return parent::report($exception);
}
+104 -53
View File
@@ -12,10 +12,12 @@ use App\Models\Depreciation;
use App\Models\Setting;
use App\Models\Statuslabel;
use App\Models\License;
use Crypt;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Contracts\Encryption\DecryptException;
use Image;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Intervention\Image\ImageManagerStatic as Image;
use Illuminate\Support\Facades\Session;
class Helper
{
@@ -60,8 +62,9 @@ class Helper
'mn' => 'mn-MN', // Mongolian
'ms' => 'ms-MY', // Malay
'nl' => 'nl-NL', // Dutch
'no' => 'no-NO', // Norwegian
'no' => 'nb-NO', // Norwegian Bokmål
'pl' => 'pl-PL', // Polish
'pt' => 'pt-PT', // Portuguese
'ro' => 'ro-RO', // Romanian
'ru' => 'ru-RU', // Russian
'sk' => 'sk-SK', // Slovak
@@ -412,7 +415,7 @@ class Helper
if ($index >= $total_colors) {
\Log::info('Status label count is '.$index.' and exceeds the allowed count of 266.');
Log::info('Status label count is '.$index.' and exceeds the allowed count of 266.');
//patch fix for array key overflow (color count starts at 1, array starts at 0)
$index = $index - $total_colors - 1;
@@ -550,7 +553,7 @@ class Helper
*/
public static function statusLabelList()
{
$statuslabel_list = ['' => trans('general.select_statuslabel')] + Statuslabel::orderBy('default_label', 'desc')->orderBy('name', 'asc')->orderBy('deployable', 'desc')
$statuslabel_list = ['' => trans('general.select_statuslabel')] + Statuslabel::orderBy('default_label', 'desc')->orderBy('name', 'asc')->orderBy('status_type', 'desc')
->pluck('name', 'id')->toArray();
return $statuslabel_list;
@@ -569,9 +572,9 @@ class Helper
*/
public static function deployableStatusLabelList()
{
$statuslabel_list = Statuslabel::where('deployable', '=', '1')->orderBy('default_label', 'desc')
$statuslabel_list = Statuslabel::where('status_type', 'deployable')->orderBy('default_label', 'desc')
->orderBy('name', 'asc')
->orderBy('deployable', 'desc')
->orderBy('status_type', 'desc')
->pluck('name', 'id')->toArray();
return $statuslabel_list;
@@ -718,7 +721,7 @@ class Helper
{
$alert_threshold = \App\Models\Setting::getSettings()->alert_threshold;
$consumables = Consumable::withCount('consumableAssignments as consumable_assignments_count')->whereNotNull('min_amt')->get();
$accessories = Accessory::withCount('users as users_count')->whereNotNull('min_amt')->get();
$accessories = Accessory::withCount('checkouts as checkouts_count')->whereNotNull('min_amt')->get();
$components = Component::whereNotNull('min_amt')->get();
$asset_models = AssetModel::where('min_amt', '>', 0)->get();
$licenses = License::where('min_amt', '>', 0)->get();
@@ -746,7 +749,7 @@ class Helper
}
foreach ($accessories as $accessory) {
$avail = $accessory->qty - $accessory->users_count;
$avail = $accessory->qty - $accessory->checkouts_count;
if ($avail < ($accessory->min_amt) + $alert_threshold) {
if ($accessory->qty > 0) {
$percent = number_format((($avail / $accessory->qty) * 100), 0);
@@ -842,7 +845,7 @@ class Helper
$filetype = @finfo_file($finfo, $file);
finfo_close($finfo);
if (($filetype == 'image/jpeg') || ($filetype == 'image/jpg') || ($filetype == 'image/png') || ($filetype == 'image/bmp') || ($filetype == 'image/gif')) {
if (($filetype == 'image/jpeg') || ($filetype == 'image/jpg') || ($filetype == 'image/png') || ($filetype == 'image/bmp') || ($filetype == 'image/gif') || ($filetype == 'image/avif')) {
return $filetype;
}
@@ -875,12 +878,15 @@ class Helper
$permission_name = $permission[$x]['permission'];
if ($permission[$x]['display'] === true) {
if ($selected_arr) {
if (is_array($selected_arr)) {
if (array_key_exists($permission_name, $selected_arr)) {
$permissions_arr[$permission_name] = $selected_arr[$permission_name];
} else {
$permissions_arr[$permission_name] = '0';
}
} else {
$permissions_arr[$permission_name] = '0';
}
@@ -908,13 +914,22 @@ class Helper
$rules = $class::rules();
foreach ($rules as $rule_name => $rule) {
if ($rule_name == $field) {
if (strpos($rule, 'required') === false) {
return false;
if (is_array($rule)) {
if (in_array('required', $rule)) {
return true;
} else {
return false;
}
} else {
return true;
}
if (strpos($rule, 'required') === false) {
return false;
} else {
return true;
}
}
}
}
return false;
}
/**
@@ -1012,7 +1027,7 @@ class Helper
try {
$tmp_date = new \Carbon($date);
$tmp_date = new Carbon($date);
if ($type == 'datetime') {
$dt['datetime'] = $tmp_date->format('Y-m-d H:i:s');
@@ -1029,7 +1044,7 @@ class Helper
return $dt['formatted'];
} catch (\Exception $e) {
\Log::warning($e);
Log::warning($e);
return $date.' (Invalid '.$type.' value.)';
}
@@ -1106,6 +1121,9 @@ class Helper
'jpeg' => 'far fa-image',
'gif' => 'far fa-image',
'png' => 'far fa-image',
'webp' => 'far fa-image',
'avif' => 'far fa-image',
'svg' => 'fas fa-vector-square',
// word
'doc' => 'far fa-file-word',
'docx' => 'far fa-file-word',
@@ -1118,7 +1136,7 @@ class Helper
//Text
'txt' => 'far fa-file-alt',
'rtf' => 'far fa-file-alt',
'xml' => 'far fa-file-alt',
'xml' => 'fas fa-code',
// Misc
'pdf' => 'far fa-file-pdf',
'lic' => 'far fa-save',
@@ -1131,39 +1149,7 @@ class Helper
return 'far fa-file';
}
public static function show_file_inline($filename)
{
$extension = substr(strrchr($filename, '.'), 1);
if ($extension) {
switch ($extension) {
case 'jpg':
case 'jpeg':
case 'gif':
case 'png':
return true;
break;
default:
return false;
}
}
return false;
}
/**
* Generate a random encrypted password.
*
* @author Wes Hulette <jwhulette@gmail.com>
*
* @since 5.0.0
*
* @return string
*/
public static function generateEncyrptedPassword(): string
{
return bcrypt(self::generateUnencryptedPassword());
}
/**
* Get a random unencrypted password.
@@ -1338,7 +1324,7 @@ class Helper
public static function isDemoMode() {
if (config('app.lock_passwords') === true) {
return true;
\Log::debug('app locked!');
Log::debug('app locked!');
}
return false;
@@ -1431,7 +1417,6 @@ class Helper
foreach (self::$language_map as $legacy => $new) {
if ($language_code == $legacy) {
\Log::debug('Current language is '.$legacy.', using '.$new.' instead');
return $new;
}
}
@@ -1442,6 +1427,7 @@ class Helper
public static function mapBackToLegacyLocale($new_locale = null)
{
if (strlen($new_locale) <= 4) {
return $new_locale; //"new locale" apparently wasn't quite so new
}
@@ -1449,10 +1435,75 @@ class Helper
// This does a *reverse* search against our new language map array - given the value, find the *key* for it
$legacy_locale = array_search($new_locale, self::$language_map);
if($legacy_locale !== false) {
if ($legacy_locale !== false) {
return $legacy_locale;
}
return $new_locale; // better that you have some weird locale that doesn't fit into our mappings anywhere than 'void'
}
public static function determineLanguageDirection() {
return in_array(app()->getLocale(),
[
'ar-SA',
'fa-IR',
'he-IL'
]) ? 'rtl' : 'ltr';
}
static public function getRedirectOption($request, $id, $table, $item_id = null)
{
$redirect_option = Session::get('redirect_option');
$checkout_to_type = Session::get('checkout_to_type');
// return to index
if ($redirect_option == 'index') {
switch ($table) {
case "Assets":
return route('hardware.index');
case "Users":
return route('users.index');
case "Licenses":
return route('licenses.index');
case "Accessories":
return route('accessories.index');
case "Components":
return route('components.index');
case "Consumables":
return route('consumables.index');
}
}
// return to thing being assigned
if ($redirect_option == 'item') {
switch ($table) {
case "Assets":
return route('hardware.show', $id ?? $item_id);
case "Users":
return route('users.show', $id ?? $item_id);
case "Licenses":
return route('licenses.show', $id ?? $item_id);
case "Accessories":
return route('accessories.show', $id ?? $item_id);
case "Components":
return route('components.show', $id ?? $item_id);
case "Consumables":
return route('consumables.show', $id ?? $item_id);
}
}
// return to assignment target
if ($redirect_option == 'target') {
switch ($checkout_to_type) {
case 'user':
return route('users.show', ['user' => $request->assigned_user]);
case 'location':
return route('locations.show', ['location' => $request->assigned_location]);
case 'asset':
return route('hardware.show', ['hardware' => $request->assigned_asset]);
}
}
return redirect()->back()->with('error', trans('admin/hardware/message.checkout.error'));
}
}
+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';
}
}
}
+66 -2
View File
@@ -3,10 +3,14 @@
namespace App\Helpers;
use Illuminate\Support\Facades\Storage;
use Illuminate\Http\Response;
use Illuminate\Http\RedirectResponse;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Illuminate\Contracts\Filesystem\FileNotFoundException;
class StorageHelper
{
public static function downloader($filename, $disk = 'default')
public static function downloader($filename, $disk = 'default') : BinaryFileResponse | RedirectResponse | StreamedResponse
{
if ($disk == 'default') {
$disk = config('filesystems.default');
@@ -22,4 +26,64 @@ class StorageHelper
return Storage::disk($disk)->download($filename);
}
}
/**
* This determines the file types that should be allowed inline and checks their fileinfo extension
* to determine that they are safe to display inline.
*
* @author <A. Gianotto> [<snipe@snipe.net]>
* @since v7.0.14
* @param $file_with_path
* @return bool
*/
public static function allowSafeInline($file_with_path) {
$allowed_inline = [
'pdf',
'svg',
'jpg',
'gif',
'svg',
'avif',
'webp',
'png',
];
// The file exists and is allowed to be displayed inline
if (Storage::exists($file_with_path) && (in_array(pathinfo($file_with_path, PATHINFO_EXTENSION), $allowed_inline))) {
return true;
}
return false;
}
/**
* Decide whether to show the file inline or download it.
*/
public static function showOrDownloadFile($file, $filename) {
$headers = [];
if (request('inline') == 'true') {
$headers = [
'Content-Disposition' => 'inline',
];
// This is NOT allowed as inline - force it to be displayed as text in the browser
if (self::allowSafeInline($file) != true) {
$headers = array_merge($headers, ['Content-Type' => 'text/plain']);
}
}
// Everything else seems okay, but the file doesn't exist on the server.
if (Storage::missing($file)) {
throw new FileNotFoundException();
}
return Storage::download($file, $filename, $headers);
}
}
@@ -7,10 +7,11 @@ use App\Http\Controllers\Controller;
use App\Http\Requests\ImageUploadRequest;
use App\Models\Accessory;
use App\Models\Company;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use Redirect;
use \Illuminate\Contracts\View\View;
use \Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Log;
/** This controller handles all actions related to Accessories for
* the Snipe-IT Asset Management application.
@@ -26,13 +27,10 @@ class AccessoriesController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see AccessoriesController::getDatatable() method that generates the JSON response
* @since [v1.0]
* @return View
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function index()
public function index() : View
{
$this->authorize('index', Accessory::class);
return view('accessories/index');
}
@@ -40,10 +38,8 @@ class AccessoriesController extends Controller
* Returns a view with a form to create a new Accessory.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @return View
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function create()
public function create() : View
{
$this->authorize('create', Accessory::class);
$category_type = 'accessory';
@@ -57,10 +53,8 @@ class AccessoriesController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param ImageUploadRequest $request
* @return Redirect
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function store(ImageUploadRequest $request)
public function store(ImageUploadRequest $request) : RedirectResponse
{
$this->authorize(Accessory::class);
@@ -79,16 +73,17 @@ class AccessoriesController extends Controller
$accessory->purchase_date = request('purchase_date');
$accessory->purchase_cost = request('purchase_cost');
$accessory->qty = request('qty');
$accessory->user_id = Auth::user()->id;
$accessory->created_by = auth()->id();
$accessory->supplier_id = request('supplier_id');
$accessory->notes = request('notes');
$accessory = $request->handleImages($accessory);
session()->put(['redirect_option' => $request->get('redirect_option')]);
// Was the accessory created?
if ($accessory->save()) {
// Redirect to the new accessory page
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.create.success'));
return redirect()->to(Helper::getRedirectOption($request, $accessory->id, 'Accessories'))->with('success', trans('admin/accessories/message.create.success'));
}
return redirect()->back()->withInput()->withErrors($accessory->getErrors());
@@ -99,15 +94,12 @@ class AccessoriesController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $accessoryId
* @return View
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function edit($accessoryId = null)
public function edit($accessoryId = null) : View | RedirectResponse
{
if ($item = Accessory::find($accessoryId)) {
$this->authorize($item);
return view('accessories/edit', compact('item'))->with('category_type', 'accessory');
}
@@ -121,9 +113,8 @@ class AccessoriesController extends Controller
* @author [J. Vinsmoke]
* @param int $accessoryId
* @since [v6.0]
* @return View
*/
public function getClone($accessoryId = null)
public function getClone($accessoryId = null) : View | RedirectResponse
{
$this->authorize('create', Accessory::class);
@@ -150,17 +141,15 @@ class AccessoriesController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param ImageUploadRequest $request
* @param int $accessoryId
* @return Redirect
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function update(ImageUploadRequest $request, $accessoryId = null)
public function update(ImageUploadRequest $request, $accessoryId = null) : RedirectResponse
{
if ($accessory = Accessory::withCount('users as users_count')->find($accessoryId)) {
if ($accessory = Accessory::withCount('checkouts as checkouts_count')->find($accessoryId)) {
$this->authorize($accessory);
$validator = Validator::make($request->all(), [
"qty" => "required|numeric|min:$accessory->users_count"
"qty" => "required|numeric|min:$accessory->checkouts_count"
]);
if ($validator->fails()) {
@@ -188,9 +177,10 @@ class AccessoriesController extends Controller
$accessory = $request->handleImages($accessory);
// Was the accessory updated?
session()->put(['redirect_option' => $request->get('redirect_option')]);
if ($accessory->save()) {
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.update.success'));
return redirect()->to(Helper::getRedirectOption($request, $accessory->id, 'Accessories'))->with('success', trans('admin/accessories/message.update.success'));
}
} else {
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
@@ -204,10 +194,8 @@ class AccessoriesController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $accessoryId
* @return Redirect
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function destroy($accessoryId)
public function destroy($accessoryId) : RedirectResponse
{
if (is_null($accessory = Accessory::find($accessoryId))) {
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.not_found'));
@@ -224,7 +212,7 @@ class AccessoriesController extends Controller
try {
Storage::disk('public')->delete('accessories'.'/'.$accessory->image);
} catch (\Exception $e) {
\Log::debug($e);
Log::debug($e);
}
}
@@ -242,12 +230,10 @@ class AccessoriesController extends Controller
* @param int $accessoryID
* @see AccessoriesController::getDataView() method that generates the JSON response
* @since [v1.0]
* @return View
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function show($accessoryID = null)
public function show($accessoryID = null) : View | RedirectResponse
{
$accessory = Accessory::withCount('users as users_count')->find($accessoryID);
$accessory = Accessory::withCount('checkouts as checkouts_count')->find($accessoryID);
$this->authorize('view', $accessory);
if (isset($accessory->id)) {
return view('accessories/view', compact('accessory'));
@@ -7,9 +7,13 @@ use App\Http\Controllers\Controller;
use App\Http\Requests\UploadFileRequest;
use App\Models\Actionlog;
use App\Models\Accessory;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Storage;
use Symfony\Accessory\HttpFoundation\JsonResponse;
use Illuminate\Support\Facades\Log;
use \Illuminate\Contracts\View\View;
use \Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Response;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\StreamedResponse;
class AccessoriesFilesController extends Controller
{
@@ -18,20 +22,17 @@ class AccessoriesFilesController extends Controller
*
* @param UploadFileRequest $request
* @param int $accessoryId
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*@author [A. Gianotto] [<snipe@snipe.net>]
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @todo Switch to using the AssetFileRequest form request validator.
*/
public function store(UploadFileRequest $request, $accessoryId = null)
public function store(UploadFileRequest $request, $accessoryId = null) : RedirectResponse
{
if (config('app.lock_passwords')) {
return redirect()->route('accessories.show', ['accessory'=>$accessoryId])->with('error', trans('general.feature_disabled'));
}
$accessory = Accessory::find($accessoryId);
if (isset($accessory->id)) {
@@ -68,10 +69,8 @@ class AccessoriesFilesController extends Controller
* @since [v1.0]
* @param int $accessoryId
* @param int $fileId
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function destroy($accessoryId = null, $fileId = null)
public function destroy($accessoryId = null, $fileId = null) : RedirectResponse
{
$accessory = Accessory::find($accessoryId);
@@ -85,7 +84,7 @@ class AccessoriesFilesController extends Controller
try {
Storage::delete('accessories/'.$log->filename);
} catch (\Exception $e) {
\Log::debug($e);
Log::debug($e);
}
}
@@ -106,53 +105,30 @@ class AccessoriesFilesController extends Controller
* @since [v1.4]
* @param int $accessoryId
* @param int $fileId
* @return \Symfony\Accessory\HttpFoundation\Response
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function show($accessoryId = null, $fileId = null, $download = true)
public function show($accessoryId = null, $fileId = null) : View | RedirectResponse | Response | BinaryFileResponse | StreamedResponse
{
\Log::debug('Private filesystem is: '.config('filesystems.default'));
$accessory = Accessory::find($accessoryId);
// the accessory is valid
if (isset($accessory->id)) {
if ($accessory = Accessory::find($accessoryId)) {
$this->authorize('view', $accessory);
$this->authorize('accessories.files', $accessory);
if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $accessory->id)->find($fileId)) {
return redirect()->route('accessories.index')->with('error', trans('admin/users/message.log_record_not_found'));
}
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $accessory->id)->find($fileId)) {
$file = 'private_uploads/accessories/'.$log->filename;
$file = 'private_uploads/accessories/'.$log->filename;
if (Storage::missing($file)) {
\Log::debug('FILE DOES NOT EXISTS for '.$file);
\Log::debug('URL should be '.Storage::url($file));
return response('File '.$file.' ('.Storage::url($file).') not found on server', 404)
->header('Content-Type', 'text/plain');
} else {
// Display the file inline
if (request('inline') == 'true') {
$headers = [
'Content-Disposition' => 'inline',
];
return Storage::download($file, $log->filename, $headers);
}
// We have to override the URL stuff here, since local defaults in Laravel's Flysystem
// won't work, as they're not accessible via the web
if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer?
return StorageHelper::downloader($file);
try {
return StorageHelper::showOrDownloadFile($file, $log->filename);
} catch (\Exception $e) {
return redirect()->route('accessories.show', ['accessory' => $accessory])->with('error', trans('general.file_not_found'));
}
}
return redirect()->route('accessories.show', ['accessory' => $accessory])->with('error', trans('general.log_record_not_found'));
}
return redirect()->route('accessories.index')->with('error', trans('general.file_does_not_exist', ['id' => $fileId]));
return redirect()->route('accessories.index')->with('error', trans('general.file_not_found'));
}
}
@@ -3,12 +3,15 @@
namespace App\Http\Controllers\Accessories;
use App\Events\CheckoutableCheckedIn;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Models\Accessory;
use App\Models\AccessoryCheckout;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use \Illuminate\Contracts\View\View;
use \Illuminate\Http\RedirectResponse;
class AccessoryCheckinController extends Controller
{
@@ -19,15 +22,10 @@ class AccessoryCheckinController extends Controller
* @param Request $request
* @param int $accessoryUserId
* @param string $backto
* @return View
* @internal param int $accessoryId
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function create($accessoryUserId = null, $backto = null)
public function create($accessoryUserId = null, $backto = null) : View | RedirectResponse
{
// Check if the accessory exists
if (is_null($accessory_user = DB::table('accessories_users')->find($accessoryUserId))) {
// Redirect to the accessory management page with error
if (is_null($accessory_user = DB::table('accessories_checkout')->find($accessoryUserId))) {
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.not_found'));
}
@@ -42,21 +40,16 @@ class AccessoryCheckinController extends Controller
*
* @uses Accessory::checkin_email() to determine if an email can and should be sent
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param null $accessoryUserId
* @param null $accessoryCheckoutId
* @param string $backto
* @return Redirect
* @throws \Illuminate\Auth\Access\AuthorizationException
* @internal param int $accessoryId
*/
public function store(Request $request, $accessoryUserId = null, $backto = null)
public function store(Request $request, $accessoryCheckoutId = null, $backto = null) : RedirectResponse
{
// Check if the accessory exists
if (is_null($accessory_user = DB::table('accessories_users')->find($accessoryUserId))) {
// Redirect to the accessory management page with error
if (is_null($accessory_checkout = AccessoryCheckout::find($accessoryCheckoutId))) {
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
}
$accessory = Accessory::find($accessory_user->accessory_id);
$accessory = Accessory::find($accessory_checkout->accessory_id);
$this->authorize('checkin', $accessory);
@@ -67,12 +60,12 @@ class AccessoryCheckinController extends Controller
}
// Was the accessory updated?
if (DB::table('accessories_users')->where('id', '=', $accessory_user->id)->delete()) {
$return_to = e($accessory_user->assigned_to);
if ($accessory_checkout->delete()) {
event(new CheckoutableCheckedIn($accessory, $accessory_checkout->assignedTo, auth()->user(), $request->input('note'), $checkin_at));
event(new CheckoutableCheckedIn($accessory, User::find($return_to), Auth::user(), $request->input('note'), $checkin_at));
session()->put(['redirect_option' => $request->get('redirect_option')]);
return redirect()->route('accessories.show', $accessory->id)->with('success', trans('admin/accessories/message.checkin.success'));
return redirect()->to(Helper::getRedirectOption($request, $accessory->id, 'Accessories'))->with('success', trans('admin/accessories/message.checkin.success'));
}
// Redirect to the accessory management page with error
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.checkin.error'));
@@ -3,29 +3,34 @@
namespace App\Http\Controllers\Accessories;
use App\Events\CheckoutableCheckedOut;
use App\Helpers\Helper;
use App\Http\Controllers\CheckInOutRequest;
use App\Http\Controllers\Controller;
use App\Http\Requests\AccessoryCheckoutRequest;
use App\Models\Accessory;
use App\Models\AccessoryCheckout;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Input;
use \Illuminate\Contracts\View\View;
use \Illuminate\Http\RedirectResponse;
class AccessoryCheckoutController extends Controller
{
use CheckInOutRequest;
/**
* Return the form to checkout an Accessory to a user.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $id
* @return View
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function create($id)
public function create($id) : View | RedirectResponse
{
if ($accessory = Accessory::withCount('users as users_count')->find($id)) {
if ($accessory = Accessory::withCount('checkouts as checkouts_count')->find($id)) {
$this->authorize('checkout', $accessory);
@@ -58,46 +63,38 @@ class AccessoryCheckoutController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param Request $request
* @param int $accessoryId
* @return Redirect
* @throws \Illuminate\Auth\Access\AuthorizationException
* @param Accessory $accessory
*/
public function store(Request $request, $accessoryId)
public function store(AccessoryCheckoutRequest $request, Accessory $accessory) : RedirectResponse
{
// Check if the accessory exists
if (is_null($accessory = Accessory::withCount('users as users_count')->find($accessoryId))) {
// Redirect to the accessory management page with error
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.user_not_found'));
}
$this->authorize('checkout', $accessory);
if (!$user = User::find($request->input('assigned_to'))) {
return redirect()->route('accessories.checkout.show', $accessory->id)->with('error', trans('admin/accessories/message.checkout.user_does_not_exist'));
$target = $this->determineCheckoutTarget();
$accessory->checkout_qty = $request->input('checkout_qty', 1);
for ($i = 0; $i < $accessory->checkout_qty; $i++) {
AccessoryCheckout::create([
'accessory_id' => $accessory->id,
'created_at' => Carbon::now(),
'created_by' => auth()->id(),
'assigned_to' => $target->id,
'assigned_type' => $target::class,
'note' => $request->input('note'),
]);
}
event(new CheckoutableCheckedOut($accessory, $target, auth()->user(), $request->input('note')));
// Make sure there is at least one available to checkout
if ($accessory->numRemaining() <= 0){
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.checkout.unavailable'));
}
// Set this as user since we only allow checkout to user for this item type
$request->request->add(['checkout_to_type' => request('checkout_to_type')]);
$request->request->add(['assigned_user' => $target->id]);
session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => $request->get('checkout_to_type')]);
// Update the accessory data
$accessory->assigned_to = e($request->input('assigned_to'));
$accessory->users()->attach($accessory->id, [
'accessory_id' => $accessory->id,
'created_at' => Carbon::now(),
'user_id' => Auth::id(),
'assigned_to' => $request->get('assigned_to'),
'note' => $request->input('note'),
]);
DB::table('accessories_users')->where('assigned_to', '=', $accessory->assigned_to)->where('accessory_id', '=', $accessory->id)->first();
event(new CheckoutableCheckedOut($accessory, $user, Auth::user(), $request->input('note')));
// Redirect to the new accessory page
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.checkout.success'));
return redirect()->to(Helper::getRedirectOption($request, $accessory->id, 'Accessories'))
->with('success', trans('admin/accessories/message.checkout.success'));
}
}
@@ -23,25 +23,23 @@ use App\Notifications\AcceptanceAssetAcceptedNotification;
use App\Notifications\AcceptanceAssetDeclinedNotification;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use App\Http\Controllers\SettingsController;
use Barryvdh\DomPDF\Facade\Pdf;
use Carbon\Carbon;
use phpDocumentor\Reflection\Types\Compound;
use \Illuminate\Contracts\View\View;
use \Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Log;
class AcceptanceController extends Controller
{
/**
* Show a listing of pending checkout acceptances for the current user
*
* @return View
*/
public function index()
public function index() : View
{
$acceptances = CheckoutAcceptance::forUser(Auth::user())->pending()->get();
$acceptances = CheckoutAcceptance::forUser(auth()->user())->pending()->get();
return view('account/accept.index', compact('acceptances'));
}
@@ -49,9 +47,8 @@ class AcceptanceController extends Controller
* Shows a form to either accept or decline the checkout acceptance
*
* @param int $id
* @return mixed
*/
public function create($id)
public function create($id) : View | RedirectResponse
{
$acceptance = CheckoutAcceptance::find($id);
@@ -64,7 +61,7 @@ class AcceptanceController extends Controller
return redirect()->route('account.accept')->with('error', trans('admin/users/message.error.asset_already_accepted'));
}
if (! $acceptance->isCheckedOutTo(Auth::user())) {
if (! $acceptance->isCheckedOutTo(auth()->user())) {
return redirect()->route('account.accept')->with('error', trans('admin/users/message.error.incorrect_user_accepted'));
}
@@ -80,9 +77,8 @@ class AcceptanceController extends Controller
*
* @param Request $request
* @param int $id
* @return Redirect
*/
public function store(Request $request, $id)
public function store(Request $request, $id) : RedirectResponse
{
$acceptance = CheckoutAcceptance::find($id);
@@ -94,7 +90,7 @@ class AcceptanceController extends Controller
return redirect()->route('account.accept')->with('error', trans('admin/users/message.error.asset_already_accepted'));
}
if (! $acceptance->isCheckedOutTo(Auth::user())) {
if (! $acceptance->isCheckedOutTo(auth()->user())) {
return redirect()->route('account.accept')->with('error', trans('admin/users/message.error.incorrect_user_accepted'));
}
@@ -222,7 +218,9 @@ class AcceptanceController extends Controller
'item_tag' => $item->asset_tag,
'item_model' => $display_model,
'item_serial' => $item->serial,
'item_status' => $item->assetstatus?->name,
'eula' => $item->getEula(),
'note' => $request->input('note'),
'check_out_date' => Carbon::parse($acceptance->created_at)->format('Y-m-d'),
'accepted_date' => Carbon::parse($acceptance->accepted_at)->format('Y-m-d'),
'assigned_to' => $assigned_to,
@@ -233,13 +231,17 @@ class AcceptanceController extends Controller
];
if ($pdf_view_route!='') {
\Log::debug($pdf_filename.' is the filename, and the route was specified.');
Log::debug($pdf_filename.' is the filename, and the route was specified.');
$pdf = Pdf::loadView($pdf_view_route, $data);
Storage::put('private_uploads/eula-pdfs/' .$pdf_filename, $pdf->output());
}
$acceptance->accept($sig_filename, $item->getEula(), $pdf_filename);
$acceptance->notify(new AcceptanceAssetAcceptedNotification($data));
$acceptance->accept($sig_filename, $item->getEula(), $pdf_filename, $request->input('note'));
try {
$acceptance->notify(new AcceptanceAssetAcceptedNotification($data));
} catch (\Exception $e) {
Log::warning($e);
}
event(new CheckoutAccepted($acceptance));
$return_msg = trans('admin/users/message.accepted');
@@ -306,10 +308,13 @@ class AcceptanceController extends Controller
$assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName;
break;
}
$data = [
'item_tag' => $item->asset_tag,
'item_model' => $display_model,
'item_serial' => $item->serial,
'item_status' => $item->assetstatus?->name,
'note' => $request->input('note'),
'declined_date' => Carbon::parse($acceptance->declined_at)->format('Y-m-d'),
'signature' => ($sig_filename) ? storage_path() . '/private_uploads/signatures/' . $sig_filename : null,
'assigned_to' => $assigned_to,
@@ -318,12 +323,12 @@ class AcceptanceController extends Controller
];
if ($pdf_view_route!='') {
\Log::debug($pdf_filename.' is the filename, and the route was specified.');
Log::debug($pdf_filename.' is the filename, and the route was specified.');
$pdf = Pdf::loadView($pdf_view_route, $data);
Storage::put('private_uploads/eula-pdfs/' .$pdf_filename, $pdf->output());
}
$acceptance->decline($sig_filename);
$acceptance->decline($sig_filename, $request->input('note'));
$acceptance->notify(new AcceptanceAssetDeclinedNotification($data));
event(new CheckoutDeclined($acceptance));
$return_msg = trans('admin/users/message.declined');
+27 -17
View File
@@ -3,34 +3,44 @@
namespace App\Http\Controllers;
use App\Helpers\Helper;
use App\Models\Actionlog;
use Response;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use \Illuminate\Http\Response;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
class ActionlogController extends Controller
{
public function displaySig($filename)
public function displaySig($filename) : RedirectResponse | Response | bool
{
// PHP doesn't let you handle file not found errors well with
// file_get_contents, so we set the error reporting for just this class
error_reporting(0);
$this->authorize('view', \App\Models\Asset::class);
$file = config('app.private_uploads').'/signatures/'.$filename;
$filetype = Helper::checkUploadIsImage($file);
$disk = config('filesystems.default');
switch (config("filesystems.disks.$disk.driver")) {
$contents = file_get_contents($file, false, stream_context_create(['http' => ['ignore_errors' => true]]));
if ($contents === false) {
\Log::warn('File '.$file.' not found');
return false;
} else {
return Response::make($contents)->header('Content-Type', $filetype);
case 's3':
$file = 'private_uploads/signatures/'.$filename;
return redirect()->away(Storage::disk($disk)->temporaryUrl($file, now()->addMinutes(5)));
default:
$this->authorize('view', \App\Models\Asset::class);
$file = config('app.private_uploads').'/signatures/'.$filename;
$filetype = Helper::checkUploadIsImage($file);
$contents = file_get_contents($file, false, stream_context_create(['http' => ['ignore_errors' => true]]));
if ($contents === false) {
Log::warning('File '.$file.' not found');
return false;
} else {
return response()->make($contents)->header('Content-Type', $filetype);
}
}
}
public function getStoredEula($filename){
public function getStoredEula($filename) : Response | BinaryFileResponse
{
$this->authorize('view', \App\Models\Asset::class);
$file = config('app.private_uploads').'/eula-pdfs/'.$filename;
return Response::download($file);
return response()->download($file);
}
}
@@ -4,20 +4,26 @@ namespace App\Http\Controllers\Api;
use App\Events\CheckoutableCheckedOut;
use App\Helpers\Helper;
use App\Http\Controllers\CheckInOutRequest;
use App\Http\Controllers\Controller;
use App\Http\Requests\AccessoryCheckoutRequest;
use App\Http\Requests\StoreAccessoryRequest;
use App\Http\Transformers\AccessoriesTransformer;
use App\Http\Transformers\SelectlistTransformer;
use App\Models\Accessory;
use App\Models\Company;
use App\Models\User;
use Auth;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
use DB;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest;
use App\Models\AccessoryCheckout;
class AccessoriesController extends Controller
{
use CheckInOutRequest;
/**
* Display a listing of the resource.
*
@@ -45,13 +51,14 @@ class AccessoriesController extends Controller
'min_amt',
'company_id',
'notes',
'users_count',
'checkouts_count',
'qty',
];
$accessories = Accessory::select('accessories.*')->with('category', 'company', 'manufacturer', 'users', 'location', 'supplier')
->withCount('users as users_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'));
@@ -104,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;
@@ -120,14 +130,13 @@ class AccessoriesController extends Controller
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\ImageUploadRequest $request
* @return \Illuminate\Http\JsonResponse
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
* @return \Illuminate\Http\Response
*/
public function store(ImageUploadRequest $request)
public function store(StoreAccessoryRequest $request)
{
$this->authorize('create', Accessory::class);
$accessory = new Accessory;
$accessory->fill($request->all());
$accessory = $request->handleImages($accessory);
@@ -143,15 +152,15 @@ class AccessoriesController extends Controller
/**
* Display the specified resource.
*
* @param int $id
* @return array
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
$this->authorize('view', Accessory::class);
$accessory = Accessory::withCount('users as users_count')->findOrFail($id);
$accessory = Accessory::withCount('checkouts as checkouts_count')->findOrFail($id);
return (new AccessoriesTransformer)->transformAccessory($accessory);
}
@@ -160,10 +169,10 @@ class AccessoriesController extends Controller
/**
* Display the specified resource.
*
* @param int $id
* @return array
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function accessory_detail($id)
{
@@ -187,35 +196,27 @@ class AccessoriesController extends Controller
$this->authorize('view', Accessory::class);
$accessory = Accessory::with('lastCheckout')->findOrFail($id);
if (! Company::isCurrentUserHasAccess($accessory)) {
return ['total' => 0, 'rows' => []];
}
$offset = request('offset', 0);
$limit = request('limit', 50);
$accessory_users = $accessory->users;
$total = $accessory_users->count();
$accessory_checkouts = $accessory->checkouts;
$total = $accessory_checkouts->count();
if ($total < $offset) {
$offset = 0;
}
$accessory_users = $accessory->users()->skip($offset)->take($limit)->get();
$accessory_checkouts = $accessory->checkouts()->skip($offset)->take($limit)->get();
if ($request->filled('search')) {
$accessory_users = $accessory->users()
->where(function ($query) use ($request) {
$search_str = '%' . $request->input('search') . '%';
$query->where('first_name', 'like', $search_str)
->orWhere('last_name', 'like', $search_str)
->orWhere('note', 'like', $search_str);
})
$accessory_checkouts = $accessory->checkouts()->TextSearch($request->input('search'))
->get();
$total = $accessory_users->count();
$total = $accessory_checkouts->count();
}
return (new AccessoriesTransformer)->transformCheckedoutAccessory($accessory, $accessory_users, $total);
return (new AccessoriesTransformer)->transformCheckedoutAccessory($accessory, $accessory_checkouts, $total);
}
@@ -272,43 +273,31 @@ class AccessoriesController extends Controller
* If Slack is enabled and/or asset acceptance is enabled, it will also
* trigger a Slack message and send an email.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $accessoryId
* @return Redirect
* @return \Illuminate\Http\JsonResponse
* @author [A. Gianotto] [<snipe@snipe.net>]
*/
public function checkout(Request $request, $accessoryId)
public function checkout(AccessoryCheckoutRequest $request, Accessory $accessory)
{
// Check if the accessory exists
if (is_null($accessory = Accessory::withCount('users as users_count')->find($accessoryId))) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/accessories/message.does_not_exist')));
}
$this->authorize('checkout', $accessory);
$target = $this->determineCheckoutTarget();
$accessory->checkout_qty = $request->input('checkout_qty', 1);
if ($accessory->numRemaining() > 0) {
if (! $user = User::find($request->input('assigned_to'))) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/accessories/message.checkout.user_does_not_exist')));
}
// Update the accessory data
$accessory->assigned_to = $request->input('assigned_to');
$accessory->users()->attach($accessory->id, [
for ($i = 0; $i < $accessory->checkout_qty; $i++) {
AccessoryCheckout::create([
'accessory_id' => $accessory->id,
'created_at' => Carbon::now(),
'user_id' => Auth::id(),
'assigned_to' => $request->get('assigned_to'),
'note' => $request->get('note'),
'created_by' => auth()->id(),
'assigned_to' => $target->id,
'assigned_type' => $target::class,
'note' => $request->input('note'),
]);
event(new CheckoutableCheckedOut($accessory, $user, Auth::user(), $request->input('note')));
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/accessories/message.checkout.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, 'No accessories remaining'));
// Set this value to be able to pass the qty through to the event
event(new CheckoutableCheckedOut($accessory, $target, auth()->user(), $request->input('note')));
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/accessories/message.checkout.success')));
}
@@ -320,34 +309,26 @@ class AccessoriesController extends Controller
* @param Request $request
* @param int $accessoryUserId
* @param string $backto
* @return Redirect
* @return \Illuminate\Http\RedirectResponse
* @internal param int $accessoryId
*/
public function checkin(Request $request, $accessoryUserId = null)
{
if (is_null($accessory_user = DB::table('accessories_users')->find($accessoryUserId))) {
if (is_null($accessory_checkout = AccessoryCheckout::find($accessoryUserId))) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/accessories/message.does_not_exist')));
}
$accessory = Accessory::find($accessory_user->accessory_id);
$accessory = Accessory::find($accessory_checkout->accessory_id);
$this->authorize('checkin', $accessory);
$logaction = $accessory->logCheckin(User::find($accessory_user->assigned_to), $request->input('note'));
$accessory->logCheckin(User::find($accessory_checkout->assigned_to), $request->input('note'));
// Was the accessory updated?
if (DB::table('accessories_users')->where('id', '=', $accessory_user->id)->delete()) {
if (! is_null($accessory_user->assigned_to)) {
$user = User::find($accessory_user->assigned_to);
if ($accessory_checkout->delete()) {
if (! is_null($accessory_checkout->assigned_to)) {
$user = User::find($accessory_checkout->assigned_to);
}
$data['log_id'] = $logaction->id;
$data['first_name'] = $user->first_name;
$data['last_name'] = $user->last_name;
$data['item_name'] = $accessory->name;
$data['checkin_date'] = $logaction->created_at;
$data['item_tag'] = '';
$data['note'] = $logaction->note;
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/accessories/message.checkin.success')));
}
@@ -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\Asset;
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 AssetFilesController extends Controller
{
/**
* Accepts a POST to upload a file to the server.
*
* @param \App\Http\Requests\UploadFileRequest $request
* @param int $assetId
* @since [v6.0]
* @author [T. Scarsbrook] [<snipe@scarzybrook.co.uk>]
*/
public function store(UploadFileRequest $request, $assetId = null) : JsonResponse
{
// Start by checking if the asset being acted upon exists
if (! $asset = Asset::find($assetId)) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 404);
}
// Make sure we are allowed to update this asset
$this->authorize('update', $asset);
if ($request->hasFile('file')) {
// If the file storage directory doesn't exist; create it
if (! Storage::exists('private_uploads/assets')) {
Storage::makeDirectory('private_uploads/assets', 775);
}
// Loop over the attached files and add them to the asset
foreach ($request->file('file') as $file) {
$file_name = $request->handleFile('private_uploads/assets/','hardware-'.$asset->id, $file);
$asset->logUpload($file_name, e($request->get('notes')));
}
// All done - report success
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/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/hardware/message.upload.nofiles')), 500);
}
/**
* List the files for an asset.
*
* @param int $assetId
* @since [v6.0]
* @author [T. Scarsbrook] [<snipe@scarzybrook.co.uk>]
*/
public function list($assetId = null) : JsonResponse
{
// Start by checking if the asset being acted upon exists
if (! $asset = Asset::find($assetId)) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 404);
}
// the asset is valid
if (isset($asset->id)) {
$this->authorize('view', $asset);
// Check that there are some uploads on this asset that can be listed
if ($asset->uploads->count() > 0) {
$files = array();
foreach ($asset->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/hardware/message.upload.success')));
}
// There are no files.
return response()->json(Helper::formatStandardApiResponse('success', array(), trans('admin/hardware/message.upload.success')));
}
// Send back an error message
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.download.error')), 500);
}
/**
* Check for permissions and display the file.
*
* @param int $assetId
* @param int $fileId
* @return \Illuminate\Http\JsonResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
* @since [v6.0]
* @author [T. Scarsbrook] [<snipe@scarzybrook.co.uk>]
*/
public function show($assetId = null, $fileId = null) : JsonResponse | StreamedResponse | Storage | StorageHelper | BinaryFileResponse
{
// Start by checking if the asset being acted upon exists
if (! $asset = Asset::find($assetId)) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 404);
}
// the asset is valid
if (isset($asset->id)) {
$this->authorize('view', $asset);
// Check that the file being requested exists for the asset
if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $asset->id)->find($fileId)) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.download.no_match', ['id' => $fileId])), 404);
}
// Form the full filename with path
$file = 'private_uploads/assets/'.$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/hardware/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/hardware/message.download.error', ['id' => $fileId])), 500);
}
/**
* Delete the associated file
*
* @param int $assetId
* @param int $fileId
* @since [v6.0]
* @author [T. Scarsbrook] [<snipe@scarzybrook.co.uk>]
*/
public function destroy($assetId = null, $fileId = null) : JsonResponse
{
// Start by checking if the asset being acted upon exists
if (! $asset = Asset::find($assetId)) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 404);
}
$rel_path = 'private_uploads/assets';
// the asset is valid
if (isset($asset->id)) {
$this->authorize('update', $asset);
// 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/hardware/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/hardware/message.deletefile.error')), 500);
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.deletefile.error')), 500);
}
}
@@ -8,10 +8,9 @@ use App\Http\Transformers\AssetMaintenancesTransformer;
use App\Models\Asset;
use App\Models\AssetMaintenance;
use App\Models\Company;
use Auth;
use Carbon\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Input;
use Illuminate\Http\JsonResponse;
/**
* This controller handles all actions related to Asset Maintenance for
@@ -22,7 +21,6 @@ use Illuminate\Support\Facades\Input;
class AssetMaintenancesController extends Controller
{
/**
* Generates the JSON response for asset maintenances listing view.
*
@@ -30,14 +28,13 @@ class AssetMaintenancesController extends Controller
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
* @since [v1.8]
* @return string JSON
*/
public function index(Request $request)
public function index(Request $request) : JsonResponse | array
{
$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'));
@@ -51,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'));
}
@@ -72,7 +73,7 @@ class AssetMaintenancesController extends Controller
'asset_tag',
'asset_name',
'serial',
'user_id',
'created_by',
'supplier',
'is_warranty',
'status_label',
@@ -82,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);
@@ -120,15 +121,14 @@ class AssetMaintenancesController extends Controller
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
* @since [v1.8]
* @return string JSON
*/
public function store(Request $request)
public function store(Request $request) : JsonResponse
{
$this->authorize('update', Asset::class);
// 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()) {
@@ -148,9 +148,8 @@ class AssetMaintenancesController extends Controller
* @param int $request
* @version v1.0
* @since [v4.0]
* @return string JSON
*/
public function update(Request $request, $id)
public function update(Request $request, $id) : JsonResponse
{
$this->authorize('update', Asset::class);
@@ -186,17 +185,13 @@ class AssetMaintenancesController extends Controller
* @param int $assetMaintenanceId
* @version v1.0
* @since [v4.0]
* @return string JSON
*/
public function destroy($assetMaintenanceId)
public function destroy($assetMaintenanceId) : JsonResponse
{
$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();
@@ -212,9 +207,8 @@ class AssetMaintenancesController extends Controller
* @param int $assetMaintenanceId
* @version v1.0
* @since [v4.0]
* @return string JSON
*/
public function show($assetMaintenanceId)
public function show($assetMaintenanceId) : JsonResponse
{
$this->authorize('view', Asset::class);
$assetMaintenance = AssetMaintenance::findOrFail($assetMaintenanceId);
@@ -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);
}
}
@@ -4,14 +4,16 @@ namespace App\Http\Controllers\Api;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Requests\StoreAssetModelRequest;
use App\Http\Transformers\AssetModelsTransformer;
use App\Http\Transformers\AssetsTransformer;
use App\Http\Transformers\SelectlistTransformer;
use App\Models\Asset;
use App\Models\AssetModel;
use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Log;
use Illuminate\Http\JsonResponse;
/**
* This class controls all actions related to asset models for
@@ -27,9 +29,8 @@ class AssetModelsController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
public function index(Request $request) : JsonResponse | array
{
$this->authorize('view', AssetModel::class);
$allowed_columns =
@@ -47,6 +48,8 @@ class AssetModelsController extends Controller
'assets_count',
'category',
'fieldset',
'deleted_at',
'updated_at',
];
$assetmodels = AssetModel::select([
@@ -66,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') {
@@ -77,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'));
}
@@ -115,10 +122,9 @@ class AssetModelsController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
* @return \Illuminate\Http\Response
* @param \App\Http\Requests\StoreAssetModelRequest $request
*/
public function store(ImageUploadRequest $request)
public function store(StoreAssetModelRequest $request) : JsonResponse
{
$this->authorize('create', AssetModel::class);
$assetmodel = new AssetModel;
@@ -139,9 +145,8 @@ class AssetModelsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
public function show($id) : array
{
$this->authorize('view', AssetModel::class);
$assetmodel = AssetModel::withCount('assets as assets_count')->findOrFail($id);
@@ -155,9 +160,8 @@ class AssetModelsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function assets($id)
public function assets($id) : array
{
$this->authorize('view', AssetModel::class);
$assets = Asset::where('model_id', '=', $id)->get();
@@ -175,7 +179,7 @@ class AssetModelsController extends Controller
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(ImageUploadRequest $request, $id)
public function update(StoreAssetModelRequest $request, $id) : JsonResponse
{
$this->authorize('update', AssetModel::class);
$assetmodel = AssetModel::findOrFail($id);
@@ -208,9 +212,8 @@ class AssetModelsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
public function destroy($id) : JsonResponse
{
$this->authorize('delete', AssetModel::class);
$assetmodel = AssetModel::findOrFail($id);
@@ -224,7 +227,7 @@ class AssetModelsController extends Controller
try {
Storage::disk('public')->delete('assetmodels/'.$assetmodel->image);
} catch (\Exception $e) {
\Log::info($e);
Log::info($e);
}
}
@@ -240,7 +243,7 @@ class AssetModelsController extends Controller
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
*/
public function selectlist(Request $request)
public function selectlist(Request $request) : array
{
$this->authorize('view.selectlists');
+222 -141
View File
@@ -4,6 +4,7 @@ namespace App\Http\Controllers\Api;
use App\Events\CheckoutableCheckedIn;
use App\Http\Requests\StoreAssetRequest;
use App\Http\Requests\UpdateAssetRequest;
use App\Http\Traits\MigratesLegacyAssetLocations;
use App\Models\CheckoutAcceptance;
use App\Models\LicenseSeat;
@@ -25,19 +26,13 @@ use App\Models\License;
use App\Models\Location;
use App\Models\Setting;
use App\Models\User;
use \Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
use DB;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest;
use Illuminate\Support\Facades\Log;
use Input;
use Paginator;
use Slack;
use Str;
use TCPDF;
use Validator;
use Route;
use Illuminate\Support\Facades\Route;
/**
@@ -57,12 +52,16 @@ class AssetsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v4.0]
* @return \Illuminate\Http\JsonResponse
*/
public function index(Request $request, $audit = null)
public function index(Request $request, $action = null, $upcoming_status = null) : JsonResponse | array
{
$filter_non_deprecable_assets = false;
// This handles the legacy audit endpoints :(
if ($action == 'audit') {
$action = 'audits';
}
$filter_non_depreciable_assets = false;
/**
* This looks MAD janky (and it is), but the AssetsController@index does a LOT of heavy lifting throughout the
@@ -76,7 +75,7 @@ class AssetsController extends Controller
* which would have been far worse of a mess. *sad face* - snipe (Sept 1, 2021)
*/
if (Route::currentRouteName()=='api.depreciation-report.index') {
$filter_non_deprecable_assets = true;
$filter_non_depreciable_assets = true;
$transformer = 'App\Http\Transformers\DepreciationReportTransformer';
$this->authorize('reports.view');
} else {
@@ -94,6 +93,7 @@ class AssetsController extends Controller
'serial',
'model_number',
'last_checkout',
'last_checkin',
'notes',
'expected_checkin',
'order_number',
@@ -126,13 +126,13 @@ 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.
if ($filter_non_deprecable_assets) {
$non_deprecable_models = AssetModel::select('id')->whereNotNull('depreciation_id')->get();
$assets->InModelList($non_deprecable_models->toArray());
if ($filter_non_depreciable_assets) {
$non_depreciable_models = AssetModel::select('id')->whereNotNull('depreciation_id')->get();
$assets->InModelList($non_depreciable_models->toArray());
}
@@ -154,17 +154,44 @@ class AssetsController extends Controller
$assets->TextSearch($request->input('search'));
}
// This is used by the audit reporting routes
if (Gate::allows('audit', Asset::class)) {
switch ($audit) {
case 'due':
$assets->DueOrOverdueForAudit($settings);
break;
case 'overdue':
$assets->overdueForAudit($settings);
break;
/**
* Handle due and overdue audits and checkin dates
*/
switch ($action) {
// Audit (singular) is left over from earlier legacy APIs
case 'audits' :
switch ($upcoming_status) {
case 'due':
$assets->DueForAudit($settings);
break;
case 'overdue':
$assets->OverdueForAudit();
break;
case 'due-or-overdue':
$assets->DueOrOverdueForAudit($settings);
break;
}
break;
case 'checkins':
switch ($upcoming_status) {
case 'due':
$assets->DueForCheckin($settings);
break;
case 'overdue':
$assets->OverdueForCheckin();
break;
case 'due-or-overdue':
$assets->DueOrOverdueForCheckin($settings);
break;
}
break;
}
}
/**
* End handling due and overdue audits and checkin dates
*/
// This is used by the sidenav, mostly
@@ -179,18 +206,14 @@ class AssetsController extends Controller
case 'Pending':
$assets->join('status_labels AS status_alias', function ($join) {
$join->on('status_alias.id', '=', 'assets.status_id')
->where('status_alias.deployable', '=', 0)
->where('status_alias.pending', '=', 1)
->where('status_alias.archived', '=', 0);
->where('status_alias.status_type', '=', 'pending');
});
break;
case 'RTD':
$assets->whereNull('assets.assigned_to')
->join('status_labels AS status_alias', function ($join) {
$join->on('status_alias.id', '=', 'assets.status_id')
->where('status_alias.deployable', '=', 1)
->where('status_alias.pending', '=', 0)
->where('status_alias.archived', '=', 0);
->where('status_alias.status_type', '=', 'deployable');
});
break;
case 'Undeployable':
@@ -199,20 +222,15 @@ class AssetsController extends Controller
case 'Archived':
$assets->join('status_labels AS status_alias', function ($join) {
$join->on('status_alias.id', '=', 'assets.status_id')
->where('status_alias.deployable', '=', 0)
->where('status_alias.pending', '=', 0)
->where('status_alias.archived', '=', 1);
->where('status_alias.status_type', '=', 'archived');
});
break;
case 'Requestable':
$assets->where('assets.requestable', '=', 1)
->join('status_labels AS status_alias', function ($join) {
$join->on('status_alias.id', '=', 'assets.status_id')
->where('status_alias.deployable', '=', 1)
->where('status_alias.pending', '=', 0)
->where('status_alias.archived', '=', 0);
->where('status_alias.status_type', '=', 'deployable');
});
break;
case 'Deployed':
// more sad, horrible workarounds for laravel bugs when doing full text searches
@@ -229,7 +247,7 @@ class AssetsController extends Controller
// terrible workaround for complex-query Laravel bug in fulltext
$assets->join('status_labels AS status_alias', function ($join) {
$join->on('status_alias.id', '=', 'assets.status_id')
->where('status_alias.archived', '=', 0);
->where('status_alias.status_type', '!=', 'archived');
});
// If there is a status ID, don't take show_archived_in_list into consideration
@@ -238,6 +256,7 @@ class AssetsController extends Controller
$join->on('status_alias.id', '=', 'assets.status_id');
});
}
break;
}
@@ -349,8 +368,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(DB::getTablePrefix() . 'assets.' . $sort_override . ' * 1 ' . $order);
} else {
$assets->orderBy($sort_override, $order);
}
} else {
$assets->orderBy($column_sort, $order);
}
break;
}
@@ -388,9 +432,8 @@ class AssetsController extends Controller
* @param string $tag
* @since [v4.2.1]
* @author [A. Gianotto] [<snipe@snipe.net>]
* @return \Illuminate\Http\JsonResponse
*/
public function showByTag(Request $request, $tag)
public function showByTag(Request $request, $tag) : JsonResponse | array
{
$this->authorize('index', Asset::class);
$assets = Asset::where('asset_tag', $tag)->with('assetstatus')->with('assignedTo');
@@ -428,7 +471,7 @@ class AssetsController extends Controller
* @since [v4.2.1]
* @return \Illuminate\Http\JsonResponse
*/
public function showBySerial(Request $request, $serial)
public function showBySerial(Request $request, $serial) : JsonResponse | array
{
$this->authorize('index', Asset::class);
$assets = Asset::where('serial', $serial)->with('assetstatus')->with('assignedTo');
@@ -455,19 +498,20 @@ class AssetsController extends Controller
* @since [v4.0]
* @return \Illuminate\Http\JsonResponse
*/
public function show(Request $request, $id)
public function show(Request $request, $id) : JsonResponse | array
{
if ($asset = Asset::with('assetstatus')->with('assignedTo')->withTrashed()
->withCount('checkins as checkins_count', 'checkouts as checkouts_count', 'userRequests as user_requests_count')->findOrFail($id)) {
if ($asset = Asset::with('assetstatus')
->with('assignedTo')->withTrashed()
->withCount('checkins as checkins_count', 'checkouts as checkouts_count', 'userRequests as user_requests_count')->find($id)) {
$this->authorize('view', $asset);
return (new AssetsTransformer)->transformAsset($asset, $request->input('components') );
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
}
public function licenses(Request $request, $id)
public function licenses(Request $request, $id) : array
{
$this->authorize('view', Asset::class);
$this->authorize('view', License::class);
@@ -484,9 +528,8 @@ class AssetsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
* @return \Illuminate\Http\JsonResponse
*/
public function selectlist(Request $request)
public function selectlist(Request $request) : array
{
$assets = Asset::select([
@@ -523,8 +566,8 @@ class AssetsController extends Controller
}
if ($asset->assetstatus->getStatuslabelType() == 'pending') {
$asset->use_text .= '('.$asset->assetstatus->getStatuslabelType().')';
if ($asset->assetstatus->status_label == 'pending') {
$asset->use_text .= '('.$asset->assetstatus->status_label.')';
}
$asset->use_image = ($asset->getImageUrl()) ? $asset->getImageUrl() : null;
@@ -547,7 +590,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
@@ -581,7 +624,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') != '')) {
@@ -591,6 +634,11 @@ class AssetsController extends Controller
}
}
}
if ($field->element == 'checkbox') {
if(is_array($field_val)) {
$field_val = implode(',', $field_val);
}
}
$asset->{$field->db_column} = $field_val;
@@ -606,7 +654,7 @@ class AssetsController extends Controller
$target = Location::find(request('assigned_location'));
}
if (isset($target)) {
$asset->checkOut($target, Auth::user(), date('Y-m-d H:i:s'), '', 'Checked out on asset creation', e($request->get('name')));
$asset->checkOut($target, auth()->user(), date('Y-m-d H:i:s'), '', 'Checked out on asset creation', e($request->get('name')));
}
if ($asset->image) {
@@ -614,6 +662,8 @@ class AssetsController extends Controller
}
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.create.success')));
return response()->json(Helper::formatStandardApiResponse('success', (new AssetsTransformer)->transformAsset($asset), trans('admin/hardware/message.create.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $asset->getErrors()), 200);
@@ -624,81 +674,87 @@ class AssetsController extends Controller
* Accepts a POST request to update an asset
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param \App\Http\Requests\ImageUploadRequest $request
* @since [v4.0]
* @return \Illuminate\Http\JsonResponse
*/
public function update(ImageUploadRequest $request, $id)
public function update(UpdateAssetRequest $request, Asset $asset): JsonResponse
{
$this->authorize('update', Asset::class);
$asset->fill($request->validated());
if ($asset = Asset::find($id)) {
$asset->fill($request->all());
if ($request->has('model_id')) {
$asset->model()->associate(AssetModel::find($request->validated()['model_id']));
}
if ($request->has('company_id')) {
$asset->company_id = Company::getIdForCurrentUser($request->validated()['company_id']);
}
if ($request->has('rtd_location_id') && !$request->has('location_id')) {
$asset->location_id = $request->validated()['rtd_location_id'];
}
if ($request->input('last_audit_date')) {
$asset->last_audit_date = Carbon::parse($request->input('last_audit_date'))->startOfDay()->format('Y-m-d H:i:s');
}
($request->filled('model_id')) ?
$asset->model()->associate(AssetModel::find($request->get('model_id'))) : null;
($request->filled('rtd_location_id')) ?
$asset->location_id = $request->get('rtd_location_id') : '';
($request->filled('company_id')) ?
$asset->company_id = Company::getIdForCurrentUser($request->get('company_id')) : '';
/**
* this is here just legacy reasons. Api\AssetController
* used image_source once to allow encoded image uploads.
*/
if ($request->has('image_source')) {
$request->offsetSet('image', $request->offsetGet('image_source'));
}
($request->filled('rtd_location_id')) ?
$asset->location_id = $request->get('rtd_location_id') : null;
/**
* this is here just legacy reasons. Api\AssetController
* used image_source once to allow encoded image uploads.
*/
if ($request->has('image_source')) {
$request->offsetSet('image', $request->offsetGet('image_source'));
}
$asset = $request->handleImages($asset);
$model = AssetModel::find($asset->model_id);
$asset = $request->handleImages($asset);
$model = $asset->model;
// Update custom fields
$problems_updating_encrypted_custom_fields = false;
if (($model) && (isset($model->fieldset))) {
foreach ($model->fieldset->fields as $field) {
$field_val = $request->input($field->db_column, null);
if ($request->has($field->db_column)) {
if ($field->field_encrypted == '1') {
if (Gate::allows('admin')) {
$asset->{$field->db_column} = \Crypt::encrypt($request->input($field->db_column));
if ($field->element == 'checkbox') {
if(is_array($field_val)) {
$field_val = implode(',', $field_val);
}
} else {
$asset->{$field->db_column} = $request->input($field->db_column);
}
if ($field->field_encrypted == '1') {
if (Gate::allows('assets.view.encrypted_custom_fields')) {
$field_val = Crypt::encrypt($field_val);
} else {
$problems_updating_encrypted_custom_fields = true;
continue;
}
}
$asset->{$field->db_column} = $field_val;
}
}
}
if ($asset->save()) {
if (($request->filled('assigned_user')) && ($target = User::find($request->get('assigned_user')))) {
$location = $target->location_id;
} elseif (($request->filled('assigned_asset')) && ($target = Asset::find($request->get('assigned_asset')))) {
$location = $target->location_id;
Asset::where('assigned_type', \App\Models\Asset::class)->where('assigned_to', $id)
Asset::where('assigned_type', \App\Models\Asset::class)->where('assigned_to', $asset->id)
->update(['location_id' => $target->location_id]);
} elseif (($request->filled('assigned_location')) && ($target = Location::find($request->get('assigned_location')))) {
$location = $target->id;
}
if (isset($target)) {
$asset->checkOut($target, Auth::user(), date('Y-m-d H:i:s'), '', 'Checked out on asset update', e($request->get('name')), $location);
$asset->checkOut($target, auth()->user(), date('Y-m-d H:i:s'), '', 'Checked out on asset update', e($request->get('name')), $location);
}
if ($asset->image) {
$asset->image = $asset->getImageUrl();
}
if ($problems_updating_encrypted_custom_fields) {
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.update.encrypted_warning')));
} else {
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.update.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $asset->getErrors()), 200);
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
return response()->json(Helper::formatStandardApiResponse('error', null, $asset->getErrors()), 200);
}
@@ -708,18 +764,24 @@ class AssetsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v4.0]
* @return \Illuminate\Http\JsonResponse
*/
public function destroy($id)
public function destroy($id) : JsonResponse
{
$this->authorize('delete', Asset::class);
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();
@@ -737,9 +799,8 @@ class AssetsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v5.1.18]
* @return \Illuminate\Http\JsonResponse
*/
public function restore(Request $request, $assetId = null)
public function restore(Request $request, $assetId = null) : JsonResponse
{
if ($asset = Asset::withTrashed()->find($assetId)) {
@@ -767,9 +828,8 @@ class AssetsController extends Controller
* @author [N. Butler]
* @param string $tag
* @since [v6.0.5]
* @return \Illuminate\Http\JsonResponse
*/
public function checkoutByTag(AssetCheckoutRequest $request, $tag)
public function checkoutByTag(AssetCheckoutRequest $request, $tag) : JsonResponse
{
if ($asset = Asset::where('asset_tag', $tag)->first()) {
return $this->checkout($request, $asset->id);
@@ -783,9 +843,8 @@ class AssetsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v4.0]
* @return \Illuminate\Http\JsonResponse
*/
public function checkout(AssetCheckoutRequest $request, $asset_id)
public function checkout(AssetCheckoutRequest $request, $asset_id) : JsonResponse
{
$this->authorize('checkout', Asset::class);
$asset = Asset::findOrFail($asset_id);
@@ -802,7 +861,6 @@ class AssetsController extends Controller
'asset_tag' => $asset->asset_tag,
];
// This item is checked out to a location
if (request('checkout_to_type') == 'location') {
$target = Location::find(request('assigned_location'));
@@ -829,13 +887,10 @@ class AssetsController extends Controller
$asset->status_id = $request->get('status_id');
}
if (! isset($target)) {
return response()->json(Helper::formatStandardApiResponse('error', $error_payload, 'Checkout target for asset '.e($asset->asset_tag).' is invalid - '.$error_payload['target_type'].' does not exist.'));
}
$checkout_at = request('checkout_at', date('Y-m-d H:i:s'));
$expected_checkin = request('expected_checkin', null);
$note = request('note', null);
@@ -851,9 +906,7 @@ class AssetsController extends Controller
// $asset->location_id = $target->rtd_location_id;
// }
if ($asset->checkOut($target, Auth::user(), $checkout_at, $expected_checkin, $note, $asset_name, $asset->location_id)) {
if ($asset->checkOut($target, auth()->user(), $checkout_at, $expected_checkin, $note, $asset_name, $asset->location_id)) {
return response()->json(Helper::formatStandardApiResponse('success', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkout.success')));
}
@@ -867,9 +920,8 @@ class AssetsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v4.0]
* @return \Illuminate\Http\JsonResponse
*/
public function checkin(Request $request, $asset_id)
public function checkin(Request $request, $asset_id) : JsonResponse
{
$asset = Asset::with('model')->findOrFail($asset_id);
$this->authorize('checkin', $asset);
@@ -905,7 +957,7 @@ class AssetsController extends Controller
}
}
if ($request->has('status_id')) {
if ($request->filled('status_id')) {
$asset->status_id = $request->input('status_id');
}
@@ -934,7 +986,7 @@ class AssetsController extends Controller
});
if ($asset->save()) {
event(new CheckoutableCheckedIn($asset, $target, Auth::user(), $request->input('note'), $checkin_at, $originalValues));
event(new CheckoutableCheckedIn($asset, $target, auth()->user(), $request->input('note'), $checkin_at, $originalValues));
return response()->json(Helper::formatStandardApiResponse('success', [
'asset_tag'=> e($asset->asset_tag),
@@ -951,12 +1003,11 @@ class AssetsController extends Controller
*
* @author [A. Janes] [<ajanes@adagiohealth.org>]
* @since [v6.0]
* @return \Illuminate\Http\JsonResponse
*/
public function checkinByTag(Request $request, $tag = null)
public function checkinByTag(Request $request, $tag = null) : JsonResponse
{
$this->authorize('checkin', Asset::class);
if(null == $tag && null !== ($request->input('asset_tag'))) {
if (null == $tag && null !== ($request->input('asset_tag'))) {
$tag = $request->input('asset_tag');
}
$asset = Asset::where('asset_tag', $tag)->first();
@@ -977,31 +1028,44 @@ class AssetsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $id
* @since [v4.0]
* @return \Illuminate\Http\JsonResponse
*/
public function audit(Request $request)
public function audit(Request $request) : JsonResponse
{
$this->authorize('audit', Asset::class);
$rules = [
'asset_tag' => 'required',
'location_id' => 'exists:locations,id|nullable|numeric',
'next_audit_date' => 'date|nullable',
];
$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) {
return response()->json(Helper::formatStandardApiResponse('error', null, $validator->errors()->all()));
}
$settings = Setting::getSettings();
$dt = Carbon::now()->addMonths($settings->audit_interval)->toDateString();
// No tag passed - return an error
if (!$request->filled('asset_tag')) {
return response()->json(Helper::formatStandardApiResponse('error', [
'asset_tag'=> '',
'error'=> trans('admin/hardware/message.no_tag'),
], trans('admin/hardware/message.no_tag')), 200);
}
$asset = Asset::where('asset_tag', '=', $request->input('asset_tag'))->first();
if ($asset) {
// We don't want to log this as a normal update, so let's bypass that
/**
* Even though we do a save() further down, we don't want to log this as a "normal" asset update,
* which would trigger the Asset Observer and would log an asset *update* log entry (because the
* de-normed fields like next_audit_date on the asset itself will change on save()) *in addition* to
* the audit log entry we're creating through this controller.
*
* To prevent this double-logging (one for update and one for audit), we skip the observer and bypass
* that de-normed update log entry by using unsetEventDispatcher(), BUT invoking unsetEventDispatcher()
* will bypass normal model-level validation that's usually handled at the observer )
*
* We handle validation on the save() by checking if the asset is valid via the ->isValid() method,
* which manually invokes Watson Validating to make sure the asset's model is valid.
*
* @see \App\Observers\AssetObserver::updating()
*/
$asset->unsetEventDispatcher();
$asset->next_audit_date = $dt;
@@ -1017,8 +1081,12 @@ class AssetsController extends Controller
$asset->last_audit_date = date('Y-m-d H:i:s');
if ($asset->save()) {
$log = $asset->logAudit(request('note'), request('location_id'));
/**
* Invoke Watson Validating to check the asset itself and check to make sure it saved correctly.
* We have to invoke this manually because of the unsetEventDispatcher() above.)
*/
if ($asset->isValid() && $asset->save()) {
$asset->logAudit(request('note'), request('location_id'));
return response()->json(Helper::formatStandardApiResponse('success', [
'asset_tag'=> e($asset->asset_tag),
@@ -1026,9 +1094,23 @@ class AssetsController extends Controller
'next_audit_date' => Helper::getFormattedDateObject($asset->next_audit_date),
], trans('admin/hardware/message.audit.success')));
}
// Asset failed validation or was not able to be saved
return response()->json(Helper::formatStandardApiResponse('error', [
'asset_tag'=> e($asset->asset_tag),
'error'=> $asset->getErrors()->first(),
], trans('admin/hardware/message.audit.error', ['error' => $asset->getErrors()->first()])), 200);
}
return response()->json(Helper::formatStandardApiResponse('error', ['asset_tag'=> e($request->input('asset_tag'))], 'Asset with tag '.e($request->input('asset_tag')).' not found'));
// No matching asset for the asset tag that was passed.
return response()->json(Helper::formatStandardApiResponse('error', [
'asset_tag'=> e($request->input('asset_tag')),
'error'=> trans('admin/hardware/message.audit.error'),
], trans('admin/hardware/message.audit.error', ['error' => trans('admin/hardware/message.does_not_exist')])), 200);
}
@@ -1038,9 +1120,8 @@ class AssetsController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return \Illuminate\Http\JsonResponse
*/
public function requestable(Request $request)
public function requestable(Request $request) : JsonResponse | array
{
$this->authorize('viewRequestable', Asset::class);
@@ -1062,8 +1143,7 @@ class AssetsController extends Controller
$assets = Asset::select('assets.*')
->with('location', 'assetstatus', 'assetlog', 'company','assignedTo',
'model.category', 'model.manufacturer', 'model.fieldset', 'supplier', 'requests')
->requestableAssets();
'model.category', 'model.manufacturer', 'model.fieldset', 'supplier', 'requests');
@@ -1071,7 +1151,7 @@ class AssetsController extends Controller
if ($request->filled('search')) {
$assets->TextSearch($request->input('search'));
}
// Search custom fields by column name
foreach ($all_custom_fields as $field) {
if ($request->filled($field->db_column_name())) {
@@ -1101,6 +1181,7 @@ class AssetsController extends Controller
break;
}
$assets->requestableAssets();
// Make sure the offset and limit are actually integers and do not exceed system limits
$offset = ($request->input('offset') > $assets->count()) ? $assets->count() : app('api_offset_value');
@@ -8,9 +8,9 @@ use App\Http\Transformers\CategoriesTransformer;
use App\Http\Transformers\SelectlistTransformer;
use App\Models\Category;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use App\Http\Requests\ImageUploadRequest;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
class CategoriesController extends Controller
{
@@ -21,7 +21,7 @@ class CategoriesController extends Controller
* @since [v4.0]
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
public function index(Request $request) : array
{
$this->authorize('view', Category::class);
$allowed_columns = [
@@ -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();
@@ -115,7 +138,7 @@ class CategoriesController extends Controller
* @param \App\Http\Requests\ImageUploadRequest $request
* @return \Illuminate\Http\Response
*/
public function store(ImageUploadRequest $request)
public function store(ImageUploadRequest $request) : JsonResponse
{
$this->authorize('create', Category::class);
$category = new Category;
@@ -136,9 +159,8 @@ class CategoriesController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
public function show($id) : array
{
$this->authorize('view', Category::class);
$category = Category::withCount('assets as assets_count', 'accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'licenses as licenses_count')->findOrFail($id);
@@ -156,7 +178,7 @@ class CategoriesController extends Controller
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(ImageUploadRequest $request, $id)
public function update(ImageUploadRequest $request, $id) : JsonResponse
{
$this->authorize('update', Category::class);
$category = Category::findOrFail($id);
@@ -164,7 +186,7 @@ class CategoriesController extends Controller
// Don't allow the user to change the category_type once it's been created
if (($request->filled('category_type')) && ($category->category_type != $request->input('category_type'))) {
return response()->json(
Helper::formatStandardApiResponse('error', null, trans('admin/categories/message.update.cannot_change_category_type'))
Helper::formatStandardApiResponse('error', null, ['category_type' => trans('admin/categories/message.update.cannot_change_category_type')], 422)
);
}
$category->fill($request->all());
@@ -185,7 +207,7 @@ class CategoriesController extends Controller
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
public function destroy($id) : JsonResponse
{
$this->authorize('delete', Category::class);
$category = Category::withCount('assets as assets_count', 'accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'licenses as licenses_count')->findOrFail($id);
@@ -208,7 +230,7 @@ class CategoriesController extends Controller
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
*/
public function selectlist(Request $request, $category_type = 'asset')
public function selectlist(Request $request, $category_type = 'asset') : array
{
$this->authorize('view.selectlists');
$categories = Category::select([
@@ -10,6 +10,7 @@ use App\Models\Company;
use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest;
use Illuminate\Support\Facades\Storage;
use Illuminate\Http\JsonResponse;
class CompaniesController extends Controller
{
@@ -18,9 +19,8 @@ class CompaniesController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
public function index(Request $request) : JsonResponse | array
{
$this->authorize('view', Company::class);
@@ -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);
@@ -79,9 +91,8 @@ class CompaniesController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
* @return \Illuminate\Http\Response
*/
public function store(ImageUploadRequest $request)
public function store(ImageUploadRequest $request) : JsonResponse
{
$this->authorize('create', Company::class);
$company = new Company;
@@ -102,9 +113,8 @@ class CompaniesController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
public function show($id) : array
{
$this->authorize('view', Company::class);
$company = Company::findOrFail($id);
@@ -120,9 +130,8 @@ class CompaniesController extends Controller
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(ImageUploadRequest $request, $id)
public function update(ImageUploadRequest $request, $id) : JsonResponse
{
$this->authorize('update', Company::class);
$company = Company::findOrFail($id);
@@ -144,9 +153,8 @@ class CompaniesController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
public function destroy($id) : JsonResponse
{
$this->authorize('delete', Company::class);
$company = Company::findOrFail($id);
@@ -169,7 +177,7 @@ class CompaniesController extends Controller
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
*/
public function selectlist(Request $request)
public function selectlist(Request $request) : array
{
$this->authorize('view.selectlists');
$companies = Company::select([
@@ -5,15 +5,17 @@ namespace App\Http\Controllers\Api;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Transformers\ComponentsTransformer;
use App\Models\Company;
use App\Models\Component;
use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest;
use App\Events\CheckoutableCheckedIn;
use App\Events\ComponentCheckedIn;
use App\Models\Asset;
use Illuminate\Support\Facades\Validator;
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Facades\Log;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;
class ComponentsController extends Controller
{
@@ -23,9 +25,8 @@ class ComponentsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
*
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
public function index(Request $request) : JsonResponse | array
{
$this->authorize('view', Component::class);
@@ -37,6 +38,7 @@ class ComponentsController extends Controller
'name',
'min_amt',
'order_number',
'model_number',
'serial',
'purchase_date',
'purchase_cost',
@@ -46,7 +48,7 @@ class ComponentsController extends Controller
];
$components = Component::select('components.*')
->with('company', 'location', 'category', 'assets', 'supplier');
->with('company', 'location', 'category', 'assets', 'supplier', 'adminuser', 'manufacturer');
if ($request->filled('search')) {
$components = $components->TextSearch($request->input('search'));
@@ -68,6 +70,14 @@ class ComponentsController extends Controller
$components->where('supplier_id', '=', $request->input('supplier_id'));
}
if ($request->filled('manufacturer_id')) {
$components->where('manufacturer_id', '=', $request->input('manufacturer_id'));
}
if ($request->filled('model_number')) {
$components->where('model_number', '=', $request->input('model_number'));
}
if ($request->filled('location_id')) {
$components->where('location_id', '=', $request->input('location_id'));
}
@@ -97,6 +107,12 @@ class ComponentsController extends Controller
case 'supplier':
$components = $components->OrderSupplier($order);
break;
case 'manufacturer':
$components = $components->OrderManufacturer($order);
break;
case 'created_by':
$components = $components->OrderByCreatedBy($order);
break;
default:
$components = $components->orderBy($column_sort, $order);
break;
@@ -115,9 +131,8 @@ class ComponentsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
* @return \Illuminate\Http\Response
*/
public function store(ImageUploadRequest $request)
public function store(ImageUploadRequest $request) : JsonResponse
{
$this->authorize('create', Component::class);
$component = new Component;
@@ -136,9 +151,8 @@ class ComponentsController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
public function show($id) : array
{
$this->authorize('view', Component::class);
$component = Component::findOrFail($id);
@@ -155,9 +169,8 @@ class ComponentsController extends Controller
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(ImageUploadRequest $request, $id)
public function update(ImageUploadRequest $request, $id) : JsonResponse
{
$this->authorize('update', Component::class);
$component = Component::findOrFail($id);
@@ -178,9 +191,8 @@ class ComponentsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
public function destroy($id) : JsonResponse
{
$this->authorize('delete', Component::class);
$component = Component::findOrFail($id);
@@ -197,9 +209,8 @@ class ComponentsController extends Controller
* @since [v4.0]
* @param Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function getAssets(Request $request, $id)
public function getAssets(Request $request, $id) : array
{
$this->authorize('view', \App\Models\Asset::class);
@@ -240,10 +251,8 @@ class ComponentsController extends Controller
* @since [v5.1.8]
* @param Request $request
* @param int $componentId
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function checkout(Request $request, $componentId)
public function checkout(Request $request, $componentId) : JsonResponse
{
// Check if the component exists
if (!$component = Component::find($componentId)) {
@@ -274,9 +283,9 @@ class ComponentsController extends Controller
$component->assets()->attach($component->id, [
'component_id' => $component->id,
'created_at' => \Carbon::now(),
'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'),
]);
@@ -296,12 +305,10 @@ class ComponentsController extends Controller
* @since [v5.1.8]
* @param Request $request
* @param $component_asset_id
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function checkin(Request $request, $component_asset_id)
public function checkin(Request $request, $component_asset_id) : JsonResponse
{
if ($component_assets = \DB::table('components_assets')->find($component_asset_id)) {
if ($component_assets = DB::table('components_assets')->find($component_asset_id)) {
if (is_null($component = Component::find($component_assets->component_id))) {
@@ -314,7 +321,7 @@ class ComponentsController extends Controller
if ($max_to_checkin > 1) {
$validator = \Validator::make($request->all(), [
$validator = Validator::make($request->all(), [
"checkin_qty" => "required|numeric|between:1,$max_to_checkin"
]);
@@ -331,21 +338,21 @@ class ComponentsController extends Controller
// actually checked out.
$component_assets->assigned_qty = $qty_remaining_in_checkout;
\Log::debug($component_asset_id.' - '.$qty_remaining_in_checkout.' remaining in record '.$component_assets->id);
Log::debug($component_asset_id.' - '.$qty_remaining_in_checkout.' remaining in record '.$component_assets->id);
\DB::table('components_assets')->where('id',
DB::table('components_assets')->where('id',
$component_asset_id)->update(['assigned_qty' => $qty_remaining_in_checkout]);
// If the checked-in qty is exactly the same as the assigned_qty,
// we can simply delete the associated components_assets record
if ($qty_remaining_in_checkout == 0) {
\DB::table('components_assets')->where('id', '=', $component_asset_id)->delete();
DB::table('components_assets')->where('id', '=', $component_asset_id)->delete();
}
$asset = Asset::find($component_assets->asset_id);
event(new CheckoutableCheckedIn($component, $asset, \Auth::user(), $request->input('note'), \Carbon::now()));
event(new CheckoutableCheckedIn($component, $asset, auth()->user(), $request->input('note'), Carbon::now()));
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/components/message.checkin.success')));
@@ -5,6 +5,7 @@ namespace App\Http\Controllers\Api;
use App\Events\CheckoutableCheckedOut;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Requests\StoreConsumableRequest;
use App\Http\Transformers\ConsumablesTransformer;
use App\Http\Transformers\SelectlistTransformer;
use App\Models\Company;
@@ -12,7 +13,8 @@ use App\Models\Consumable;
use App\Models\User;
use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Illuminate\Http\JsonResponse;
class ConsumablesController extends Controller
{
@@ -21,34 +23,13 @@ class ConsumablesController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
*
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
public function index(Request $request) : array
{
$this->authorize('index', Consumable::class);
// This array is what determines which fields should be allowed to be sorted on ON the table itself, no relations
// Relations will be handled in query scopes a little further down.
$allowed_columns =
[
'id',
'name',
'order_number',
'min_amt',
'purchase_date',
'purchase_cost',
'company',
'category',
'model_number',
'item_no',
'qty',
'image',
'notes',
];
$consumables = Consumable::select('consumables.*')
->with('company', 'location', 'category', 'users', 'manufacturer');
$consumables = Consumable::with('company', 'location', 'category', 'supplier', 'manufacturer')
->withCount('users as consumables_users_count');
if ($request->filled('search')) {
$consumables = $consumables->TextSearch(e($request->input('search')));
@@ -90,15 +71,9 @@ class ConsumablesController extends Controller
// Make sure the offset and limit are actually integers and do not exceed system limits
$offset = ($request->input('offset') > $consumables->count()) ? $consumables->count() : app('api_offset_value');
$limit = app('api_limit_value');
$allowed_columns = ['id', 'name', 'order_number', 'min_amt', 'purchase_date', 'purchase_cost', 'company', 'category', 'model_number', 'item_no', 'manufacturer', 'location', 'qty', 'image'];
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort_override = $request->input('sort');
$column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'created_at';
switch ($sort_override) {
switch ($request->input('sort')) {
case 'category':
$consumables = $consumables->OrderCategory($order);
break;
@@ -111,11 +86,37 @@ class ConsumablesController extends Controller
case 'company':
$consumables = $consumables->OrderCompany($order);
break;
case 'remaining':
$consumables = $consumables->OrderRemaining($order);
break;
case 'supplier':
$components = $consumables->OrderSupplier($order);
$consumables = $consumables->OrderSupplier($order);
break;
case 'created_by':
$consumables = $consumables->OrderByCreatedBy($order);
break;
default:
$consumables = $consumables->orderBy($column_sort, $order);
// 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',
'order_number',
'min_amt',
'purchase_date',
'purchase_cost',
'company',
'category',
'model_number',
'item_no',
'manufacturer',
'location',
'qty',
'image'
];
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
$consumables = $consumables->orderBy($sort, $order);
break;
}
@@ -131,9 +132,8 @@ class ConsumablesController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
* @return \Illuminate\Http\Response
*/
public function store(ImageUploadRequest $request)
public function store(StoreConsumableRequest $request) : JsonResponse
{
$this->authorize('create', Consumable::class);
$consumable = new Consumable;
@@ -152,9 +152,8 @@ class ConsumablesController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
public function show($id) : array
{
$this->authorize('view', Consumable::class);
$consumable = Consumable::with('users')->findOrFail($id);
@@ -169,9 +168,8 @@ class ConsumablesController extends Controller
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(ImageUploadRequest $request, $id)
public function update(StoreConsumableRequest $request, $id) : JsonResponse
{
$this->authorize('update', Consumable::class);
$consumable = Consumable::findOrFail($id);
@@ -191,9 +189,8 @@ class ConsumablesController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
public function destroy($id) : JsonResponse
{
$this->authorize('delete', Consumable::class);
$consumable = Consumable::findOrFail($id);
@@ -210,14 +207,13 @@ class ConsumablesController extends Controller
* @see \App\Http\Controllers\Consumables\ConsumablesController::getView() method that returns the form.
* @since [v1.0]
* @param int $consumableId
* @return array
*/
public function getDataView($consumableId)
public function getDataView($consumableId) : array
{
$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) {
},
@@ -235,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,
];
}
@@ -251,9 +248,8 @@ class ConsumablesController extends Controller
* @author [A. Gutierrez] [<andres@baller.tv>]
* @param int $id
* @since [v4.9.5]
* @return JsonResponse
*/
public function checkout(Request $request, $id)
public function checkout(Request $request, $id) : JsonResponse
{
// Check if the consumable exists
if (!$consumable = Consumable::with('users')->find($id)) {
@@ -262,6 +258,8 @@ class ConsumablesController extends Controller
$this->authorize('checkout', $consumable);
$consumable->checkout_qty = $request->input('checkout_qty', 1);
// Make sure there is at least one available to checkout
if ($consumable->numRemaining() <= 0) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/consumables/message.checkout.unavailable')));
@@ -272,27 +270,35 @@ class ConsumablesController extends Controller
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.invalid_item_category_single', ['type' => trans('general.consumable')])));
}
// Make sure there is at least one available to checkout
if ($consumable->numRemaining() <= 0 || $consumable->checkout_qty > $consumable->numRemaining()) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/consumables/message.checkout.unavailable', ['requested' => $consumable->checkout_qty, 'remaining' => $consumable->numRemaining() ])));
}
// Check if the user exists - @TODO: this should probably be handled via validation, not here??
if (!$user = User::find($request->input('assigned_to'))) {
// Return error message
return response()->json(Helper::formatStandardApiResponse('error', null, 'No user found'));
\Log::debug('No valid user');
}
// Update the consumable data
$consumable->assigned_to = $request->input('assigned_to');
$consumable->users()->attach($consumable->id,
for ($i = 0; $i < $consumable->checkout_qty; $i++) {
$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'),
]
);
}
event(new CheckoutableCheckedOut($consumable, $user, Auth::user(), $request->input('note')));
event(new CheckoutableCheckedOut($consumable, $user, auth()->user(), $request->input('note')));
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/consumables/message.checkout.success')));
@@ -303,7 +309,7 @@ class ConsumablesController extends Controller
*
* @see \App\Http\Transformers\SelectlistTransformer
*/
public function selectlist(Request $request)
public function selectlist(Request $request) : array
{
$consumables = Consumable::select([
'consumables.id',
@@ -8,7 +8,8 @@ use App\Http\Transformers\CustomFieldsTransformer;
use App\Models\CustomField;
use App\Models\CustomFieldset;
use Illuminate\Http\Request;
use Validator;
use Illuminate\Support\Facades\Validator;
use Illuminate\Http\JsonResponse;
class CustomFieldsController extends Controller
{
@@ -20,7 +21,7 @@ class CustomFieldsController extends Controller
* @since [v3.0]
* @return array
*/
public function index()
public function index() : array
{
$this->authorize('index', CustomField::class);
$fields = CustomField::get();
@@ -33,9 +34,8 @@ class CustomFieldsController extends Controller
* @author [V. Cordes] [<volker@fdatek.de>]
* @param int $id
* @since [v4.1.10]
* @return View
*/
public function show($id)
public function show($id) : JsonResponse | array
{
$this->authorize('view', CustomField::class);
if ($field = CustomField::find($id)) {
@@ -52,9 +52,8 @@ class CustomFieldsController extends Controller
* @since [v4.1.10]
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
public function update(Request $request, $id) : JsonResponse
{
$this->authorize('update', CustomField::class);
$field = CustomField::findOrFail($id);
@@ -86,9 +85,8 @@ class CustomFieldsController extends Controller
* @author [V. Cordes] [<volker@fdatek.de>]
* @since [v4.1.10]
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
public function store(Request $request) : JsonResponse
{
$this->authorize('create', CustomField::class);
$field = new CustomField;
@@ -136,7 +134,7 @@ class CustomFieldsController extends Controller
return $fieldset->fields()->sync($fields);
}
public function associate(Request $request, $field_id)
public function associate(Request $request, $field_id) : JsonResponse
{
$this->authorize('update', CustomFieldset::class);
@@ -155,10 +153,9 @@ class CustomFieldsController extends Controller
return response()->json(Helper::formatStandardApiResponse('success', $fieldset, trans('admin/custom_fields/message.fieldset.update.success')));
}
public function disassociate(Request $request, $field_id)
public function disassociate(Request $request, $field_id) : JsonResponse
{
$this->authorize('update', CustomFieldset::class);
$field = CustomField::findOrFail($field_id);
$fieldset_id = $request->input('fieldset_id');
@@ -179,9 +176,8 @@ class CustomFieldsController extends Controller
*
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
* @since [v1.8]
* @return Redirect
*/
public function destroy($field_id)
public function destroy($field_id) : JsonResponse
{
$field = CustomField::findOrFail($field_id);
@@ -9,8 +9,7 @@ use App\Http\Transformers\CustomFieldsTransformer;
use App\Models\CustomFieldset;
use App\Models\CustomField;
use Illuminate\Http\Request;
use Redirect;
use View;
use Illuminate\Http\JsonResponse;
/**
* This controller handles all actions related to Custom Asset Fieldsets for
@@ -30,9 +29,8 @@ class CustomFieldsetsController extends Controller
* @author [Josh Gibson]
* @param int $id
* @since [v1.8]
* @return View
*/
public function index()
public function index() : array
{
$this->authorize('index', CustomField::class);
$fieldsets = CustomFieldset::withCount('fields as fields_count', 'models as models_count')->get();
@@ -46,9 +44,8 @@ class CustomFieldsetsController extends Controller
* @author [Josh Gibson]
* @param int $id
* @since [v1.8]
* @return View
*/
public function show($id)
public function show($id) : JsonResponse | array
{
$this->authorize('view', CustomField::class);
if ($fieldset = CustomFieldset::find($id)) {
@@ -65,9 +62,8 @@ class CustomFieldsetsController extends Controller
* @since [v4.0]
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
public function update(Request $request, $id) : JsonResponse
{
$this->authorize('update', CustomField::class);
$fieldset = CustomFieldset::findOrFail($id);
@@ -86,9 +82,8 @@ class CustomFieldsetsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
public function store(Request $request) : JsonResponse
{
$this->authorize('create', CustomField::class);
$fieldset = new CustomFieldset;
@@ -118,9 +113,8 @@ class CustomFieldsetsController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return Redirect
*/
public function destroy($id)
public function destroy($id) : JsonResponse
{
$this->authorize('delete', CustomField::class);
$fieldset = CustomFieldset::findOrFail($id);
@@ -147,7 +141,7 @@ class CustomFieldsetsController extends Controller
* @param $fieldsetId
* @return string JSON
*/
public function fields($id)
public function fields($id) : array
{
$this->authorize('view', CustomField::class);
$set = CustomFieldset::findOrFail($id);
@@ -164,14 +158,11 @@ class CustomFieldsetsController extends Controller
* @param $fieldsetId
* @return string JSON
*/
public function fieldsWithDefaultValues($fieldsetId, $modelId)
public function fieldsWithDefaultValues($fieldsetId, $modelId) : array
{
$this->authorize('view', CustomField::class);
$set = CustomFieldset::findOrFail($fieldsetId);
$fields = $set->fields;
return (new CustomFieldsTransformer)->transformCustomFieldsWithDefaultValues($fields, $modelId, $fields->count());
}
}
@@ -6,12 +6,11 @@ use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Transformers\DepartmentsTransformer;
use App\Http\Transformers\SelectlistTransformer;
use App\Models\Company;
use App\Models\Department;
use Auth;
use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest;
use Illuminate\Support\Facades\Storage;
use Illuminate\Http\JsonResponse;
class DepartmentsController extends Controller
{
@@ -20,9 +19,8 @@ class DepartmentsController extends Controller
*
* @author [Godfrey Martinez] [<snipe@snipe.net>]
* @since [v4.0]
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
public function index(Request $request) : JsonResponse | array
{
$this->authorize('view', Department::class);
$allowed_columns = ['id', 'name', 'image', 'users_count'];
@@ -91,16 +89,15 @@ class DepartmentsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
* @return \Illuminate\Http\Response
*/
public function store(ImageUploadRequest $request)
public function store(ImageUploadRequest $request) : JsonResponse
{
$this->authorize('create', Department::class);
$department = new Department;
$department->fill($request->all());
$department = $request->handleImages($department);
$department->user_id = Auth::user()->id;
$department->created_by = auth()->id();
$department->manager_id = ($request->filled('manager_id') ? $request->input('manager_id') : null);
if ($department->save()) {
@@ -116,13 +113,11 @@ class DepartmentsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
public function show($id) : array
{
$this->authorize('view', Department::class);
$department = Department::findOrFail($id);
return (new DepartmentsTransformer)->transformDepartment($department);
}
@@ -133,9 +128,8 @@ class DepartmentsController extends Controller
* @since [v5.0]
* @param \App\Http\Requests\ImageUploadRequest $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(ImageUploadRequest $request, $id)
public function update(ImageUploadRequest $request, $id) : JsonResponse
{
$this->authorize('update', Department::class);
$department = Department::findOrFail($id);
@@ -156,9 +150,8 @@ class DepartmentsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $locationId
* @since [v4.0]
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy($id)
public function destroy($id) : JsonResponse
{
$department = Department::findOrFail($id);
@@ -180,7 +173,7 @@ class DepartmentsController extends Controller
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
*/
public function selectlist(Request $request)
public function selectlist(Request $request) : array
{
$this->authorize('view.selectlists');
@@ -7,6 +7,7 @@ use App\Http\Controllers\Controller;
use App\Http\Transformers\DepreciationsTransformer;
use App\Models\Depreciation;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
class DepreciationsController extends Controller
{
@@ -15,14 +16,27 @@ class DepreciationsController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
public function index(Request $request) : JsonResponse | array
{
$this->authorize('view', Depreciation::class);
$allowed_columns = ['id','name','months','depreciation_min','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','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();
@@ -48,9 +70,8 @@ class DepreciationsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
public function store(Request $request) : JsonResponse
{
$this->authorize('create', Depreciation::class);
$depreciation = new Depreciation;
@@ -69,9 +90,8 @@ class DepreciationsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
public function show($id) : JsonResponse | array
{
$this->authorize('view', Depreciation::class);
$depreciation = Depreciation::findOrFail($id);
@@ -86,9 +106,8 @@ class DepreciationsController extends Controller
* @since [v4.0]
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
public function update(Request $request, $id) : JsonResponse
{
$this->authorize('update', Depreciation::class);
$depreciation = Depreciation::findOrFail($id);
@@ -107,9 +126,8 @@ class DepreciationsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
public function destroy($id) : JsonResponse
{
$this->authorize('delete', Depreciation::class);
$depreciation = Depreciation::withCount('models as models_count')->findOrFail($id);
+34 -22
View File
@@ -7,7 +7,7 @@ use App\Http\Controllers\Controller;
use App\Http\Transformers\GroupsTransformer;
use App\Models\Group;
use Illuminate\Http\Request;
use Auth;
use Illuminate\Http\JsonResponse;
class GroupsController extends Controller
@@ -17,16 +17,14 @@ class GroupsController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
public function index(Request $request) : JsonResponse | array
{
$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'));
@@ -36,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();
@@ -56,19 +70,21 @@ class GroupsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
public function store(Request $request) : JsonResponse
{
$this->authorize('superadmin');
$group = new Group;
// Get all the available permissions
$permissions = config('permissions');
$groupPermissions = Helper::selectedPermissionsArray($permissions, $permissions);
$group->name = $request->input('name');
$group->created_by = Auth::user()->id;
$group->permissions = json_encode($request->input('permissions')); // Todo - some JSON validation stuff here
$group->created_by = auth()->id();
$group->permissions = json_encode($request->input('permissions', $groupPermissions));
if ($group->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $group, trans('admin/groups/message.create.success')));
return response()->json(Helper::formatStandardApiResponse('success', (new GroupsTransformer)->transformGroup($group), trans('admin/groups/message.success.create')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $group->getErrors()));
@@ -80,13 +96,11 @@ class GroupsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
public function show($id) : array
{
$this->authorize('superadmin');
$group = Group::findOrFail($id);
return (new GroupsTransformer)->transformGroup($group);
}
@@ -97,9 +111,8 @@ class GroupsController extends Controller
* @since [v4.0]
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
public function update(Request $request, $id) : JsonResponse
{
$this->authorize('superadmin');
$group = Group::findOrFail($id);
@@ -108,7 +121,7 @@ class GroupsController extends Controller
$group->permissions = $request->input('permissions'); // Todo - some JSON validation stuff here
if ($group->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $group, trans('admin/groups/message.update.success')));
return response()->json(Helper::formatStandardApiResponse('success', (new GroupsTransformer)->transformGroup($group), trans('admin/groups/message.success.update')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $group->getErrors()));
@@ -120,9 +133,8 @@ class GroupsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
public function destroy($id) : JsonResponse
{
$this->authorize('superadmin');
$group = Group::findOrFail($id);
+11 -11
View File
@@ -9,22 +9,23 @@ use App\Http\Transformers\ImportsTransformer;
use App\Models\Asset;
use App\Models\Company;
use App\Models\Import;
use Artisan;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Database\Eloquent\JsonEncodingException;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Storage;
use League\Csv\Reader;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Illuminate\Support\Facades\Log;
use Illuminate\Http\JsonResponse;
class ImportController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
public function index() : JsonResponse | array
{
$this->authorize('import');
$imports = Import::latest()->get();
@@ -36,9 +37,8 @@ class ImportController extends Controller
* Process and store a CSV upload file.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function store()
public function store() : JsonResponse
{
$this->authorize('import');
if (! config('app.lock_passwords')) {
@@ -151,18 +151,17 @@ class ImportController extends Controller
* Processes the specified Import.
*
* @param int $import_id
* @return \Illuminate\Http\Response
*/
public function process(ItemImportRequest $request, $import_id)
public function process(ItemImportRequest $request, $import_id) : JsonResponse
{
$this->authorize('import');
// Run a backup immediately before processing
if ($request->get('run-backup')) {
\Log::debug('Backup manually requested via importer');
Log::debug('Backup manually requested via importer');
Artisan::call('snipeit:backup', ['--filename' => 'pre-import-backup-'.date('Y-m-d-H:i:s')]);
} else {
\Log::debug('NO BACKUP requested via importer');
Log::debug('NO BACKUP requested via importer');
}
$import = Import::find($import_id);
@@ -211,9 +210,8 @@ class ImportController extends Controller
* Remove the specified resource from storage.
*
* @param int $import_id
* @return \Illuminate\Http\Response
*/
public function destroy($import_id)
public function destroy($import_id) : JsonResponse
{
$this->authorize('create', Asset::class);
@@ -230,6 +228,8 @@ class ImportController extends Controller
return response()->json(Helper::formatStandardApiResponse('warning', null, trans('admin/hardware/message.import.file_not_deleted_warning')));
}
}
return response()->json(Helper::formatStandardApiResponse('warning', null, trans('admin/hardware/message.import.file_not_deleted_warning')));
}
}
@@ -8,7 +8,7 @@ use App\Http\Transformers\LabelsTransformer;
use App\Models\Labels\Label;
use Illuminate\Http\Request;
use Illuminate\Support\ItemNotFoundException;
use Auth;
use Illuminate\Http\JsonResponse;
class LabelsController extends Controller
{
@@ -16,9 +16,8 @@ class LabelsController extends Controller
* Returns JSON listing of all labels.
*
* @author Grant Le Roux <grant.leroux+snipe-it@gmail.com>
* @return JsonResponse
*/
public function index(Request $request)
public function index(Request $request) : JsonResponse | array
{
$this->authorize('view', Label::class);
@@ -50,9 +49,8 @@ class LabelsController extends Controller
*
* @author Grant Le Roux <grant.leroux+snipe-it@gmail.com>
* @param string $labelName
* @return JsonResponse
*/
public function show(string $labelName)
public function show(string $labelName) : JsonResponse | array
{
$labelName = str_replace('/', '\\', $labelName);
try {
@@ -9,7 +9,7 @@ use App\Models\Asset;
use App\Models\License;
use App\Models\LicenseSeat;
use App\Models\User;
use Auth;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class LicenseSeatsController extends Controller
@@ -19,11 +19,10 @@ class LicenseSeatsController extends Controller
*
* @param \Illuminate\Http\Request $request
* @param int $licenseId
* @return \Illuminate\Http\Response
*/
public function index(Request $request, $licenseId)
public function index(Request $request, $licenseId) : JsonResponse | array
{
//
if ($license = License::find($licenseId)) {
$this->authorize('view', $license);
@@ -64,11 +63,10 @@ class LicenseSeatsController extends Controller
*
* @param int $licenseId
* @param int $seatId
* @return \Illuminate\Http\Response
*/
public function show($licenseId, $seatId)
public function show($licenseId, $seatId) : JsonResponse | array
{
//
$this->authorize('view', License::class);
// sanity checks:
// 1. does the license seat exist?
@@ -89,19 +87,18 @@ class LicenseSeatsController extends Controller
* @param \Illuminate\Http\Request $request
* @param int $licenseId
* @param int $seatId
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $licenseId, $seatId)
public function update(Request $request, $licenseId, $seatId) : JsonResponse | array
{
$this->authorize('checkout', License::class);
// sanity checks:
// 1. does the license seat exist?
if (! $licenseSeat = LicenseSeat::find($seatId)) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'Seat not found'));
}
// 2. does the seat belong to the specified license?
if (! $license = $licenseSeat->license()->first() || $license->id != intval($licenseId)) {
$license = $licenseSeat->license()->first();
if (!$license || $license->id != intval($licenseId)) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'Seat does not belong to the specified license'));
}
@@ -110,7 +107,7 @@ class LicenseSeatsController extends Controller
// attempt to update the license seat
$licenseSeat->fill($request->all());
$licenseSeat->user_id = Auth::user()->id;
$licenseSeat->created_by = auth()->id();
// check if this update is a checkin operation
// 1. are relevant fields touched at all?
+16 -19
View File
@@ -4,14 +4,12 @@ namespace App\Http\Controllers\Api;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Transformers\LicenseSeatsTransformer;
use App\Http\Transformers\LicensesTransformer;
use App\Http\Transformers\SelectlistTransformer;
use App\Models\Company;
use App\Models\License;
use App\Models\LicenseSeat;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\JsonResponse;
class LicensesController extends Controller
{
@@ -21,16 +19,15 @@ class LicensesController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
*
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
public function index(Request $request) : JsonResponse | array
{
$this->authorize('view', License::class);
$licenses = License::with('company', 'manufacturer', 'supplier','category')->withCount('freeSeats as free_seats_count');
$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')) {
@@ -73,6 +70,9 @@ class LicensesController extends Controller
$licenses->where('depreciation_id', '=', $request->input('depreciation_id'));
}
if ($request->filled('created_by')) {
$licenses->where('created_by', '=', $request->input('created_by'));
}
if (($request->filled('maintained')) && ($request->input('maintained')=='true')) {
$licenses->where('maintained','=',1);
@@ -116,6 +116,9 @@ class LicensesController extends Controller
case 'company':
$licenses = $licenses->leftJoin('companies', 'licenses.company_id', '=', 'companies.id')->orderBy('companies.name', $order);
break;
case 'created_by':
$licenses = $licenses->OrderByCreatedBy($order);
break;
default:
$allowed_columns =
[
@@ -156,11 +159,9 @@ class LicensesController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
public function store(Request $request) : JsonResponse
{
//
$this->authorize('create', License::class);
$license = new License;
$license->fill($request->all());
@@ -177,12 +178,11 @@ class LicensesController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
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);
@@ -195,9 +195,8 @@ class LicensesController extends Controller
* @since [v4.0]
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
public function update(Request $request, $id) : JsonResponse | array
{
//
$this->authorize('update', License::class);
@@ -218,11 +217,9 @@ class LicensesController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
public function destroy($id) : JsonResponse
{
//
$license = License::findOrFail($id);
$this->authorize('delete', $license);
@@ -248,7 +245,7 @@ class LicensesController extends Controller
*
* @see \App\Http\Transformers\SelectlistTransformer
*/
public function selectlist(Request $request)
public function selectlist(Request $request) : array
{
$licenses = License::select([
'licenses.id',
@@ -5,12 +5,15 @@ namespace App\Http\Controllers\Api;
use App\Helpers\Helper;
use App\Http\Requests\ImageUploadRequest;
use App\Http\Controllers\Controller;
use App\Http\Transformers\AssetsTransformer;
use App\Http\Transformers\LocationsTransformer;
use App\Http\Transformers\SelectlistTransformer;
use App\Models\Asset;
use App\Models\Location;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
use Illuminate\Http\JsonResponse;
class LocationsController extends Controller
{
@@ -21,7 +24,7 @@ class LocationsController extends Controller
* @since [v4.0]
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
public function index(Request $request) : JsonResponse | array
{
$this->authorize('view', Location::class);
$allowed_columns = [
@@ -138,9 +141,8 @@ class LocationsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
* @return \Illuminate\Http\Response
*/
public function store(ImageUploadRequest $request)
public function store(ImageUploadRequest $request) : JsonResponse
{
$this->authorize('create', Location::class);
$location = new Location;
@@ -160,9 +162,8 @@ class LocationsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
public function show($id) : JsonResponse | array
{
$this->authorize('view', Location::class);
$location = Location::with('parent', 'manager', 'children')
@@ -199,9 +200,8 @@ class LocationsController extends Controller
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
* @param int $id
* @return \Illuminate\Http\JsonResponse
*/
public function update(ImageUploadRequest $request, $id)
public function update(ImageUploadRequest $request, $id) : JsonResponse
{
$this->authorize('update', Location::class);
$location = Location::findOrFail($id);
@@ -224,21 +224,36 @@ class LocationsController extends Controller
return response()->json(Helper::formatStandardApiResponse('error', null, $location->getErrors()));
}
public function assets(Request $request, Location $location) : JsonResponse | array
{
$this->authorize('view', Asset::class);
$this->authorize('view', $location);
$assets = Asset::where('assigned_to', '=', $location->id)->where('assigned_type', '=', Location::class)->with('model', 'model.category', 'assetstatus', 'location', 'company', 'defaultLoc');
$assets = $assets->get();
return (new AssetsTransformer)->transformAssets($assets, $assets->count(), $request);
}
/**
* Remove the specified resource from storage.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
public function destroy($id) : JsonResponse
{
$this->authorize('delete', Location::class);
$location = Location::findOrFail($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')
->withCount('accessories as accessories_count')
->findOrFail($id);
if (! $location->isDeletable()) {
return response()
->json(Helper::formatStandardApiResponse('error', null, trans('admin/companies/message.assoc_users')));
->json(Helper::formatStandardApiResponse('error', null, trans('admin/locations/message.assoc_users')));
}
$this->authorize('delete', $location);
$location->delete();
@@ -274,7 +289,7 @@ class LocationsController extends Controller
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
*/
public function selectlist(Request $request)
public function selectlist(Request $request) : array
{
// If a user is in the process of editing their profile, as determined by the referrer,
// then we check that they have permission to edit their own location.
@@ -319,7 +334,6 @@ class LocationsController extends Controller
$paginated_results = new LengthAwarePaginator($locations_formatted->forPage($page, 500), $locations_formatted->count(), 500, $page, []);
//return [];
return (new SelectlistTransformer)->transformSelectlist($paginated_results);
}
}
@@ -10,8 +10,8 @@ use App\Models\Actionlog;
use App\Models\Manufacturer;
use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Illuminate\Http\JsonResponse;
class ManufacturersController extends Controller
{
@@ -22,14 +22,46 @@ class ManufacturersController extends Controller
* @since [v4.0]
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
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')
->withCount('components as components_count');
if ($request->input('deleted') == 'true') {
$manufacturers->onlyTrashed();
@@ -66,10 +98,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();
@@ -83,9 +123,8 @@ class ManufacturersController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
* @return \Illuminate\Http\Response
*/
public function store(ImageUploadRequest $request)
public function store(ImageUploadRequest $request) : JsonResponse
{
$this->authorize('create', Manufacturer::class);
$manufacturer = new Manufacturer;
@@ -105,9 +144,8 @@ class ManufacturersController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
public function show($id) : JsonResponse | array
{
$this->authorize('view', Manufacturer::class);
$manufacturer = Manufacturer::withCount('assets as assets_count')->withCount('licenses as licenses_count')->withCount('consumables as consumables_count')->withCount('accessories as accessories_count')->findOrFail($id);
@@ -122,9 +160,8 @@ class ManufacturersController extends Controller
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(ImageUploadRequest $request, $id)
public function update(ImageUploadRequest $request, $id) : JsonResponse
{
$this->authorize('update', Manufacturer::class);
$manufacturer = Manufacturer::findOrFail($id);
@@ -144,9 +181,8 @@ class ManufacturersController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
public function destroy($id) : JsonResponse
{
$this->authorize('delete', Manufacturer::class);
$manufacturer = Manufacturer::findOrFail($id);
@@ -167,10 +203,9 @@ class ManufacturersController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v6.3.4]
* @param int $id
* @return \Illuminate\Http\JsonResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function restore($id)
public function restore($id) : JsonResponse
{
$this->authorize('delete', Manufacturer::class);
@@ -186,7 +221,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::user()->id;
$logaction->created_by = auth()->id();
$logaction->logaction('restore');
return response()->json(Helper::formatStandardApiResponse('success', trans('admin/manufacturers/message.restore.success')), 200);
@@ -206,7 +241,7 @@ class ManufacturersController extends Controller
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
*/
public function selectlist(Request $request)
public function selectlist(Request $request) : array
{
$this->authorize('view.selectlists');
@@ -7,6 +7,8 @@ use App\Http\Controllers\Controller;
use App\Http\Transformers\PredefinedKitsTransformer;
use App\Models\PredefinedKit;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use App\Http\Transformers\SelectlistTransformer;
/**
* @author [D. Minaev.] [<dmitriy.minaev.v@gmail.com>]
@@ -18,12 +20,11 @@ class PredefinedKitsController extends Controller
*
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
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'));
@@ -34,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();
@@ -47,9 +65,8 @@ class PredefinedKitsController extends Controller
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
public function store(Request $request) : JsonResponse
{
$this->authorize('create', PredefinedKit::class);
$kit = new PredefinedKit;
@@ -66,9 +83,8 @@ class PredefinedKitsController extends Controller
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
public function show($id) : array
{
$this->authorize('view', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($id);
@@ -81,9 +97,8 @@ class PredefinedKitsController extends Controller
*
* @param \Illuminate\Http\Request $request
* @param int $id kit id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
public function update(Request $request, $id) : JsonResponse
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($id);
@@ -100,9 +115,8 @@ class PredefinedKitsController extends Controller
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
public function destroy($id) : JsonResponse
{
$this->authorize('delete', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($id);
@@ -123,7 +137,7 @@ class PredefinedKitsController extends Controller
*
* @see \App\Http\Transformers\SelectlistTransformer
*/
public function selectlist(Request $request)
public function selectlist(Request $request) : array
{
$kits = PredefinedKit::select([
'id',
@@ -145,7 +159,7 @@ class PredefinedKitsController extends Controller
* @param int $id
* @return \Illuminate\Http\Response
*/
public function indexLicenses($kit_id)
public function indexLicenses($kit_id) : array
{
$this->authorize('view', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
@@ -160,7 +174,7 @@ class PredefinedKitsController extends Controller
* @param int $id
* @return \Illuminate\Http\Response
*/
public function storeLicense(Request $request, $kit_id)
public function storeLicense(Request $request, $kit_id) : JsonResponse
{
$this->authorize('update', PredefinedKit::class);
@@ -186,9 +200,8 @@ class PredefinedKitsController extends Controller
*
* @param \Illuminate\Http\Request $request
* @param int $kit_id
* @return \Illuminate\Http\Response
*/
public function updateLicense(Request $request, $kit_id, $license_id)
public function updateLicense(Request $request, $kit_id, $license_id) : JsonResponse
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
@@ -205,9 +218,8 @@ class PredefinedKitsController extends Controller
* Remove the specified resource from storage.
*
* @param int $kit_id
* @return \Illuminate\Http\Response
*/
public function detachLicense($kit_id, $license_id)
public function detachLicense($kit_id, $license_id) : JsonResponse
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
@@ -221,9 +233,8 @@ class PredefinedKitsController extends Controller
* Display the specified resource.
*
* @param int $kit_id
* @return \Illuminate\Http\Response
*/
public function indexModels($kit_id)
public function indexModels($kit_id) : array
{
$this->authorize('view', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
@@ -236,9 +247,8 @@ class PredefinedKitsController extends Controller
* Store the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function storeModel(Request $request, $kit_id)
public function storeModel(Request $request, $kit_id) : JsonResponse
{
$this->authorize('update', PredefinedKit::class);
@@ -252,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]);
@@ -264,9 +274,8 @@ class PredefinedKitsController extends Controller
*
* @param \Illuminate\Http\Request $request
* @param int $kit_id
* @return \Illuminate\Http\Response
*/
public function updateModel(Request $request, $kit_id, $model_id)
public function updateModel(Request $request, $kit_id, $model_id) : JsonResponse
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
@@ -283,9 +292,8 @@ class PredefinedKitsController extends Controller
* Remove the specified resource from storage.
*
* @param int $kit_id
* @return \Illuminate\Http\Response
*/
public function detachModel($kit_id, $model_id)
public function detachModel($kit_id, $model_id) : JsonResponse
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
@@ -299,9 +307,8 @@ class PredefinedKitsController extends Controller
* Display the specified resource.
*
* @param int $kit_id
* @return \Illuminate\Http\Response
*/
public function indexConsumables($kit_id)
public function indexConsumables($kit_id) : array
{
$this->authorize('view', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
@@ -314,9 +321,8 @@ class PredefinedKitsController extends Controller
* Store the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function storeConsumable(Request $request, $kit_id)
public function storeConsumable(Request $request, $kit_id) : JsonResponse
{
$this->authorize('update', PredefinedKit::class);
@@ -342,9 +348,8 @@ class PredefinedKitsController extends Controller
*
* @param \Illuminate\Http\Request $request
* @param int $kit_id
* @return \Illuminate\Http\Response
*/
public function updateConsumable(Request $request, $kit_id, $consumable_id)
public function updateConsumable(Request $request, $kit_id, $consumable_id) : JsonResponse
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
@@ -361,9 +366,8 @@ class PredefinedKitsController extends Controller
* Remove the specified resource from storage.
*
* @param int $kit_id
* @return \Illuminate\Http\Response
*/
public function detachConsumable($kit_id, $consumable_id)
public function detachConsumable($kit_id, $consumable_id) : JsonResponse
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
@@ -377,9 +381,8 @@ class PredefinedKitsController extends Controller
* Display the specified resource.
*
* @param int $kit_id
* @return \Illuminate\Http\Response
*/
public function indexAccessories($kit_id)
public function indexAccessories($kit_id) : array
{
$this->authorize('view', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
@@ -392,9 +395,8 @@ class PredefinedKitsController extends Controller
* Store the specified resource.
*
* @param int $kit_id
* @return \Illuminate\Http\Response
*/
public function storeAccessory(Request $request, $kit_id)
public function storeAccessory(Request $request, $kit_id) : JsonResponse
{
$this->authorize('update', PredefinedKit::class);
@@ -420,9 +422,8 @@ class PredefinedKitsController extends Controller
*
* @param \Illuminate\Http\Request $request
* @param int $kit_id
* @return \Illuminate\Http\Response
*/
public function updateAccessory(Request $request, $kit_id, $accessory_id)
public function updateAccessory(Request $request, $kit_id, $accessory_id) : JsonResponse
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
@@ -439,9 +440,8 @@ class PredefinedKitsController extends Controller
* Remove the specified resource from storage.
*
* @param int $kit_id
* @return \Illuminate\Http\Response
*/
public function detachAccessory($kit_id, $accessory_id)
public function detachAccessory($kit_id, $accessory_id) : JsonResponse
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
+15 -20
View File
@@ -6,13 +6,13 @@ use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Models\CheckoutRequest;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
use Laravel\Passport\TokenRepository;
use Illuminate\Contracts\Validation\Factory as ValidationFactory;
use Illuminate\Support\Facades\Gate;
use App\Models\CustomField;
use DB;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\JsonResponse;
class ProfileController extends Controller
{
@@ -42,12 +42,10 @@ class ProfileController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.3.0]
*
* @return array
*/
public function requestedAssets()
public function requestedAssets() : array
{
$checkoutRequests = CheckoutRequest::where('user_id', '=', Auth::user()->id)->get();
$checkoutRequests = CheckoutRequest::where('user_id', '=', auth()->id())->get();
$results = array();
$show_field = array();
@@ -95,10 +93,9 @@ class ProfileController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v6.0.5]
*
* @return \Illuminate\Http\Response
*/
public function createApiToken(Request $request) {
public function createApiToken(Request $request) : JsonResponse
{
if (!Gate::allows('self.api')) {
abort(403);
@@ -106,14 +103,14 @@ class ProfileController extends Controller
$accessTokenName = $request->input('name', 'Auth Token');
if ($accessToken = Auth::user()->createToken($accessTokenName)->accessToken) {
if ($accessToken = auth()->user()->createToken($accessTokenName)->accessToken) {
// Get the ID so we can return that with the payload
$token = DB::table('oauth_access_tokens')->where('user_id', '=', Auth::user()->id)->where('name','=',$accessTokenName)->orderBy('created_at', 'desc')->first();
$token = DB::table('oauth_access_tokens')->where('user_id', '=', auth()->id())->where('name','=',$accessTokenName)->orderBy('created_at', 'desc')->first();
$accessTokenData['id'] = $token->id;
$accessTokenData['token'] = $accessToken;
$accessTokenData['name'] = $accessTokenName;
return response()->json(Helper::formatStandardApiResponse('success', $accessTokenData, 'Personal access token '.$accessTokenName.' created successfully'));
return response()->json(Helper::formatStandardApiResponse('success', $accessTokenData, trans('account/general.personal_api_keys_success', ['key' => $accessTokenName])));
}
return response()->json(Helper::formatStandardApiResponse('error', null, 'Token could not be created.'));
@@ -125,17 +122,16 @@ class ProfileController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v6.0.5]
*
* @return \Illuminate\Http\Response
*/
public function deleteApiToken($tokenId) {
public function deleteApiToken($tokenId) : Response
{
if (!Gate::allows('self.api')) {
abort(403);
}
$token = $this->tokenRepository->findForUser(
$tokenId, Auth::user()->getAuthIdentifier()
$tokenId, auth()->user()->getAuthIdentifier()
);
if (is_null($token)) {
@@ -154,16 +150,15 @@ class ProfileController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v6.0.5]
*
* @return \Illuminate\Http\Response
*/
public function showApiTokens(Request $request) {
public function showApiTokens() : JsonResponse
{
if (!Gate::allows('self.api')) {
abort(403);
}
$tokens = $this->tokenRepository->forUser(Auth::user()->getAuthIdentifier());
$tokens = $this->tokenRepository->forUser(auth()->user()->getAuthIdentifier());
$token_values = $tokens->load('client')->filter(function ($token) {
return $token->client->personal_access_client && ! $token->revoked;
})->values();
+26 -9
View File
@@ -6,6 +6,7 @@ use App\Http\Controllers\Controller;
use App\Http\Transformers\ActionlogsTransformer;
use App\Models\Actionlog;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
class ReportsController extends Controller
{
@@ -14,13 +15,12 @@ class ReportsController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return View
*/
public function index(Request $request)
public function index(Request $request) : JsonResponse | array
{
$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')));
@@ -32,19 +32,26 @@ class ReportsController extends Controller
}
if (($request->filled('item_type')) && ($request->filled('item_id'))) {
$actionlogs = $actionlogs->where('item_id', '=', $request->input('item_id'))
$actionlogs = $actionlogs->where(function($query) use ($request)
{
$query->where('item_id', '=', $request->input('item_id'))
->where('item_type', '=', 'App\\Models\\'.ucwords($request->input('item_type')))
->orWhere(function($query) use ($request)
{
$query->where('target_id', '=', $request->input('item_id'))
->where('target_type', '=', 'App\\Models\\'.ucwords($request->input('item_type')));
});
});
}
if ($request->filled('action_type')) {
$actionlogs = $actionlogs->where('action_type', '=', $request->input('action_type'))->orderBy('created_at', 'desc');
}
if ($request->filled('created_by')) {
$actionlogs = $actionlogs->where('created_by', '=', $request->input('created_by'));
}
if ($request->filled('action_source')) {
$actionlogs = $actionlogs->where('action_source', '=', $request->input('action_source'))->orderBy('created_at', 'desc');
}
@@ -61,25 +68,35 @@ 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',
];
$total = $actionlogs->count();
// Make sure the offset and limit are actually integers and do not exceed system limits
$offset = ($request->input('offset') > $actionlogs->count()) ? $actionlogs->count() : app('api_offset_value');
$offset = ($request->input('offset') > $total) ? $total : app('api_offset_value');
$limit = app('api_limit_value');
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
$order = ($request->input('order') == 'asc') ? 'asc' : 'desc';
$total = $actionlogs->count();
$actionlogs = $actionlogs->orderBy($sort, $order)->skip($offset)->take($limit)->get();
switch ($request->input('sort')) {
case 'created_by':
$actionlogs->OrderByCreatedBy($order);
break;
default:
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
$actionlogs = $actionlogs->orderBy($sort, $order);
break;
}
$actionlogs = $actionlogs->skip($offset)->take($limit)->get();
return response()->json((new ActionlogsTransformer)->transformActionlogs($actionlogs, $total), 200, ['Content-Type' => 'application/json;charset=utf8'], JSON_UNESCAPED_UNICODE);
}
+31 -38
View File
@@ -9,42 +9,38 @@ use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Ldap;
use App\Models\Setting;
use Mail;
use App\Notifications\SlackTest;
use App\Notifications\MailTest;
use GuzzleHttp\Client;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use App\Http\Requests\SlackSettingsRequest;
use Illuminate\Support\Facades\Validator;
use App\Http\Transformers\LoginAttemptsTransformer;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
class SettingsController extends Controller
{
public function ldaptest()
public function ldaptest() : JsonResponse
{
$settings = Setting::getSettings();
if ($settings->ldap_enabled!='1') {
\Log::debug('LDAP is not enabled cannot test.');
Log::debug('LDAP is not enabled cannot test.');
return response()->json(['message' => 'LDAP is not enabled, cannot test.'], 400);
}
\Log::debug('Preparing to test LDAP connection');
Log::debug('Preparing to test LDAP connection');
$message = []; //where we collect together test messages
try {
$connection = Ldap::connectToLdap();
try {
$message['bind'] = ['message' => 'Successfully bound to LDAP server.'];
\Log::debug('attempting to bind to LDAP for LDAP test');
Log::debug('attempting to bind to LDAP for LDAP test');
Ldap::bindAdminToLdap($connection);
$message['login'] = [
'message' => 'Successfully connected to LDAP server.',
@@ -75,24 +71,24 @@ class SettingsController extends Controller
return response()->json($message, 200);
} catch (\Exception $e) {
\Log::debug('Bind failed');
\Log::debug("Exception was: ".$e->getMessage());
Log::debug('Bind failed');
Log::debug("Exception was: ".$e->getMessage());
return response()->json(['message' => $e->getMessage()], 400);
//return response()->json(['message' => $e->getMessage()], 500);
}
} catch (\Exception $e) {
\Log::debug('Connection failed but we cannot debug it any further on our end.');
Log::debug('Connection failed but we cannot debug it any further on our end.');
return response()->json(['message' => $e->getMessage()], 500);
}
}
public function ldaptestlogin(Request $request)
public function ldaptestlogin(Request $request) : JsonResponse
{
if (Setting::getSettings()->ldap_enabled != '1') {
\Log::debug('LDAP is not enabled. Cannot test.');
Log::debug('LDAP is not enabled. Cannot test.');
return response()->json(['message' => 'LDAP is not enabled, cannot test.'], 400);
}
@@ -104,39 +100,39 @@ class SettingsController extends Controller
$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) {
\Log::debug('LDAP Validation test failed.');
Log::debug('LDAP Validation test failed.');
$validation_errors = implode(' ',$validator->errors()->all());
return response()->json(['message' => $validator->errors()->all()], 400);
}
\Log::debug('Preparing to test LDAP login');
Log::debug('Preparing to test LDAP login');
try {
$connection = Ldap::connectToLdap();
try {
Ldap::bindAdminToLdap($connection);
\Log::debug('Attempting to bind to LDAP for LDAP test');
Log::debug('Attempting to bind to LDAP for LDAP test');
try {
$ldap_user = Ldap::findAndBindUserLdap($request->input('ldaptest_user'), $request->input('ldaptest_password'));
if ($ldap_user) {
\Log::debug('It worked! '. $request->input('ldaptest_user').' successfully binded to LDAP.');
Log::debug('It worked! '. $request->input('ldaptest_user').' successfully binded to LDAP.');
return response()->json(['message' => 'It worked! '. $request->input('ldaptest_user').' successfully binded to LDAP.'], 200);
}
return response()->json(['message' => 'Login Failed. '. $request->input('ldaptest_user').' did not successfully bind to LDAP.'], 400);
} catch (\Exception $e) {
\Log::debug('LDAP login failed');
Log::debug('LDAP login failed');
return response()->json(['message' => $e->getMessage()], 400);
}
} catch (\Exception $e) {
\Log::debug('Bind failed');
Log::debug('Bind failed');
return response()->json(['message' => $e->getMessage()], 400);
//return response()->json(['message' => $e->getMessage()], 500);
}
} catch (\Exception $e) {
\Log::debug('Connection failed');
Log::debug('Connection failed');
return response()->json(['message' => $e->getMessage()], 500);
}
@@ -148,9 +144,8 @@ class SettingsController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return JsonResponse
*/
public function ajaxTestEmail()
public function ajaxTestEmail() : JsonResponse
{
if (!config('app.lock_passwords')) {
try {
@@ -170,9 +165,8 @@ class SettingsController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v5.0.0]
* @return JsonResponse
*/
public function purgeBarcodes()
public function purgeBarcodes() : JsonResponse
{
$file_count = 0;
$files = Storage::disk('public')->files('barcodes');
@@ -181,19 +175,19 @@ class SettingsController extends Controller
$file_parts = explode('.', $file);
$extension = end($file_parts);
\Log::debug($extension);
Log::debug($extension);
// Only generated barcodes would have a .png file extension
if ($extension == 'png') {
\Log::debug('Deleting: '.$file);
Log::debug('Deleting: '.$file);
try {
Storage::disk('public')->delete($file);
\Log::debug('Deleting: '.$file);
Log::debug('Deleting: '.$file);
$file_count++;
} catch (\Exception $e) {
\Log::debug($e);
Log::debug($e);
}
}
}
@@ -211,9 +205,8 @@ class SettingsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v5.0.0]
* @param \Illuminate\Http\Request $request
* @return array | JsonResponse
*/
public function showLoginAttempts(Request $request)
public function showLoginAttempts(Request $request) : array
{
$allowed_columns = ['id', 'username', 'remote_ip', 'user_agent', 'successful', 'created_at'];
@@ -233,9 +226,9 @@ class SettingsController extends Controller
* Lists backup files
*
* @author [A. Gianotto]
* @return array | JsonResponse
*/
public function listBackups() {
public function listBackups() : array
{
$settings = Setting::getSettings();
$path = 'app/backups';
$backup_files = Storage::files($path);
@@ -276,9 +269,9 @@ class SettingsController extends Controller
* exhausts memory on larger files.
*
* @author [A. Gianotto]
* @return JsonResponse|\Symfony\Component\HttpFoundation\BinaryFileResponse
*/
public function downloadBackup($file) {
public function downloadBackup($file) : JsonResponse | BinaryFileResponse
{
$path = storage_path('app/backups');
@@ -296,9 +289,9 @@ class SettingsController extends Controller
*
* @author [A. Gianotto]
* @since [v6.3.1]
* @return JsonResponse|\Symfony\Component\HttpFoundation\BinaryFileResponse
*/
public function downloadLatestBackup() {
public function downloadLatestBackup() : JsonResponse | BinaryFileResponse
{
$fileData = collect();
foreach (Storage::files('app/backups') as $file) {
@@ -8,10 +8,11 @@ use App\Http\Transformers\AssetsTransformer;
use App\Http\Transformers\SelectlistTransformer;
use App\Http\Transformers\StatuslabelsTransformer;
use App\Models\Asset;
use App\Models\Setting;
use App\Models\Statuslabel;
use Illuminate\Http\Request;
use App\Http\Transformers\PieChartTransformer;
use Illuminate\Support\Arr;
use Illuminate\Http\JsonResponse;
class StatuslabelsController extends Controller
{
@@ -20,14 +21,22 @@ class StatuslabelsController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
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',
'status_type',
];
$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'));
@@ -41,23 +50,30 @@ class StatuslabelsController extends Controller
// if a status_type is passed, filter by that
if ($request->filled('status_type')) {
if (strtolower($request->input('status_type')) == 'pending') {
$statuslabels = $statuslabels->Pending();
} elseif (strtolower($request->input('status_type')) == 'archived') {
$statuslabels = $statuslabels->Archived();
} elseif (strtolower($request->input('status_type')) == 'deployable') {
$statuslabels = $statuslabels->Deployable();
$statuslabels->where('status_type', '=', 'pending');
} elseif (strtolower($request->input('status_type')) == 'archived') $statuslabels->where('status_type', '=', 'archived');
elseif (strtolower($request->input('status_type')) == 'deployable') {
$statuslabels->where('status_type', '=', 'deployable');
} elseif (strtolower($request->input('status_type')) == 'undeployable') {
$statuslabels = $statuslabels->Undeployable();
$statuslabels->whereNot('status_type', 'deployable');
}
}
// 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();
@@ -72,24 +88,15 @@ class StatuslabelsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
public function store(Request $request) : JsonResponse
{
$this->authorize('create', Statuslabel::class);
$request->except('deployable', 'pending', 'archived');
if (! $request->filled('type')) {
return response()->json(Helper::formatStandardApiResponse('error', null, ['type' => ['Status label type is required.']]), 500);
}
$statuslabel = new Statuslabel;
$statuslabel->fill($request->all());
$statusType = Statuslabel::getStatuslabelTypesForDB($request->input('type'));
$statuslabel->deployable = $statusType['deployable'];
$statuslabel->pending = $statusType['pending'];
$statuslabel->archived = $statusType['archived'];
$statuslabel->status_type = $request->input('status_type');
$statuslabel->color = $request->input('color');
$statuslabel->show_in_nav = $request->input('show_in_nav', 0);
$statuslabel->default_label = $request->input('default_label', 0);
@@ -108,9 +115,8 @@ class StatuslabelsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
public function show($id) : array
{
$this->authorize('view', Statuslabel::class);
$statuslabel = Statuslabel::findOrFail($id);
@@ -126,26 +132,17 @@ class StatuslabelsController extends Controller
* @since [v4.0]
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
public function update(Request $request, $id) : JsonResponse
{
$this->authorize('update', Statuslabel::class);
$statuslabel = Statuslabel::findOrFail($id);
$request->except('deployable', 'pending', 'archived');
if (! $request->filled('type')) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'Status label type is required.'));
}
$statuslabel->fill($request->all());
$statusType = Statuslabel::getStatuslabelTypesForDB($request->input('type'));
$statuslabel->deployable = $statusType['deployable'];
$statuslabel->pending = $statusType['pending'];
$statuslabel->archived = $statusType['archived'];
$statuslabel->status_type = $request->input('status_type');
$statuslabel->color = $request->input('color');
$statuslabel->show_in_nav = $request->input('show_in_nav', 0);
$statuslabel->default_label = $request->input('default_label', 0);
@@ -163,9 +160,8 @@ class StatuslabelsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
public function destroy($id) : JsonResponse
{
$this->authorize('delete', Statuslabel::class);
$statuslabel = Statuslabel::findOrFail($id);
@@ -188,13 +184,18 @@ class StatuslabelsController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return array
*/
public function getAssetCountByStatuslabel()
public function getAssetCountByStatuslabel() : array
{
$this->authorize('view', Statuslabel::class);
$statuslabels = Statuslabel::withCount('assets')->get();
$total = Array();
if (Setting::getSettings()->show_archived_in_list == 0 ) {
$statuslabels = Statuslabel::withCount('assets')->whereNot('status_type','archived')->get();
} else {
$statuslabels = Statuslabel::withCount('assets')->get();
}
$total = [];
foreach ($statuslabels as $statuslabel) {
@@ -215,9 +216,8 @@ class StatuslabelsController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v6.0.11]
* @return array
*/
public function getAssetCountByMetaStatus()
public function getAssetCountByMetaStatus() : array
{
$this->authorize('view', Statuslabel::class);
@@ -245,9 +245,8 @@ class StatuslabelsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function assets(Request $request, $id)
public function assets(Request $request, $id) : array
{
$this->authorize('view', Statuslabel::class);
$this->authorize('index', Asset::class);
@@ -281,12 +280,11 @@ class StatuslabelsController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return bool
*/
public function checkIfDeployable($id)
public function checkIfDeployable($id) : string
{
$statuslabel = Statuslabel::findOrFail($id);
if ($statuslabel->getStatuslabelType() == 'deployable') {
if ($statuslabel->status_type == 'deployable') {
return '1';
}
@@ -300,26 +298,26 @@ class StatuslabelsController extends Controller
* @since [v6.1.1]
* @see \App\Http\Transformers\SelectlistTransformer
*/
public function selectlist(Request $request)
public function selectlist(Request $request) : array
{
$this->authorize('view.selectlists');
$statuslabels = Statuslabel::orderBy('default_label', 'desc')->orderBy('name', 'asc')->orderBy('deployable', 'desc');
$statuslabels = Statuslabel::orderBy('default_label', 'desc')->orderBy('name', 'asc')->orderBy('status_type', 'desc');
if ($request->filled('search')) {
$statuslabels = $statuslabels->where('name', 'LIKE', '%'.$request->get('search').'%');
}
if ($request->filled('deployable')) {
$statuslabels = $statuslabels->where('deployable', '=', '1');
$statuslabels = $statuslabels->where('status_type', '=', 'deployable');
}
if ($request->filled('pending')) {
$statuslabels = $statuslabels->where('pending', '=', '1');
$statuslabels = $statuslabels->where('status_type', '=', 'pending');
}
if ($request->filled('archived')) {
$statuslabels = $statuslabels->where('archived', '=', '1');
$statuslabels = $statuslabels->where('status_type', '=', 'archived');
}
$statuslabels = $statuslabels->orderBy('name', 'ASC')->paginate(50);
@@ -10,6 +10,7 @@ use App\Models\Supplier;
use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest;
use Illuminate\Support\Facades\Storage;
use Illuminate\Http\JsonResponse;
class SuppliersController extends Controller
{
@@ -20,7 +21,7 @@ class SuppliersController extends Controller
* @since [v4.0]
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
public function index(Request $request): array
{
$this->authorize('view', Supplier::class);
$allowed_columns = ['
@@ -114,9 +115,8 @@ class SuppliersController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
* @return \Illuminate\Http\Response
*/
public function store(ImageUploadRequest $request)
public function store(ImageUploadRequest $request) : JsonResponse
{
$this->authorize('create', Supplier::class);
$supplier = new Supplier;
@@ -136,9 +136,8 @@ class SuppliersController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
public function show($id) : array
{
$this->authorize('view', Supplier::class);
$supplier = Supplier::findOrFail($id);
@@ -154,9 +153,8 @@ class SuppliersController extends Controller
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(ImageUploadRequest $request, $id)
public function update(ImageUploadRequest $request, $id) : JsonResponse
{
$this->authorize('update', Supplier::class);
$supplier = Supplier::findOrFail($id);
@@ -176,9 +174,8 @@ class SuppliersController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
public function destroy($id) : JsonResponse
{
$this->authorize('delete', Supplier::class);
$supplier = Supplier::with('asset_maintenances', 'assets', 'licenses')->withCount('asset_maintenances as asset_maintenances_count', 'assets as assets_count', 'licenses as licenses_count')->findOrFail($id);
@@ -209,7 +206,7 @@ class SuppliersController extends Controller
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
*/
public function selectlist(Request $request)
public function selectlist(Request $request) : array
{
$this->authorize('view.selectlists');
+189 -153
View File
@@ -13,15 +13,19 @@ use App\Http\Transformers\SelectlistTransformer;
use App\Http\Transformers\UsersTransformer;
use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\Accessory;
use App\Models\Company;
use App\Models\Consumable;
use App\Models\License;
use App\Models\User;
use App\Notifications\CurrentInventory;
use Auth;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Log;
use App\Http\Requests\DeleteUserRequest;
use Illuminate\Http\JsonResponse;
class UsersController extends Controller
{
@@ -31,21 +35,22 @@ class UsersController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
*
* @return \Illuminate\Http\Response
* @return array
*/
public function index(Request $request)
public function index(Request $request) : array
{
$this->authorize('view', User::class);
$users = User::select([
'users.activated',
'users.created_by',
'users.address',
'users.avatar',
'users.city',
'users.company_id',
'users.country',
'users.created_by',
'users.created_at',
'users.updated_at',
'users.deleted_at',
'users.department_id',
'users.email',
@@ -64,7 +69,6 @@ class UsersController extends Controller
'users.state',
'users.two_factor_enrolled',
'users.two_factor_optin',
'users.updated_at',
'users.username',
'users.zip',
'users.remote',
@@ -75,10 +79,14 @@ class UsersController extends Controller
'users.autoassign_licenses',
'users.website',
])->with('manager', 'groups', 'userloc', 'company', 'department', 'assets', 'licenses', 'accessories', 'consumables', 'createdBy',)
->withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count');
])->with('manager', 'groups', 'userloc', 'company', 'department', 'assets', 'licenses', 'accessories', 'consumables', 'createdBy', 'managesUsers', 'managedLocations')
->withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count', 'managesUsers as manages_users_count', 'managedLocations as manages_locations_count');
if ($request->filled('search') != '') {
$users = $users->TextSearch($request->input('search'));
}
if ($request->filled('activated')) {
$users = $users->where('users.activated', '=', $request->input('activated'));
}
@@ -187,12 +195,27 @@ class UsersController extends Controller
$users->has('accessories', '=', $request->input('accessories_count'));
}
if ($request->filled('manages_users_count')) {
$users->has('manages_users_count', '=', $request->input('manages_users_count'));
}
if ($request->filled('manages_locations_count')) {
$users->has('manages_locations_count', '=', $request->input('manages_locations_count'));
}
if ($request->filled('autoassign_licenses')) {
$users->where('autoassign_licenses', '=', $request->input('autoassign_licenses'));
}
if ($request->filled('search')) {
$users = $users->TextSearch($request->input('search'));
if ($request->filled('locale')) {
$users = $users->where('users.locale', '=', $request->input('locale'));
}
if (($request->filled('deleted')) && ($request->input('deleted') == 'true')) {
$users = $users->onlyTrashed();
} elseif (($request->filled('all')) && ($request->input('all') == 'true')) {
$users = $users->withTrashed();
}
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
@@ -230,13 +253,10 @@ class UsersController extends Controller
'jobtitle',
'username',
'employee_num',
'assets',
'accessories',
'consumables',
'licenses',
'groups',
'activated',
'created_at',
'updated_at',
'two_factor_enrolled',
'two_factor_optin',
'last_login',
@@ -244,6 +264,8 @@ class UsersController extends Controller
'licenses_count',
'consumables_count',
'accessories_count',
'manages_users_count',
'manages_locations_count',
'phone',
'address',
'city',
@@ -260,20 +282,14 @@ class UsersController extends Controller
'end_date',
'autoassign_licenses',
'website',
'locale',
];
$sort = in_array($request->get('sort'), $allowed_columns) ? $request->get('sort') : 'first_name';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'first_name';
$users = $users->orderBy($sort, $order);
break;
}
if (($request->filled('deleted')) && ($request->input('deleted') == 'true')) {
$users = $users->onlyTrashed();
} elseif (($request->filled('all')) && ($request->input('all') == 'true')) {
$users = $users->withTrashed();
}
$users = Company::scopeCompanyables($users);
// Make sure the offset and limit are actually integers and do not exceed system limits
@@ -293,7 +309,7 @@ class UsersController extends Controller
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
*/
public function selectlist(Request $request)
public function selectlist(Request $request) : array
{
$users = User::select(
[
@@ -308,8 +324,6 @@ class UsersController extends Controller
]
)->where('show_in_list', '=', '1');
$users = Company::scopeCompanyables($users);
if ($request->filled('search')) {
$users = $users->where(function ($query) use ($request) {
$query->SimpleNameSearch($request->get('search'))
@@ -351,21 +365,21 @@ class UsersController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(SaveUserRequest $request)
public function store(SaveUserRequest $request) : JsonResponse
{
$this->authorize('create', User::class);
$user = new User;
$user->fill($request->all());
$user->created_by = Auth::user()->id;
$user->company_id = Company::getIdForCurrentUser($request->input('company_id'));
$user->created_by = auth()->id();
if ($request->has('permissions')) {
$permissions_array = $request->input('permissions');
// Strip out the superuser permission if the API user isn't a superadmin
if (! Auth::user()->isSuperUser()) {
if (! auth()->user()->isSuperUser()) {
unset($permissions_array['superuser']);
}
$user->permissions = $permissions_array;
@@ -398,14 +412,18 @@ class UsersController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
public function show($id) : JsonResponse | array
{
$this->authorize('view', User::class);
$user = User::withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count')->findOrFail($id);
return (new UsersTransformer)->transformUser($user);
if ($user = User::withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count', 'managesUsers as manages_users_count', 'managedLocations as manages_locations_count')->find($id)) {
$this->authorize('view', $user);
return (new UsersTransformer)->transformUser($user);
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found', compact('id'))));
}
@@ -416,89 +434,76 @@ class UsersController extends Controller
* @since [v4.0]
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(SaveUserRequest $request, $id)
public function update(SaveUserRequest $request, User $user): JsonResponse
{
$this->authorize('update', User::class);
$user = User::findOrFail($id);
$this->authorize('update', $user);
/**
* 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
*
*/
/**
* 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'))) {
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')) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot be your own manager'));
}
if ($request->filled('password')) {
$user->password = bcrypt($request->input('password'));
}
// We need to use has() instead of filled()
// here because we need to overwrite permissions
// if someone needs to null them out
if ($request->has('permissions')) {
$permissions_array = $request->input('permissions');
// Strip out the superuser permission if the API user isn't a superadmin
if (! Auth::user()->isSuperUser()) {
unset($permissions_array['superuser']);
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->permissions = $permissions_array;
}
$user->fill($request->all());
if ($request->filled('company_id')) {
$user->company_id = Company::getIdForCurrentUser($request->input('company_id'));
}
// 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)]);
if ($user->id == $request->input('manager_id')) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot be your own manager'));
}
app('App\Http\Requests\ImageUploadRequest')->handleImages($user, 600, 'image', 'avatars', 'avatar');
if ($user->save()) {
if ($request->filled('password')) {
$user->password = bcrypt($request->input('password'));
}
// Sync group memberships:
// This was changed in Snipe-IT v4.6.x to 4.7, since we upgraded to Laravel 5.5
// which changes the behavior of has vs filled.
// The $request->has method will now return true even if the input value is an empty string or null.
// A new $request->filled method has was added that provides the previous behavior of the has method.
// We need to use has() instead of filled()
// here because we need to overwrite permissions
// if someone needs to null them out
if ($request->has('permissions')) {
$permissions_array = $request->input('permissions');
// Check if the request has groups passed and has a value
if ($request->filled('groups')) {
$validator = Validator::make($request->all(), [
'groups.*' => 'integer|exists:permission_groups,id',
]);
if ($validator->fails()){
return response()->json(Helper::formatStandardApiResponse('error', null, $user->getErrors()));
// Strip out the individual superuser permission if the API user isn't a superadmin
if (!auth()->user()->isSuperUser()) {
unset($permissions_array['superuser']);
}
$user->groups()->sync($request->input('groups'));
// The groups field has been passed but it is null, so we should blank it out
} elseif ($request->has('groups')) {
$user->groups()->sync([]);
$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)]);
return response()->json(Helper::formatStandardApiResponse('success', (new UsersTransformer)->transformUser($user), trans('admin/users/message.success.update')));
}
app('App\Http\Requests\ImageUploadRequest')->handleImages($user, 600, 'image', 'avatars', 'avatar');
return response()->json(Helper::formatStandardApiResponse('error', null, $user->getErrors()));
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())) {
$validator = Validator::make($request->only('groups'), [
'groups.*' => 'integer|exists:permission_groups,id',
]);
if ($validator->fails()) {
return response()->json(Helper::formatStandardApiResponse('error', null, $validator->errors()));
}
// 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()));
}
/**
@@ -507,45 +512,35 @@ class UsersController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
public function destroy(DeleteUserRequest $request, $id) : JsonResponse
{
$this->authorize('delete', User::class);
$user = User::findOrFail($id);
$this->authorize('delete', $user);
if (($user->assets) && ($user->assets->count() > 0)) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.error.delete_has_assets')));
}
if ($user = User::withTrashed()->find($id)) {
if (($user->licenses) && ($user->licenses->count() > 0)) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'This user still has '.$user->licenses->count().' license(s) associated with them and cannot be deleted.'));
}
$this->authorize('delete', $user);
if (($user->accessories) && ($user->accessories->count() > 0)) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'This user still has '.$user->accessories->count().' accessories associated with them.'));
}
if ($user->delete()) {
if (($user->managedLocations()) && ($user->managedLocations()->count() > 0)) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'This user still has '.$user->managedLocations()->count().' locations that they manage.'));
}
if ($user->delete()) {
// Remove the user's avatar if they have one
if (Storage::disk('public')->exists('avatars/'.$user->avatar)) {
try {
Storage::disk('public')->delete('avatars/'.$user->avatar);
} catch (\Exception $e) {
\Log::debug($e);
// Remove the user's avatar if they have one
if (Storage::disk('public')->exists('avatars/' . $user->avatar)) {
try {
Storage::disk('public')->delete('avatars/' . $user->avatar);
} catch (\Exception $e) {
Log::debug($e);
}
}
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.success.delete')));
}
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.success.delete')));
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.error.delete')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.error.delete')));
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found')));
}
/**
@@ -554,15 +549,41 @@ class UsersController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @param $userId
* @return string JSON
*/
public function assets(Request $request, $id)
public function assets(Request $request, $id) : JsonResponse | array
{
$this->authorize('view', User::class);
$this->authorize('view', Asset::class);
$assets = Asset::where('assigned_to', '=', $id)->where('assigned_type', '=', User::class)->with('model')->get();
return (new AssetsTransformer)->transformAssets($assets, $assets->count(), $request);
if ($user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find($id)) {
$this->authorize('view', $user);
$assets = Asset::where('assigned_to', '=', $id)->where('assigned_type', '=', User::class)->with('model');
// Filter on category ID
if ($request->filled('category_id')) {
$assets = $assets->InCategory($request->input('category_id'));
}
// Filter on model ID
if ($request->filled('model_id')) {
$model_ids = $request->input('model_id');
if (!is_array($model_ids)) {
$model_ids = array($model_ids);
}
$assets = $assets->InModelList($model_ids);
}
$assets = $assets->get();
return (new AssetsTransformer)->transformAssets($assets, $assets->count(), $request);
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found', compact('id'))));
}
/**
@@ -572,19 +593,26 @@ class UsersController extends Controller
* @since [v6.0.13]
* @param Request $request
* @param $id
* @return string JSON
*/
public function emailAssetList(Request $request, $id)
{
$user = User::findOrFail($id);
public function emailAssetList(Request $request, $id) : JsonResponse
if (empty($user->email)) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.inventorynotification.error')));
{
$this->authorize('update', User::class);
if ($user = User::find($id)) {
$this->authorize('update', $user);
if (empty($user->email)) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.inventorynotification.error')));
}
$user->notify((new CurrentInventory($user)));
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.inventorynotification.success')));
}
$user->notify((new CurrentInventory($user)));
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found', compact('id'))));
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.inventorynotification.success')));
}
/**
@@ -593,13 +621,13 @@ class UsersController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @param $userId
* @return string JSON
*/
public function consumables(Request $request, $id)
public function consumables(Request $request, $id) : array
{
$this->authorize('view', User::class);
$this->authorize('view', Consumable::class);
$user = User::findOrFail($id);
$this->authorize('view', $user);
$consumables = $user->consumables;
return (new ConsumablesTransformer)->transformConsumables($consumables, $consumables->count(), $request);
}
@@ -610,12 +638,12 @@ class UsersController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.6.14]
* @param $userId
* @return string JSON
*/
public function accessories($id)
public function accessories($id) : array
{
$this->authorize('view', User::class);
$user = User::findOrFail($id);
$this->authorize('view', $user);
$this->authorize('view', Accessory::class);
$accessories = $user->accessories;
@@ -628,14 +656,14 @@ class UsersController extends Controller
* @author [N. Mathar] [<snipe@snipe.net>]
* @since [v5.0]
* @param $userId
* @return string JSON
*/
public function licenses($id)
public function licenses($id) : JsonResponse | array
{
$this->authorize('view', User::class);
$this->authorize('view', License::class);
if ($user = User::where('id', $id)->withTrashed()->first()) {
$this->authorize('update', $user);
$licenses = $user->licenses()->get();
return (new LicensesTransformer())->transformLicenses($licenses, $licenses->count());
}
@@ -650,18 +678,28 @@ class UsersController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @param $userId
* @return string JSON
*/
public function postTwoFactorReset(Request $request)
public function postTwoFactorReset(Request $request) : JsonResponse
{
$this->authorize('update', User::class);
if ($request->filled('id')) {
try {
$user = User::find($request->get('id'));
$this->authorize('update', $user);
$user->two_factor_secret = null;
$user->two_factor_enrolled = 0;
$user->save();
$user->saveQuietly();
// Log the reset
$logaction = new Actionlog();
$logaction->target_type = User::class;
$logaction->target_id = $user->id;
$logaction->item_type = User::class;
$logaction->item_id = $user->id;
$logaction->created_at = date('Y-m-d H:i:s');
$logaction->created_by = auth()->id();
$logaction->logaction('2FA reset');
return response()->json(['message' => trans('admin/settings/general.two_factor_reset_success')], 200);
} catch (\Exception $e) {
@@ -679,9 +717,8 @@ class UsersController extends Controller
* @author [Juan Font] [<juanfontalonso@gmail.com>]
* @since [v4.4.2]
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function getCurrentUserInfo(Request $request)
public function getCurrentUserInfo(Request $request) : array
{
return (new UsersTransformer)->transformUser($request->user());
}
@@ -692,12 +729,13 @@ class UsersController extends Controller
* @author [E. Taylor] [<dev@evantaylor.name>]
* @param int $userId
* @since [v6.0.0]
* @return JsonResponse
*/
public function restore($userId = null)
public function restore($userId) : JsonResponse
{
$this->authorize('delete', User::class);
if ($user = User::withTrashed()->find($userId)) {
$this->authorize('delete', $user);
if ($user->deleted_at == '') {
@@ -710,14 +748,12 @@ 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::user()->id;
$logaction->created_by = auth()->id();
$logaction->logaction('restore');
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.success.restored')), 200);
}
// Check validation to make sure we're not restoring a user with the same username as an existing user
return response()->json(Helper::formatStandardApiResponse('error', null, $user->getErrors()));
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found')), 200);
@@ -2,17 +2,14 @@
namespace App\Http\Controllers;
use App\Helpers\Helper;
use App\Models\Asset;
use App\Models\AssetMaintenance;
use App\Models\Company;
use Auth;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Slack;
use Str;
use TCPDF;
use View;
use \Illuminate\Contracts\View\View;
use \Illuminate\Http\RedirectResponse;
/**
* This controller handles all actions related to Asset Maintenance for
@@ -29,9 +26,8 @@ class AssetMaintenancesController extends Controller
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
* @since [v1.8]
* @return View
*/
private static function getInsufficientPermissionsRedirect()
private static function getInsufficientPermissionsRedirect(): RedirectResponse
{
return redirect()->route('maintenances.index')
->with('error', trans('general.insufficient_permissions'));
@@ -46,9 +42,8 @@ class AssetMaintenancesController extends Controller
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
* @since [v1.8]
* @return View
*/
public function index()
public function index() : View
{
$this->authorize('view', Asset::class);
return view('asset_maintenances/index');
@@ -63,7 +58,7 @@ class AssetMaintenancesController extends Controller
* @since [v1.8]
* @return mixed
*/
public function create()
public function create() : View
{
$this->authorize('update', Asset::class);
$asset = null;
@@ -92,9 +87,8 @@ class AssetMaintenancesController extends Controller
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
* @since [v1.8]
* @return mixed
*/
public function store(Request $request)
public function store(Request $request) : RedirectResponse
{
$this->authorize('update', Asset::class);
// create a new model instance
@@ -115,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 !== '')
@@ -144,9 +138,8 @@ class AssetMaintenancesController extends Controller
* @param int $assetMaintenanceId
* @version v1.0
* @since [v1.8]
* @return mixed
*/
public function edit($assetMaintenanceId = null)
public function edit($assetMaintenanceId = null) : View | RedirectResponse
{
$this->authorize('update', Asset::class);
// Check if the asset maintenance exists
@@ -162,14 +155,9 @@ class AssetMaintenancesController extends Controller
return static::getInsufficientPermissionsRedirect();
}
// Prepare Improvement Type List
$assetMaintenanceType = [
'' => 'Select an improvement type',
] + AssetMaintenance::getImprovementOptions();
$assetMaintenanceType = ['' => 'Select an improvement type'] + AssetMaintenance::getImprovementOptions();
// Get Supplier List
// Render the view
return view('asset_maintenances/edit')
->with('selectedAsset', null)
->with('assetMaintenanceType', $assetMaintenanceType)
@@ -183,11 +171,10 @@ class AssetMaintenancesController extends Controller
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @param Request $request
* @param int $assetMaintenanceId
* @return mixed
* @version v1.0
* @since [v1.8]
*/
public function update(Request $request, $assetMaintenanceId = null)
public function update(Request $request, $assetMaintenanceId = null) : View | RedirectResponse
{
$this->authorize('update', Asset::class);
// Check if the asset maintenance exists
@@ -255,9 +242,8 @@ class AssetMaintenancesController extends Controller
* @param int $assetMaintenanceId
* @version v1.0
* @since [v1.8]
* @return mixed
*/
public function destroy($assetMaintenanceId)
public function destroy($assetMaintenanceId) : RedirectResponse
{
$this->authorize('update', Asset::class);
// Check if the asset maintenance exists
@@ -284,9 +270,8 @@ class AssetMaintenancesController extends Controller
* @param int $assetMaintenanceId
* @version v1.0
* @since [v1.8]
* @return View
*/
public function show($assetMaintenanceId)
public function show($assetMaintenanceId) : View | RedirectResponse
{
$this->authorize('view', Asset::class);
+47 -75
View File
@@ -4,19 +4,21 @@ namespace App\Http\Controllers;
use App\Helpers\Helper;
use App\Http\Requests\ImageUploadRequest;
use App\Http\Requests\StoreAssetModelRequest;
use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\AssetModel;
use App\Models\CustomField;
use App\Models\SnipeModel;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\View;
use Illuminate\Support\Facades\Validator;
use Redirect;
use Request;
use Storage;
use Symfony\Component\HttpFoundation\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Log;
use \Illuminate\Contracts\View\View;
use \Illuminate\Http\RedirectResponse;
/**
* This class controls all actions related to asset models for
@@ -33,10 +35,8 @@ class AssetModelsController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function index()
public function index() : View
{
$this->authorize('index', AssetModel::class);
@@ -48,10 +48,8 @@ class AssetModelsController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function create()
public function create() : View
{
$this->authorize('create', AssetModel::class);
@@ -66,16 +64,12 @@ class AssetModelsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @param ImageUploadRequest $request
* @return Redirect
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function store(ImageUploadRequest $request)
public function store(StoreAssetModelRequest $request) : RedirectResponse
{
$this->authorize('create', AssetModel::class);
// Create a new asset model
$model = new AssetModel;
// Save the model data
$model->eol = $request->input('eol');
$model->depreciation_id = $request->input('depreciation_id');
$model->name = $request->input('name');
@@ -84,8 +78,8 @@ 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->requestable = Request::has('requestable');
$model->created_by = auth()->id();
$model->requestable = $request->has('requestable');
if ($request->input('fieldset_id') != '') {
$model->fieldset_id = $request->input('fieldset_id');
@@ -93,7 +87,6 @@ class AssetModelsController extends Controller
$model = $request->handleImages($model);
// Was it created?
if ($model->save()) {
if ($this->shouldAddDefaultValues($request->input())) {
if (!$this->assignCustomFieldsDefaultValues($model, $request->input('default_values'))){
@@ -113,18 +106,14 @@ class AssetModelsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @param int $modelId
* @return View
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function edit($modelId = null)
public function edit($modelId = null) : View | RedirectResponse
{
$this->authorize('update', AssetModel::class);
if ($item = AssetModel::find($modelId)) {
$category_type = 'asset';
$view = View::make('models/edit', compact('item', 'category_type'));
$view->with('depreciation_list', Helper::depreciationList());
return view('models/edit', compact('item', 'category_type'))->with('depreciation_list', Helper::depreciationList());
return $view;
}
return redirect()->route('models.index')->with('error', trans('admin/models/message.does_not_exist'));
@@ -139,15 +128,14 @@ class AssetModelsController extends Controller
* @since [v1.0]
* @param ImageUploadRequest $request
* @param int $modelId
* @return Redirect
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function update(ImageUploadRequest $request, $modelId = null)
public function update(StoreAssetModelRequest $request, $modelId) : RedirectResponse
{
$this->authorize('update', AssetModel::class);
// Check if the model exists
if (is_null($model = AssetModel::find($modelId))) {
// Redirect to the models management page
return redirect()->route('models.index')->with('error', trans('admin/models/message.does_not_exist'));
}
@@ -163,20 +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;
@@ -200,10 +185,8 @@ class AssetModelsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @param int $modelId
* @return Redirect
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function destroy($modelId)
public function destroy($modelId) : RedirectResponse
{
$this->authorize('delete', AssetModel::class);
// Check if the model exists
@@ -219,8 +202,9 @@ 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);
Log::info($e);
}
}
@@ -237,10 +221,8 @@ class AssetModelsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @param int $id
* @return Redirect
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function getRestore($id)
public function getRestore($id) : RedirectResponse
{
$this->authorize('create', AssetModel::class);
@@ -252,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::user()->id;
$logaction->created_by = auth()->id();
$logaction->logaction('restore');
@@ -282,13 +264,11 @@ class AssetModelsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @param int $modelId
* @return View
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function show($modelId = null)
public function show($modelId = null) : View | RedirectResponse
{
$this->authorize('view', AssetModel::class);
$model = AssetModel::withTrashed()->withCount('assets')->find($modelId);
$model = AssetModel::withTrashed()->find($modelId);
if (isset($model->id)) {
return view('models/view', compact('model'));
@@ -303,9 +283,8 @@ class AssetModelsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @param int $modelId
* @return View
*/
public function getClone($modelId = null)
public function getClone($modelId = null) : View | RedirectResponse
{
$this->authorize('create', AssetModel::class);
// Check if the model exists
@@ -331,9 +310,8 @@ class AssetModelsController extends Controller
* @author [B. Wetherington] [<uberbrady@gmail.com>]
* @since [v2.0]
* @param int $modelId
* @return View
*/
public function getCustomFields($modelId)
public function getCustomFields($modelId) : View
{
return view('models.custom_fields_form')->with('model', AssetModel::find($modelId));
}
@@ -345,9 +323,8 @@ class AssetModelsController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.7]
* @return \Illuminate\Contracts\View\View
*/
public function postBulkEdit(Request $request)
public function postBulkEdit(Request $request) : View | RedirectResponse
{
$models_raw_array = $request->input('ids');
@@ -389,9 +366,8 @@ class AssetModelsController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.7]
* @return \Illuminate\Contracts\View\View
*/
public function postBulkEditSave(Request $request)
public function postBulkEditSave(Request $request) : RedirectResponse
{
$models_raw_array = $request->input('ids');
$update_array = [];
@@ -429,9 +405,8 @@ class AssetModelsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @param int $modelId
* @return Redirect
*/
public function postBulkDelete(Request $request)
public function postBulkDelete(Request $request) : RedirectResponse
{
$models_raw_array = $request->input('ids');
@@ -470,9 +445,8 @@ class AssetModelsController extends Controller
* any default values were entered into the form.
*
* @param array $input
* @return bool
*/
private function shouldAddDefaultValues(array $input)
private function shouldAddDefaultValues(array $input) : bool
{
return ! empty($input['add_default_values'])
&& ! empty($input['default_values'])
@@ -484,28 +458,27 @@ class AssetModelsController extends Controller
*
* @param AssetModel $model
* @param array $defaultValues
* @return void
*/
private function assignCustomFieldsDefaultValues(AssetModel $model, array $defaultValues)
private function assignCustomFieldsDefaultValues(AssetModel|SnipeModel $model, array $defaultValues): bool
{
$data = array();
foreach ($defaultValues as $customFieldId => $defaultValue) {
$customField = \App\Models\CustomField::find($customFieldId);
$customField = CustomField::find($customFieldId);
$data[$customField->db_column] = $defaultValue;
}
$fieldsets = $model->fieldset->validation_rules();
$allRules = $model->fieldset->validation_rules();
$rules = array();
foreach ($fieldsets as $fieldset => $validation){
foreach ($allRules as $field => $validation) {
// If the field is marked as required, eliminate the rule so it doesn't interfere with the default values
// (we are at model level, the rule still applies when creating a new asset using this model)
$index = array_search('required', $validation);
if ($index !== false){
$validation[$index] = 'nullable';
}
$rules[$fieldset] = $validation;
$rules[$field] = $validation;
}
$validator = Validator::make($data, $rules);
@@ -527,9 +500,8 @@ class AssetModelsController extends Controller
/**
* Removes all default values
*
* @return void
*/
private function removeCustomFieldsDefaultValues(AssetModel $model)
private function removeCustomFieldsDefaultValues(AssetModel|SnipeModel $model): void
{
$model->defaultValues()->detach();
}
@@ -6,8 +6,11 @@ use App\Helpers\StorageHelper;
use App\Http\Requests\UploadFileRequest;
use App\Models\Actionlog;
use App\Models\AssetModel;
use Illuminate\Support\Facades\Response;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Storage;
use \Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
class AssetModelsFilesController extends Controller
{
@@ -16,12 +19,12 @@ class AssetModelsFilesController extends Controller
*
* @param UploadFileRequest $request
* @param int $modelId
* @return Redirect
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*@since [v1.0]
* @author [A. Gianotto] [<snipe@snipe.net>]
*/
public function store(UploadFileRequest $request, $modelId = null)
public function store(UploadFileRequest $request, $modelId = null) : RedirectResponse
{
if (! $model = AssetModel::find($modelId)) {
return redirect()->route('models.index')->with('error', trans('admin/hardware/message.does_not_exist'));
@@ -38,7 +41,7 @@ class AssetModelsFilesController extends Controller
$file_name = $request->handleFile('private_uploads/assetmodels/','model-'.$model->id,$file);
$model->logUpload($file_name, e($request->get('notes')));
$model->logUpload($file_name, $request->get('notes'));
}
return redirect()->back()->with('success', trans('general.file_upload_success'));
@@ -54,10 +57,8 @@ class AssetModelsFilesController extends Controller
* @param int $modelId
* @param int $fileId
* @since [v1.0]
* @return View
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function show($modelId = null, $fileId = null)
public function show($modelId = null, $fileId = null) : StreamedResponse | Response | RedirectResponse | BinaryFileResponse
{
$model = AssetModel::find($modelId);
// the asset is valid
@@ -70,8 +71,6 @@ class AssetModelsFilesController extends Controller
}
$file = 'private_uploads/assetmodels/'.$log->filename;
\Log::debug('Checking for '.$file);
if (! Storage::exists($file)) {
return response('File '.$file.' not found on server', 404)
@@ -103,10 +102,8 @@ class AssetModelsFilesController extends Controller
* @param int $modelId
* @param int $fileId
* @since [v1.0]
* @return View
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function destroy($modelId = null, $fileId = null)
public function destroy($modelId = null, $fileId = null) : RedirectResponse
{
$model = AssetModel::find($modelId);
$this->authorize('update', $model);
@@ -11,9 +11,9 @@ use App\Models\Asset;
use App\Models\CheckoutAcceptance;
use App\Models\LicenseSeat;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\View;
use Illuminate\Support\Facades\Log;
use \Illuminate\Contracts\View\View;
use \Illuminate\Http\RedirectResponse;
class AssetCheckinController extends Controller
{
@@ -25,11 +25,9 @@ class AssetCheckinController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @param string $backto
* @return View
* @throws \Illuminate\Auth\Access\AuthorizationException
* @since [v1.0]
*/
public function create($assetId, $backto = null)
public function create($assetId, $backto = null) : View | RedirectResponse
{
// Check if the asset exists
if (is_null($asset = Asset::find($assetId))) {
@@ -39,7 +37,17 @@ class AssetCheckinController extends Controller
$this->authorize('checkin', $asset);
return view('hardware/checkin', compact('asset'))->with('statusLabel_list', Helper::statusLabelList())->with('backto', $backto);
// This asset is already checked in, redirect
if (is_null($asset->assignedTo)) {
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkin.already_checked_in'));
}
if (!$asset->model) {
return redirect()->route('hardware.show', $asset->id)->with('error', trans('admin/hardware/general.model_invalid_fix'));
}
return view('hardware/checkin', compact('asset'))->with('statusLabel_list', Helper::statusLabelList())->with('backto', $backto)->with('table_name', 'Assets');
}
/**
@@ -49,11 +57,9 @@ class AssetCheckinController extends Controller
* @param AssetCheckinRequest $request
* @param int $assetId
* @param null $backto
* @return Redirect
* @throws \Illuminate\Auth\Access\AuthorizationException
* @since [v1.0]
*/
public function store(AssetCheckinRequest $request, $assetId = null, $backto = null)
public function store(AssetCheckinRequest $request, $assetId = null, $backto = null) : RedirectResponse
{
// Check if the asset exists
if (is_null($asset = Asset::find($assetId))) {
@@ -64,6 +70,11 @@ class AssetCheckinController extends Controller
if (is_null($target = $asset->assignedTo)) {
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkin.already_checked_in'));
}
if (!$asset->model) {
return redirect()->route('hardware.show', $asset->id)->with('error', trans('admin/hardware/general.model_invalid_fix'));
}
$this->authorize('checkin', $asset);
if ($asset->assignedType() == Asset::USER) {
@@ -71,7 +82,6 @@ class AssetCheckinController extends Controller
}
$asset->expected_checkin = null;
//$asset->last_checkout = null;
$asset->last_checkin = now();
$asset->assignedTo()->disassociate($asset);
$asset->accepted = null;
@@ -86,7 +96,7 @@ class AssetCheckinController extends Controller
$asset->location_id = $asset->rtd_location_id;
if ($request->filled('location_id')) {
\Log::debug('NEW Location ID: '.$request->get('location_id'));
Log::debug('NEW Location ID: '.$request->get('location_id'));
$asset->location_id = $request->get('location_id');
if ($request->get('update_default_location') == 0){
@@ -116,15 +126,12 @@ class AssetCheckinController extends Controller
$acceptance->delete();
});
// Was the asset updated?
session()->put('redirect_option', $request->get('redirect_option'));
if ($asset->save()) {
event(new CheckoutableCheckedIn($asset, $target, Auth::user(), $request->input('note'), $checkin_at, $originalValues));
if ((isset($user)) && ($backto == 'user')) {
return redirect()->route('users.show', $user->id)->with('success', trans('admin/hardware/message.checkin.success'));
}
return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.checkin.success'));
event(new CheckoutableCheckedIn($asset, $target, auth()->user(), $request->input('note'), $checkin_at, $originalValues));
return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets'))->with('success', trans('admin/hardware/message.checkin.success'));
}
// Redirect to the asset management page with error
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkin.error').$asset->getErrors());
@@ -9,7 +9,9 @@ use App\Http\Controllers\Controller;
use App\Http\Requests\AssetCheckoutRequest;
use App\Models\Asset;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
use \Illuminate\Contracts\View\View;
use \Illuminate\Http\RedirectResponse;
class AssetCheckoutController extends Controller
{
@@ -22,9 +24,9 @@ class AssetCheckoutController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v1.0]
* @return View
* @return \Illuminate\Contracts\View\View
*/
public function create($assetId)
public function create($assetId) : View | RedirectResponse
{
// Check if the asset exists
if (is_null($asset = Asset::with('company')->find(e($assetId)))) {
@@ -33,11 +35,17 @@ class AssetCheckoutController extends Controller
$this->authorize('checkout', $asset);
if (!$asset->model) {
return redirect()->route('hardware.show', $asset->id)->with('error', trans('admin/hardware/general.model_invalid_fix'));
}
if ($asset->availableForCheckout()) {
return view('hardware/checkout', compact('asset'))
->with('statusLabel_list', Helper::deployableStatusLabelList());
->with('statusLabel_list', Helper::deployableStatusLabelList())
->with('table_name', 'Assets');
}
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkout.not_available'));
}
@@ -46,11 +54,9 @@ class AssetCheckoutController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param AssetCheckoutRequest $request
* @param int $assetId
* @return Redirect
* @since [v1.0]
*/
public function store(AssetCheckoutRequest $request, $assetId)
public function store(AssetCheckoutRequest $request, $assetId) : RedirectResponse
{
try {
// Check if the asset exists
@@ -60,9 +66,14 @@ class AssetCheckoutController extends Controller
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkout.not_available'));
}
$this->authorize('checkout', $asset);
$admin = Auth::user();
$target = $this->determineCheckoutTarget($asset);
if (!$asset->model) {
return redirect()->route('hardware.show', $asset->id)->with('error', trans('admin/hardware/general.model_invalid_fix'));
}
$admin = auth()->user();
$target = $this->determineCheckoutTarget();
$asset = $this->updateAssetLocation($asset, $target);
@@ -97,11 +108,13 @@ class AssetCheckoutController extends Controller
return redirect()->to("hardware/$assetId/checkout")->with('error', trans('general.error_user_company'));
}
}
if ($asset->checkOut($target, $admin, $checkout_at, $expected_checkin, $request->get('note'), $request->get('name'))) {
return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.checkout.success'));
}
session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => $request->get('checkout_to_type')]);
if ($asset->checkOut($target, $admin, $checkout_at, $expected_checkin, $request->get('note'), $request->get('name'))) {
return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets'))
->with('success', trans('admin/hardware/message.checkout.success'));
}
// Redirect to the asset management page with error
return redirect()->to("hardware/$assetId/checkout")->with('error', trans('admin/hardware/message.checkout.error').$asset->getErrors());
} catch (ModelNotFoundException $e) {
@@ -7,8 +7,12 @@ use App\Http\Controllers\Controller;
use App\Http\Requests\UploadFileRequest;
use App\Models\Actionlog;
use App\Models\Asset;
use Illuminate\Support\Facades\Response;
use \Illuminate\Http\Response;
use Illuminate\Support\Facades\Storage;
use \Illuminate\Contracts\View\View;
use \Illuminate\Http\RedirectResponse;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
class AssetFilesController extends Controller
{
@@ -17,12 +21,12 @@ class AssetFilesController extends Controller
*
* @param UploadFileRequest $request
* @param int $assetId
* @return Redirect
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*@since [v1.0]
* @author [A. Gianotto] [<snipe@snipe.net>]
*/
public function store(UploadFileRequest $request, $assetId = null)
public function store(UploadFileRequest $request, $assetId = null) : RedirectResponse
{
if (! $asset = Asset::find($assetId)) {
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
@@ -38,7 +42,7 @@ class AssetFilesController extends Controller
foreach ($request->file('file') as $file) {
$file_name = $request->handleFile('private_uploads/assets/','hardware-'.$asset->id, $file);
$asset->logUpload($file_name, e($request->get('notes')));
$asset->logUpload($file_name, $request->get('notes'));
}
return redirect()->back()->with('success', trans('admin/hardware/message.upload.success'));
@@ -54,49 +58,33 @@ class AssetFilesController extends Controller
* @param int $assetId
* @param int $fileId
* @since [v1.0]
* @return View
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function show($assetId = null, $fileId = null)
public function show($assetId = null, $fileId = null) : View | RedirectResponse | Response | StreamedResponse | BinaryFileResponse
{
$asset = Asset::find($assetId);
// the asset is valid
if (isset($asset->id)) {
if ($asset = Asset::find($assetId)) {
$this->authorize('view', $asset);
if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $asset->id)->find($fileId)) {
return response('No matching record for that asset/file', 500)
->header('Content-Type', 'text/plain');
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $asset->id)->find($fileId)) {
$file = 'private_uploads/assets/'.$log->filename;
if ($log->action_type == 'audit') {
$file = 'private_uploads/audits/'.$log->filename;
}
try {
return StorageHelper::showOrDownloadFile($file, $log->filename);
} catch (\Exception $e) {
return redirect()->route('hardware.show', ['hardware' => $asset])->with('error', trans('general.file_not_found'));
}
}
$file = 'private_uploads/assets/'.$log->filename;
\Log::debug('Checking for '.$file);
if ($log->action_type == 'audit') {
$file = 'private_uploads/audits/'.$log->filename;
}
if (! Storage::exists($file)) {
return response('File '.$file.' not found on server', 404)
->header('Content-Type', 'text/plain');
}
if (request('inline') == 'true') {
$headers = [
'Content-Disposition' => 'inline',
];
return Storage::download($file, $log->filename, $headers);
}
return StorageHelper::downloader($file);
return redirect()->route('hardware.show', ['hardware' => $asset])->with('error', trans('general.log_record_not_found'));
}
// Prepare the error message
$error = trans('admin/hardware/message.does_not_exist', ['id' => $fileId]);
// Redirect to the hardware management page
return redirect()->route('hardware.index')->with('error', $error);
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
}
/**
@@ -106,10 +94,8 @@ class AssetFilesController extends Controller
* @param int $assetId
* @param int $fileId
* @since [v1.0]
* @return View
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function destroy($assetId = null, $fileId = null)
public function destroy($assetId = null, $fileId = null) : RedirectResponse
{
$asset = Asset::find($assetId);
$this->authorize('update', $asset);
@@ -132,7 +118,6 @@ class AssetFilesController extends Controller
->with('success', trans('admin/hardware/message.deletefile.success'));
}
// Redirect to the hardware management page
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
}
}
+159 -103
View File
@@ -2,11 +2,12 @@
namespace App\Http\Controllers\Assets;
use App\Events\CheckoutableCheckedIn;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Requests\ImageUploadRequest;
use App\Models\Actionlog;
use App\Models\Manufacturer;
use App\Http\Requests\UploadFileRequest;
use Illuminate\Support\Facades\Log;
use App\Models\Asset;
use App\Models\AssetModel;
@@ -16,18 +17,19 @@ use App\Models\Location;
use App\Models\Setting;
use App\Models\Statuslabel;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use App\View\Label;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\View;
use Illuminate\Support\Facades\Gate;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use League\Csv\Reader;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Http\Response;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
/**
* This class controls all actions related to assets for
@@ -55,10 +57,8 @@ class AssetsController extends Controller
* @see AssetController::getDatatable() method that generates the JSON response
* @since [v1.0]
* @param Request $request
* @return View
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function index(Request $request)
public function index(Request $request) : View
{
$this->authorize('index', Asset::class);
$company = Company::find($request->input('company_id'));
@@ -72,13 +72,12 @@ class AssetsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @param Request $request
* @return View
* @internal param int $model_id
*/
public function create(Request $request)
public function create(Request $request) : View
{
$this->authorize('create', Asset::class);
$view = View::make('hardware/edit')
$view = view('hardware/edit')
->with('statuslabel_list', Helper::statusLabelList())
->with('item', new Asset)
->with('statuslabel_types', Helper::statusTypeList());
@@ -96,12 +95,15 @@ class AssetsController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return Redirect
*/
public function store(ImageUploadRequest $request)
public function store(ImageUploadRequest $request) : RedirectResponse
{
$this->authorize(Asset::class);
// There are a lot more rules to add here but prevents
// errors around `asset_tags` not being present below.
$this->validate($request, ['asset_tags' => ['required', 'array']]);
// Handle asset tags - there could be one, or potentially many.
// This is only necessary on create, not update, since bulk editing is handled
// differently
@@ -109,8 +111,10 @@ class AssetsController extends Controller
$settings = Setting::getSettings();
$success = false;
$successes = [];
$failures = [];
$serials = $request->input('serials');
$asset = null;
for ($a = 1; $a <= count($asset_tags); $a++) {
$asset = new Asset();
@@ -130,7 +134,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');
@@ -163,7 +167,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 {
@@ -194,30 +198,43 @@ class AssetsController extends Controller
}
if (isset($target)) {
$asset->checkOut($target, Auth::user(), date('Y-m-d H:i:s'), $request->input('expected_checkin', null), 'Checked out on asset creation', $request->get('name'), $location);
$asset->checkOut($target, auth()->user(), date('Y-m-d H:i:s'), $request->input('expected_checkin', null), 'Checked out on asset creation', $request->get('name'), $location);
}
$success = true;
$successes[] = "<a href='" . route('hardware.show', ['hardware' => $asset->id]) . "' style='color: white;'>" . e($asset->asset_tag) . "</a>";
} else {
$failures[] = join(",", $asset->getErrors()->all());
}
}
if ($success) {
\Log::debug(e($asset->asset_tag));
return redirect()->route('hardware.index')
->with('success-unescaped', trans('admin/hardware/message.create.success_linked', ['link' => route('hardware.show', $asset->id), 'id', 'tag' => e($asset->asset_tag)]));
session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => $request->get('checkout_to_type')]);
if ($successes) {
if ($failures) {
//some succeeded, some failed
return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets')) //FIXME - not tested
->with('success-unescaped', trans_choice('admin/hardware/message.create.multi_success_linked', $successes, ['links' => join(", ", $successes)]))
->with('warning', trans_choice('admin/hardware/message.create.partial_failure', $failures, ['failures' => join("; ", $failures)]));
} else {
if (count($successes) == 1) {
//the most common case, keeping it so we don't have to make every use of that translation string be trans_choice'ed
//and re-translated
return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets'))
->with('success-unescaped', trans('admin/hardware/message.create.success_linked', ['link' => route('hardware.show', ['hardware' => $asset->id]), 'id', 'tag' => e($asset->asset_tag)]));
} else {
//multi-success
return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets'))
->with('success-unescaped', trans_choice('admin/hardware/message.create.multi_success_linked', $successes, ['links' => join(", ", $successes)]));
}
}
}
return redirect()->back()->withInput()->withErrors($asset->getErrors());
}
public function getOptionCookie(Request $request){
$value = $request->cookie('optional_info');
echo $value;
return $value;
}
/**
* Returns a view that presents a form to edit an existing asset.
@@ -225,9 +242,9 @@ class AssetsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v1.0]
* @return View
* @return \Illuminate\Contracts\View\View
*/
public function edit($assetId = null)
public function edit($assetId = null) : View | RedirectResponse
{
if (! $item = Asset::find($assetId)) {
// Redirect to the asset management page with error
@@ -248,9 +265,9 @@ class AssetsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v1.0]
* @return View
* @return \Illuminate\Contracts\View\View
*/
public function show($assetId = null)
public function show($assetId = null) : View | RedirectResponse
{
$asset = Asset::withTrashed()->find($assetId);
$this->authorize('view', $asset);
@@ -288,12 +305,12 @@ class AssetsController extends Controller
* Validate and process asset edit form.
*
* @param int $assetId
* @return \Illuminate\Http\RedirectResponse|Redirect
*@since [v1.0]
* @since [v1.0]
* @author [A. Gianotto] [<snipe@snipe.net>]
*/
public function update(ImageUploadRequest $request, $assetId = null)
public function update(ImageUploadRequest $request, $assetId = null) : RedirectResponse
{
// Check if the asset exists
if (! $asset = Asset::find($assetId)) {
// Redirect to the asset management page with error
@@ -304,7 +321,8 @@ class AssetsController extends Controller
$asset->status_id = $request->input('status_id', null);
$asset->warranty_months = $request->input('warranty_months', null);
$asset->purchase_cost = $request->input('purchase_cost', null);
$asset->purchase_date = $request->input('purchase_date', null);
$asset->purchase_date = $request->input('purchase_date', null);
$asset->next_audit_date = $request->input('next_audit_date', null);
if ($request->filled('purchase_date') && !$request->filled('asset_eol_date') && ($asset->model->eol > 0)) {
$asset->purchase_date = $request->input('purchase_date', null);
$asset->asset_eol_date = Carbon::parse($request->input('purchase_date'))->addMonths($asset->model->eol)->format('Y-m-d');
@@ -327,16 +345,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->archived){
// This is a non-deployable status label - we should check the asset back in.
if (($status && $status->status_type != '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 == '') {
@@ -354,14 +377,26 @@ class AssetsController extends Controller
}
// Update the asset data
$asset_tag = $request->input('asset_tags');
$serial = $request->input('serials');
$asset->serial = $request->input('serials');
if (is_array($request->input('serials'))) {
$asset->serial = $serial[1];
}
$asset->name = $request->input('name');
$asset->serial = $serial[1];
$asset->company_id = Company::getIdForCurrentUser($request->input('company_id'));
$asset->model_id = $request->input('model_id');
$asset->order_number = $request->input('order_number');
$asset->asset_tag = $asset_tag[1];
$asset_tags = $request->input('asset_tags');
$asset->asset_tag = $request->input('asset_tags');
if (is_array($request->input('asset_tags'))) {
$asset->asset_tag = $asset_tags[1];
}
$asset->notes = $request->input('notes');
$asset = $request->handleImages($asset);
@@ -373,8 +408,9 @@ class AssetsController extends Controller
$model = AssetModel::find($request->get('model_id'));
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 {
@@ -391,9 +427,10 @@ class AssetsController extends Controller
}
}
session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => $request->get('checkout_to_type')]);
if ($asset->save()) {
return redirect()->route('hardware.show', $assetId)
return redirect()->to(Helper::getRedirectOption($request, $assetId, 'Assets'))
->with('success', trans('admin/hardware/message.update.success'));
}
@@ -406,9 +443,8 @@ class AssetsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v1.0]
* @return Redirect
*/
public function destroy($assetId)
public function destroy(Request $request, $assetId) : RedirectResponse
{
// Check if the asset exists
if (is_null($asset = Asset::find($assetId))) {
@@ -418,9 +454,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 {
@@ -440,9 +484,8 @@ class AssetsController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return Redirect
*/
public function getAssetBySerial(Request $request)
public function getAssetBySerial(Request $request) : RedirectResponse
{
$topsearch = ($request->get('topsearch')=="true");
@@ -458,16 +501,23 @@ class AssetsController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return Redirect
* @return \Illuminate\Http\RedirectResponse
*/
public function getAssetByTag(Request $request, $tag=null)
public function getAssetByTag(Request $request, $tag=null) : RedirectResponse
{
$tag = $tag ? $tag : $request->get('assetTag');
$topsearch = ($request->get('topsearch') == 'true');
if (! $asset = Asset::where('asset_tag', '=', $tag)->first()) {
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
// Search for an exact and unique asset tag match
$assets = Asset::where('asset_tag', '=', $tag);
// If not a unique result, redirect to the index view
if ($assets->count() != 1) {
return redirect()->route('hardware.index')
->with('search', $tag)
->with('warning', trans('admin/hardware/message.does_not_exist_var', [ 'asset_tag' => $tag ]));
}
$asset = $assets->first();
$this->authorize('view', $asset);
return redirect()->route('hardware.show', $asset->id)->with('topsearch', $topsearch);
@@ -480,9 +530,8 @@ class AssetsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v1.0]
* @return Response
*/
public function getQrCode($assetId = null)
public function getQrCode($assetId = null) : Response | BinaryFileResponse | string | bool
{
$settings = Setting::getSettings();
@@ -509,6 +558,7 @@ class AssetsController extends Controller
return 'That asset is invalid';
}
return false;
}
/**
@@ -556,7 +606,7 @@ class AssetsController extends Controller
*
* @author [L. Swartzendruber] [<logan.swartzendruber@gmail.com>
* @param int $assetId
* @return View
* @return \Illuminate\Contracts\View\View
*/
public function getLabel($assetId = null)
{
@@ -580,28 +630,22 @@ class AssetsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v1.0]
* @return View
* @return \Illuminate\Contracts\View\View
*/
public function getClone($assetId = null)
public function getClone(Asset $asset)
{
// Check if the asset exists
if (is_null($asset_to_clone = Asset::find($assetId))) {
// Redirect to the asset management page
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
}
$this->authorize('create', $asset_to_clone);
$asset = clone $asset_to_clone;
$asset->id = null;
$asset->asset_tag = '';
$asset->serial = '';
$asset->assigned_to = '';
$this->authorize('create', $asset);
$cloned = clone $asset;
$cloned->id = null;
$cloned->asset_tag = '';
$cloned->serial = '';
$cloned->assigned_to = '';
$cloned->deleted_at = '';
return view('hardware/edit')
->with('statuslabel_list', Helper::statusLabelList())
->with('statuslabel_types', Helper::statusTypeList())
->with('item', $asset);
->with('item', $cloned);
}
/**
@@ -609,7 +653,7 @@ class AssetsController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
* @return \Illuminate\Contracts\View\View
*/
public function getImportHistory()
{
@@ -631,7 +675,7 @@ class AssetsController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.3]
* @return View
* @return \Illuminate\Contracts\View\View
*/
public function postImportHistory(Request $request)
{
@@ -725,8 +769,8 @@ class AssetsController extends Controller
Actionlog::firstOrCreate([
'item_id' => $asset->id,
'item_type' => Asset::class,
'user_id' => Auth::user()->id,
'note' => 'Checkout imported by '.Auth::user()->present()->fullName().' from history importer',
'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,
'created_at' => $item[$asset_tag][$batch_counter]['checkout_date'],
@@ -753,8 +797,8 @@ class AssetsController extends Controller
Actionlog::firstOrCreate([
'item_id' => $item[$asset_tag][$batch_counter]['asset_id'],
'item_type' => Asset::class,
'user_id' => Auth::user()->id,
'note' => 'Checkin imported by '.Auth::user()->present()->fullName().' from history importer',
'created_by' => auth()->id(),
'note' => 'Checkin imported by '.auth()->user()->present()->fullName().' from history importer',
'target_id' => null,
'created_at' => $checkin_date,
'action_type' => 'checkin',
@@ -791,7 +835,7 @@ class AssetsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v1.0]
* @return View
* @return \Illuminate\Contracts\View\View
*/
public function getRestore($assetId = null)
{
@@ -830,7 +874,7 @@ class AssetsController extends Controller
{
$this->authorize('checkin', Asset::class);
return view('hardware/quickscan-checkin');
return view('hardware/quickscan-checkin')->with('statusLabel_list', Helper::statusLabelList());
}
public function audit($id)
@@ -850,15 +894,15 @@ class AssetsController extends Controller
return view('hardware/audit-due');
}
public function overdueForAudit()
public function dueForCheckin()
{
$this->authorize('audit', Asset::class);
$this->authorize('checkin', Asset::class);
return view('hardware/audit-overdue');
return view('hardware/checkin-due');
}
public function auditStore(Request $request, $id)
public function auditStore(UploadFileRequest $request, $id)
{
$this->authorize('audit', Asset::class);
@@ -875,7 +919,21 @@ class AssetsController extends Controller
$asset = Asset::findOrFail($id);
// We don't want to log this as a normal update, so let's bypass that
/**
* Even though we do a save() further down, we don't want to log this as a "normal" asset update,
* which would trigger the Asset Observer and would log an asset *update* log entry (because the
* de-normed fields like next_audit_date on the asset itself will change on save()) *in addition* to
* the audit log entry we're creating through this controller.
*
* To prevent this double-logging (one for update and one for audit), we skip the observer and bypass
* that de-normed update log entry by using unsetEventDispatcher(), BUT invoking unsetEventDispatcher()
* will bypass normal model-level validation that's usually handled at the observer )
*
* We handle validation on the save() by checking if the asset is valid via the ->isValid() method,
* which manually invokes Watson Validating to make sure the asset's model is valid.
*
* @see \App\Observers\AssetObserver::updating()
*/
$asset->unsetEventDispatcher();
$asset->next_audit_date = $request->input('next_audit_date');
@@ -884,29 +942,27 @@ class AssetsController extends Controller
// Check to see if they checked the box to update the physical location,
// not just note it in the audit notes
if ($request->input('update_location') == '1') {
Log::debug('update location in audit');
$asset->location_id = $request->input('location_id');
}
/**
* Invoke Watson Validating to check the asset itself and check to make sure it saved correctly.
* We have to invoke this manually because of the unsetEventDispatcher() above.)
*/
if ($asset->isValid() && $asset->save()) {
if ($asset->save()) {
$file_name = '';
// Upload an image, if attached
$file_name = null;
// Create the image (if one was chosen.)
if ($request->hasFile('image')) {
$path = 'private_uploads/audits';
if (! Storage::exists($path)) {
Storage::makeDirectory($path, 775);
}
$upload = $image = $request->file('image');
$ext = $image->getClientOriginalExtension();
$file_name = 'audit-'.str_random(18).'.'.$ext;
Storage::putFileAs($path, $upload, $file_name);
$file_name = $request->handleFile('private_uploads/audits/', 'audit-'.$asset->id, $request->file('image'));
}
$asset->logAudit($request->input('note'), $request->input('location_id'), $file_name);
return redirect()->route('assets.audit.due')->with('success', trans('admin/hardware/message.audit.success'));
}
return redirect()->back()->withInput()->withErrors($asset->getErrors());
}
public function getRequestedIndex($user_id = null)
@@ -2,7 +2,6 @@
namespace App\Http\Controllers\Assets;
use App\Models\Actionlog;
use App\Helpers\Helper;
use App\Http\Controllers\CheckInOutRequest;
use App\Http\Controllers\Controller;
@@ -11,13 +10,17 @@ 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\Auth;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Session;
use App\Http\Requests\AssetCheckoutRequest;
use App\Models\CustomField;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Database\Eloquent\ModelNotFoundException;
class BulkAssetsController extends Controller
{
@@ -34,12 +37,10 @@ class BulkAssetsController extends Controller
* action would make a lot more sense here and make things a lot more clear.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @return View
* @internal param int $assetId
* @since [v2.0]
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function edit(Request $request)
public function edit(Request $request) : View | RedirectResponse
{
$this->authorize('view', Asset::class);
@@ -51,6 +52,10 @@ class BulkAssetsController extends Controller
}
$asset_ids = $request->input('ids');
if ($request->input('bulk_actions') === 'checkout') {
$request->session()->flashInput(['selected_assets' => $asset_ids]);
return redirect()->route('hardware.bulkcheckout.show');
}
// Figure out where we need to send the user after the update is complete, and store that in the session
$bulk_back_url = request()->headers->get('referer');
@@ -92,7 +97,9 @@ class BulkAssetsController extends Controller
// This handles all of the pivot sorting below (versus the assets.* fields in the allowed_columns array)
$column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'assets.id';
$assets = Asset::with('assignedTo', 'location', 'model')->whereIn('assets.id', $asset_ids);
$assets = Asset::with('assignedTo', 'location', 'model')
->whereIn('assets.id', $asset_ids)
->withTrashed();
$assets = $assets->get();
@@ -189,11 +196,10 @@ class BulkAssetsController extends Controller
* Save bulk edits
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @return Redirect
* @internal param array $assets
* @since [v2.0]
*/
public function update(Request $request)
public function update(Request $request) : RedirectResponse
{
$this->authorize('update', Asset::class);
$has_errors = 0;
@@ -214,7 +220,7 @@ class BulkAssetsController extends Controller
}
$assets = Asset::whereIn('id', array_keys($request->input('ids')))->get();
$assets = Asset::whereIn('id', $request->input('ids'))->get();
@@ -226,7 +232,8 @@ class BulkAssetsController extends Controller
* its checkout status.
*/
if (($request->filled('purchase_date'))
if (($request->filled('name'))
|| ($request->filled('purchase_date'))
|| ($request->filled('expected_checkin'))
|| ($request->filled('purchase_cost'))
|| ($request->filled('supplier_id'))
@@ -238,6 +245,7 @@ class BulkAssetsController extends Controller
|| ($request->filled('status_id'))
|| ($request->filled('model_id'))
|| ($request->filled('next_audit_date'))
|| ($request->filled('null_name'))
|| ($request->filled('null_purchase_date'))
|| ($request->filled('null_expected_checkin_date'))
|| ($request->filled('null_next_audit_date'))
@@ -250,13 +258,14 @@ class BulkAssetsController extends Controller
$this->update_array = [];
/**
* Leave out model_id and status here because we do math on that later. We have to do some extra
* validation and checks on those two.
* Leave out model_id and status here because we do math on that later. We have to do some
* extra validation and checks on those two.
*
* It's tempting to make these match the request check above, but some of these values require
* extra work to make sure the data makes sense.
*/
$this->conditionallyAddItem('purchase_date')
$this->conditionallyAddItem('name')
->conditionallyAddItem('purchase_date')
->conditionallyAddItem('expected_checkin')
->conditionallyAddItem('order_number')
->conditionallyAddItem('requestable')
@@ -267,11 +276,36 @@ 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
*/
if ($request->input('null_name')=='1') {
$this->update_array['name'] = null;
}
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') {
@@ -379,28 +413,30 @@ class BulkAssetsController extends Controller
foreach ($asset->model->fieldset->fields as $field) {
if ((array_key_exists($field->db_column, $this->update_array)) && ($field->field_encrypted == '1')) {
$decrypted_old = Helper::gracefulDecrypt($field, $asset->{$field->db_column});
if (Gate::allows('admin')) {
$decrypted_old = Helper::gracefulDecrypt($field, $asset->{$field->db_column});
/*
* Check if the decrypted existing value is different from one we just submitted
* and if not, pull it out of the object since it shouldn't really be updating at all.
* If we don't do this, it will try to re-encrypt it, and the same value encrypted two
* different times will have different values, so it will *look* like it was updated
* but it wasn't.
*/
if ($decrypted_old != $this->update_array[$field->db_column]) {
$asset->{$field->db_column} = \Crypt::encrypt($this->update_array[$field->db_column]);
} else {
/*
* Remove the encrypted custom field from the update_array, since nothing changed
* Check if the decrypted existing value is different from one we just submitted
* and if not, pull it out of the object since it shouldn't really be updating at all.
* If we don't do this, it will try to re-encrypt it, and the same value encrypted two
* different times will have different values, so it will *look* like it was updated
* but it wasn't.
*/
unset($this->update_array[$field->db_column]);
unset($asset->{$field->db_column});
}
if ($decrypted_old != $this->update_array[$field->db_column]) {
$asset->{$field->db_column} = Crypt::encrypt($this->update_array[$field->db_column]);
} else {
/*
* Remove the encrypted custom field from the update_array, since nothing changed
*/
unset($this->update_array[$field->db_column]);
unset($asset->{$field->db_column});
}
/*
* These custom fields aren't encrypted, just carry on as usual
*/
/*
* These custom fields aren't encrypted, just carry on as usual
*/
}
} else {
if ((array_key_exists($field->db_column, $this->update_array)) && ($asset->{$field->db_column} != $this->update_array[$field->db_column])) {
@@ -452,9 +488,8 @@ class BulkAssetsController extends Controller
/**
* Adds parameter to update array for an item if it exists in request
* @param string $field field name
* @return BulkAssetsController Model for Chaining
*/
protected function conditionallyAddItem($field)
protected function conditionallyAddItem($field) : BulkAssetsController
{
if (request()->filled($field)) {
$this->update_array[$field] = request()->input($field);
@@ -468,12 +503,10 @@ class BulkAssetsController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param Request $request
* @return View
* @throws \Illuminate\Auth\Access\AuthorizationException
* @internal param array $assets
* @since [v2.0]
*/
public function destroy(Request $request)
public function destroy(Request $request) : RedirectResponse
{
$this->authorize('delete', Asset::class);
@@ -485,12 +518,7 @@ class BulkAssetsController extends Controller
if ($request->filled('ids')) {
$assets = Asset::find($request->get('ids'));
foreach ($assets as $asset) {
$update_array['deleted_at'] = date('Y-m-d H:i:s');
$update_array['assigned_to'] = null;
DB::table('assets')
->where('id', $asset->id)
->update($update_array);
$asset->delete();
} // endforeach
return redirect($bulk_back_url)->with('success', trans('admin/hardware/message.delete.success'));
@@ -502,27 +530,23 @@ class BulkAssetsController extends Controller
/**
* Show Bulk Checkout Page
* @return View View to checkout multiple assets
*/
public function showCheckout()
public function showCheckout() : View
{
$this->authorize('checkout', Asset::class);
// Filter out assets that are not deployable.
return view('hardware/bulk-checkout');
}
/**
* Process Multiple Checkout Request
* @return View
*/
public function storeCheckout(AssetCheckoutRequest $request)
public function storeCheckout(AssetCheckoutRequest $request) : RedirectResponse | ModelNotFoundException
{
$this->authorize('checkout', Asset::class);
try {
$admin = Auth::user();
$admin = auth()->user();
$target = $this->determineCheckoutTarget();
@@ -551,47 +575,52 @@ class BulkAssetsController extends Controller
}
$errors = [];
DB::transaction(function () use ($target, $admin, $checkout_at, $expected_checkin, $errors, $asset_ids, $request) {
DB::transaction(function () use ($target, $admin, $checkout_at, $expected_checkin, &$errors, $asset_ids, $request) { //NOTE: $errors is passsed by reference!
foreach ($asset_ids as $asset_id) {
$asset = Asset::findOrFail($asset_id);
$this->authorize('checkout', $asset);
$error = $asset->checkOut($target, $admin, $checkout_at, $expected_checkin, e($request->get('note')), $asset->name, null);
$checkout_success = $asset->checkOut($target, $admin, $checkout_at, $expected_checkin, e($request->get('note')), $asset->name, null);
//TODO - I think this logic is duplicated in the checkOut method?
if ($target->location_id != '') {
$asset->location_id = $target->location_id;
$asset->unsetEventDispatcher();
$asset->save();
// TODO - I don't know why this is being saved without events
$asset::withoutEvents(function () use ($asset) {
$asset->save();
});
}
if ($error) {
array_merge_recursive($errors, $asset->getErrors()->toArray());
if (!$checkout_success) {
$errors = array_merge_recursive($errors, $asset->getErrors()->toArray());
}
}
});
if (! $errors) {
// Redirect to the new asset page
return redirect()->to('hardware')->with('success', trans('admin/hardware/message.checkout.success'));
return redirect()->to('hardware')->with('success', trans_choice('admin/hardware/message.multi-checkout.success', $asset_ids));
}
// Redirect to the asset management page with error
return redirect()->route('hardware.bulkcheckout.show')->with('error', trans('admin/hardware/message.checkout.error'))->withErrors($errors);
return redirect()->route('hardware.bulkcheckout.show')->withInput()->with('error', trans_choice('admin/hardware/message.multi-checkout.error', $asset_ids))->withErrors($errors);
} catch (ModelNotFoundException $e) {
return redirect()->route('hardware.bulkcheckout.show')->with('error', $e->getErrors());
}
}
public function restore(Request $request) {
public function restore(Request $request) : RedirectResponse
{
$this->authorize('update', Asset::class);
$assetIds = $request->get('ids');
if (empty($assetIds)) {
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.restore.nothing_updated'));
$assetIds = $request->get('ids');
if (empty($assetIds)) {
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.restore.nothing_updated'));
} else {
foreach ($assetIds as $key => $assetId) {
$asset = Asset::withTrashed()->find($assetId);
$asset->restore();
$asset = Asset::withTrashed()->find($assetId);
$asset->restore();
}
return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.restore.success'));
return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.restore.success'));
}
}
}
@@ -5,7 +5,7 @@ namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class ForgotPasswordController extends Controller
{
/*
@@ -79,16 +79,16 @@ class ForgotPasswordController extends Controller
)
);
} catch(\Exception $e) {
\Log::info('Password reset attempt: User '.$request->input('username').'failed with exception: '.$e );
Log::info('Password reset attempt: User '.$request->input('username').'failed with exception: '.$e );
}
// Prevent timing attack to enumerate users.
usleep(500000 + random_int(0, 1500000));
if ($response === \Password::RESET_LINK_SENT) {
\Log::info('Password reset attempt: User '.$request->input('username').' WAS found, password reset sent');
Log::info('Password reset attempt: User '.$request->input('username').' WAS found, password reset sent');
} else {
\Log::info('Password reset attempt: User matching username '.$request->input('username').' NOT FOUND or user is inactive');
Log::info('Password reset attempt: User matching username '.$request->input('username').' NOT FOUND or user is inactive');
}
/**
+20 -24
View File
@@ -16,7 +16,7 @@ use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Validator;
use Log;
use Illuminate\Support\Facades\Log;
use Redirect;
/**
@@ -122,12 +122,12 @@ class LoginController extends Controller
Auth::login($user);
} else {
$username = $saml->getUsername();
\Log::debug("SAML user '$username' could not be found in database.");
Log::debug("SAML user '$username' could not be found in database.");
$request->session()->flash('error', trans('auth/message.signin.error'));
$saml->clearData();
}
if ($user = Auth::user()) {
if ($user = auth()->user()) {
$user->last_login = \Carbon::now();
$user->saveQuietly();
}
@@ -137,7 +137,7 @@ class LoginController extends Controller
$s->save();
} catch (\Exception $e) {
\Log::debug('There was an error authenticating the SAML user: '.$e->getMessage());
Log::debug('There was an error authenticating the SAML user: '.$e->getMessage());
throw $e;
}
@@ -146,7 +146,7 @@ class LoginController extends Controller
// Better logging
if (empty($samlData)) {
\Log::debug("SAML page requested, but samlData seems empty.");
Log::debug("SAML page requested, but samlData seems empty.");
}
}
@@ -261,19 +261,19 @@ class LoginController extends Controller
/**
* Account sign in form processing.
*
* @return Redirect
* @return \Illuminate\Http\RedirectResponse
*/
public function login(Request $request)
{
//If the environment is set to ALWAYS require SAML, return access denied
if (config('app.require_saml')) {
\Log::debug('require SAML is enabled in the .env - return a 403');
Log::debug('require SAML is enabled in the .env - return a 403');
return view('errors.403');
}
if (Setting::getSettings()->login_common_disabled == '1') {
\Log::debug('login_common_disabled is set to 1 - return a 403');
Log::debug('login_common_disabled is set to 1 - return a 403');
return view('errors.403');
}
@@ -326,7 +326,7 @@ class LoginController extends Controller
}
}
if ($user = Auth::user()) {
if ($user = auth()->user()) {
$user->last_login = \Carbon::now();
$user->activated = 1;
$user->saveQuietly();
@@ -339,7 +339,7 @@ class LoginController extends Controller
/**
* Two factor enrollment page
*
* @return Redirect
* @return \Illuminate\Http\RedirectResponse
*/
public function getTwoFactorEnroll()
{
@@ -350,7 +350,7 @@ class LoginController extends Controller
}
$settings = Setting::getSettings();
$user = Auth::user();
$user = auth()->user();
// We wouldn't normally see this page if 2FA isn't enforced via the
// \App\Http\Middleware\CheckForTwoFactor middleware AND if a device isn't enrolled,
@@ -389,7 +389,7 @@ class LoginController extends Controller
/**
* Two factor code form page
*
* @return Redirect
* @return \Illuminate\Http\RedirectResponse
*/
public function getTwoFactorAuth()
{
@@ -398,7 +398,7 @@ class LoginController extends Controller
return redirect()->route('login')->with('error', trans('auth/general.login_prompt'));
}
$user = Auth::user();
$user = auth()->user();
// Check whether there is a device enrolled.
// This *should* be handled via the \App\Http\Middleware\CheckForTwoFactor middleware
@@ -415,7 +415,7 @@ class LoginController extends Controller
*
* @param Request $request
*
* @return Redirect
* @return \Illuminate\Http\RedirectResponse
*/
public function postTwoFactorAuth(Request $request)
{
@@ -427,11 +427,7 @@ class LoginController extends Controller
return redirect()->route('two-factor')->with('error', trans('auth/message.two_factor.code_required'));
}
if (! $request->has('two_factor_secret')) { // TODO this seems almost the same as above?
return redirect()->route('two-factor')->with('error', 'Two-factor code is required.');
}
$user = Auth::user();
$user = auth()->user();
$secret = $request->input('two_factor_secret');
if (Google2FA::verifyKey($user->two_factor_secret, $secret)) {
@@ -439,7 +435,7 @@ class LoginController extends Controller
$user->saveQuietly();
$request->session()->put('2fa_authed', $user->id);
return redirect()->route('home')->with('success', 'You are logged in!');
return redirect()->route('home')->with('success', trans('auth/message.signin.success'));
}
return redirect()->route('two-factor')->with('error', trans('auth/message.two_factor.invalid_code'));
@@ -451,7 +447,7 @@ class LoginController extends Controller
*
* @param Request $request
*
* @return Redirect
* @return Illuminate\Http\RedirectResponse
*/
public function logout(Request $request)
{
@@ -512,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',
]);
}
@@ -537,7 +533,7 @@ class LoginController extends Controller
$minutes = round($seconds / 60);
$message = \Lang::get('auth/message.throttle', ['minutes' => $minutes]);
$message = trans('auth/message.throttle', ['minutes' => $minutes]);
return redirect()->back()
->withInput($request->only($this->username(), 'remember'))
@@ -7,7 +7,7 @@ use App\Models\Setting;
use App\Models\User;
use Illuminate\Foundation\Auth\ResetsPasswords;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class ResetPasswordController extends Controller
{
@@ -66,7 +66,7 @@ class ResetPasswordController extends Controller
$credentials = $request->only('email', 'token');
if (is_null($this->broker()->getUser($credentials))) {
\Log::debug('Password reset form FAILED - this token is not valid.');
Log::debug('Password reset form FAILED - this token is not valid.');
return redirect()->route('password.request')->with('error', trans('passwords.token'));
}
@@ -87,12 +87,12 @@ class ResetPasswordController extends Controller
'password.not_in' => trans('validation.disallow_same_pwd_as_user_fields'),
];
$request->validate($this->rules(), $request->all(), $this->validationErrorMessages());
$request->validate($this->rules());
\Log::debug('Checking if '.$request->input('username').' exists');
Log::debug('Checking if '.$request->input('username').' exists');
// Check to see if the user even exists - we'll treat the response the same to prevent user sniffing
if ($user = User::where('username', '=', $request->input('username'))->where('activated', '1')->whereNotNull('email')->first()) {
\Log::debug($user->username.' exists');
Log::debug($user->username.' exists');
// handle the password validation rules set by the admin settings
@@ -112,17 +112,17 @@ class ResetPasswordController extends Controller
// Check if the password reset above actually worked
if ($response == \Password::PASSWORD_RESET) {
\Log::debug('Password reset for '.$user->username.' worked');
Log::debug('Password reset for '.$user->username.' worked');
return redirect()->guest('login')->with('success', trans('passwords.reset'));
}
\Log::debug('Password reset for '.$user->username.' FAILED - this user exists but the token is not valid');
Log::debug('Password reset for '.$user->username.' FAILED - this user exists but the token is not valid');
return redirect()->back()->withInput($request->only('email'))->with('success', trans('passwords.reset'));
}
\Log::debug('Password reset for '.$request->input('username').' FAILED - user does not exist or does not have an email address - but make it look like it succeeded');
Log::debug('Password reset for '.$request->input('username').' FAILED - user does not exist or does not have an email address - but make it look like it succeeded');
return redirect()->guest('login')->with('success', trans('passwords.reset'));
}
+25 -13
View File
@@ -5,7 +5,7 @@ namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Services\Saml;
use Illuminate\Http\Request;
use Log;
use Illuminate\Support\Facades\Log;
/**
* This controller provides the endpoint for SAML communication and metadata.
@@ -51,7 +51,7 @@ class SamlController extends Controller
$metadata = $this->saml->getSPMetadata();
if (empty($metadata)) {
\Log::debug('SAML metadata is empty - return a 403');
Log::debug('SAML metadata is empty - return a 403');
return response()->view('errors.403', [], 403);
}
@@ -71,7 +71,7 @@ class SamlController extends Controller
*
* @param Request $request
*
* @return Redirect
* @return \Illuminate\Http\RedirectResponse
*/
public function login(Request $request)
{
@@ -93,18 +93,24 @@ class SamlController extends Controller
*
* @param Request $request
*
* @return Redirect
* @return \Illuminate\Http\RedirectResponse
*/
public function acs(Request $request)
{
$saml = $this->saml;
$auth = $saml->getAuth();
$auth->processResponse();
$saml_exception = false;
try {
$auth->processResponse();
} catch (\Exception $e) {
Log::warning("Exception caught in SAML login: " . $e->getMessage());
$saml_exception = true;
}
$errors = $auth->getErrors();
if (! empty($errors)) {
Log::error('There was an error with SAML ACS: '.implode(', ', $errors));
Log::error('Reason: '.$auth->getLastErrorReason());
if (!empty($errors) || $saml_exception) {
Log::warning('There was an error with SAML ACS: ' . implode(', ', $errors));
Log::warning('Reason: ' . $auth->getLastErrorReason());
return redirect()->route('login')->with('error', trans('auth/message.signin.error'));
}
@@ -126,18 +132,24 @@ class SamlController extends Controller
*
* @param Request $request
*
* @return Redirect
* @return \Illuminate\Http\RedirectResponse
*/
public function sls(Request $request)
{
$auth = $this->saml->getAuth();
$retrieveParametersFromServer = $this->saml->getSetting('retrieveParametersFromServer', false);
$sloUrl = $auth->processSLO(true, null, $retrieveParametersFromServer, null, true);
$saml_exception = false;
try {
$sloUrl = $auth->processSLO(true, null, $retrieveParametersFromServer, null, true);
} catch (\Exception $e) {
Log::warning("Exception caught in SAML single-logout: " . $e->getMessage());
$saml_exception = true;
}
$errors = $auth->getErrors();
if (! empty($errors)) {
Log::error('There was an error with SAML SLS: '.implode(', ', $errors));
Log::error('Reason: '.$auth->getLastErrorReason());
if (!empty($errors) || $saml_exception) {
Log::warning('There was an error with SAML SLS: ' . implode(', ', $errors));
Log::warning('Reason: ' . $auth->getLastErrorReason());
return view('errors.403');
}
@@ -5,8 +5,8 @@ namespace App\Http\Controllers;
use App\Helpers\Helper;
use App\Models\AssetModel;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Http\RedirectResponse;
use \Illuminate\Contracts\View\View;
class BulkAssetModelsController extends Controller
{
@@ -16,9 +16,8 @@ class BulkAssetModelsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.7]
* @param Request $request
* @return \Illuminate\Contracts\View\View
*/
public function edit(Request $request)
public function edit(Request $request) : View | RedirectResponse
{
$models_raw_array = $request->input('ids');
@@ -61,9 +60,8 @@ class BulkAssetModelsController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.7]
* @param Request $request
* @return \Illuminate\Contracts\View\View
*/
public function update(Request $request)
public function update(Request $request): View | RedirectResponse
{
$this->authorize('update', AssetModel::class);
@@ -105,9 +103,8 @@ class BulkAssetModelsController extends Controller
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return Redirect
*/
public function destroy(Request $request)
public function destroy(Request $request) : RedirectResponse
{
$this->authorize('delete', AssetModel::class);

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