Compare commits

...

557 Commits

Author SHA1 Message Date
snipe bb382f3d2a Merge remote-tracking branch 'origin/develop' 2022-06-30 18:52:02 -07:00
snipe 25cb32ca6a Fixed typo
Signed-off-by: snipe <snipe@snipe.net>
2022-06-30 18:51:44 -07:00
snipe 6a13a7e096 Merge remote-tracking branch 'origin/develop' 2022-06-30 18:38:25 -07:00
snipe e366caf3d1 Merge pull request #11438 from uberbrady/backout_linear_depreciation_math
Revert a change in our Linear Depreciation math
2022-06-30 18:38:03 -07:00
Brady Wetherington f72aa2415f Revert a change in our Linear Depreciation math; I think the old algorithm was correct 2022-06-30 18:24:45 -07:00
snipe 7969a66552 Merge remote-tracking branch 'origin/develop' 2022-06-30 18:17:51 -07:00
snipe 4edba064d5 Removed duplicate model column in depreciation report
Signed-off-by: snipe <snipe@snipe.net>
2022-06-30 18:17:30 -07:00
snipe f3a3c59b7b Fixed branch name
Signed-off-by: snipe <snipe@snipe.net>
2022-06-30 18:05:46 -07:00
snipe aa54c23f98 Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2022-06-30 18:04:53 -07:00
snipe df1e2687d6 Updated languages
Signed-off-by: snipe <snipe@snipe.net>
2022-06-30 17:35:02 -07:00
snipe 4f07e77bf9 Add @naveensrinivasan as a contributor 2022-06-30 17:35:02 -07:00
snipe a10f570350 Merge pull request #11436 from turrisxyz/Pinned-Dependencies-GitHub
chore: Set permissions for GitHub actions
2022-06-30 17:30:17 -07:00
naveen ac94aa8e46 chore: Set permissions for GitHub actions
Restrict the GitHub token permissions only to the required ones; this way, even if the attackers will succeed in compromising your workflow, they won’t be able to do much.

- Included permissions for the action. https://github.com/ossf/scorecard/blob/main/docs/checks.md#token-permissions

https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions

https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs

[Keeping your GitHub Actions and workflows secure Part 1: Preventing pwn requests](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/)

Signed-off-by: naveen <172697+naveensrinivasan@users.noreply.github.com>
2022-07-01 00:29:21 +00:00
snipe 7ebf125dae Merge remote-tracking branch 'origin/develop' 2022-06-30 15:44:51 -07:00
snipe 9a361d573f Merge pull request #11435 from snipe/features/ldap_warnings
Added warnings for common LDAP misconfigs
2022-06-30 15:44:33 -07:00
snipe 1a423a252b Derp
Signed-off-by: snipe <snipe@snipe.net>
2022-06-30 15:22:58 -07:00
snipe 7591f3f092 Added auth filter check regex
Signed-off-by: snipe <snipe@snipe.net>
2022-06-30 15:15:49 -07:00
snipe 2cace3c73a Added LDAP warnings on page load
Signed-off-by: snipe <snipe@snipe.net>
2022-06-30 15:08:12 -07:00
snipe 97afafdd48 Merge remote-tracking branch 'origin/develop' 2022-06-30 14:20:34 -07:00
snipe 656efc5f92 Fixed missing trans()
Signed-off-by: snipe <snipe@snipe.net>
2022-06-30 14:20:15 -07:00
snipe 46d055cf74 Fixed weird extra padding on crown
Signed-off-by: snipe <snipe@snipe.net>
2022-06-30 14:17:53 -07:00
snipe 423e7439ee Merge remote-tracking branch 'origin/develop' 2022-06-30 14:09:19 -07:00
snipe 2262ef818e Merge pull request #11427 from Godmartinz/email_users_list
[feature] adds button to email user list of assets from profile
2022-06-29 15:25:18 -07:00
snipe 02459aad26 Merge pull request #11430 from uberbrady/scim_more_tolerant
Make SCIM be more tolerant of missing fields
2022-06-29 15:24:25 -07:00
Brady Wetherington 2451bb9a2b Make SCIM be more tolerant of missing fields 2022-06-29 14:48:59 -07:00
Godfrey M cd9d2d0cec adds docblock 2022-06-29 13:01:29 -07:00
Godfrey M fc636ea888 removed redundant header 2022-06-29 12:01:56 -07:00
Godfrey M e471aa8639 adds button to email user list of assets from profile 2022-06-29 11:15:15 -07:00
snipe 180f36d145 Merge remote-tracking branch 'origin/develop' 2022-06-29 05:04:21 -07:00
snipe f8fd87b896 Add @ntbutler-nbcs as a contributor 2022-06-29 05:04:07 -07:00
snipe 130c8ea1b0 Add @ntbutler-nbcs as a contributor 2022-06-29 05:03:22 -07:00
snipe 5af6330398 Merge pull request #11417 from ntbutler-nbcs/master
[Feature] - Add checkoutByTag API endpoint for assets
2022-06-29 05:03:01 -07:00
snipe daaf8713d8 Merge branch 'dampfklon-9813-duplicate-accept-asset' into develop 2022-06-29 04:58:26 -07:00
snipe 5b02d9ed06 Merge branch '9813-duplicate-accept-asset' of https://github.com/dampfklon/snipe-it into dampfklon-9813-duplicate-accept-asset
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	resources/views/account/accept/create.blade.php
2022-06-29 04:58:13 -07:00
snipe b04cf20735 Merge pull request #10758 from inietov/fixes/badmethodcallexception_undefined_method_Asset.unaccepted_develop
Fixes BadMethodCallException Call to undefined method App\Models\Asset::unaccepted() for master [ch-17636]
2022-06-29 04:34:51 -07:00
Nathan Butler 6531657ee0 Revert version to dev for pull request 2022-06-29 18:00:15 +10:00
Nathan Butler e28e7e37b8 Removed unneeded checks when searching for asset 2022-06-29 17:49:50 +10:00
snipe 467f59e193 Merge remote-tracking branch 'origin/develop' 2022-06-29 00:25:00 -07:00
snipe be9e6fe847 Another typo
Signed-off-by: snipe <snipe@snipe.net>
2022-06-29 00:24:33 -07:00
snipe b0e13611f7 Fixed typo
Signed-off-by: snipe <snipe@snipe.net>
2022-06-29 00:24:08 -07:00
snipe f3887aef33 Merge remote-tracking branch 'origin/develop' 2022-06-29 00:10:38 -07:00
snipe 7b3f891edd Merge pull request #11418 from snipe/features/api_backup_download
Download backup via API
2022-06-29 00:07:09 -07:00
snipe b590f29f33 Attempt a download via API
Signed-off-by: snipe <snipe@snipe.net>
2022-06-28 23:59:13 -07:00
snipe 1debdc47cf Backups endpoint
Signed-off-by: snipe <snipe@snipe.net>
2022-06-28 23:30:17 -07:00
snipe bb7662a214 Merge pull request #11416 from snipe/features/personal_access_endpoint
Added personal access endpoint to API
2022-06-28 23:27:21 -07:00
snipe 53bc15900b Formatted show api
Signed-off-by: snipe <snipe@snipe.net>
2022-06-28 23:23:55 -07:00
snipe 90fe7af863 Small refactor
Signed-off-by: snipe <snipe@snipe.net>
2022-06-28 23:18:16 -07:00
snipe 67ad24af08 Return token ID in cli
Signed-off-by: snipe <snipe@snipe.net>
2022-06-28 23:13:25 -07:00
Nathan Butler 67e9b7795a Added asset checkoutByTag API endpoint 2022-06-29 16:11:57 +10:00
snipe 52332bc9ed Include token ID in payload
Signed-off-by: snipe <snipe@snipe.net>
2022-06-28 23:10:56 -07:00
snipe dc27d3bec9 Change to plural endpoints
Signed-off-by: snipe <snipe@snipe.net>
2022-06-28 23:10:40 -07:00
snipe a711e608c9 Changed siganture to be clearer
Signed-off-by: snipe <snipe@snipe.net>
2022-06-28 22:26:37 -07:00
snipe 2f7c04362e Make -kkey-only a flag
Signed-off-by: snipe <snipe@snipe.net>
2022-06-28 22:20:55 -07:00
snipe 9b6fd7e19a Set $accessTokenName
Signed-off-by: snipe <snipe@snipe.net>
2022-06-28 22:11:46 -07:00
snipe 9680b02bce Check that the user has permission to create their own API keys
Signed-off-by: snipe <snipe@snipe.net>
2022-06-28 22:09:18 -07:00
snipe e7de7d1716 Show user info as well
Signed-off-by: snipe <snipe@snipe.net>
2022-06-28 22:06:46 -07:00
snipe 112f147596 Console script to generate API tokens
Signed-off-by: snipe <snipe@snipe.net>
2022-06-28 22:04:39 -07:00
snipe 413487de80 Made method naming consistent
Signed-off-by: snipe <snipe@snipe.net>
2022-06-28 21:32:12 -07:00
snipe 1158fa9ea8 Added personal access tokens to api
Signed-off-by: snipe <snipe@snipe.net>
2022-06-28 21:29:15 -07:00
snipe a8e8112b34 Merge pull request #11415 from snipe/features/more_api_filters
Added additional filters for api indexes
2022-06-28 20:04:01 -07:00
snipe 3df9260ca8 Added additional filters for api indexes
Signed-off-by: snipe <snipe@snipe.net>
2022-06-28 19:59:45 -07:00
snipe 14ba3af086 Merge pull request #11414 from snipe/features/additional_search_fields_for_locations
Added additional search filters for location API
2022-06-28 19:08:08 -07:00
snipe 71c8050883 Added additional search filters for location API
Signed-off-by: snipe <snipe@snipe.net>
2022-06-28 19:07:11 -07:00
snipe df5b01492c Merge remote-tracking branch 'origin/develop' 2022-06-28 18:55:59 -07:00
snipe 9dbb355e8d Merge pull request #11412 from snipe/features/model_uploads
Added model uploads
2022-06-28 18:42:05 -07:00
snipe 0f3778f07b Merge pull request #11413 from uberbrady/add_username_index
Add index across username and deleted_at to improve performance
2022-06-28 17:16:01 -07:00
Brady Wetherington f515bd2dc8 Add index across username and deleted_at to improve large directory sync performance 2022-06-28 17:12:14 -07:00
snipe f3075facb4 Added delete button
Signed-off-by: snipe <snipe@snipe.net>
2022-06-28 16:25:22 -07:00
snipe ed95adb45c Show model files on hardware page
Signed-off-by: snipe <snipe@snipe.net>
2022-06-28 16:17:46 -07:00
snipe 95d4f7c62e Added models router to BS tables
Signed-off-by: snipe <snipe@snipe.net>
2022-06-28 15:56:18 -07:00
snipe c90ed9f25f Allow models uploads
Signed-off-by: snipe <snipe@snipe.net>
2022-06-28 15:50:07 -07:00
snipe 7f664a7971 Layout changes for file upload
Signed-off-by: snipe <snipe@snipe.net>
2022-06-28 12:32:12 -07:00
snipe 14c6879f06 Merge remote-tracking branch 'origin/develop' 2022-06-28 11:41:56 -07:00
snipe d8d12d4590 Merge pull request #11408 from uberbrady/add_filter_option_to_ldap_sync
Add a new `--filter` option to Artisan ldap-sync command
2022-06-28 09:50:48 -07:00
Brady Wetherington be3388d647 Add a new --filter option to Artisan ldap-sync command 2022-06-27 19:49:59 -07:00
snipe 242836719d Bumped hash
Signed-off-by: snipe <snipe@snipe.net>
2022-06-27 19:32:10 -07:00
snipe 393c32558b Gotta bump that hash up
Signed-off-by: snipe <snipe@snipe.net>
2022-06-27 19:31:26 -07:00
snipe 94e723a88f Merge pull request #11404 from snipe/features/fix_transliteration
Fixed custom field transliteration
2022-06-27 17:42:02 -07:00
snipe 14d8fb66aa Merge pull request #11405 from snipe/fixes/use_db_column_instead_of_converted_value
Only care about the custom field's converted name when updating the custom field itself
2022-06-27 17:36:26 -07:00
snipe ae73d4cc7c Merge pull request #11407 from snipe/features/disclosure_arrows_on_user_screen
Added disclosure arrows for lesser used options on user screen
2022-06-27 17:33:31 -07:00
snipe bf08e73f8f Removed comments and server side cookie info
Signed-off-by: snipe <snipe@snipe.net>
2022-06-27 16:36:09 -07:00
snipe 4a3f56acf2 Removed old cooke stuff
Signed-off-by: snipe <snipe@snipe.net>
2022-06-27 16:35:54 -07:00
snipe e33a4c2ef2 Added disclosure arrows to use screen
Signed-off-by: snipe <snipe@snipe.net>
2022-06-27 16:35:44 -07:00
snipe 52bd7d0d68 Merge remote-tracking branch 'origin/develop' 2022-06-27 14:25:38 -07:00
snipe baad3b9d58 Only care about the converted name when updating the custom field itself
Signed-off-by: snipe <snipe@snipe.net>
2022-06-27 14:17:07 -07:00
snipe 131edb611e Refine output and checks
Signed-off-by: snipe <snipe@snipe.net>
2022-06-27 13:54:21 -07:00
snipe 518395bbc7 Merge pull request #11403 from uberbrady/remember_disclosure_triangles
Remember the state of the disclosure triangles in Assets
2022-06-27 13:28:14 -07:00
Brady Wetherington 34b4499178 Remember the state of the disclosure triangles in Assets 2022-06-27 12:57:19 -07:00
snipe 8f900fb4e1 More UI tweaks
Signed-off-by: snipe <snipe@snipe.net>
2022-06-27 12:15:11 -07:00
snipe 9355689dd4 Nicer output for custom fields error
Signed-off-by: snipe <snipe@snipe.net>
2022-06-27 11:52:51 -07:00
snipe 0909feaa6b Few more UI tweaks
Signed-off-by: snipe <snipe@snipe.net>
2022-06-27 11:01:19 -07:00
snipe 7f18180105 Fixed toggle
Signed-off-by: snipe <snipe@snipe.net>
2022-06-27 10:26:37 -07:00
snipe bee694e605 Fixed typo
Signed-off-by: snipe <snipe@snipe.net>
2022-06-27 09:57:20 -07:00
snipe 08525a3c20 Few more changes
Signed-off-by: snipe <snipe@snipe.net>
2022-06-27 09:43:32 -07:00
snipe d70b36750c Merge pull request #10967 from veenone/fix/hide_optional_field_on_create_asset
Fixes #8155 -  improve the workflow during asset creation
2022-06-24 18:53:07 -07:00
snipe 8c85d7bc97 Merge pull request #11370 from inietov/fixes/customfields_default_values_not_validating
Adds validation to custom fields' default values
2022-06-24 18:11:16 -07:00
snipe cb225cb1ce Merge remote-tracking branch 'origin/develop' 2022-06-24 18:00:21 -07:00
snipe 7e7ae3bb95 Really reverting this time
Signed-off-by: snipe <snipe@snipe.net>
2022-06-24 17:55:34 -07:00
snipe 838579e9a8 Reverting :(
Signed-off-by: snipe <snipe@snipe.net>
2022-06-24 17:30:56 -07:00
snipe a99896618d Merge branch 'develop' of https://github.com/snipe/snipe-it into develop
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	composer.json
#	composer.lock
2022-06-24 17:21:57 -07:00
snipe 24cb13d52b Upgraded guzzle (not broken this time)
Signed-off-by: snipe <snipe@snipe.net>
2022-06-24 17:18:34 -07:00
snipe cc7513e202 Merge pull request #11392 from snipe/security/upgrade_guzzle
Upgraded guzzle to 7.4.5
2022-06-24 17:04:17 -07:00
snipe c0b6d5aa2c Upgraded guzzle to 7.4.5
Signed-off-by: snipe <snipe@snipe.net>
2022-06-24 17:01:24 -07:00
snipe 5788038b49 Merge pull request #11391 from snipe/security/upgrade_webpack
Upgrade webpack from 5.72.1 to 5.73.0
2022-06-24 16:41:59 -07:00
snipe fbf0815b16 Upgrade webpack from 5.72.1 to 5.73.0
Signed-off-by: snipe <snipe@snipe.net>
2022-06-24 16:41:19 -07:00
snipe e2c227f02b Merge remote-tracking branch 'origin/develop' 2022-06-24 16:21:10 -07:00
snipe be0f0fc421 Merge pull request #11388 from snipe/features/disable_purge_in_env
Disallow purge backup deletion by default and, enable via .env
2022-06-24 16:12:00 -07:00
snipe a03075b6ea Merge pull request #11389 from uberbrady/errmagerd_the_gerneral
Typo of 'general' was in the migration blade a few places
2022-06-24 16:05:40 -07:00
Brady Wetherington 3b3f1a817e Typo of 'general' was in the migration blade a few places 2022-06-24 16:00:15 -07:00
snipe 601f7a6994 Moved new variables in example env
Signed-off-by: snipe <snipe@snipe.net>
2022-06-24 16:00:05 -07:00
snipe 75d19d815d Still show the purge button even if not allowed to avoid confusion
Signed-off-by: snipe <snipe@snipe.net>
2022-06-24 15:59:40 -07:00
snipe d167d2a10f Disallow backup deletion and log attempt if not allowed
Signed-off-by: snipe <snipe@snipe.net>
2022-06-24 15:49:22 -07:00
snipe fce4f0dc0e Disable delete button if not allowed
Signed-off-by: snipe <snipe@snipe.net>
2022-06-24 15:49:07 -07:00
snipe 657039882c Added purge and backup strings
Signed-off-by: snipe <snipe@snipe.net>
2022-06-24 15:48:46 -07:00
snipe cf99d42413 Added backup delete to app config
Signed-off-by: snipe <snipe@snipe.net>
2022-06-24 15:48:37 -07:00
snipe f483eafae9 Added backup delete env
Signed-off-by: snipe <snipe@snipe.net>
2022-06-24 15:44:11 -07:00
snipe 77bf28bcb6 Disallow purge
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 20:11:43 -07:00
snipe 6c2d06efb9 Merge remote-tracking branch 'origin/develop' 2022-06-23 20:02:19 -07:00
snipe d0081188c7 Merge pull request #11387 from snipe/fixes/nicer_settings_search
Moved the settings search box higher
2022-06-23 19:31:24 -07:00
snipe ce2362459c Layout tweak for search and back placement
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 19:30:52 -07:00
snipe 4e568bec8a Moves the settings search box higher
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 19:25:30 -07:00
snipe 18c37c97b8 Dark skin prod assets
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 19:14:12 -07:00
snipe 82e5faa869 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-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
2022-06-23 19:14:01 -07:00
snipe dec7122ac7 Dark skin dev assets
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 19:13:01 -07:00
snipe a75fc8af7e Merge remote-tracking branch 'origin/develop' 2022-06-23 19:12:13 -07:00
snipe 86d2c2b153 Small naming changes
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 19:11:59 -07:00
snipe 9fc4565bc1 Merge remote-tracking branch 'origin/develop' 2022-06-23 18:56:04 -07:00
snipe f0cc418965 Merge pull request #11383 from snipe/features/adds_user_id_to_users
Added created_by to users
2022-06-23 18:48:42 -07:00
snipe 0bc3ca5c42 Fixed comments
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 18:44:27 -07:00
snipe 62ab867051 Fixed url param
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 18:43:10 -07:00
snipe 9fd3541520 Missed on createdBy
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 18:42:22 -07:00
snipe 3e559044b2 Changed method and scope names
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 18:41:13 -07:00
snipe 75a631b91f Merge pull request #11375 from Godmartinz/bootS_dropdown_menu_fix
fixes dropdown column select font color  in bootstrap tables
2022-06-23 18:31:36 -07:00
snipe 3a8786fdb7 Updated assets for prod
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 18:27:31 -07:00
snipe f2a89161b3 Merge remote-tracking branch 'origin/develop' 2022-06-23 18:26:36 -07:00
snipe 1c25057e42 Merge pull request #11379 from Godmartinz/license_acceptance_eula
adds eula blade for licenses/consumables/components and fixes assigned_to for dom_pdf
2022-06-23 18:26:19 -07:00
snipe 590630e4e0 Merge pull request #11386 from snipe/fixes/default_skin_settings_colors
Small fixes to default blue
2022-06-23 18:23:45 -07:00
snipe 487dedba25 Merge pull request #11384 from snipe/fixes/bs_tables_undefined_for_archived
Fixed missing archived tooltip
2022-06-23 18:16:31 -07:00
snipe f4c346a57c Small fixes to default blue skin
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 18:11:42 -07:00
snipe 35365882ac Used new settings_button class in settings index
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 18:10:28 -07:00
snipe ea254ccc04 Tweaked default @blue
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 18:10:14 -07:00
snipe 06d5b5f4b1 Small change to color in overrides
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 18:10:03 -07:00
snipe 2536b02ace Fixed some colors on default skin
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 18:09:52 -07:00
snipe 6b8abb1511 Fixed missing archived tooltip
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 17:32:39 -07:00
snipe 9c9f5be6fe Do not show the creating admin by default in list view
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 17:28:34 -07:00
snipe d8daec2e0a Added created_by results to user index API
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 17:19:30 -07:00
snipe c9b81d65f1 Save the user id who is creating the user
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 17:19:08 -07:00
snipe 7f05029089 Added created_by to API output
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 17:18:31 -07:00
snipe 23c50ea9a5 Added admihn scopes
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 17:18:11 -07:00
snipe 2e5e8f363b Added admin to oresenter
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 17:18:04 -07:00
snipe e63183649a Show admin in user view
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 17:17:48 -07:00
snipe ef86c0273a Added migration to store admin ID
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 17:17:38 -07:00
snipe dd8d90aa39 Merge remote-tracking branch 'origin/develop' 2022-06-23 16:16:04 -07:00
snipe 670a46e85c Merge pull request #11382 from snipe/fixes/check_for_archived_setting_on_counts
Fixes check for archived setting on counts
2022-06-23 16:13:20 -07:00
snipe daf6c72005 Fleshed out comments on new scope
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 16:02:54 -07:00
snipe 1a4579b770 Missed one
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 16:00:27 -07:00
snipe 398c77bfdc Use new scope for additional tabs
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 15:37:39 -07:00
snipe d45d322b54 Use scoped query for asset count
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 13:43:23 -07:00
Godfrey M b0897a1fc9 adds acceptance for consumables and components 2022-06-23 11:52:35 -07:00
Godfrey M d00b469001 fixed the search for the license 2022-06-23 11:33:36 -07:00
snipe c5a6cec194 Merge pull request #11380 from snipe/features/better_excel_export
Fixed #11378 - Added better excel export
2022-06-23 11:25:33 -07:00
snipe e2b1494511 Reordered and added xlsx to export list
Signed-off-by: snipe <snipe@snipe.net>
2022-06-23 11:18:59 -07:00
Godfrey M df76e6eacf adds eula blade for licenses and fixes assigned_to for dom_pdf 2022-06-23 11:15:15 -07:00
Godfrey M 541ae919d9 fixes dropdown column select font color in bootstrap tables 2022-06-23 09:38:44 -07:00
Ivan Nieto Vivanco 7976401aa2 Add error message when the default customfield values can't be validated 2022-06-22 22:17:05 -05:00
Ivan Nieto Vivanco 7e10abe605 Fix the date control in custom fields' default values form to show the selected date 2022-06-22 21:47:08 -05:00
Ivan Nieto Vivanco afdf93ca63 Adds controls for custom fields of type date in the default value form 2022-06-22 21:37:11 -05:00
Ivan Nieto Vivanco 321367b974 Adds validation to custom fields' default values 2022-06-22 21:06:07 -05:00
snipe 366f3aacef Merge pull request #11367 from snipe/js_library_updates
Updated/upgraded assets
2022-06-22 16:23:03 -07:00
snipe 4b9ec9218d Upgraded/updates assets
Signed-off-by: snipe <snipe@snipe.net>
2022-06-22 15:54:58 -07:00
snipe cae66753fb Merge pull request #11323 from Godmartinz/bug/sc-19255/issues-with-black-light-sk
fixes non-dark mode black theme
2022-06-22 15:47:55 -07:00
snipe 5ac9efa9a3 Merge remote-tracking branch 'origin/develop' 2022-06-22 12:20:04 -07:00
snipe ded635207f Merge pull request #11365 from snipe/fixes/adds_missing_zip_to_user_view
Added missing postal code from user view
2022-06-22 12:19:27 -07:00
snipe f0f37df76e Added missing postal code from user view
Signed-off-by: snipe <snipe@snipe.net>
2022-06-22 12:18:57 -07:00
snipe f5702532f0 Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2022-06-22 11:21:51 -07:00
snipe 2f02eee69b Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2022-06-22 11:21:04 -07:00
snipe 89c234b1c2 Merge pull request #11358 from snipe/fixes/missing_token_lang
Fixed missing password.token string and checked for user existing before attempting to send reset email
2022-06-22 11:15:08 -07:00
snipe c24052cb2d Merge pull request #11364 from snipe/features/link_asset_to_order_number
Fixed #11351 - add link on asset view to order number
2022-06-22 11:08:40 -07:00
snipe a7a61a3620 Fixed #11351 - add link on asset view to order number
Signed-off-by: snipe <snipe@snipe.net>
2022-06-22 11:07:54 -07:00
snipe 135fdae209 Merge pull request #11337 from mikeroq/fixes/user_edit_website_missing
Fixed #11332 Added website field that was missing from update and store method.
2022-06-22 10:16:38 -07:00
snipe 5c30de517d Use rate limiter for API calls
Signed-off-by: snipe <snipe@snipe.net>
2022-06-22 09:11:40 -07:00
snipe a7dc6162fa Simplify password attempts rate limiting
Signed-off-by: snipe <snipe@snipe.net>
2022-06-22 09:11:24 -07:00
snipe 18778d3723 Additional example variables
Signed-off-by: snipe <snipe@snipe.net>
2022-06-22 09:07:48 -07:00
snipe 5ff1b5fd50 Increased throttle
Signed-off-by: snipe <snipe@snipe.net>
2022-06-21 19:39:50 -07:00
snipe 1c1f3dc42c Added password requests cleanup to scheduler
Signed-off-by: snipe <snipe@snipe.net>
2022-06-21 19:35:16 -07:00
snipe d67afc3bd0 Merge pull request #11359 from uberbrady/dont_show_images_on_checkin_email_if_not_requested
Fixes issue where asset images were showing up in checkin emails
2022-06-21 19:34:22 -07:00
snipe a5b857c753 Return error if token is incorrect
Signed-off-by: snipe <snipe@snipe.net>
2022-06-21 19:30:51 -07:00
snipe b00db3cc56 Added throttling to password reset token form
Signed-off-by: snipe <snipe@snipe.net>
2022-06-21 19:30:11 -07:00
snipe 57720cb978 Added comment block
Signed-off-by: snipe <snipe@snipe.net>
2022-06-21 19:12:57 -07:00
snipe 172e8d463f Use newer forgotten password variables
Signed-off-by: snipe <snipe@snipe.net>
2022-06-21 19:11:57 -07:00
snipe 284dbb7553 Set higher threshhold, moved throttle settings
Signed-off-by: snipe <snipe@snipe.net>
2022-06-21 19:11:39 -07:00
Brady Wetherington 1156eea8af Fixes issue where asset images were showing up in checkin emails 2022-06-21 19:11:16 -07:00
snipe 17ee332715 Remove throttle from GET in password reset
Signed-off-by: snipe <snipe@snipe.net>
2022-06-21 18:53:14 -07:00
snipe 2f258a3e3d Make the strings match
Signed-off-by: snipe <snipe@snipe.net>
2022-06-21 18:48:22 -07:00
snipe a31bca1798 Check that the user is activated before letting them reset their password
Signed-off-by: snipe <snipe@snipe.net>
2022-06-21 18:48:02 -07:00
snipe 791f77f641 Fixed throttle variables
Signed-off-by: snipe <snipe@snipe.net>
2022-06-21 18:41:12 -07:00
snipe 1b6df232aa Updated string
Signed-off-by: snipe <snipe@snipe.net>
2022-06-21 18:41:02 -07:00
snipe 386272a618 Manually add the additional routes so we can throttle them
Signed-off-by: snipe <snipe@snipe.net>
2022-06-21 18:40:53 -07:00
snipe 7f8fc7add9 Make SAML debugging less noisy
Signed-off-by: snipe <snipe@snipe.net>
2022-06-21 17:57:17 -07:00
snipe 6bc525bc25 Merge pull request #11352 from inietov/fixes/assets_transformer_date_customfields_fixes
Fixed #11335 Assets transformer date customfields issues
2022-06-21 17:56:17 -07:00
snipe de048e1009 Updated language
Signed-off-by: snipe <snipe@snipe.net>
2022-06-21 16:13:59 -07:00
snipe 68150d11b7 Make logo clickable
Signed-off-by: snipe <snipe@snipe.net>
2022-06-21 16:13:52 -07:00
snipe f4f400ed87 Handle workflow better for invalid users
Signed-off-by: snipe <snipe@snipe.net>
2022-06-21 16:13:43 -07:00
snipe a49ccf0863 Removed unused rules
Signed-off-by: snipe <snipe@snipe.net>
2022-06-21 16:13:26 -07:00
snipe 300879847f Added a few comments to make it clearer what’s happening
Signed-off-by: snipe <snipe@snipe.net>
2022-06-21 14:33:10 -07:00
snipe d4c53945d9 Tweaked language
Signed-off-by: snipe <snipe@snipe.net>
2022-06-21 14:19:49 -07:00
snipe 21875100b6 Fixed missing password.token string and checked for user existing before trying to reset
Signed-off-by: snipe <snipe@snipe.net>
2022-06-21 14:15:38 -07:00
snipe 87980643ea Merge pull request #11357 from snipe/fixes/11343_null_asset_name
Fixed #11343 - ability to null asset name on checkin
2022-06-21 10:58:28 -07:00
snipe 675f42401c Fixed #11343 - ability to null asset name
Signed-off-by: snipe <snipe@snipe.net>
2022-06-21 10:57:39 -07:00
Ivan Nieto Vivanco 3a5c09c424 Used the getFormattedDateObject() function with the expected parameters 2022-06-20 19:58:51 -05:00
snipe 3b462ffadc Merge pull request #11329 from mikeroq/fixes/deprecations_pagination_missing
Fixed #11285 - Depreciation index table missing pagination
2022-06-18 19:58:32 -07:00
mikeroq d60af478ad Added website field that was missing from update and store method. 2022-06-17 08:09:39 -05:00
snipe cabef8ff12 Merge pull request #11326 from snipe/features/added_number_format_to_tab_badges
Added number_format() to tab badges
2022-06-16 14:05:29 -07:00
Mike Roquemore 8a27ef30d5 Missing total argument on transformDeprecations method
Removed duplicate array key on transformDeprecation method
2022-06-15 21:52:15 -05:00
snipe a111482217 Use number_format on badges
Signed-off-by: snipe <snipe@snipe.net>
2022-06-15 14:59:06 -07:00
snipe a758e825ed Dev assets
Signed-off-by: snipe <snipe@snipe.net>
2022-06-15 13:45:33 -07:00
snipe af66f83a3d Check for blank (not null) values i asset transformer date
Signed-off-by: snipe <snipe@snipe.net>
2022-06-15 13:42:30 -07:00
snipe b3605fa141 Merge remote-tracking branch 'origin/develop' 2022-06-15 11:39:16 -07:00
snipe 6f713985fb Merge pull request #11324 from snipe/features/add_badges_to_companies
Features/add badges to companies
2022-06-15 11:38:32 -07:00
snipe 677e5a8cf1 Added tab badges to company detail view
Signed-off-by: snipe <snipe@snipe.net>
2022-06-15 11:37:44 -07:00
snipe 872600a7a7 Link company on license page
Signed-off-by: snipe <snipe@snipe.net>
2022-06-15 11:37:26 -07:00
Godfrey M 3a879bda4a more adjustments 2022-06-15 11:08:42 -07:00
Godfrey M a6852cf4d2 fixes non-dark mode black theme 2022-06-15 10:20:25 -07:00
snipe 61c601dbdf 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
2022-06-15 02:09:32 -07:00
snipe 74bc06cc49 Removed debugging code
Signed-off-by: snipe <snipe@snipe.net>
2022-06-15 02:07:58 -07:00
snipe 5fe1078013 Squashed commit of the following:
commit a011b07d99
Merge: b392ed269 6059e9e11
Author: snipe <snipe@snipe.net>
Date:   Tue Jun 14 17:52:50 2022 -0700

    Merge pull request #11315 from snipe/features/adds_fullscreen_option_to_tables

    Added fullscreen option to tables

commit b392ed269b
Merge: 693043e64 e6d792bdf
Author: snipe <snipe@snipe.net>
Date:   Tue Jun 14 17:52:41 2022 -0700

    Merge pull request #11316 from snipe/fixes/smaller_padlock_on_table_header

    Tweaked CSS for smaller padlock

commit 6059e9e119
Author: snipe <snipe@snipe.net>
Date:   Tue Jun 14 17:49:00 2022 -0700

    Added fullscreen option to tables

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

commit e6d792bdf7
Author: snipe <snipe@snipe.net>
Date:   Tue Jun 14 17:43:12 2022 -0700

    Tweaked CSS for smaller padlock

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

Signed-off-by: snipe <snipe@snipe.net>
2022-06-14 17:54:18 -07:00
snipe a011b07d99 Merge pull request #11315 from snipe/features/adds_fullscreen_option_to_tables
Added fullscreen option to tables
2022-06-14 17:52:50 -07:00
snipe b392ed269b Merge pull request #11316 from snipe/fixes/smaller_padlock_on_table_header
Tweaked CSS for smaller padlock
2022-06-14 17:52:41 -07:00
snipe 6059e9e119 Added fullscreen option to tables
Signed-off-by: snipe <snipe@snipe.net>
2022-06-14 17:49:00 -07:00
snipe e6d792bdf7 Tweaked CSS for smaller padlock
Signed-off-by: snipe <snipe@snipe.net>
2022-06-14 17:43:12 -07:00
snipe f16a4b6aef Removed footer from show category
Signed-off-by: snipe <snipe@snipe.net>
2022-06-14 17:16:14 -07:00
snipe d74b4f55fb Merge remote-tracking branch 'origin/develop' 2022-06-14 17:15:39 -07:00
snipe 693043e645 Merge pull request #11313 from snipe/fixes/nicer_suppliers_mfgs_ui
Nicer suppliers and manufacturers UI
2022-06-14 17:14:53 -07:00
snipe e935a34946 Merge remote-tracking branch 'origin/develop' 2022-06-14 16:25:50 -07:00
snipe 4052e360c1 Merge pull request #11314 from snipe/fixes/deja_vu_font_pdf
Fixed #11175 - Use the Deja Vu font in PDFs to be able to support Cyrillic, etc
2022-06-14 16:25:33 -07:00
snipe cc6a2f2d49 Use the Deja Vu font to be able to support cyrllic, etc
Signed-off-by: snipe <snipe@snipe.net>
2022-06-14 16:23:30 -07:00
snipe 07bc2fd742 Added maintenance scope for ordering by supplier
Signed-off-by: snipe <snipe@snipe.net>
2022-06-14 16:11:43 -07:00
snipe a57a6486e7 Only add http:// if the url variable isn’t blank
Signed-off-by: snipe <snipe@snipe.net>
2022-06-14 16:11:13 -07:00
snipe a33276cb3d Additional filters on maintenances UI
Signed-off-by: snipe <snipe@snipe.net>
2022-06-14 16:10:48 -07:00
snipe bfec0059c5 Improved manufacturers UI
Signed-off-by: snipe <snipe@snipe.net>
2022-06-14 16:10:36 -07:00
snipe aea9dd1de5 Improved suplpiers UI
Signed-off-by: snipe <snipe@snipe.net>
2022-06-14 16:06:56 -07:00
snipe 954b54f914 Removed duplicated $allowed_columns
Signed-off-by: snipe <snipe@snipe.net>
2022-06-14 15:06:04 -07:00
snipe 56a15731ef Merge remote-tracking branch 'origin/develop' 2022-06-14 12:56:16 -07:00
snipe 766e59acde Merge pull request #11310 from snipe/fixes/statuslabels_bulk_edit
Fixes #11308 - bulk edit on statuslabels detail page
2022-06-14 12:55:56 -07:00
snipe f1a63f25e7 Partialize and add data atributes to statuslabel bulk
Signed-off-by: snipe <snipe@snipe.net>
2022-06-14 12:50:26 -07:00
snipe 88dfdb7538 Fixed bug in uncheck
Signed-off-by: snipe <snipe@snipe.net>
2022-06-14 12:50:10 -07:00
snipe 9072f7c6c9 Added click-to-select to tables
Signed-off-by: snipe <snipe@snipe.net>
2022-06-14 12:49:50 -07:00
snipe bff34063cd Merge pull request #11309 from uberbrady/ldap_troubleshooter_improvements
Fixed SC-19104 - fixes to ldap:troubleshoot artisan command
2022-06-14 12:24:24 -07:00
Brady Wetherington 1e685ca835 Fixed SC-19104 - fixes to ldap:troubleshoot artisan command 2022-06-14 12:18:42 -07:00
snipe b55630aafa Merge remote-tracking branch 'origin/develop' 2022-06-14 11:45:27 -07:00
snipe c3b644797e Merge pull request #11169 from inietov/fixes/user_update_from_import_location_in_assets
Fixes Asset location doesn't change when assigned user's location change via importer
2022-06-14 11:44:26 -07:00
snipe 1806dacb9d Bumped hash on master to 6.0.4
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2022-06-13 23:59:43 -07:00
snipe abb7f23ca5 Bumped version to 6.0.4
Signed-off-by: snipe <snipe@snipe.net>
2022-06-13 23:58:53 -07:00
snipe b448c89655 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2022-06-13 23:52:48 -07:00
snipe 8857391da7 Merge pull request #11305 from inietov/fixes/trying_to_access_array_offset_on_value_of_type_null
Fixed #11304 Trying to access array offset on value of type null at .../Transformers/AssetsTransformer.php
2022-06-13 23:51:51 -07:00
Ivan Nieto Vivanco 50c008ead5 Adds check in condition that format custom dates 2022-06-14 01:37:15 -05:00
snipe 3e8837dd6e Bumped dev branch to 6.0.3
Signed-off-by: snipe <snipe@snipe.net>
2022-06-13 22:13:18 -07:00
snipe ea1ff1e8bb Bumped version to 6.0.3
Signed-off-by: snipe <snipe@snipe.net>
2022-06-13 22:12:40 -07:00
snipe a7b155108d Merge remote-tracking branch 'origin/develop' 2022-06-13 22:07:13 -07:00
snipe 44c0c1bf0e Merge pull request #11301 from snipe/features/models_view_in_categories
Added models view (and bulk edit) in category detail view
2022-06-13 21:45:43 -07:00
snipe 7cd35a80b6 Updated assets for production
Signed-off-by: snipe <snipe@snipe.net>
2022-06-13 20:52:47 -07:00
snipe e8973f08b5 Added a back button
Signed-off-by: snipe <snipe@snipe.net>
2022-06-13 20:47:35 -07:00
snipe dd9c9520fb Correctly filter by category_id
Signed-off-by: snipe <snipe@snipe.net>
2022-06-13 20:42:21 -07:00
snipe aec033d8d2 Use better phrasing for tab
Signed-off-by: snipe <snipe@snipe.net>
2022-06-13 20:33:37 -07:00
snipe 5496b62b33 Split categories into two tabs if the type = asset
Signed-off-by: snipe <snipe@snipe.net>
2022-06-13 20:30:50 -07:00
snipe e393e2eb4b Fixed issue in BS tables where uncheck-all then checking a few would not uncheck properly
Signed-off-by: snipe <snipe@snipe.net>
2022-06-13 20:30:35 -07:00
snipe 10781a6e4b Use new bulk edit partial
Signed-off-by: snipe <snipe@snipe.net>
2022-06-13 20:29:17 -07:00
snipe 5a86004081 Created new models bulk edit partial
Signed-off-by: snipe <snipe@snipe.net>
2022-06-13 20:29:08 -07:00
snipe 91ade1f33e Merge remote-tracking branch 'origin/develop' 2022-06-13 20:02:52 -07:00
snipe eaecf8137a Updated assets for develop
Signed-off-by: snipe <snipe@snipe.net>
2022-06-13 19:52:27 -07:00
snipe 92bb8fac32 Removed log statement
Signed-off-by: snipe <snipe@snipe.net>
2022-06-13 19:49:14 -07:00
snipe d4a7811078 Merge pull request #11282 from Godmartinz/new_Yellow_skin
redone none dark mode yellow skin
2022-06-13 19:48:24 -07:00
snipe cb8dbcc172 Merge pull request #11281 from Godmartinz/chore_dark_mode_color_clean_up
cleans up dark modes
2022-06-13 19:48:15 -07:00
snipe 495e68d23c Merge pull request #11258 from Godmartinz/bug/sc-19123/link-colors-slightly-different-settings
Fixed colors in light color skins
2022-06-13 19:48:05 -07:00
snipe 20a0c4e3b5 Merge pull request #11272 from inietov/fixes/date_localization_in_customfields
Fixes #8143 Date localization not working on custom fields
2022-06-13 19:47:20 -07:00
snipe 4d773829f8 Merge pull request #10988 from bestlong/bestlong-patch-1
Ensure schedule analysis job never runs on forked repos
2022-06-13 19:45:36 -07:00
snipe bcb9804be8 Added a little more context to mail template
Signed-off-by: snipe <snipe@snipe.net>
2022-06-13 19:44:18 -07:00
snipe 5e59fa2598 Default to $snipeSettings->site_name
Signed-off-by: snipe <snipe@snipe.net>
2022-06-13 19:29:46 -07:00
snipe 6ea722d41e Merge pull request #11271 from inietov/fixes/bulk_delete_not_checking_assignedto_type
Fix typo in language files
2022-06-13 19:24:08 -07:00
snipe 66346684a9 Merge pull request #11288 from snipe/fixes/set_crons_as_app_user_in_installer
Fixes - set crons as app user in installer
2022-06-13 19:18:55 -07:00
snipe 9731a31cb6 Merge remote-tracking branch 'origin/develop' 2022-06-13 18:37:18 -07:00
snipe ef3e016667 Merge pull request #11300 from snipe/fixes/fa_map_icon_in_chrome
Fixed font-awesome leading class
2022-06-13 18:37:04 -07:00
snipe 93e4d23143 Changed font-awesome leading class
Signed-off-by: snipe <snipe@snipe.net>
2022-06-13 18:36:13 -07:00
snipe 0153a37cd7 Merge pull request #11264 from snipe/fixes/set_default_ldap_version
Fixed default ldap version if not specified
2022-06-13 17:14:57 -07:00
snipe cce5846018 Squashed commit of the following:
commit a070f7cd5e
Merge: 166f52630 4c1104147
Author: snipe <snipe@snipe.net>
Date:   Thu Jun 9 17:23:05 2022 -0700

    Merge pull request #11291 from snipe/fixes/regression_missing_restore_command

    Fixed regression: missing restore option for assets via API

commit 4c11041477
Author: snipe <snipe@snipe.net>
Date:   Thu Jun 9 17:17:38 2022 -0700

    Fixed regression: missing restore option for assets via API

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

Signed-off-by: snipe <snipe@snipe.net>
2022-06-09 17:23:50 -07:00
snipe a070f7cd5e Merge pull request #11291 from snipe/fixes/regression_missing_restore_command
Fixed regression: missing restore option for assets via API
2022-06-09 17:23:05 -07:00
snipe 4c11041477 Fixed regression: missing restore option for assets via API
Signed-off-by: snipe <snipe@snipe.net>
2022-06-09 17:17:38 -07:00
snipe 166f526302 Merge pull request #11290 from inietov/fixes/asset_observer_fails_checkout_on_creating
Fixes observer fails when creating and assigning a new asset
2022-06-09 16:13:12 -07:00
Ivan Nieto Vivanco f8718ffc1e Fixes observer fails when creating and assigning asset 2022-06-09 18:08:04 -05:00
snipe 31e4d3b725 Added second run_as_app_user
Signed-off-by: snipe <snipe@snipe.net>
2022-06-09 14:31:02 -07:00
snipe a766572a2f Set crons as app user for installer
Signed-off-by: snipe <snipe@snipe.net>
2022-06-09 14:21:38 -07:00
snipe 6a8824a467 Merge pull request #11286 from inietov/fixes/return_element_type_of_customfield
Fixes #11092 Add element type of customfield to API response
2022-06-09 11:40:09 -07:00
Ivan Nieto Vivanco 0c3972d7b7 Add spaces to the code for consistency 2022-06-09 13:02:31 -05:00
Ivan Nieto Vivanco 4a0eb2b3f1 Add element type of customfield to API response 2022-06-09 12:57:20 -05:00
Godfrey M b3559ac74e redone none dark mode yellow skin 2022-06-08 13:59:46 -07:00
Godfrey M 4252bd2348 cleans up dark modes 2022-06-08 13:17:16 -07:00
snipe 728338bfa8 Merge pull request #10824 from inietov/fixes/accessories_consumables_negative_numbers_develop
Fixes Accessories total quantity shows a negative number for develop branch
2022-06-08 10:53:57 -07:00
snipe df8834fd88 Merge pull request #11278 from Godmartinz/bug/sc-19134/possible-missing-wrong-translations-in-ldap
fixes translation references in the users ldap blade
2022-06-08 10:47:03 -07:00
Godfrey M c8bc0eff11 fixes translation references in the users ldap blade 2022-06-08 09:52:55 -07:00
snipe 8b6e869215 Merge pull request #11276 from snipe/fixes/added_bulk_data_attributes_to_manufacturers
Added new JS data attributes for assets in manufacturers
2022-06-08 04:19:38 -07:00
snipe 063893c109 Added new JS data attributes for assets in manufacturers
Signed-off-by: snipe <snipe@snipe.net>
2022-06-08 04:18:05 -07:00
Ivan Nieto Vivanco 44f4f20187 Only fix typo in 'en' file 2022-06-07 19:09:59 -05:00
Ivan Nieto Vivanco 792b18f845 Return language files to previous state 2022-06-07 19:09:03 -05:00
snipe 0671e478cd Merge pull request #11273 from inietov/fixes/eol_without_specified_date_format
Fixes EOL field doesn't have date formatter applied
2022-06-07 17:01:46 -07:00
Ivan Nieto Vivanco d2fc27e21d Add formatted date to EOL field in asset detailed view 2022-06-07 18:22:09 -05:00
Ivan Nieto Vivanco 740f27198f Evaluate if a custom field is a Date to present it with the correct format 2022-06-07 18:00:46 -05:00
Ivan Nieto Vivanco 064f4b3fc6 Fix typo in language files 2022-06-07 16:30:18 -05:00
snipe 5458676ead Default to v3 of LDAP on settings save
Signed-off-by: snipe <snipe@snipe.net>
2022-06-06 21:00:22 -07:00
snipe 8337628323 Set elvis operator to ensure ldap version is 3 if null
Signed-off-by: snipe <snipe@snipe.net>
2022-06-06 20:57:18 -07:00
snipe 7faaa4ce24 Merge pull request #11263 from inietov/fixes/dont_save_update_action_if_nothings_changed
Fixes log update action even if no changes are made to assets [sc-19131]
2022-06-06 20:06:19 -07:00
snipe 9583a72016 Merge pull request #11262 from snipe/fixes/11093_use_true_false_in_custom_fields_fieldsets
Fixed #11093 - Return true/false for custom fields/fieldsets required value in API
2022-06-06 20:04:52 -07:00
snipe e0102ddbf0 Fixes #11093 Return true/false for custom fields/fieldsets required in API
Signed-off-by: snipe <snipe@snipe.net>
2022-06-06 20:03:20 -07:00
Ivan Nieto Vivanco 1030ad9a27 Early returns if no change is made in the Asset so the 'update' action doesn't log 2022-06-06 22:00:05 -05:00
snipe ab8dcdcc40 Merge remote-tracking branch 'origin/master' into develop 2022-06-06 19:35:29 -07:00
snipe 773997a492 Merge pull request #11261 from snipe/features/11255_add_location_2_to_locations_listing
Fixed #11255 - add address 2 field to locations listing
2022-06-06 19:35:07 -07:00
snipe 8333c80b7a Added address2 to column selector for locations listing
Signed-off-by: snipe <snipe@snipe.net>
2022-06-06 19:31:08 -07:00
snipe 96644ab6b9 Merge pull request #11259 from inietov/fixes/history_issues
Fixes some issues in the asset observer
2022-06-06 18:25:05 -07:00
Ivan Nieto Vivanco f977c53ecb Fixes some issues in the asset observer 2022-06-06 19:14:32 -05:00
Godfrey M 8c1843b351 updates colors in light color modes 2022-06-06 11:40:57 -07:00
snipe c9e86ac194 Merge remote-tracking branch 'origin/develop' 2022-06-06 10:23:37 -07:00
snipe f7449921e9 Merge pull request #11253 from snipe/features/nicer_locations_ui
Nicer locations UI
2022-06-06 10:23:04 -07:00
snipe 5f79534f4a Merge remote-tracking branch 'origin/develop' 2022-06-05 22:44:53 -07:00
snipe 3bcd5d94d6 Merge pull request #11254 from snipe/fixes/11224_only_show_possible_options_in_bulk_menu
Fixed  #11224 - only show menu options if the user is allowed
2022-06-05 22:44:26 -07:00
snipe 01348187c8 Fixed #11224 - only show menu options if the user is allowed
Signed-off-by: snipe <snipe@snipe.net>
2022-06-05 22:41:53 -07:00
snipe b26a4ad333 Added missing headers
Signed-off-by: snipe <snipe@snipe.net>
2022-06-05 21:35:57 -07:00
snipe 89f45d3d05 Removed extra console logs and unused variable
Signed-off-by: snipe <snipe@snipe.net>
2022-06-05 21:16:29 -07:00
snipe e83a062eda Use translation string for model editing
Signed-off-by: snipe <snipe@snipe.net>
2022-06-05 21:11:50 -07:00
snipe 1ea667e709 Update views with additional data fields
Signed-off-by: snipe <snipe@snipe.net>
2022-06-05 21:03:56 -07:00
snipe 5326ebd136 Removed toolbar div we weren’t using
Signed-off-by: snipe <snipe@snipe.net>
2022-06-05 21:03:45 -07:00
snipe 4db9892f8c Use partial in overdue audit screen
Signed-off-by: snipe <snipe@snipe.net>
2022-06-05 21:03:12 -07:00
snipe 880828379e Update bulki partials with new values
Signed-off-by: snipe <snipe@snipe.net>
2022-06-05 21:02:51 -07:00
snipe 9b54077409 Additional tweaks to BS tables partial
Signed-off-by: snipe <snipe@snipe.net>
2022-06-05 21:02:19 -07:00
snipe 9f478b51e2 Additional JS tweaking
Signed-off-by: snipe <snipe@snipe.net>
2022-06-05 20:13:51 -07:00
snipe 7c77e03c5a Initial rework of locations display
Signed-off-by: snipe <snipe@snipe.net>
2022-06-05 18:08:15 -07:00
snipe 9d3aed42b7 Add @denzfarid as a contributor 2022-06-05 17:16:58 -07:00
snipe 3dedd51b84 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2022-06-05 17:16:21 -07:00
snipe 711c713ab8 Bumped hash
Signed-off-by: snipe <snipe@snipe.net>
2022-06-05 17:15:29 -07:00
snipe 5bc5e9f108 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	resources/lang/en/admin/locations/general.php
2022-06-05 17:14:31 -07:00
snipe 9770692d07 Merge pull request #11251 from denzfarid/fixes/docker-php-redis-extension
Fixed #10910  : Add php-redis extension
2022-06-05 17:09:39 -07:00
snipe 133da6569b Merge pull request #11252 from snipe/fixes/locations_improvements
Fixes/locations improvements
2022-06-05 17:05:25 -07:00
snipe 985e683896 Small display improvements
Signed-off-by: snipe <snipe@snipe.net>
2022-06-05 16:59:53 -07:00
Raden Farid Nugraha c3698053ea Fixed ( #10910 ) : Add php redis extension 2022-06-06 06:58:07 +07:00
snipe dba06a3a9e Check for valid location before trying to print
Signed-off-by: snipe <snipe@snipe.net>
2022-06-03 16:56:15 -07:00
snipe 07b1062fb2 Better handle API calls to nonexistent users
Signed-off-by: snipe <snipe@snipe.net>
2022-06-03 16:55:23 -07:00
snipe be0933a708 Merge pull request #11249 from snipe/fixes/better_handle_bad_date_values
Fixed crashing on date formatting helper when value is not actually a date
2022-06-03 16:46:09 -07:00
snipe d31f185cce Display the actual value
Signed-off-by: snipe <snipe@snipe.net>
2022-06-03 15:36:52 -07:00
snipe 5901182885 Removed stray character
Signed-off-by: snipe <snipe@snipe.net>
2022-06-03 15:30:34 -07:00
snipe f033aeda83 Fixed typo in comments
Signed-off-by: snipe <snipe@snipe.net>
2022-06-03 15:28:00 -07:00
snipe 53f9e2bc7a Wrap the Carbon method in a try/catch to prevent crashing on bad data
Signed-off-by: snipe <snipe@snipe.net>
2022-06-03 15:25:39 -07:00
snipe 514db05770 Merge remote-tracking branch 'origin/develop' 2022-06-03 13:29:04 -07:00
snipe 7ca617f077 Merge pull request #11246 from snipe/fixes/clearer_placeholder_text_for_ldap
Added explicit “Example:” text in placeholders
2022-06-03 13:28:40 -07:00
snipe 8f5ac5fb55 Removed quotes around filter query
Signed-off-by: snipe <snipe@snipe.net>
2022-06-03 13:01:53 -07:00
snipe 54f828743e Merge remote-tracking branch 'origin/develop' 2022-06-03 12:54:13 -07:00
snipe f519fb747f Merge pull request #11248 from snipe/fixes/corrected_gate_on_assetmodels
Updated Asset Model gate to correctly display the button on view
2022-06-03 12:53:52 -07:00
snipe 36f714e414 Updated Asset Model gate to correctly display the button on view
Signed-off-by: snipe <snipe@snipe.net>
2022-06-03 12:52:53 -07:00
snipe 773c773773 Merge pull request #11247 from snipe/fixes/added_missing_validation_translations
Added the validation strings for user creation password options
2022-06-03 12:03:47 -07:00
snipe 3071a83ae0 Added the validation strings for user creation password options
Signed-off-by: snipe <snipe@snipe.net>
2022-06-03 12:00:56 -07:00
snipe 1c4864a3cc Added explicit “Example:” text in placeholders
Signed-off-by: snipe <snipe@snipe.net>
2022-06-03 11:25:18 -07:00
snipe 50c92d4730 Merge remote-tracking branch 'origin/develop' 2022-06-02 17:09:52 -07:00
snipe f8a0bf6a4b Merge pull request #11244 from snipe/fixes/drop_log_level_to_warn_on_SAML
Dropped log level to warn on SAML error
2022-06-02 17:09:32 -07:00
snipe 910fc08406 Dropped log level to warn on SAML error
Signed-off-by: snipe <snipe@snipe.net>
2022-06-02 17:07:49 -07:00
snipe eebc56d54b Merge remote-tracking branch 'origin/develop' 2022-06-02 16:33:04 -07:00
snipe b5ddc2c85b Merge pull request #11243 from snipe/fixes/fix_diff_time_in_audit_report
Don’t use the formatted date for diff days in audit report
2022-06-02 16:32:46 -07:00
snipe 4e03ebe284 Don’t use the formatted date for diff days in audit report
Signed-off-by: snipe <snipe@snipe.net>
2022-06-02 16:30:26 -07:00
snipe 7577fc61e4 Merge pull request #11235 from Godmartinz/gh_5644-checkout_history_for_accessories
fixed issue with misplaced div
2022-06-01 17:03:23 -07:00
Godfrey M d302675056 fixed a div placement 2022-06-01 16:58:29 -07:00
Godfrey M 5316f41eba fixed a div placement 2022-06-01 16:56:01 -07:00
snipe fa6c463d46 Merge pull request #11046 from Godmartinz/gh_5644-checkout_history_for_accessories
Added history tab to accessories
2022-06-01 12:46:38 -07:00
snipe 23a441e7c8 Merge remote-tracking branch 'origin/develop' 2022-06-01 10:27:50 -07:00
snipe ac993184ee Merge pull request #11233 from snipe/fixes/11232_depreciation_layout
Fixed #11232 - missing closing div
2022-06-01 10:27:25 -07:00
snipe 1dbc1f4aa2 Fixed #11232 - missing closing div
Signed-off-by: snipe <snipe@snipe.net>
2022-06-01 10:26:26 -07:00
Achmad Fienan Rahardianto fe65de1207 implements cookie to maintain display preference 2022-06-01 11:54:05 +07:00
snipe 089704c4f9 Merge remote-tracking branch 'origin/develop' 2022-05-31 14:17:23 -07:00
snipe bb933e5214 Merge pull request #11227 from inietov/fixes/exception_getimagesize
Fixes #11116 Error exception in getimagesize
2022-05-31 14:09:18 -07:00
Ivan Nieto Vivanco eb34cf7917 Evaluates if logo is uploaded before export PDF 2022-05-31 15:59:01 -05:00
snipe 4909cf2a9e Merge pull request #11212 from inietov/fixes/checkout_logs_require_target
Fixes Exception checkout logs require target
2022-05-28 06:12:55 -07:00
Ivan Nieto Vivanco 37f9cca5ec Minor stylistic change 2022-05-28 08:11:13 -05:00
Ivan Nieto Vivanco 72192257f2 Delete a test file 2022-05-26 18:18:13 -05:00
Ivan Nieto Vivanco e0050bc844 Don't let a license to be checked out to a non-existent target 2022-05-26 18:06:53 -05:00
snipe d2d0842737 Merge pull request #11206 from snipe/features/suggest_updating_global_composer
Added a self-update suggestion in the upgrader
2022-05-26 11:30:09 -07:00
snipe fe3b9f9e86 Added a self-update suggestion in the upgrader
Signed-off-by: snipe <snipe@snipe.net>
2022-05-25 19:18:37 -07:00
snipe 0ea6671bfa Merge pull request #11202 from snipe/fixes/livewire_config
Starter Livewire config (for subdirectories)
2022-05-25 17:32:17 -07:00
snipe 9209675d45 Merge pull request #11204 from inietov/fixes/file_uploads_dont_show_in_target_activity_report
Fixes #11193 File Uploads don't show target in Activity report
2022-05-25 17:30:01 -07:00
Ivan Nieto Vivanco 3e44f39f4d Set the new File column as not visible by default 2022-05-25 19:19:25 -05:00
Ivan Nieto Vivanco 1f6ab340a6 Give a more descriptive name to variable 2022-05-25 18:53:17 -05:00
Ivan Nieto Vivanco f208869aff Add column to show filenames in Activity Report if the log action is 'uploaded' 2022-05-25 18:50:32 -05:00
snipe c031686825 Fixed path
Signed-off-by: snipe <snipe@snipe.net>
2022-05-25 15:12:38 -07:00
snipe 791c39d977 Starter Livewire config (for subdirectories)
Signed-off-by: snipe <snipe@snipe.net>
2022-05-25 15:10:20 -07:00
snipe aac432b00c Merge remote-tracking branch 'origin/develop' 2022-05-24 20:53:36 -07:00
snipe 2b5b3273e2 Strip quote marks from env_values
Signed-off-by: snipe <snipe@snipe.net>
2022-05-24 20:52:03 -07:00
snipe 4f57eebf24 Merge remote-tracking branch 'origin/develop' 2022-05-24 20:10:13 -07:00
snipe 0c9a1a8922 Merge pull request #11198 from snipe/features/check_for_dev_v_prod_in_updater
Check for APP_ENV in upgrader
2022-05-24 20:09:43 -07:00
snipe fa2a3e4b03 Added a line break
Signed-off-by: snipe <snipe@snipe.net>
2022-05-24 20:08:04 -07:00
snipe 94a337fc9e Rearrange a few thing
Signed-off-by: snipe <snipe@snipe.net>
2022-05-24 20:03:10 -07:00
snipe 8d9cdf9c15 Check for APP_ENV
Signed-off-by: snipe <snipe@snipe.net>
2022-05-24 19:56:42 -07:00
snipe fb8d52d599 Merge remote-tracking branch 'origin/develop' 2022-05-24 19:37:34 -07:00
snipe 070c36ffe6 Merge pull request #11197 from uberbrady/improve_ldap_php_81
Fixes #11119 - Downgraded/Removed log statements
2022-05-24 19:37:04 -07:00
snipe 5db1c50816 Merge pull request #11196 from snipe/fearures/env_checker_in_upgrader
Added a simple .env checker into the upgrader
2022-05-24 19:36:21 -07:00
snipe 43e97ea6ea Make printout more consistent
Signed-off-by: snipe <snipe@snipe.net>
2022-05-24 19:36:01 -07:00
Brady Wetherington 8fdedf9441 Downgraded/Removed log statements 2022-05-24 19:30:22 -07:00
snipe b67ed3eac2 Check for present APP_KEY as well
Signed-off-by: snipe <snipe@snipe.net>
2022-05-24 19:24:03 -07:00
snipe 116ce931ce Fixed path name to backup temp dir
Signed-off-by: snipe <snipe@snipe.net>
2022-05-24 18:44:32 -07:00
snipe 15d0fb4feb Added permissions check
Signed-off-by: snipe <snipe@snipe.net>
2022-05-24 18:40:15 -07:00
snipe 132b164a74 Slightly clarified error text
Signed-off-by: snipe <snipe@snipe.net>
2022-05-24 17:51:46 -07:00
snipe bdbe2c3ac6 Added a simple .env checker into the upgrader
Signed-off-by: snipe <snipe@snipe.net>
2022-05-24 17:43:23 -07:00
snipe 2db6cf85a7 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2022-05-24 15:10:46 -07:00
snipe 5be7dee3d3 Updated language strings
Signed-off-by: snipe <snipe@snipe.net>
2022-05-24 15:07:14 -07:00
snipe 72799973e7 Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2022-05-24 14:41:44 -07:00
snipe d8a8e03bf6 Nicer styling
Signed-off-by: snipe <snipe@snipe.net>
2022-05-24 14:39:01 -07:00
snipe a243823e5e Merge pull request #11190 from inietov/fixes/requested_assets_models_workflow
Adjust requested assets and models workflow a little bit.
2022-05-24 14:31:40 -07:00
Ivan Nieto Vivanco a4cf601c98 Remove extra tag and other stylistic changes 2022-05-24 16:27:55 -05:00
Ivan Nieto Vivanco 1e3c0d597e Use @can view directive instead of @if superadmin 2022-05-24 15:53:26 -05:00
snipe 91822d2e45 Use shorter helper config method
Signed-off-by: snipe <snipe@snipe.net>
2022-05-24 13:26:29 -07:00
snipe 43c5b412ca Merge remote-tracking branch 'origin/develop' 2022-05-24 13:17:39 -07:00
snipe 08ff71aae3 Merge pull request #11192 from snipe/fixes/typo_on_maintenance_screen
Fixed typo on maintenance screen
2022-05-24 13:16:50 -07:00
snipe 5d83516659 Fixed typoe on maintenance screen
Signed-off-by: snipe <snipe@snipe.net>
2022-05-24 13:15:01 -07:00
snipe f39005d295 Merge remote-tracking branch 'origin/develop' 2022-05-24 13:13:21 -07:00
snipe 0e6c82776a Merge pull request #11191 from snipe/fixes/corrected_activated_language_in_bulk_edit
Updated language strings from activated to able to login
2022-05-24 13:13:02 -07:00
snipe 67616dbcf4 Updated language strings from activated to able to login
Signed-off-by: snipe <snipe@snipe.net>
2022-05-24 13:12:02 -07:00
snipe 5881eef2c6 Merge remote-tracking branch 'origin/develop' 2022-05-24 13:01:16 -07:00
snipe 4839985f38 Added forced space after admin/superadmin badge
Signed-off-by: snipe <snipe@snipe.net>
2022-05-24 12:59:36 -07:00
Ivan Nieto Vivanco aa841a4674 Check permission before show links or not in requestable asset models view 2022-05-24 14:40:32 -05:00
Ivan Nieto Vivanco 6d1de73cad Fixes some html structure in the requested assets view 2022-05-24 14:06:05 -05:00
Ivan Nieto Vivanco e0b64a4879 Fixes constraint violation when ordering some columns 2022-05-24 14:00:23 -05:00
Ivan Nieto Vivanco 0a6626891e Add links to requestable Models' name 2022-05-24 13:36:13 -05:00
snipe 2ec7644a33 Merge remote-tracking branch 'origin/develop' 2022-05-24 10:49:13 -07:00
snipe 810578ff5d Merge pull request #11189 from snipe/fixes/show_username_on_user_view_if_not_admin
Fixed bug where username wasn’t showing for regular users
2022-05-24 10:48:55 -07:00
snipe 64eafb062e Fixed bug where username wasn’t showing for regular users
Signed-off-by: snipe <snipe@snipe.net>
2022-05-24 10:48:02 -07:00
snipe ad56928d04 Merge remote-tracking branch 'origin/develop' 2022-05-23 20:35:40 -07:00
snipe 30583f920d Merge pull request #11184 from uberbrady/fix_google_ldap_rebased
Google client-side TLS auth works better with null as context(?)
2022-05-23 20:35:15 -07:00
Brady Wetherington 5130a86854 Google client-side TLS auth works better with null as context(?) 2022-05-23 20:31:43 -07:00
snipe e4e32307de Merge remote-tracking branch 'origin/develop' 2022-05-23 20:15:33 -07:00
snipe e34ea32a5e Fixed translation styring reference
Signed-off-by: snipe <snipe@snipe.net>
2022-05-23 20:15:22 -07:00
snipe b8e6df545a Bumped hash
Signed-off-by: snipe <snipe@snipe.net>
2022-05-23 18:55:57 -07:00
snipe 90a4ce5723 Merge remote-tracking branch 'origin/develop' 2022-05-23 18:54:40 -07:00
snipe 8333089278 Merge pull request #11172 from snipe/rebased_added_gitkeep_to_to_eula_pdfs
Accept asset/accessory improvements and fixes
2022-05-23 12:59:01 -07:00
snipe 70344cc02e Merge pull request #11149 from Godmartinz/gh11129_setting_disclosure_arrow
Fixed #11129 - settings treeview won't stay active.
2022-05-23 12:55:11 -07:00
Godfrey M 4adb990a5d removed line breaks and deadspace 2022-05-23 09:37:20 -07:00
Godfrey M 160a147a58 removed line breaks and deadspace 2022-05-23 09:35:19 -07:00
snipe bd384d3f10 Small formatting fixes
Signed-off-by: snipe <snipe@snipe.net>
2022-05-19 17:55:59 -07:00
snipe ad8143b0bd Added comments
Signed-off-by: snipe <snipe@snipe.net>
2022-05-19 17:55:59 -07:00
snipe f439970e7a Fixed typo
Signed-off-by: snipe <snipe@snipe.net>
2022-05-19 17:55:59 -07:00
snipe 625f120813 Removed unused cases
Signed-off-by: snipe <snipe@snipe.net>
2022-05-19 17:55:59 -07:00
snipe a37a576ee5 FIxed translation string
Signed-off-by: snipe <snipe@snipe.net>
2022-05-19 17:55:59 -07:00
snipe 2bd0679a81 A few more tweaks to PDFs
Signed-off-by: snipe <snipe@snipe.net>
2022-05-19 17:55:59 -07:00
snipe b7eb72fe49 Rough refactor of the acceptance controller
Signed-off-by: snipe <snipe@snipe.net>
2022-05-19 17:55:59 -07:00
snipe afb3843fad Added sig and filename to acceptedCheckout method
Signed-off-by: snipe <snipe@snipe.net>
2022-05-19 17:55:59 -07:00
snipe 8e85d316c9 Removed stored_eula_file from API transformer
Signed-off-by: snipe <snipe@snipe.net>
2022-05-19 17:55:59 -07:00
snipe ebd3c11129 Added singleton
Signed-off-by: snipe <snipe@snipe.net>
2022-05-19 17:55:59 -07:00
snipe 75acb0f28a Added sig and eula pdf to checkout_acceptance
Signed-off-by: snipe <snipe@snipe.net>
2022-05-19 17:55:59 -07:00
snipe eb5f33e815 Removed logging statement
Signed-off-by: snipe <snipe@snipe.net>
2022-05-19 17:55:59 -07:00
snipe 8c64e7359a Added signature column, removed stored_eula_file column
Signed-off-by: snipe <snipe@snipe.net>
2022-05-19 17:55:59 -07:00
snipe 14495cd1da Nicer PDF display
Signed-off-by: snipe <snipe@snipe.net>
2022-05-19 17:55:59 -07:00
snipe 93eba43b76 Removed trailing slash from route
Signed-off-by: snipe <snipe@snipe.net>
2022-05-19 17:55:59 -07:00
snipe adbac82c30 Removed stored_eula_file from actionlog
Signed-off-by: snipe <snipe@snipe.net>
2022-05-19 17:55:59 -07:00
snipe e467ce912b Added some debugging and comments
Signed-off-by: snipe <snipe@snipe.net>
2022-05-19 17:55:59 -07:00
snipe 4eab5fd075 Removed older comments
Signed-off-by: snipe <snipe@snipe.net>
2022-05-19 17:55:59 -07:00
snipe d0e8a4ca09 Added some comments for clarity
Signed-off-by: snipe <snipe@snipe.net>
2022-05-19 17:55:59 -07:00
snipe bcd0671213 Migration to drop stored_eula_column
It’s extraneous, since we already have a file field in the action_logs, and we already store the stored_eula_file in checkout_acceptances.

Signed-off-by: snipe <snipe@snipe.net>
2022-05-19 17:55:59 -07:00
snipe 266a9e5328 Removed stored_eula_file from controller
Signed-off-by: snipe <snipe@snipe.net>
2022-05-19 17:55:59 -07:00
snipe a37fbe6abf Merge pull request #11171 from inietov/fixes/checkout_date_missing_in_mail_when_importing_assets
Fixes Checkout date missing in asset delivery mail
2022-05-19 15:49:43 -07:00
Ivan Nieto Vivanco 52901f50eb Add date to checkout action when importing assets 2022-05-19 17:38:10 -05:00
Ivan Nieto Vivanco 340c59969c Add query to update assigned assets location when importing users 2022-05-19 13:34:50 -05:00
snipe 8706b6d8a9 Merge pull request #11167 from inietov/fixes/error_500_on_import_page
Fixes #9019 Import page returns error 500
2022-05-19 10:50:59 -07:00
Ivan Nieto Vivanco 5d29f77d60 Initialize result variable so return don't crash 2022-05-19 12:47:12 -05:00
snipe 61a6c83418 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/css/dist/skins/skin-black.css
#	public/css/dist/skins/skin-black.min.css
#	public/css/dist/skins/skin-blue.css
#	public/css/dist/skins/skin-blue.min.css
#	public/css/dist/skins/skin-green.css
#	public/css/dist/skins/skin-green.min.css
#	public/css/dist/skins/skin-orange.css
#	public/css/dist/skins/skin-orange.min.css
#	public/css/dist/skins/skin-purple.css
#	public/css/dist/skins/skin-purple.min.css
#	public/css/dist/skins/skin-red.css
#	public/css/dist/skins/skin-red.min.css
#	public/css/dist/skins/skin-yellow.css
#	public/css/dist/skins/skin-yellow.min.css
#	public/mix-manifest.json
2022-05-18 17:21:32 -07:00
snipe deda1c2fd6 Merge pull request #11161 from snipe/fixes/corrects_retagging_script
Small fixes for asset tag regeneration script
2022-05-18 17:19:40 -07:00
snipe 4669bb54fe Small fixes for asset tag regeneration script
Signed-off-by: snipe <snipe@snipe.net>
2022-05-18 17:14:22 -07:00
snipe 319eae7810 Recompiled dev assets
Signed-off-by: snipe <snipe@snipe.net>
2022-05-18 16:21:04 -07:00
snipe 8449b5ca1e Merge pull request #11160 from uberbrady/improve_default_custom_field_value_on_asset_create
Fixed: #11098 - Smartly overwrite fields with default values for custom fields
2022-05-18 16:12:12 -07:00
Brady Wetherington e4b24e17f3 Improve comments because the logic is complicated and unintuitive 2022-05-18 16:06:39 -07:00
Brady Wetherington 981741062b Try to intelligently overwrite fields with default values for custom field 2022-05-18 15:51:32 -07:00
snipe a55adfc0a1 Merge pull request #11152 from Godmartinz/link_inconsistentcies
Thanks!
2022-05-18 15:45:30 -07:00
snipe f609146c29 Corrected field name
Signed-off-by: snipe <snipe@snipe.net>
2022-05-18 15:37:10 -07:00
snipe 891009dc67 Nicer formatting for buttons in bulk user edit
Signed-off-by: snipe <snipe@snipe.net>
2022-05-18 15:35:57 -07:00
Godfrey M ab23e04c65 re-adds Request::is to setting categories 2022-05-18 14:33:41 -07:00
Godfrey M 877b1bd0a3 re-adds Request::is to setting categories 2022-05-18 14:31:03 -07:00
snipe c0d352dd7d Merge remote-tracking branch 'origin/develop' 2022-05-18 14:17:51 -07:00
snipe bef895eaf4 Merge pull request #11158 from snipe/fixes/perform_db_migrate_on_restore
Run migrations after restore
2022-05-18 14:17:21 -07:00
snipe 014a32b050 Run migrations after restore
Signed-off-by: snipe <snipe@snipe.net>
2022-05-18 14:12:17 -07:00
snipe 937472feb0 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
2022-05-18 13:37:31 -07:00
snipe f14a4d3bc7 Recompiled dev assets
Signed-off-by: snipe <snipe@snipe.net>
2022-05-18 13:35:38 -07:00
snipe 9e9d371e1c Merge pull request #11157 from uberbrady/fix_select2_autofocus
Downgrade jQuery to 3.5.1 from 3.6.0 to re-enable select2 autofocus
2022-05-18 13:34:22 -07:00
Brady Wetherington 9e2bcfe168 Downgrade jQuery to 3.5.1 from 3.6.0 to re-enable select2 autofocus 2022-05-18 13:24:02 -07:00
Godfrey M eaeb74c576 readded comment 2022-05-18 13:13:38 -07:00
Godfrey M 23891054dc removed dead space and unused namespace 2022-05-18 13:11:20 -07:00
Godfrey M cfc4c58da3 fixes the Settings Tree menu to remain active when opened 2022-05-18 13:06:06 -07:00
snipe 5f187f71c8 Merge remote-tracking branch 'origin/develop' 2022-05-18 13:05:47 -07:00
snipe b2250ecb7a Merge pull request #11156 from inietov/fixes/error_500_on_unaccepeted_assets_report
Fixes error 500 on Unaccepted Assets Report
2022-05-18 13:04:54 -07:00
Ivan Nieto Vivanco 1453b36484 Add filter to only get Assets for the unaccepted assets report 2022-05-18 14:46:48 -05:00
snipe 4b21d9e7f4 Rebuild production assets
Signed-off-by: snipe <snipe@snipe.net>
2022-05-18 11:13:18 -07:00
snipe 4644f1479b Merge pull request #11154 from inietov/fixes/username_required_on_import
Fixes Username required on import process
2022-05-18 11:12:07 -07:00
snipe 3bf2328db2 Regenerated dev assets
Signed-off-by: snipe <snipe@snipe.net>
2022-05-18 11:11:34 -07:00
snipe 7d637eaa5a Merge pull request #11153 from Godmartinz/gh11146_license_detail_formatting
updated less files for license details to adhere to dark skin themes
2022-05-18 11:09:26 -07:00
Ivan Nieto Vivanco 32111a863b Call User::generateFormattedNameFromFullName() in the UserImporter 2022-05-18 13:02:44 -05:00
Godfrey M 0ed59753da updated less files for license details to adhere to dark skin themes 2022-05-18 10:55:57 -07:00
Godfrey M 75f5f3a0a8 fixes inconsistencies with links styling 2022-05-18 09:37:53 -07:00
Godfrey M 07679aa376 settings treeview won't stay active. still experimenting with potential solutions 2022-05-18 08:40:37 -07:00
snipe b7b21689f2 Merge remote-tracking branch 'origin/develop' 2022-05-18 04:25:23 -07:00
snipe b426fa352e Merge pull request #11147 from inietov/fixes/argument_passed_to_ItemImportRequest_is_null
FixesArgument 1 passed to App\Http\Requests\ItemImportRequest::import() must be an instance of App\Models\Import, null given
2022-05-18 04:24:46 -07:00
Ivan Nieto Vivanco a771984619 Add an early return if for some reason the import record is not found 2022-05-18 06:15:46 -05:00
snipe 71828d5461 One more trim…. sigh..
Signed-off-by: snipe <snipe@snipe.net>
2022-05-18 03:53:42 -07:00
snipe d9817ec696 Added a trim
Signed-off-by: snipe <snipe@snipe.net>
2022-05-18 03:51:53 -07:00
snipe 33ded3f18a More debugging
Signed-off-by: snipe <snipe@snipe.net>
2022-05-18 03:48:09 -07:00
snipe 004d567253 Added some debugging
Signed-off-by: snipe <snipe@snipe.net>
2022-05-18 03:31:00 -07:00
snipe e2fd5199c3 Merge remote-tracking branch 'origin/develop' 2022-05-18 02:43:14 -07:00
snipe b7b3b1a776 Merge pull request #11144 from snipe/fixes/add_spinner_to_backup_upload_icon
Added spinner onClick for file upload button on backups
2022-05-18 02:42:40 -07:00
snipe 4078e4e323 Added spinner onClick for file upload button on backups
Signed-off-by: snipe <snipe@snipe.net>
2022-05-18 02:40:32 -07:00
snipe 64d457425e Merge remote-tracking branch 'origin/develop' 2022-05-18 01:06:53 -07:00
snipe 524ef8261b Merge pull request #11142 from snipe/fixes/11141_fixed_accessories_api_endpoint
Fixed #11141 - accessories endpoint missing from API
2022-05-18 01:06:29 -07:00
snipe 344dcc10c1 Fixed #11141 - accessories endpoint missing from API
Signed-off-by: snipe <snipe@snipe.net>
2022-05-18 01:04:50 -07:00
snipe 2ad97ca040 Merge remote-tracking branch 'origin/develop' 2022-05-18 00:59:33 -07:00
snipe 7880e15672 Merge pull request #11140 from snipe/fixes/11120_textarea_on_fieldset
Fixed #11120 - custom fields not showing when textarea is present as field type
2022-05-18 00:59:13 -07:00
snipe ceffbb950f Fixed #11120 - custom fields not showing when textarea is present as field type
Signed-off-by: snipe <snipe@snipe.net>
2022-05-18 00:47:22 -07:00
snipe b941ea6950 Merge remote-tracking branch 'origin/develop' 2022-05-17 20:07:41 -07:00
snipe 54c1659210 Merge pull request #11139 from uberbrady/reduce_saml_debugging
Reduce saml debugging
2022-05-17 20:07:09 -07:00
Brady Wetherington b4a0d33ba8 Reduce logging further; we know the main error condition now 2022-05-17 19:57:42 -07:00
Brady Wetherington 4e65a8d755 Reduce SAML debugging output to actual error conditions 2022-05-17 19:54:14 -07:00
snipe bf028adcc3 Updated production assets
Signed-off-by: snipe <snipe@snipe.net>
2022-05-17 19:33:50 -07:00
snipe 137b558bef Merge pull request #11138 from snipe/fixes/updated_packages
Bumped packages
2022-05-17 19:32:18 -07:00
snipe be5be7a8b9 Bumped packages
Signed-off-by: snipe <snipe@snipe.net>
2022-05-17 19:30:57 -07:00
snipe 2b3a1ee120 Merge pull request #11137 from snipe/fixes/removed_weird_file_in_upgrader
Delete vendor/symfony/translation/TranslatorInterface.php in upgrader
2022-05-17 19:13:20 -07:00
snipe d316a3f044 Added trailing comma per convention
Signed-off-by: snipe <snipe@snipe.net>
2022-05-17 19:13:07 -07:00
snipe 105750bfde Delete vendor/symfony/translation/TranslatorInterface.php in upgrader
Signed-off-by: snipe <snipe@snipe.net>
2022-05-17 19:11:03 -07:00
snipe 3e34027ae0 Merge pull request #11136 from snipe/fixes/new_maintenance_page
Fixed #11124 - updated maintenance page
2022-05-17 19:03:54 -07:00
snipe 0f9559c1ff Fixed #11124 - updated maintenance page
Signed-off-by: snipe <snipe@snipe.net>
2022-05-17 19:01:37 -07:00
snipe 11db243514 Merge pull request #11135 from uberbrady/improve_restore_erroring
Do some better erroring if you can't launch the mysql binary
2022-05-17 18:16:40 -07:00
Brady Wetherington d391980b06 Do some better erroring if you can't launch the mysql binary 2022-05-17 17:01:23 -07:00
snipe a8eb138ae0 Merge pull request #11133 from inietov/fixes/backup_createdat_time_incorrect
Fixes #11096 Backup created_at time is incorrect
2022-05-17 14:39:19 -07:00
Ivan Nieto Vivanco 72493d54aa Show the date and time as the user select in their settings 2022-05-17 16:36:05 -05:00
Ivan Nieto Vivanco 91c7a89f93 Change to use the date() function instead of Helper::getFormattedDateObject() 2022-05-17 16:24:52 -05:00
snipe 11f540daaf Added debug line
Signed-off-by: snipe <snipe@snipe.net>
2022-05-17 09:41:35 -07:00
snipe 700b4ef058 Merge pull request #11127 from trav-c/bugfix/issue-11126-custom-css-encoding
Fixed #11126: don't entitise custom CSS on the labels view
2022-05-17 07:22:21 -07:00
Travers Carter 1fc0adf7b7 Fixed #11126: don't entitise custom CSS on the labels view 2022-05-18 00:16:18 +10:00
snipe 58875d5606 Added gitgnore to eula-pdfs
Signed-off-by: snipe <snipe@snipe.net>
2022-05-17 04:28:18 -07:00
snipe 0dfc98a493 Force db:wipe
Signed-off-by: snipe <snipe@snipe.net>
2022-05-17 04:27:48 -07:00
snipe 15a1db480a Merge pull request #11115 from snipe/fixes/update_constraints_to_php82
Update constraints to allow up to 8.2
2022-05-16 17:42:50 -07:00
snipe 3dc4f56fb4 Update constraints to allow up to 8.2
Signed-off-by: snipe <snipe@snipe.net>
2022-05-16 17:23:41 -07:00
snipe 7da8ec8448 Merge remote-tracking branch 'origin/develop' 2022-05-16 17:02:54 -07:00
snipe a973c0626e Merge pull request #11114 from uberbrady/bad_header_label_for_size_in_backups
We inadvertently used the wrong label for one of the headers
2022-05-16 17:02:31 -07:00
Brady Wetherington 213d990e47 We inadvertently used the wrong label for one of the headers on the backups page 2022-05-16 17:00:22 -07:00
snipe a5fbfdbab4 Merge remote-tracking branch 'origin/develop' 2022-05-16 16:51:46 -07:00
snipe b705878318 Merge pull request #11113 from snipe/fixes/11112_correct_formatter_for_locations
Fixed #11112 - use correct formatter for locations on dashboard
2022-05-16 16:51:22 -07:00
snipe 925529923a Fixed #11112 - use correct formatter for locations on dashboard
Signed-off-by: snipe <snipe@snipe.net>
2022-05-16 16:50:47 -07:00
snipe 13ce7513f0 Merge remote-tracking branch 'origin/develop' 2022-05-16 15:59:54 -07:00
snipe 7a1b17ff6a Backslash log:: (we shouldn’t have to do this tho?)
Signed-off-by: snipe <snipe@snipe.net>
2022-05-16 15:59:41 -07:00
Godfrey M 8ebe64e630 fixes final visual issue 2022-05-11 12:13:36 -07:00
Godfrey M c07a244bab fixes 1/2 visual issues, adds history tab to accessories 2022-05-10 11:20:42 -07:00
Shao Yu-Lung (Allen) 8a032ee040 fix type 2022-05-07 22:54:47 +08:00
Shao Yu-Lung (Allen) a835401cb2 skip run schedule analysis job on forked repos 2022-05-07 22:50:01 +08:00
Shao Yu-Lung (Allen) 2cd7c7a357 Ensure analysis job never runs on forked repos 2022-04-28 16:51:53 +08:00
Achmad Fienan Rahardianto dafe353050 Implements #8155 to improve the workflow during asset creation
- adding 2 options to hide optional information
2022-04-23 14:41:38 +07:00
Ivan Nieto Vivanco b5378eff64 Fix several typos 2022-04-05 16:12:31 -05:00
Ivan Nieto Vivanco 570dd09dcd Add validation to Accessories and Consumables to not let the user update the number of items to less than they already have checked out 2022-03-15 17:52:19 -06:00
Ivan Nieto Vivanco 0df9dd8320 Delete a function that is not longer used 2022-03-01 18:59:50 -06:00
Dampfklon 0d49fc3a2e remove unused route, controller functions and view 2022-02-13 12:10:19 +01:00
Dampfklon 43d92bec5b apply translation to view
rearrange eula on top
small design fixes
2022-02-13 12:02:20 +01:00
1239 changed files with 15302 additions and 7010 deletions
+25
View File
@@ -2621,6 +2621,31 @@
"contributions": [
"code"
]
},
{
"login": "denzfarid",
"name": "denzfarid",
"avatar_url": "https://avatars.githubusercontent.com/u/1294403?v=4",
"profile": "https://github.com/denzfarid",
"contributions": []
},
{
"login": "ntbutler-nbcs",
"name": "ntbutler-nbcs",
"avatar_url": "https://avatars.githubusercontent.com/u/94018771?v=4",
"profile": "https://github.com/ntbutler-nbcs",
"contributions": [
"code"
]
},
{
"login": "naveensrinivasan",
"name": "Naveen",
"avatar_url": "https://avatars.githubusercontent.com/u/172697?v=4",
"profile": "https://naveensrinivasan.dev",
"contributions": [
"code"
]
}
]
}
+9 -2
View File
@@ -70,7 +70,8 @@ IMAGE_LIB=gd
MAIL_BACKUP_NOTIFICATION_DRIVER=null
MAIL_BACKUP_NOTIFICATION_ADDRESS=null
BACKUP_ENV=true
ALLOW_BACKUP_DELETE=false
ALLOW_DATA_PURGE=false
# --------------------------------------------
# OPTIONAL: SESSION SETTINGS
@@ -146,7 +147,13 @@ AWS_DEFAULT_REGION=null
# --------------------------------------------
LOGIN_MAX_ATTEMPTS=5
LOGIN_LOCKOUT_DURATION=60
RESET_PASSWORD_LINK_EXPIRES=900
# --------------------------------------------
# OPTIONAL: FORGOTTEN PASSWORD SETTINGS
# --------------------------------------------
RESET_PASSWORD_LINK_EXPIRES=15
PASSWORD_CONFIRM_TIMEOUT=10800
PASSWORD_RESET_MAX_ATTEMPTS_PER_MIN=50
# --------------------------------------------
# OPTIONAL: MISC
+8
View File
@@ -17,8 +17,16 @@ on:
schedule:
- cron: '36 23 * * 3'
permissions:
contents: read
jobs:
codacy-security-scan:
# Ensure schedule job never runs on forked repos. It's only executed for 'snipe/snipe-it'
permissions:
contents: read # for actions/checkout to fetch code
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
if: (github.repository == 'snipe/snipe-it') || ((github.repository != 'snipe/snipe-it') && (github.event_name != 'schedule'))
name: Codacy Security Scan
runs-on: ubuntu-latest
steps:
+3
View File
@@ -15,6 +15,9 @@ on:
pull_request:
permissions:
contents: read
jobs:
docker:
# Ensure this job never runs on forked repos. It's only executed for 'snipe/snipe-it'
+3
View File
@@ -15,6 +15,9 @@ on:
pull_request:
permissions:
contents: read
jobs:
docker:
# Ensure this job never runs on forked repos. It's only executed for 'snipe/snipe-it'
+1
View File
@@ -23,6 +23,7 @@ php7.4-xml \
php7.4-mbstring \
php7.4-zip \
php7.4-bcmath \
php7.4-redis \
patch \
curl \
wget \
+1
View File
@@ -27,6 +27,7 @@ RUN apk add --no-cache \
php7-xmlwriter \
php7-xmlreader \
php7-sodium \
php7-redis \
curl \
wget \
vim \
+3 -2
View File
@@ -1,5 +1,5 @@
![Build Status](https://app.chipperci.com/projects/0e5f8979-31eb-4ee6-9abf-050b76ab0383/status/master) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/snipe-it/localized.svg)](https://crowdin.com/project/snipe-it) [![Docker Pulls](https://img.shields.io/docker/pulls/snipe/snipe-it.svg)](https://hub.docker.com/r/snipe/snipe-it/) [![Twitter Follow](https://img.shields.io/twitter/follow/snipeitapp.svg?style=social)](https://twitter.com/snipeitapp) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/553ce52037fc43ea99149785afcfe641)](https://www.codacy.com/app/snipe/snipe-it?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=snipe/snipe-it&amp;utm_campaign=Badge_Grade)
[![All Contributors](https://img.shields.io/badge/all_contributors-286-orange.svg?style=flat-square)](#contributors) [![Discord](https://badgen.net/badge/icon/discord?icon=discord&label)](https://discord.gg/yZFtShAcKk) [![huntr](https://cdn.huntr.dev/huntr_security_badge_mono.svg)](https://huntr.dev)
[![All Contributors](https://img.shields.io/badge/all_contributors-291-orange.svg?style=flat-square)](#contributors) [![Discord](https://badgen.net/badge/icon/discord?icon=discord&label)](https://discord.gg/yZFtShAcKk) [![huntr](https://cdn.huntr.dev/huntr_security_badge_mono.svg)](https://huntr.dev)
## Snipe-IT - Open Source Asset Management System
@@ -131,7 +131,8 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
| [<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/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") |
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
@@ -0,0 +1,97 @@
<?php
namespace App\Console\Commands;
use App\Helpers\Helper;
use Illuminate\Console\Command;
use App\Models\User;
use Laravel\Passport\TokenRepository;
use Illuminate\Contracts\Validation\Factory as ValidationFactory;
use DB;
class GeneratePersonalAccessToken extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'snipeit:make-api-key
{--user_id= : The ID of the user to create the token for.}
{--name= : The name of the new API token}
{--key-only : Only return the value of the API key}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'This console command allows you to generate Personal API tokens to be used with the Snipe-IT JSON REST API on behalf of a user.';
/**
* The token repository implementation.
*
* @var \Laravel\Passport\TokenRepository
*/
protected $tokenRepository;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct(TokenRepository $tokenRepository, ValidationFactory $validation)
{
$this->validation = $validation;
$this->tokenRepository = $tokenRepository;
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$accessTokenName = $this->option('name');
if ($accessTokenName=='') {
$accessTokenName = 'CLI Auth Token';
}
if ($this->option('user_id')=='') {
return $this->error('ERROR: user_id cannot be blank.');
}
if ($user = User::find($this->option('user_id'))) {
$createAccessToken = $user->createToken($accessTokenName)->accessToken;
if ($this->option('key-only')) {
$this->info($createAccessToken);
} else {
$this->warn('Your API Token has been created. Be sure to copy this token now, as it will not be accessible again.');
if ($token = DB::table('oauth_access_tokens')->where('user_id', '=', $user->id)->where('name','=',$accessTokenName)->orderBy('created_at', 'desc')->first()) {
$this->info('API Token ID: '.$token->id);
}
$this->info('API Token User: '.$user->present()->fullName.' ('.$user->username.')');
$this->info('API Token Name: '.$accessTokenName);
$this->info('API Token: '.$createAccessToken);
}
} else {
return $this->error('ERROR: Invalid user. API key was not created.');
}
}
}
+7 -3
View File
@@ -17,7 +17,7 @@ class LdapSync extends Command
*
* @var string
*/
protected $signature = 'snipeit:ldap-sync {--location=} {--location_id=} {--base_dn=} {--summary} {--json_summary}';
protected $signature = 'snipeit:ldap-sync {--location=} {--location_id=} {--base_dn=} {--filter=} {--summary} {--json_summary}';
/**
* The console command description.
@@ -80,7 +80,11 @@ class LdapSync extends Command
} else {
$search_base = null;
}
$results = Ldap::findLdapUsers($search_base);
if ($this->option('filter') != '') {
$results = Ldap::findLdapUsers($search_base, -1, $this->option('filter'));
} else {
$results = Ldap::findLdapUsers($search_base);
}
} catch (\Exception $e) {
if ($this->option('json_summary')) {
$json_summary = ['error' => true, 'error_message' => $e->getMessage(), 'summary' => []];
@@ -109,7 +113,7 @@ class LdapSync extends Command
}
/* Process locations with explicitly defined OUs, if doing a full import. */
if ($this->option('base_dn') == '') {
if ($this->option('base_dn') == '' && $this->option('filter') == '') {
// Retrieve locations with a mapped OU, and sort them from the shallowest to deepest OU (see #3993)
$ldap_ou_locations = Location::where('ldap_ou', '!=', '')->get()->toArray();
$ldap_ou_lengths = [];
+62 -48
View File
@@ -27,6 +27,19 @@ function ip_in_range( $ip, $range ) {
}
// NOTE - this function was shamelessly stolen from this gist: https://gist.github.com/tott/7684443
/**
* Ensure LDAP filters are parentheses-wrapped
*/
function parenthesized_filter($filter)
{
if(substr($filter,0,1) == "(" ) {
return $filter;
} else {
return "(".$filter.")";
}
}
class LdapTroubleshooter extends Command
{
/**
@@ -70,6 +83,47 @@ class LdapTroubleshooter extends Command
}
}
/**
* Clean the results from ldap_get_entries into something useful
* @param array $array
* @return array
*/
public function ldap_results_cleaner ($array) {
$cleaned = [];
for($i = 0; $i < $array['count']; $i++) {
$row = $array[$i];
$clean_row = [];
foreach($row AS $key => $val ) {
$this->debugout("Key is: ".$key);
if($key == "count" || is_int($key) || $key == "dn") {
$this->debugout(" and we're gonna skip it\n");
continue;
}
$this->debugout(" And that seems fine.\n");
if(array_key_exists('count',$val)) {
if($val['count'] == 1) {
$clean_row[$key] = $val[0];
} else {
unset($val['count']); //these counts are annoying
$elements = [];
foreach($val as $entry) {
if(isset($ldap_constants[$entry])) {
$elements[] = $ldap_constants[$entry];
} else {
$elements[] = $entry;
}
}
$clean_row[$key] = $elements;
}
} else {
$clean_row[$key] = $val;
}
}
$cleaned[$i] = $clean_row;
}
return $cleaned;
}
/**
* Execute the console command.
*
@@ -102,16 +156,12 @@ class LdapTroubleshooter extends Command
$output[] = "LDAPTLS_KEY=storage/ldap_client_tls.key";
}
$output[] = "ldapsearch";
$output[] = $settings->ldap_server;
$output[] = "-H ".$settings->ldap_server;
$output[] = "-x";
$output[] = "-b ".escapeshellarg($settings->ldap_basedn);
$output[] = "-D ".escapeshellarg($settings->ldap_uname);
$output[] = "-w ".escapeshellarg(\Crypt::Decrypt($settings->ldap_pword));
if(substr($settings->ldap_filter,0,1) == "(" ) {
$output[] = escapeshellarg($settings->ldap_filter);
} else {
$output[] = escapeshellarg("(".$settings->ldap_filter.")");
}
$output[] = escapeshellarg(parenthesized_filter($settings->ldap_filter));
if($settings->ldap_tls) {
$this->line("# adding STARTTLS option");
$output[] = "-Z";
@@ -290,45 +340,8 @@ class LdapTroubleshooter extends Command
}
$this->debugout("LDAP constants are: ".print_r($ldap_constants,true));
// recursive function that 'cleans' the returned array from ldap_get_entries which are formatted awfully
$cleaner = function ($array) {
$cleaned = [];
for($i = 0; $i < $array['count']; $i++) {
$row = $array[$i];
$clean_row = [];
foreach($row AS $key => $val ) {
$this->debugout("Key is: ".$key);
if($key == "count" || is_int($key) || $key == "dn") {
$this->debugout(" and we're gonna skip it\n");
continue;
}
$this->debugout(" And that seems fine.\n");
if(array_key_exists('count',$val)) {
if($val['count'] == 1) {
$clean_row[$key] = $val[0];
} else {
unset($val['count']); //these counts are annoying
$elements = [];
foreach($val as $entry) {
if(isset($ldap_constants[$entry])) {
$elements[] = $ldap_constants[$entry];
} else {
$elements[] = $entry;
}
}
$clean_row[$key] = $elements;
}
} else {
$clean_row[$key] = $val;
}
}
$cleaned[$i] = $clean_row;
}
return $cleaned;
};
foreach($ldap_urls AS $ldap_url) {
if($this->test_informational_bind($ldap_url[0],$ldap_url[1],$ldap_url[2],$settings->ldap_uname,Crypt::decrypt($settings->ldap_pword))) {
if($this->test_informational_bind($ldap_url[0],$ldap_url[1],$ldap_url[2],$settings->ldap_uname,Crypt::decrypt($settings->ldap_pword),$settings)) {
$this->info("Success getting informational bind!");
} else {
$this->error("Unable to get information from bind.");
@@ -422,9 +435,9 @@ class LdapTroubleshooter extends Command
});
}
public function test_informational_bind($ldap_url, $check_cert, $start_tls, $username, $password)
public function test_informational_bind($ldap_url, $check_cert, $start_tls, $username, $password,$settings)
{
return $this->timed_boolean_execute(function () use ($ldap_url, $check_cert, $start_tls, $username, $password) {
return $this->timed_boolean_execute(function () use ($ldap_url, $check_cert, $start_tls, $username, $password, $settings) {
try { // TODO - copypasta'ed from test_authed_bind
$conn = $this->connect_to_ldap($ldap_url, $check_cert, $start_tls);
$bind_results = ldap_bind($conn, $username, $password);
@@ -435,12 +448,13 @@ class LdapTroubleshooter extends Command
$this->info("SUCCESS - Able to bind to $ldap_url as $username");
$result = ldap_read($conn, '', '(objectClass=*)'/* , ['supportedControl']*/);
$results = ldap_get_entries($conn, $result);
$cleaned_results = $cleaner($results);
$cleaned_results = $this->ldap_results_cleaner($results);
$this->line(print_r($cleaned_results,true));
//okay, great - now how do we display those results? I have no idea.
// I don't see why this throws an Exception for Google LDAP, but I guess we ought to try and catch it?
$this->comment("I guess we're trying to do the ldap search here, but sometimes it takes too long?");
$search_results = ldap_search($conn, $settings->base_dn, $settings->filter);
$this->debugout("Base DN is: ".$settings->ldap_basedn." and filter is: ".parenthesized_filter($settings->ldap_filter));
$search_results = ldap_search($conn, $settings->ldap_basedn, parenthesized_filter($settings->ldap_filter));
$this->info("Printing first 10 results: ");
for($i=0;$i<10;$i++) {
$this->info($search_results[$i]);
+12 -2
View File
@@ -41,10 +41,20 @@ class MergeUsersByUsername extends Command
{
// Get the list of users who have an email address as their username
$users = User::where('username', 'LIKE', '%@%')->whereNull('deleted_at')->get();
$this->info($users->count().' total non-deleted users whose usernames contain a @ symbol.');
foreach ($users as $user) {
$parts = explode('@', $user->username);
$bad_users = User::where('username', '=', $parts[0])->whereNull('deleted_at')->with('assets', 'manager', 'userlog', 'licenses', 'consumables', 'accessories', 'managedLocations')->get();
$parts = explode('@', trim($user->username));
$this->info('Checking against username '.trim($parts[0]).'.');
$bad_users = User::where('username', '=', trim($parts[0]))
->whereNull('deleted_at')
->with('assets', 'manager', 'userlog', 'licenses', 'consumables', 'accessories', 'managedLocations')
->get();
foreach ($bad_users as $bad_user) {
$this->info($bad_user->username.' ('.$bad_user->id.') will be merged into '.$user->username.' ('.$user->id.') ');
@@ -71,22 +71,31 @@ class ReEncodeCustomFieldNames extends Command
*/
$last_part = substr(strrchr($asset_column, '_snipeit_'), 1);
$custom_field_columns[$last_part] = $asset_column;
}
}
foreach ($fields as $field) {
$this->info($field->name.' ('.$field->id.') column should be '.$field->convertUnicodeDbSlug().'');
$this->info($field->name.' ('.$field->id.') column should be '.$field->convertUnicodeDbSlug());
/** The assets table has the column it should have, all is well */
if (\Schema::hasColumn('assets', $field->convertUnicodeDbSlug())) {
$this->info('-- ✓ This field exists - all good');
if ($field->db_column == $field->convertUnicodeDbSlug() && \Schema::hasColumn('assets', $field->convertUnicodeDbSlug())) {
$this->info('-- ✓ This field exists on the assets table and the value for db_column matches in the custom_fields table.');
/**
* There is a mismatch between the fieldname on the assets table and
* what $field->convertUnicodeDbSlug() is *now* expecting.
*/
} else {
$this->warn('-- X Field mismatch: updating... ');
if ($field->db_column != $field->convertUnicodeDbSlug()) {
$this->error('-- ✘ Field mismatch: '.$field->name.' value should be '.$field->convertUnicodeDbSlug().' but is '.$field->db_column.' in the custom_fields table');
} else {
$this->error('-- ✘ Field mismatch: '.$field->name.' column should be '.$field->convertUnicodeDbSlug().' but is '.$custom_field_columns[$field->id].' on the assets table.');
}
/** Make sure the custom_field_columns array has the ID */
if (array_key_exists($field->id, $custom_field_columns)) {
@@ -95,13 +104,19 @@ class ReEncodeCustomFieldNames extends Command
* Update the asset schema to the corrected fieldname that will be recognized by the
* system elsewhere that we use $field->convertUnicodeDbSlug()
*/
$this->info('-- ✓ Updating field from '.$field->db_column.' to '.$field->convertUnicodeDbSlug().' in the assets table');
\Schema::table('assets', function ($table) use ($custom_field_columns, $field) {
$table->renameColumn($custom_field_columns[$field->id], $field->convertUnicodeDbSlug());
});
$this->warn('-- ✓ Field updated from '.$custom_field_columns[$field->id].' to '.$field->convertUnicodeDbSlug());
$this->info('-- ✓ Updating field from '.$field->db_column.' to '.$field->convertUnicodeDbSlug().' in the custom fields table');
$field->db_column = $field->convertUnicodeDbSlug();
$field->save();
} else {
$this->warn('-- X WARNING: There is no field on the assets table ending in '.$field->id.'. This may require more in-depth investigation and may mean the schema was altered manually.');
$this->warn('-- WARNING: There is no field on the assets table ending in '.$field->id.'. This may require more in-depth investigation and may mean the schema was altered manually.');
}
}
+8 -1
View File
@@ -60,7 +60,7 @@ class RegenerateAssetTags extends Command
}
foreach ($total_assets as $asset) {
$start_tag++;
$output['info'][] = 'Asset tag:'.$asset->asset_tag;
$asset->asset_tag = $settings->auto_increment_prefix.$settings->auto_increment_prefix.$start_tag;
@@ -72,8 +72,15 @@ class RegenerateAssetTags extends Command
// Use forceSave here to override model level validation
$asset->forceSave();
$start_tag++;
if ($bar) {
$bar->advance();
}
}
$settings->next_auto_tag_base = Asset::zerofill($start_tag, $settings->zerofill_count);
$settings->save();
$bar->finish();
$this->info("\n");
+20 -10
View File
@@ -227,6 +227,9 @@ class RestoreFromBackup extends Command
return $this->error('Unable to invoke mysql via CLI');
}
stream_set_blocking($pipes[1], false); // use non-blocking reads for stdout
stream_set_blocking($pipes[2], false); // use non-blocking reads for stderr
// $this->info("Stdout says? ".fgets($pipes[1])); //FIXME: I think we might need to set non-blocking mode to use this properly?
// $this->info("Stderr says? ".fgets($pipes[2])); //FIXME: ditto, same.
// should we read stdout?
@@ -247,18 +250,25 @@ class RestoreFromBackup extends Command
}
$bytes_read = 0;
while (($buffer = fgets($sql_contents, self::$buffer_size)) !== false) {
$bytes_read += strlen($buffer);
// \Log::debug("Buffer is: '$buffer'");
$bytes_written = fwrite($pipes[0], $buffer);
try {
while (($buffer = fgets($sql_contents, self::$buffer_size)) !== false) {
$bytes_read += strlen($buffer);
// \Log::debug("Buffer is: '$buffer'");
$bytes_written = fwrite($pipes[0], $buffer);
if ($bytes_written === false) {
$stdout = fgets($pipes[1]);
$this->info($stdout);
$stderr = fgets($pipes[2]);
$this->info($stderr);
return false;
if ($bytes_written === false) {
throw new Exception("Unable to write to pipe");
}
}
} catch (\Exception $e) {
\Log::error("Error during restore!!!! ".$e->getMessage());
$err_out = fgets($pipes[1]);
$err_err = fgets($pipes[2]);
\Log::error("Error OUTPUT: ".$err_out);
$this->info($err_out);
\Log::error("Error ERROR : ".$err_err);
$this->error($err_err);
throw $e;
}
if (!feof($sql_contents) || $bytes_read == 0) {
+1
View File
@@ -24,6 +24,7 @@ class Kernel extends ConsoleKernel
$schedule->command('snipeit:backup')->weekly();
$schedule->command('backup:clean')->daily();
$schedule->command('snipeit:upcoming-audits')->daily();
$schedule->command('auth:clear-resets')->everyFifteenMinutes();
}
/**
+1 -1
View File
@@ -41,7 +41,7 @@ class Handler extends ExceptionHandler
public function report(Throwable $exception)
{
if ($this->shouldReport($exception)) {
Log::error($exception);
\Log::error($exception);
return parent::report($exception);
}
}
+49 -13
View File
@@ -1,7 +1,6 @@
<?php
namespace App\Helpers;
use App\Models\Accessory;
use App\Models\Component;
use App\Models\Consumable;
@@ -842,6 +841,16 @@ class Helper
return preg_replace('/\s+/u', '_', trim($string));
}
/**
* Return an array (or null) of the the raw and formatted date object for easy use in
* the API and the bootstrap table listings.
*
* @param $date
* @param $type
* @param $array
* @return array|string|null
*/
public static function getFormattedDateObject($date, $type = 'datetime', $array = true)
{
if ($date == '') {
@@ -849,21 +858,42 @@ class Helper
}
$settings = Setting::getSettings();
$tmp_date = new \Carbon($date);
if ($type == 'datetime') {
$dt['datetime'] = $tmp_date->format('Y-m-d H:i:s');
$dt['formatted'] = $tmp_date->format($settings->date_display_format.' '.$settings->time_display_format);
} else {
$dt['date'] = $tmp_date->format('Y-m-d');
$dt['formatted'] = $tmp_date->format($settings->date_display_format);
/**
* Wrap this in a try/catch so that if Carbon crashes, for example if the $date value
* isn't actually valid, we don't crash out completely.
*
* While this *shouldn't* typically happen since we validate dates before entering them
* into the database (and we use date/datetime fields for native fields in the system),
* it is a possible scenario that a custom field could be created as an "ANY" field, data gets
* added, and then the custom field format gets edited later. If someone put bad data in the
* database before then - or if they manually edited the field's value - it will crash.
*
*/
try {
$tmp_date = new \Carbon($date);
if ($type == 'datetime') {
$dt['datetime'] = $tmp_date->format('Y-m-d H:i:s');
$dt['formatted'] = $tmp_date->format($settings->date_display_format.' '.$settings->time_display_format);
} else {
$dt['date'] = $tmp_date->format('Y-m-d');
$dt['formatted'] = $tmp_date->format($settings->date_display_format);
}
if ($array == 'true') {
return $dt;
}
return $dt['formatted'];
} catch (\Exception $e) {
\Log::warning($e);
return $date.' (Invalid '.$type.' value.)';
}
if ($array == 'true') {
return $dt;
}
return $dt['formatted'];
}
// Nicked from Drupal :)
@@ -1089,4 +1119,10 @@ class Helper
return $bytes;
}
public static function SettingUrls(){
$settings=['#','fields.index', 'statuslabels.index', 'models.index', 'categories.index', 'manufacturers.index', 'suppliers.index', 'departments.index', 'locations.index', 'companies.index', 'depreciations.index'];
return $settings;
}
}
@@ -9,6 +9,7 @@ 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;
/** This controller handles all actions related to Accessories for
@@ -130,6 +131,17 @@ class AccessoriesController extends Controller
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
}
$min = $accessory->numCheckedOut();
$validator = Validator::make($request->all(), [
"qty" => "required|numeric|min:$min"
]);
if ($validator->fails()) {
return redirect()->back()
->withErrors($validator)
->withInput();
}
$this->authorize($accessory);
// Update the accessory data
@@ -15,6 +15,9 @@ use App\Models\Contracts\Acceptable;
use App\Models\User;
use App\Models\AssetModel;
use App\Models\Accessory;
use App\Models\License;
use App\Models\Component;
use App\Models\Consumable;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
@@ -23,6 +26,7 @@ use Illuminate\Support\Str;
use App\Http\Controllers\SettingsController;
use Barryvdh\DomPDF\Facade\Pdf;
use Carbon\Carbon;
use phpDocumentor\Reflection\Types\Compound;
class AcceptanceController extends Controller
{
@@ -106,87 +110,128 @@ class AcceptanceController extends Controller
Storage::makeDirectory('private_uploads/signatures', 775);
}
$sig_filename = '';
if ($request->filled('signature_output')) {
$sig_filename = 'siglog-'.Str::uuid().'-'.date('Y-m-d-his').'.png';
$data_uri = e($request->input('signature_output'));
$encoded_image = explode(',', $data_uri);
$decoded_image = base64_decode($encoded_image[1]);
$acceptance->stored_eula_file = 'accepted-eula-'.date('Y-m-d-h-i-s').'.pdf';
$path = Storage::put('private_uploads/signatures/'.$sig_filename, (string) $decoded_image);
}
if ($request->input('asset_acceptance') == 'accepted') {
$acceptance->accept($sig_filename);
event(new CheckoutAccepted($acceptance));
$return_msg = trans('admin/users/message.accepted');
} else {
$acceptance->decline($sig_filename);
event(new CheckoutDeclined($acceptance));
$return_msg = trans('admin/users/message.declined');
/**
* Check for the eula-pdfs directory
*/
if (! Storage::exists('private_uploads/eula-pdfs')) {
Storage::makeDirectory('private_uploads/eula-pdfs', 775);
}
$item = $acceptance->checkoutable_type::find($acceptance->checkoutable_id);
$display_model = '';
$pdf_view_route = '';
$pdf_filename = 'accepted-eula-'.date('Y-m-d-h-i-s').'.pdf';
$sig_filename='';
if ($acceptance->checkoutable_type== 'App\Models\Asset') {
$assigned_to = User::find($item->assigned_to);
$asset_model = AssetModel::find($item->model_id);
if ($request->input('asset_acceptance') == 'accepted') {
// The item was accepted, check for a signature
if ($request->filled('signature_output')) {
$sig_filename = 'siglog-'.Str::uuid().'-'.date('Y-m-d-his').'.png';
$data_uri = $request->input('signature_output');
$encoded_image = explode(',', $data_uri);
$decoded_image = base64_decode($encoded_image[1]);
Storage::put('private_uploads/signatures/'.$sig_filename, (string) $decoded_image);
}
// this is horrible
switch($acceptance->checkoutable_type){
case 'App\Models\Asset':
$pdf_view_route ='account.accept.accept-asset-eula';
$asset_model = AssetModel::find($item->model_id);
$display_model = $asset_model->name;
$assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName;
break;
case 'App\Models\Accessory':
$pdf_view_route ='account.accept.accept-accessory-eula';
$accessory = Accessory::find($item->id);
$display_model = $accessory->name;
$assigned_to = User::find($item->assignedTo);
break;
case 'App\Models\LicenseSeat':
$pdf_view_route ='account.accept.accept-license-eula';
$license = License::find($item->license_id);
$display_model = $license->name;
$assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName;
break;
case 'App\Models\Component':
$pdf_view_route ='account.accept.accept-component-eula';
$component = Component::find($item->id);
$display_model = $component->name;
$assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName;
break;
case 'App\Models\Consumable':
$pdf_view_route ='account.accept.accept-consumable-eula';
$consumable = Consumable::find($item->id);
$display_model = $consumable->name;
$assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName;
break;
}
// if ($acceptance->checkoutable_type == 'App\Models\Asset') {
// $pdf_view_route ='account.accept.accept-asset-eula';
// $asset_model = AssetModel::find($item->model_id);
// $display_model = $asset_model->name;
// $assigned_to = User::find($item->assigned_to)->present()->fullName;
//
// } elseif ($acceptance->checkoutable_type== 'App\Models\Accessory') {
// $pdf_view_route ='account.accept.accept-accessory-eula';
// $accessory = Accessory::find($item->id);
// $display_model = $accessory->name;
// $assigned_to = User::find($item->assignedTo);
//
// }
/**
* Gather the data for the PDF. We fire this whether there is a signature required or not,
* since we want the moment-in-time proof of what the EULA was when they accepted it.
*/
$branding_settings = SettingsController::getPDFBranding();
if (is_null($branding_settings->logo)){
$path_logo = "";
} else {
$path_logo = public_path() . '/uploads/' . $branding_settings->logo;
}
$data = [
'item_tag' => $item->asset_tag,
'item_model' => $asset_model->name,
'item_model' => $display_model,
'item_serial' => $item->serial,
'eula' => $item->getEula(),
'check_out_date' => Carbon::parse($acceptance->created_at)->format($branding_settings->date_display_format),
'accepted_date' => Carbon::parse($acceptance->accepted_at)->format($branding_settings->date_display_format),
'assigned_to' => $assigned_to->first_name . ' ' . $assigned_to->last_name,
'assigned_to' => $assigned_to,
'company_name' => $branding_settings->site_name,
'signature' => storage_path() . '/private_uploads/signatures/' . $sig_filename,
'logo' => public_path() . '/uploads/' . $branding_settings->logo,
'signature' => ($sig_filename) ? storage_path() . '/private_uploads/signatures/' . $sig_filename : null,
'logo' => $path_logo,
'date_settings' => $branding_settings->date_display_format,
];
$pdf = Pdf::loadView('account.accept.accept-asset-eula', $data);
Storage::put('private_uploads/eula-pdfs/' . $acceptance->stored_eula_file, $pdf->output());
$a = new Actionlog();
$a->stored_eula = $item->getEula();
$a->stored_eula_file = $acceptance->stored_eula_file;
$a->save();
if ($pdf_view_route!='') {
\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());
}
return redirect()->to('account/accept')->with('success', $return_msg);
$acceptance->accept($sig_filename, $item->getEula(), $pdf_filename);
event(new CheckoutAccepted($acceptance));
$return_msg = trans('admin/users/message.accepted');
} else {
$acceptance->decline($sig_filename);
event(new CheckoutDeclined($acceptance));
$return_msg = trans('admin/users/message.declined');
}
//
$accessory_user= DB::table('checkout_acceptances')->find($acceptance->assigned_to_id);
$assigned_to = User::find($accessory_user->assigned_to_id);
$accessory_model = Accessory::find($item->id);
$branding_settings = SettingsController::getPDFBranding();
$data = [
'item_tag' => $item->model_number,
'item_model' => $accessory_model->name,
'eula' => $item->getEula(),
'check_out_date' => Carbon::parse($acceptance->created_at)->format($branding_settings->date_display_format),
'accepted_date' => Carbon::parse($acceptance->accepted_at)->format($branding_settings->date_display_format),
// 'assigned_by' => self
'assigned_to' => $assigned_to->first_name . ' ' . $assigned_to->last_name,
'company_name' => $branding_settings->site_name,
'signature' => storage_path() . '/private_uploads/signatures/' . $sig_filename,
'logo' => public_path() . '/uploads/' . $branding_settings->logo,
'date_settings' => $branding_settings->date_display_format,
];
$pdf = Pdf::loadView('account.accept.accept-accessory-eula', $data);
Storage::put('private_uploads/eula-pdfs/' . $acceptance->stored_eula_file, $pdf->output());
$a = new Actionlog();
$a->stored_eula = $item->getEula();
$a->stored_eula_file = $acceptance->stored_eula_file;
$a->save();
return redirect()->to('account/accept')->with('success', $return_msg);
}
}
@@ -27,8 +27,7 @@ class AccessoriesController extends Controller
public function index(Request $request)
{
$this->authorize('view', Accessory::class);
$allowed_columns = ['id', 'name', 'model_number', 'eol', 'notes', 'created_at', 'min_amt', 'company_id'];
// 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 =
@@ -35,7 +35,8 @@ class AssetMaintenancesController extends Controller
public function index(Request $request)
{
$this->authorize('view', Asset::class);
$maintenances = AssetMaintenance::with('asset', 'asset.model', 'asset.location', 'supplier', 'asset.company', 'admin');
$maintenances = AssetMaintenance::select('asset_maintenances.*')->with('asset', 'asset.model', 'asset.location', 'supplier', 'asset.company', 'admin');
if ($request->filled('search')) {
$maintenances = $maintenances->TextSearch($request->input('search'));
@@ -45,6 +46,15 @@ class AssetMaintenancesController extends Controller
$maintenances->where('asset_id', '=', $request->input('asset_id'));
}
if ($request->filled('supplier_id')) {
$maintenances->where('supplier_id', '=', $request->input('supplier_id'));
}
if ($request->filled('asset_maintenance_type')) {
$maintenances->where('asset_maintenance_type', '=', $request->input('asset_maintenance_type'));
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($maintenances) && ($request->get('offset') > $maintenances->count())) ? $maintenances->count() : $request->get('offset', 0);
@@ -64,6 +74,7 @@ class AssetMaintenancesController extends Controller
'asset_tag',
'asset_name',
'user_id',
'supplier'
];
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
@@ -72,6 +83,9 @@ class AssetMaintenancesController extends Controller
case 'user_id':
$maintenances = $maintenances->OrderAdmin($order);
break;
case 'supplier':
$maintenances = $maintenances->OrderBySupplier($order);
break;
case 'asset_tag':
$maintenances = $maintenances->OrderByTag($order);
break;
@@ -70,6 +70,10 @@ class AssetModelsController extends Controller
$assetmodels->onlyTrashed();
}
if ($request->filled('category_id')) {
$assetmodels = $assetmodels->where('models.category_id', '=', $request->input('category_id'));
}
if ($request->filled('search')) {
$assetmodels->TextSearch($request->input('search'));
}
+42 -19
View File
@@ -544,11 +544,11 @@ class AssetsController extends Controller
foreach ($model->fieldset->fields as $field) {
// Set the field value based on what was sent in the request
$field_val = $request->input($field->convertUnicodeDbSlug(), null);
$field_val = $request->input($field->db_column, null);
// If input value is null, use custom field's default value
if ($field_val == null) {
\Log::debug('Field value for '.$field->convertUnicodeDbSlug().' is null');
\Log::debug('Field value for '.$field->db_column.' is null');
$field_val = $field->defaultValue($request->get('model_id'));
\Log::debug('Use the default fieldset value of '.$field->defaultValue($request->get('model_id')));
}
@@ -563,13 +563,13 @@ class AssetsController extends Controller
if (($field_val == null) && ($request->has('model_id') != '')) {
$field_val = \Crypt::encrypt($field->defaultValue($request->get('model_id')));
} else {
$field_val = \Crypt::encrypt($request->input($field->convertUnicodeDbSlug()));
$field_val = \Crypt::encrypt($request->input($field->db_column));
}
}
}
$asset->{$field->convertUnicodeDbSlug()} = $field_val;
$asset->{$field->db_column} = $field_val;
}
}
@@ -634,13 +634,13 @@ class AssetsController extends Controller
// Update custom fields
if (($model = AssetModel::find($asset->model_id)) && (isset($model->fieldset))) {
foreach ($model->fieldset->fields as $field) {
if ($request->has($field->convertUnicodeDbSlug())) {
if ($request->has($field->db_column)) {
if ($field->field_encrypted == '1') {
if (Gate::allows('admin')) {
$asset->{$field->convertUnicodeDbSlug()} = \Crypt::encrypt($request->input($field->convertUnicodeDbSlug()));
$asset->{$field->db_column} = \Crypt::encrypt($request->input($field->db_column));
}
} else {
$asset->{$field->convertUnicodeDbSlug()} = $request->input($field->convertUnicodeDbSlug());
$asset->{$field->db_column} = $request->input($field->db_column);
}
}
}
@@ -714,30 +714,53 @@ class AssetsController extends Controller
* @since [v5.1.18]
* @return JsonResponse
*/
public function restore($assetId = null)
public function restore(Request $request, $assetId = null)
{
// Get asset information
$asset = Asset::withTrashed()->find($assetId);
$this->authorize('delete', $asset);
if (isset($asset->id)) {
// Restore the asset
Asset::withTrashed()->where('id', $assetId)->restore();
$logaction = new Actionlog();
$logaction->item_type = Asset::class;
$logaction->item_id = $asset->id;
$logaction->created_at = date("Y-m-d H:i:s");
$logaction->user_id = Auth::user()->id;
$logaction->logaction('restored');
if ($asset->deleted_at=='') {
$message = 'Asset was not deleted. No data was changed.';
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/hardware/message.restore.success')));
} else {
$message = trans('admin/hardware/message.restore.success');
// Restore the asset
Asset::withTrashed()->where('id', $assetId)->restore();
$logaction = new Actionlog();
$logaction->item_type = Asset::class;
$logaction->item_id = $asset->id;
$logaction->created_at = date("Y-m-d H:i:s");
$logaction->user_id = Auth::user()->id;
$logaction->logaction('restored');
}
return response()->json(Helper::formatStandardApiResponse('success', (new AssetsTransformer)->transformAsset($asset, $request), $message));
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
}
/**
* Checkout an asset by its tag.
*
* @author [N. Butler]
* @param string $tag
* @since [v6.0.5]
* @return JsonResponse
*/
public function checkoutByTag(AssetCheckoutRequest $request, $tag)
{
if ($asset = Asset::where('asset_tag', $tag)->first()) {
return $this->checkout($request, $asset->id);
}
return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 200);
}
/**
* Checkout an asset
@@ -849,7 +872,7 @@ class AssetsController extends Controller
$asset->assignedTo()->disassociate($asset);
$asset->accepted = null;
if ($request->filled('name')) {
if ($request->has('name')) {
$asset->name = $request->input('name');
}
@@ -32,6 +32,28 @@ class CategoriesController extends Controller
$categories = $categories->TextSearch($request->input('search'));
}
if ($request->filled('name')) {
$categories->where('name', '=', $request->input('name'));
}
if ($request->filled('category_type')) {
$categories->where('category_type', '=', $request->input('category_type'));
}
if ($request->filled('use_default_eula')) {
$categories->where('use_default_eula', '=', $request->input('use_default_eula'));
}
if ($request->filled('require_acceptance')) {
$categories->where('require_acceptance', '=', $request->input('require_acceptance'));
}
if ($request->filled('checkin_email')) {
$categories->where('checkin_email', '=', $request->input('checkin_email'));
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($categories) && ($request->get('offset') > $categories->count())) ? $categories->count() : $request->get('offset', 0);
@@ -43,6 +43,11 @@ class CompaniesController extends Controller
$companies->TextSearch($request->input('search'));
}
if ($request->filled('name')) {
$companies->where('name', '=', $request->input('name'));
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($companies) && ($request->get('offset') > $companies->count())) ? $companies->count() : $request->get('offset', 0);
@@ -51,6 +51,10 @@ class ComponentsController extends Controller
$components = $components->TextSearch($request->input('search'));
}
if ($request->filled('name')) {
$components->where('name', '=', $request->input('name'));
}
if ($request->filled('company_id')) {
$components->where('company_id', '=', $request->input('company_id'));
}
@@ -55,6 +55,10 @@ class ConsumablesController extends Controller
$consumables = $consumables->TextSearch(e($request->input('search')));
}
if ($request->filled('name')) {
$consumables->where('name', '=', $request->input('name'));
}
if ($request->filled('company_id')) {
$consumables->where('company_id', '=', $request->input('company_id'));
}
@@ -42,6 +42,22 @@ class DepartmentsController extends Controller
$departments = $departments->TextSearch($request->input('search'));
}
if ($request->filled('name')) {
$departments->where('name', '=', $request->input('name'));
}
if ($request->filled('company_id')) {
$departments->where('company_id', '=', $request->input('company_id'));
}
if ($request->filled('manager_id')) {
$departments->where('manager_id', '=', $request->input('manager_id'));
}
if ($request->filled('location_id')) {
$departments->where('location_id', '=', $request->input('location_id'));
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($departments) && ($request->get('offset') > $departments->count())) ? $departments->count() : $request->get('offset', 0);
@@ -28,6 +28,10 @@ class GroupsController extends Controller
$groups = $groups->TextSearch($request->input('search'));
}
if ($request->filled('name')) {
$groups->where('name', '=', $request->input('name'));
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($groups) && ($request->get('offset') > $groups->count())) ? $groups->count() : $request->get('offset', 0);
@@ -134,7 +134,14 @@ class ImportController extends Controller
\Log::debug('NO BACKUP requested via importer');
}
$errors = $request->import(Import::find($import_id));
$import = Import::find($import_id);
if(is_null($import)){
$error[0][0] = trans("validation.exists", ["attribute" => "file"]);
return response()->json(Helper::formatStandardApiResponse('import-errors', null, $error), 500);
}
$errors = $request->import($import);
$redirectTo = 'hardware.index';
switch ($request->get('import-type')) {
case 'asset':
@@ -116,16 +116,20 @@ class LicenseSeatsController extends Controller
return response()->json(Helper::formatStandardApiResponse('success', $licenseSeat, trans('admin/licenses/message.update.success')));
}
// the logging functions expect only one "target". if both asset and user are present in the request,
// we simply let assets take precedence over users...
if ($licenseSeat->isDirty('assigned_to')) {
$target = $is_checkin ? $oldUser : User::find($licenseSeat->assigned_to);
}
if ($licenseSeat->isDirty('asset_id')) {
$target = $is_checkin ? $oldAsset : Asset::find($licenseSeat->asset_id);
}
if (is_null($target)){
return response()->json(Helper::formatStandardApiResponse('error', null, 'Target not found'));
}
if ($licenseSeat->save()) {
// the logging functions expect only one "target". if both asset and user are present in the request,
// we simply let assets take precedence over users...
$changes = $licenseSeat->getChanges();
if (array_key_exists('assigned_to', $changes)) {
$target = $is_checkin ? $oldUser : User::find($changes['assigned_to']);
}
if (array_key_exists('asset_id', $changes)) {
$target = $is_checkin ? $oldAsset : Asset::find($changes['asset_id']);
}
if ($is_checkin) {
$licenseSeat->logCheckin($target, $request->input('note'));
@@ -53,6 +53,30 @@ class LocationsController extends Controller
$locations = $locations->TextSearch($request->input('search'));
}
if ($request->filled('name')) {
$locations->where('locations.name', '=', $request->input('name'));
}
if ($request->filled('address')) {
$locations->where('locations.address', '=', $request->input('address'));
}
if ($request->filled('address2')) {
$locations->where('locations.address2', '=', $request->input('address2'));
}
if ($request->filled('city')) {
$locations->where('locations.city', '=', $request->input('city'));
}
if ($request->filled('zip')) {
$locations->where('locations.zip', '=', $request->input('zip'));
}
if ($request->filled('country')) {
$locations->where('locations.country', '=', $request->input('country'));
}
$offset = (($locations) && (request('offset') > $locations->count())) ? $locations->count() : request('offset', 0);
// Check to make sure the limit is not higher than the max allowed
@@ -37,6 +37,26 @@ class ManufacturersController extends Controller
$manufacturers = $manufacturers->TextSearch($request->input('search'));
}
if ($request->filled('name')) {
$manufacturers->where('name', '=', $request->input('name'));
}
if ($request->filled('url')) {
$manufacturers->where('url', '=', $request->input('url'));
}
if ($request->filled('support_url')) {
$manufacturers->where('support_url', '=', $request->input('support_url'));
}
if ($request->filled('support_phone')) {
$manufacturers->where('support_phone', '=', $request->input('support_phone'));
}
if ($request->filled('support_email')) {
$manufacturers->where('support_email', '=', $request->input('support_email'));
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($manufacturers) && ($request->get('offset') > $manufacturers->count())) ? $manufacturers->count() : $request->get('offset', 0);
+114 -1
View File
@@ -5,10 +5,37 @@ namespace App\Http\Controllers\Api;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Models\CheckoutRequest;
use Auth;
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 Gate;
use DB;
class ProfileController extends Controller
{
/**
* The token repository implementation.
*
* @var \Laravel\Passport\TokenRepository
*/
protected $tokenRepository;
/**
* Create a controller instance.
*
* @param \Laravel\Passport\TokenRepository $tokenRepository
* @param \Illuminate\Contracts\Validation\Factory $validation
* @return void
*/
public function __construct(TokenRepository $tokenRepository, ValidationFactory $validation)
{
$this->validation = $validation;
$this->tokenRepository = $tokenRepository;
}
/**
* Display a listing of requested assets.
*
@@ -42,4 +69,90 @@ class ProfileController extends Controller
return $results;
}
/**
* Delete an API token
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v6.0.5]
*
* @return \Illuminate\Http\Response
*/
public function createApiToken(Request $request) {
if (!Gate::allows('self.api')) {
abort(403);
}
$accessTokenName = $request->input('name', 'Auth Token');
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();
$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('error', null, 'Token could not be created.'));
}
/**
* Delete an API token
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v6.0.5]
*
* @return \Illuminate\Http\Response
*/
public function deleteApiToken($tokenId) {
if (!Gate::allows('self.api')) {
abort(403);
}
$token = $this->tokenRepository->findForUser(
$tokenId, Auth::user()->getAuthIdentifier()
);
if (is_null($token)) {
return new Response('', 404);
}
$token->revoke();
return new Response('', Response::HTTP_NO_CONTENT);
}
/**
* Show user's API tokens
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v6.0.5]
*
* @return \Illuminate\Http\Response
*/
public function showApiTokens(Request $request) {
if (!Gate::allows('self.api')) {
abort(403);
}
$tokens = $this->tokenRepository->forUser(Auth::user()->getAuthIdentifier());
$token_values = $tokens->load('client')->filter(function ($token) {
return $token->client->personal_access_client && ! $token->revoked;
})->values();
return response()->json(Helper::formatStandardApiResponse('success', $token_values, null));
}
}
@@ -52,7 +52,6 @@ class ReportsController extends Controller
'accept_signature',
'action_type',
'note',
'stored_eula_file',
];
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
@@ -2,6 +2,9 @@
namespace App\Http\Controllers\Api;
use App\Helpers\Helper;
use App\Helpers\StorageHelper;
use App\Http\Transformers\DatatablesTransformer;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Ldap;
@@ -265,4 +268,52 @@ class SettingsController extends Controller
return (new LoginAttemptsTransformer)->transformLoginAttempts($login_attempt_results, $total);
}
public function listBackups() {
$settings = Setting::getSettings();
$path = 'app/backups';
$backup_files = Storage::files($path);
$files_raw = [];
$count = 0;
if (count($backup_files) > 0) {
for ($f = 0; $f < count($backup_files); $f++) {
// Skip dotfiles like .gitignore and .DS_STORE
if ((substr(basename($backup_files[$f]), 0, 1) != '.')) {
$file_timestamp = Storage::lastModified($backup_files[$f]);
$files_raw[] = [
'filename' => basename($backup_files[$f]),
'filesize' => Setting::fileSizeConvert(Storage::size($backup_files[$f])),
'modified_value' => $file_timestamp,
'modified_display' => date($settings->date_display_format.' '.$settings->time_display_format, $file_timestamp),
];
$count++;
}
}
}
$files = array_reverse($files_raw);
return (new DatatablesTransformer)->transformDatatables($files, $count);
}
public function downloadBackup($file) {
$path = 'app/backups';
if (Storage::exists($path.'/'.$file)) {
$headers = ['ContentType' => 'application/zip'];
return Storage::download($path.'/'.$file, $file, $headers);
} else {
return response()->json(Helper::formatStandardApiResponse('error', null, 'File not found'));
}
}
}
@@ -30,6 +30,10 @@ class StatuslabelsController extends Controller
$statuslabels = $statuslabels->TextSearch($request->input('search'));
}
if ($request->filled('name')) {
$statuslabels->where('name', '=', $request->input('name'));
}
// if a status_type is passed, filter by that
if ($request->filled('status_type')) {
@@ -34,6 +34,46 @@ class SuppliersController extends Controller
$suppliers = $suppliers->TextSearch($request->input('search'));
}
if ($request->filled('name')) {
$suppliers->where('name', '=', $request->input('name'));
}
if ($request->filled('address')) {
$suppliers->where('address', '=', $request->input('address'));
}
if ($request->filled('address2')) {
$suppliers->where('address2', '=', $request->input('address2'));
}
if ($request->filled('city')) {
$suppliers->where('city', '=', $request->input('city'));
}
if ($request->filled('zip')) {
$suppliers->where('zip', '=', $request->input('zip'));
}
if ($request->filled('country')) {
$suppliers->where('country', '=', $request->input('country'));
}
if ($request->filled('fax')) {
$suppliers->where('fax', '=', $request->input('fax'));
}
if ($request->filled('email')) {
$suppliers->where('email', '=', $request->input('email'));
}
if ($request->filled('url')) {
$suppliers->where('url', '=', $request->input('url'));
}
if ($request->filled('notes')) {
$suppliers->where('notes', '=', $request->input('notes'));
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($suppliers) && ($request->get('offset') > $suppliers->count())) ? $suppliers->count() : $request->get('offset', 0);
+16 -4
View File
@@ -36,6 +36,7 @@ class UsersController extends Controller
$users = User::select([
'users.activated',
'users.created_by',
'users.address',
'users.avatar',
'users.city',
@@ -66,7 +67,7 @@ class UsersController extends Controller
'users.remote',
'users.ldap_import',
])->with('manager', 'groups', 'userloc', 'company', 'department', 'assets', 'licenses', 'accessories', 'consumables')
])->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');
$users = Company::scopeCompanyables($users);
@@ -89,6 +90,10 @@ class UsersController extends Controller
$users = $users->where('users.location_id', '=', $request->input('location_id'));
}
if ($request->filled('created_by')) {
$users = $users->where('users.created_by', '=', $request->input('created_by'));
}
if ($request->filled('email')) {
$users = $users->where('users.email', '=', $request->input('email'));
}
@@ -182,6 +187,9 @@ class UsersController extends Controller
case 'department':
$users = $users->OrderDepartment($order);
break;
case 'created_by':
$users = $users->OrderByCreatedBy($order);
break;
case 'company':
$users = $users->OrderCompany($order);
break;
@@ -519,10 +527,14 @@ class UsersController extends Controller
{
$this->authorize('view', User::class);
$this->authorize('view', License::class);
$user = User::where('id', $id)->withTrashed()->first();
$licenses = $user->licenses()->get();
if ($user = User::where('id', $id)->withTrashed()->first()) {
$licenses = $user->licenses()->get();
return (new LicensesTransformer())->transformLicenses($licenses, $licenses->count());
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found', compact('id'))));
return (new LicensesTransformer())->transformLicenses($licenses, $licenses->count());
}
/**
+23 -2
View File
@@ -8,6 +8,7 @@ use App\Models\AssetModel;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\View;
use Illuminate\Support\Facades\Validator;
use Redirect;
use Request;
use Storage;
@@ -90,7 +91,9 @@ class AssetModelsController extends Controller
// Was it created?
if ($model->save()) {
if ($this->shouldAddDefaultValues($request->input())) {
$this->assignCustomFieldsDefaultValues($model, $request->input('default_values'));
if (!$this->assignCustomFieldsDefaultValues($model, $request->input('default_values'))){
return redirect()->back()->withInput()->with('error', trans('admin/custom_fields/message.fieldset_default_value.error'));
}
}
// Redirect to the new model page
@@ -163,7 +166,9 @@ class AssetModelsController extends Controller
$model->fieldset_id = $request->input('custom_fieldset');
if ($this->shouldAddDefaultValues($request->input())) {
$this->assignCustomFieldsDefaultValues($model, $request->input('default_values'));
if (!$this->assignCustomFieldsDefaultValues($model, $request->input('default_values'))){
return redirect()->back()->withInput()->with('error', trans('admin/custom_fields/message.fieldset_default_value.error'));
}
}
}
@@ -451,6 +456,21 @@ class AssetModelsController extends Controller
*/
private function assignCustomFieldsDefaultValues(AssetModel $model, array $defaultValues)
{
$data = array();
foreach ($defaultValues as $customFieldId => $defaultValue) {
$customField = \App\Models\CustomField::find($customFieldId);
$data[$customField->db_column] = $defaultValue;
}
$rules = $model->fieldset->validation_rules();
$validator = Validator::make($data, $rules);
if($validator->fails()){
return false;
}
foreach ($defaultValues as $customFieldId => $defaultValue) {
if(is_array($defaultValue)){
$model->defaultValues()->attach($customFieldId, ['default_value' => implode(', ', $defaultValue)]);
@@ -458,6 +478,7 @@ class AssetModelsController extends Controller
$model->defaultValues()->attach($customFieldId, ['default_value' => $defaultValue]);
}
}
return true;
}
/**
@@ -0,0 +1,155 @@
<?php
namespace App\Http\Controllers;
use App\Helpers\StorageHelper;
use App\Http\Requests\AssetFileRequest;
use App\Models\Actionlog;
use App\Models\AssetModel;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Storage;
use enshrined\svgSanitize\Sanitizer;
class AssetModelsFilesController extends Controller
{
/**
* Upload a file to the server.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param AssetFileRequest $request
* @param int $modelId
* @return Redirect
* @since [v1.0]
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function store(AssetFileRequest $request, $modelId = null)
{
if (! $model = AssetModel::find($modelId)) {
return redirect()->route('models.index')->with('error', trans('admin/hardware/message.does_not_exist'));
}
$this->authorize('update', $model);
if ($request->hasFile('file')) {
if (! Storage::exists('private_uploads/assetmodels')) {
Storage::makeDirectory('private_uploads/assetmodels', 775);
}
foreach ($request->file('file') as $file) {
$extension = $file->getClientOriginalExtension();
$file_name = 'model-'.$model->id.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
// Check for SVG and sanitize it
if ($extension=='svg') {
\Log::debug('This is an SVG');
$sanitizer = new Sanitizer();
$dirtySVG = file_get_contents($file->getRealPath());
$cleanSVG = $sanitizer->sanitize($dirtySVG);
try {
Storage::put('private_uploads/assetmodels/'.$file_name, $cleanSVG);
} catch (\Exception $e) {
\Log::debug('Upload no workie :( ');
\Log::debug($e);
}
} else {
Storage::put('private_uploads/assetmodels/'.$file_name, file_get_contents($file));
}
$model->logUpload($file_name, e($request->get('notes')));
}
return redirect()->back()->with('success', trans('admin/hardware/message.upload.success'));
}
return redirect()->back()->with('error', trans('admin/hardware/message.upload.nofiles'));
}
/**
* Check for permissions and display the file.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $modelId
* @param int $fileId
* @since [v1.0]
* @return View
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function show($modelId = null, $fileId = null, $download = true)
{
$model = AssetModel::find($modelId);
// the asset is valid
if (isset($model->id)) {
$this->authorize('view', $model);
if (! $log = Actionlog::find($fileId)) {
return response('No matching record for that model/file', 500)
->header('Content-Type', 'text/plain');
}
$file = 'private_uploads/assetmodels/'.$log->filename;
\Log::debug('Checking for '.$file);
if (! Storage::exists($file)) {
return response('File '.$file.' not found on server', 404)
->header('Content-Type', 'text/plain');
}
if ($download != 'true') {
if ($contents = file_get_contents(Storage::url($file))) {
return Response::make(Storage::url($file)->header('Content-Type', mime_content_type($file)));
}
return JsonResponse::create(['error' => 'Failed validation: '], 500);
}
return StorageHelper::downloader($file);
}
// 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);
}
/**
* Delete the associated file
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $modelId
* @param int $fileId
* @since [v1.0]
* @return View
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function destroy($modelId = null, $fileId = null)
{
$model = AssetModel::find($modelId);
$this->authorize('update', $model);
$rel_path = 'private_uploads/assetmodels';
// the asset is valid
if (isset($model->id)) {
$this->authorize('update', $model);
$log = Actionlog::find($fileId);
if ($log) {
if (Storage::exists($rel_path.'/'.$log->filename)) {
Storage::delete($rel_path.'/'.$log->filename);
}
$log->delete();
return redirect()->back()->with('success', trans('admin/hardware/message.deletefile.success'));
}
return redirect()->back()
->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'));
}
}
@@ -98,9 +98,6 @@ class AssetCheckinController extends Controller
}
$asset->location_id = $asset->rtd_location_id;
\Log::debug('After Location ID: '.$asset->location_id);
\Log::debug('After RTD Location ID: '.$asset->rtd_location_id);
if ($request->filled('location_id')) {
\Log::debug('NEW Location ID: '.$request->get('location_id'));
@@ -20,6 +20,7 @@ use Gate;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Cookie;
use Input;
use Intervention\Image\Facades\Image;
use League\Csv\Reader;
@@ -167,17 +168,17 @@ class AssetsController extends Controller
foreach ($model->fieldset->fields as $field) {
if ($field->field_encrypted == '1') {
if (Gate::allows('admin')) {
if (is_array($request->input($field->convertUnicodeDbSlug()))) {
$asset->{$field->convertUnicodeDbSlug()} = \Crypt::encrypt(implode(', ', $request->input($field->convertUnicodeDbSlug())));
if (is_array($request->input($field->db_column))) {
$asset->{$field->db_column} = \Crypt::encrypt(implode(', ', $request->input($field->db_column)));
} else {
$asset->{$field->convertUnicodeDbSlug()} = \Crypt::encrypt($request->input($field->convertUnicodeDbSlug()));
$asset->{$field->db_column} = \Crypt::encrypt($request->input($field->db_column));
}
}
} else {
if (is_array($request->input($field->convertUnicodeDbSlug()))) {
$asset->{$field->convertUnicodeDbSlug()} = implode(', ', $request->input($field->convertUnicodeDbSlug()));
if (is_array($request->input($field->db_column))) {
$asset->{$field->db_column} = implode(', ', $request->input($field->db_column));
} else {
$asset->{$field->convertUnicodeDbSlug()} = $request->input($field->convertUnicodeDbSlug());
$asset->{$field->db_column} = $request->input($field->db_column);
}
}
}
@@ -201,18 +202,30 @@ class AssetsController extends Controller
}
$success = true;
}
}
if ($success) {
// Redirect to the asset listing page
$minutes = 518400;
// dd( $_POST['options']);
// Cookie::queue(Cookie::make('optional_info', json_decode($_POST['options']), $minutes));
return redirect()->route('hardware.index')
->with('success', trans('admin/hardware/message.create.success'));
}
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.
*
@@ -343,17 +356,17 @@ class AssetsController extends Controller
foreach ($model->fieldset->fields as $field) {
if ($field->field_encrypted == '1') {
if (Gate::allows('admin')) {
if (is_array($request->input($field->convertUnicodeDbSlug()))) {
$asset->{$field->convertUnicodeDbSlug()} = \Crypt::encrypt(implode(', ', $request->input($field->convertUnicodeDbSlug())));
if (is_array($request->input($field->db_column))) {
$asset->{$field->db_column} = \Crypt::encrypt(implode(', ', $request->input($field->db_column)));
} else {
$asset->{$field->convertUnicodeDbSlug()} = \Crypt::encrypt($request->input($field->convertUnicodeDbSlug()));
$asset->{$field->db_column} = \Crypt::encrypt($request->input($field->db_column));
}
}
} else {
if (is_array($request->input($field->convertUnicodeDbSlug()))) {
$asset->{$field->convertUnicodeDbSlug()} = implode(', ', $request->input($field->convertUnicodeDbSlug()));
if (is_array($request->input($field->db_column))) {
$asset->{$field->db_column} = implode(', ', $request->input($field->db_column));
} else {
$asset->{$field->convertUnicodeDbSlug()} = $request->input($field->convertUnicodeDbSlug());
$asset->{$field->db_column} = $request->input($field->db_column);
}
}
}
@@ -104,15 +104,12 @@ class LoginController extends Controller
*/
private function loginViaSaml(Request $request)
{
\Log::debug('Attempting to login via SAML');
$saml = $this->saml;
$samlData = $request->session()->get('saml_login');
if ($saml->isEnabled() && ! empty($samlData)) {
\Log::debug('SAML is enabled, and the samleData is not empty');
try {
Log::debug('Attempting to log user in by SAML authentication.');
$user = $saml->samlLogin($samlData);
if (!is_null($user)) {
@@ -139,13 +136,12 @@ class LoginController extends Controller
// Better logging
if (!$saml->isEnabled()) {
\Log::warning("SAML page requested, but SAML does not seem to enabled.");
\Log::debug("SAML page requested, but SAML does not seem to enabled.");
} else {
\Log::warning("SAML page requested, but samlData seems empty.");
}
}
\Log::warning("Something else went wrong while trying to login as SAML user");
}
@@ -3,13 +3,11 @@
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Http\Requests\SaveUserRequest;
use App\Models\Setting;
use App\Models\User;
use Illuminate\Foundation\Auth\ResetsPasswords;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Validator;
class ResetPasswordController extends Controller
{
@@ -63,6 +61,14 @@ class ResetPasswordController extends Controller
public function showResetForm(Request $request, $token = null)
{
$credentials = $request->only('email', 'token');
if (is_null($this->broker()->getUser($credentials))) {
\Log::debug('Password reset form FAILED - this token is not valid.');
return redirect()->route('password.request')->with('error', trans('passwords.token'));
}
return view('auth.passwords.reset')->with(
[
'token' => $token,
@@ -73,38 +79,53 @@ class ResetPasswordController extends Controller
public function reset(Request $request)
{
$broker = $this->broker();
$messages = [
'password.not_in' => trans('validation.disallow_same_pwd_as_user_fields'),
];
$request->validate($this->rules(), $request->all(), $this->validationErrorMessages());
// Check to see if the user even exists
$user = User::where('username', '=', $request->input('username'))->first();
\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');
// handle the password validation rules set by the admin settings
if (strpos(Setting::passwordComplexityRulesSaving('store'), 'disallow_same_pwd_as_user_fields') !== false) {
$request->validate(
[
'password' => 'required|notIn:["'.$user->email.'","'.$user->username.'","'.$user->first_name.'","'.$user->last_name.'"',
], $messages);
}
// set the response
$response = $broker->reset(
$this->credentials($request), function ($user, $password) {
$this->resetPassword($user, $password);
});
// Check if the password reset above actually worked
if ($response == \Password::PASSWORD_RESET) {
\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');
return redirect()->back()->withInput($request->only('email'))->with('error', trans('passwords.token'));
$broker = $this->broker();
if (strpos(Setting::passwordComplexityRulesSaving('store'), 'disallow_same_pwd_as_user_fields') !== false) {
$request->validate(
[
'password' => 'required|notIn:["'.$user->email.'","'.$user->username.'","'.$user->first_name.'","'.$user->last_name.'"',
], $messages);
}
$response = $broker->reset(
$this->credentials($request), function ($user, $password) {
$this->resetPassword($user, $password);
}
);
return $response == \Password::PASSWORD_RESET
? $this->sendResetResponse($request, $response)
: $this->sendResetFailedResponse($request, $response);
\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'));
}
protected function sendResetFailedResponse(Request $request, $response)
{
return redirect()->back()
->withInput(['username'=> $request->input('username')])
->withErrors(['username' => trans($response), 'password' => trans($response)]);
}
}
@@ -129,7 +129,7 @@ class ComponentsController extends Controller
if (is_null($component = Component::find($componentId))) {
return redirect()->route('components.index')->with('error', trans('admin/components/message.does_not_exist'));
}
$min = $component->numCHeckedOut();
$min = $component->numCheckedOut();
$validator = Validator::make($request->all(), [
'qty' => "required|numeric|min:$min",
]);
@@ -9,6 +9,7 @@ use App\Models\Company;
use App\Models\Consumable;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Validator;
/**
* This controller handles all actions related to Consumables for
@@ -128,6 +129,17 @@ class ConsumablesController extends Controller
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist'));
}
$min = $consumable->numCheckedOut();
$validator = Validator::make($request->all(), [
"qty" => "required|numeric|min:$min"
]);
if ($validator->fails()) {
return redirect()->back()
->withErrors($validator)
->withInput();
}
$this->authorize($consumable);
$consumable->name = $request->input('name');
+24 -12
View File
@@ -211,23 +211,35 @@ class LocationsController extends Controller
public function print_assigned($id)
{
$location = Location::where('id', $id)->first();
$parent = Location::where('id', $location->parent_id)->first();
$manager = User::where('id', $location->manager_id)->first();
$users = User::where('location_id', $id)->with('company', 'department', 'location')->get();
$assets = Asset::where('assigned_to', $id)->where('assigned_type', Location::class)->with('model', 'model.category')->get();
return view('locations/print')->with('assets', $assets)->with('users', $users)->with('location', $location)->with('parent', $parent)->with('manager', $manager);
if ($location = Location::where('id', $id)->first()) {
$parent = Location::where('id', $location->parent_id)->first();
$manager = User::where('id', $location->manager_id)->first();
$users = User::where('location_id', $id)->with('company', 'department', 'location')->get();
$assets = Asset::where('assigned_to', $id)->where('assigned_type', Location::class)->with('model', 'model.category')->get();
return view('locations/print')->with('assets', $assets)->with('users', $users)->with('location', $location)->with('parent', $parent)->with('manager', $manager);
}
return redirect()->route('locations.index')->with('error', trans('admin/locations/message.does_not_exist'));
}
public function print_all_assigned($id)
{
$location = Location::where('id', $id)->first();
$parent = Location::where('id', $location->parent_id)->first();
$manager = User::where('id', $location->manager_id)->first();
$users = User::where('location_id', $id)->with('company', 'department', 'location')->get();
$assets = Asset::where('location_id', $id)->with('model', 'model.category')->get();
if ($location = Location::where('id', $id)->first()) {
$parent = Location::where('id', $location->parent_id)->first();
$manager = User::where('id', $location->manager_id)->first();
$users = User::where('location_id', $id)->with('company', 'department', 'location')->get();
$assets = Asset::where('location_id', $id)->with('model', 'model.category')->get();
return view('locations/print')->with('assets', $assets)->with('users', $users)->with('location', $location)->with('parent', $parent)->with('manager', $manager);
}
return redirect()->route('locations.index')->with('error', trans('admin/locations/message.does_not_exist'));
return view('locations/print')->with('assets', $assets)->with('users', $users)->with('location', $location)->with('parent', $parent)->with('manager', $manager);
}
}
+2 -16
View File
@@ -939,9 +939,9 @@ class ReportsController extends Controller
* Get all assets with pending checkout acceptances
*/
if($showDeleted) {
$acceptances = CheckoutAcceptance::pending()->withTrashed()->with(['assignedTo' , 'checkoutable.assignedTo', 'checkoutable.model'])->get();
$acceptances = CheckoutAcceptance::pending()->where('checkoutable_type', 'App\Models\Asset')->withTrashed()->with(['assignedTo' , 'checkoutable.assignedTo', 'checkoutable.model'])->get();
} else {
$acceptances = CheckoutAcceptance::pending()->with(['assignedTo' => function ($query) {
$acceptances = CheckoutAcceptance::pending()->where('checkoutable_type', 'App\Models\Asset')->with(['assignedTo' => function ($query) {
$query->withTrashed();
}, 'checkoutable.assignedTo', 'checkoutable.model'])->get();
}
@@ -1148,18 +1148,4 @@ class ReportsController extends Controller
$this->getModelsInCategoriesThatRequireAcceptance($this->getCategoriesThatRequireAcceptance())
);
}
/**
* getAssetsNotAcceptedYet
*
* @return array
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
*/
protected function getAssetsNotAcceptedYet()
{
$this->authorize('reports.view');
return Asset::unaccepted();
}
}
+100 -38
View File
@@ -25,6 +25,7 @@ use Response;
use App\Http\Requests\SlackSettingsRequest;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Artisan;
use Validator;
/**
* This controller handles all actions related to Settings for
@@ -910,7 +911,24 @@ class SettingsController extends Controller
{
$setting = Setting::getSettings();
return view('settings.ldap', compact('setting'));
/**
* This validator is only temporary (famous last words.) - @snipe
*/
$messages = [
'ldap_username_field.not_in' => '<code>sAMAccountName</code> (mixed case) will likely not work. You should use <code>samaccountname</code> (lowercase) instead. ',
'ldap_auth_filter_query.not_in' => '<code>uid=samaccountname</code> is probably not a valid auth filter. You probably want <code>uid=</code> ',
'ldap_filter.regex' => 'This value should probably not be wrapped in parentheses.',
];
$validator = Validator::make($setting->toArray(), [
'ldap_username_field' => 'not_in:sAMAccountName',
'ldap_auth_filter_query' => 'not_in:uid=samaccountname',
'ldap_filter' => 'regex:"^[^(]"',
], $messages);
return view('settings.ldap', compact('setting'))->withErrors($validator);
}
/**
@@ -942,7 +960,7 @@ class SettingsController extends Controller
$setting->ldap_lname_field = $request->input('ldap_lname_field');
$setting->ldap_fname_field = $request->input('ldap_fname_field');
$setting->ldap_auth_filter_query = $request->input('ldap_auth_filter_query');
$setting->ldap_version = $request->input('ldap_version');
$setting->ldap_version = $request->input('ldap_version', 3);
$setting->ldap_active_flag = $request->input('ldap_active_flag');
$setting->ldap_emp_num = $request->input('ldap_emp_num');
$setting->ldap_email = $request->input('ldap_email');
@@ -1044,7 +1062,7 @@ class SettingsController extends Controller
*/
public function getBackups()
{
$settings = Setting::getSettings();
$path = 'app/backups';
$backup_files = Storage::files($path);
$files_raw = [];
@@ -1061,7 +1079,7 @@ class SettingsController extends Controller
'filename' => basename($backup_files[$f]),
'filesize' => Setting::fileSizeConvert(Storage::size($backup_files[$f])),
'modified_value' => $file_timestamp,
'modified_display' => Helper::getFormattedDateObject($file_timestamp, $type = 'datetime', false),
'modified_display' => date($settings->date_display_format.' '.$settings->time_display_format, $file_timestamp),
];
}
@@ -1147,23 +1165,31 @@ class SettingsController extends Controller
*/
public function deleteFile($filename = null)
{
if (! config('app.lock_passwords')) {
$path = 'app/backups';
if (config('app.allow_backup_delete')=='true') {
if (Storage::exists($path.'/'.$filename)) {
try {
Storage::delete($path.'/'.$filename);
if (!config('app.lock_passwords')) {
$path = 'app/backups';
return redirect()->route('settings.backups.index')->with('success', trans('admin/settings/message.backup.file_deleted'));
} catch (\Exception $e) {
\Log::debug($e);
if (Storage::exists($path . '/' . $filename)) {
try {
Storage::delete($path . '/' . $filename);
return redirect()->route('settings.backups.index')->with('success', trans('admin/settings/message.backup.file_deleted'));
} catch (\Exception $e) {
\Log::debug($e);
}
} else {
return redirect()->route('settings.backups.index')->with('error', trans('admin/settings/message.backup.file_not_found'));
}
} else {
return redirect()->route('settings.backups.index')->with('error', trans('admin/settings/message.backup.file_not_found'));
}
} else {
return redirect()->route('settings.backups.index')->with('error', trans('general.feature_disabled'));
}
// Hell to the no
\Log::warning('User ID '.Auth::user()->id.' is attempting to delete backup file '.$filename.' and is not authorized to.');
return redirect()->route('settings.backups.index')->with('error', trans('general.backup_delete_not_allowed'));
}
@@ -1198,9 +1224,10 @@ class SettingsController extends Controller
Storage::putFileAs('app/backups', $request->file('file'), $upload_filename);
return redirect()->route('settings.backups.index')->with('success', 'File uploaded');
} else {
return redirect()->route('settings.backups.index')->withErrors($request->getErrors());
}
return redirect()->route('settings.backups.index')->withErrors($request->getErrors());
}
} else {
@@ -1234,7 +1261,11 @@ class SettingsController extends Controller
// TODO: run a backup
Artisan::call('db:wipe');
Artisan::call('db:wipe', [
'--force' => true,
]);
\Log::debug('Attempting to restore from: '. storage_path($path).'/'.$filename);
// run the restore command
Artisan::call('snipeit:restore',
@@ -1246,19 +1277,26 @@ class SettingsController extends Controller
// If it's greater than 300, it probably worked
$output = Artisan::output();
if (strlen($output) > 300) {
$find_user = DB::table('users')->where('first_name', $user->first_name)->where('last_name', $user->last_name)->exists();
if(!$find_user){
if (!$find_user){
\Log::warning('Attempting to restore user: ' . $user->first_name . ' ' . $user->last_name);
$new_user = $user->replicate();
$new_user->push();
}
$session_files = glob(storage_path("framework/sessions/*"));
foreach ($session_files as $file) {
if (is_file($file))
unlink($file);
}
\Log::debug('Logging all users out..');
Artisan::call('snipeit:global-logout', ['--force' => true]);
/* run migrations */
\Log::debug('Migrating database...');
Artisan::call('migrate', ['--force' => true]);
$migrate_output = Artisan::output();
\Log::debug($migrate_output);
DB::table('users')->update(['remember_token' => null]);
\Auth::logout();
@@ -1287,9 +1325,15 @@ class SettingsController extends Controller
*/
public function getPurge()
{
\Log::warning('User ID '.Auth::user()->id.' is attempting a PURGE');
return view('settings.purge-form');
\Log::warning('User '.Auth::user()->username.' (ID'.Auth::user()->id.') is attempting a PURGE');
if (config('app.allow_purge')=='true') {
return view('settings.purge-form');
}
return redirect()->route('settings.index')->with('error', trans('general.purge_not_allowed'));
}
/**
@@ -1303,22 +1347,40 @@ class SettingsController extends Controller
*/
public function postPurge(Request $request)
{
if (! config('app.lock_passwords')) {
if ('DELETE' == $request->input('confirm_purge')) {
\Log::warning('User ID '.Auth::user()->id.' initiated a PURGE!');
// Run a backup immediately before processing
Artisan::call('backup:run');
Artisan::call('snipeit:purge', ['--force' => 'true', '--no-interaction' => true]);
$output = Artisan::output();
\Log::warning('User '.Auth::user()->username.' (ID'.Auth::user()->id.') is attempting a PURGE');
return view('settings/purge')
->with('output', $output)->with('success', trans('admin/settings/message.purge.success'));
if (config('app.allow_purge')=='true') {
\Log::debug('Purging is not allowed via the .env');
if (!config('app.lock_passwords')) {
if ($request->input('confirm_purge')=='DELETE') {
\Log::warning('User ID ' . Auth::user()->id . ' initiated a PURGE!');
// Run a backup immediately before processing
Artisan::call('backup:run');
Artisan::call('snipeit:purge', ['--force' => 'true', '--no-interaction' => true]);
$output = Artisan::output();
return redirect()->route('settings.index')
->with('output', $output)->with('success', trans('admin/settings/message.purge.success'));
} else {
return redirect()->route('settings.purge.index')
->with('error', trans('admin/settings/message.purge.validation_failed'));
}
} else {
return redirect()->back()->with('error', trans('admin/settings/message.purge.validation_failed'));
return redirect()->route('settings.index')
->with('error', trans('general.feature_disabled'));
}
} else {
return redirect()->back()->with('error', trans('general.feature_disabled'));
}
\Log::error('User '.Auth::user()->username.' (ID'.Auth::user()->id.') is attempting to purge deleted data and is not authorized to.');
// Nope.
return redirect()->route('settings.index')
->with('error', trans('general.purge_not_allowed'));
}
/**
@@ -91,8 +91,10 @@ class BulkUsersController extends Controller
->conditionallyAddItem('company_id')
->conditionallyAddItem('locale')
->conditionallyAddItem('remote')
->conditionallyAddItem('ldap_import')
->conditionallyAddItem('activated');
// If the manager_id is one of the users being updated, generate a warning.
if (array_search($request->input('manager_id'), $user_raw_array)) {
$manager_conflict = true;
@@ -107,7 +109,7 @@ class BulkUsersController extends Controller
User::whereIn('id', $user_raw_array)
->where('id', '!=', Auth::id())->update($this->update_array);
if(array_key_exists('location_id', $this->update_array)){
if (array_key_exists('location_id', $this->update_array)){
Asset::where('assigned_type', User::class)
->whereIn('assigned_to', $user_raw_array)
->update(['location_id' => $this->update_array['location_id']]);
+27 -1
View File
@@ -23,6 +23,7 @@ use Redirect;
use Str;
use Symfony\Component\HttpFoundation\StreamedResponse;
use View;
use App\Notifications\CurrentInventory;
/**
* This controller handles all actions related to Users for
@@ -116,6 +117,8 @@ class UsersController extends Controller
$user->country = $request->input('country', null);
$user->zip = $request->input('zip', null);
$user->remote = $request->input('remote', 0);
$user->website = $request->input('website', null);
$user->created_by = Auth::user()->id;
// Strip out the superuser permission if the user isn't a superadmin
$permissions_array = $request->input('permission');
@@ -266,6 +269,7 @@ class UsersController extends Controller
$user->activated = $request->input('activated', 0);
$user->zip = $request->input('zip', null);
$user->remote = $request->input('remote', 0);
$user->website = $request->input('website', null);
// Update the location of any assets checked out to this user
Asset::where('assigned_type', User::class)
@@ -612,6 +616,28 @@ class UsersController extends Controller
->with('settings', Setting::getSettings());
}
/**
* Emails user a list of assigned assets
*
* @author [G. Martinez] [<godmartinz@gmail.com>]
* @since [v6.0.5]
* @param \App\Http\Controllers\Users\UsersController $id
* @return \Illuminate\Http\RedirectResponse
*/
public function emailAssetList($id)
{
$this->authorize('view', User::class);
if( User::where('id', $id)->first()->exists())
{
$user= User::where('id', $id)->first();
$user->notify((new CurrentInventory($user)));
return redirect()->back()->with('success', trans('admin/users/general.user_notified'));
}
return redirect()->back()->with('error', 'admin/accessories/message.user_does_not_exist');
}
/**
* Send individual password reset email
*
@@ -636,4 +662,4 @@ class UsersController extends Controller
return redirect()->back()->with('error', 'User is not activated, is LDAP synced, or does not have an email address ');
}
}
}
@@ -180,123 +180,4 @@ class ViewAssetsController extends Controller
{
return view('account/requested');
}
// Get the acceptance screen
public function getAcceptAsset($logID = null)
{
$findlog = Actionlog::where('id', $logID)->first();
if (! $findlog) {
return redirect()->to('account/view-assets')->with('error', 'No matching record.');
}
if ($findlog->accepted_id != '') {
return redirect()->to('account/view-assets')->with('error', trans('admin/users/message.error.asset_already_accepted'));
}
$user = Auth::user();
// TODO - Fix this for non-assets
if (($findlog->item_type == Asset::class) && ($user->id != $findlog->item->assigned_to)) {
return redirect()->to('account/view-assets')->with('error', trans('admin/users/message.error.incorrect_user_accepted'));
}
$item = $findlog->item;
// Check if the asset exists
if (is_null($item)) {
// Redirect to the asset management page
return redirect()->to('account')->with('error', trans('admin/hardware/message.does_not_exist'));
} elseif (! Company::isCurrentUserHasAccess($item)) {
return redirect()->route('requestable-assets')->with('error', trans('general.insufficient_permissions'));
} else {
return view('account/accept-asset', compact('item'))->with('findlog', $findlog)->with('item', $item);
}
}
// Save the acceptance
public function postAcceptAsset(Request $request, $logID = null)
{
// Check if the asset exists
if (is_null($findlog = Actionlog::where('id', $logID)->first())) {
// Redirect to the asset management page
return redirect()->to('account/view-assets')->with('error', trans('admin/hardware/message.does_not_exist'));
}
if ($findlog->accepted_id != '') {
// Redirect to the asset management page
return redirect()->to('account/view-assets')->with('error', trans('admin/users/message.error.asset_already_accepted'));
}
if ($request->missing('asset_acceptance')) {
return redirect()->back()->with('error', trans('admin/users/message.error.accept_or_decline'));
}
$user = Auth::user();
if (($findlog->item_type == Asset::class) && ($user->id != $findlog->item->assigned_to)) {
return redirect()->to('account/view-assets')->with('error', trans('admin/users/message.error.incorrect_user_accepted'));
}
if ($request->filled('signature_output')) {
$path = config('app.private_uploads').'/signatures';
$sig_filename = 'siglog-'.$findlog->id.'-'.date('Y-m-d-his').'.png';
$data_uri = e($request->get('signature_output'));
$encoded_image = explode(',', $data_uri);
$decoded_image = base64_decode($encoded_image[1]);
Storage::putFileAs($path, $decoded_image, $sig_filename);
//file_put_contents($path.'/'.$sig_filename, $decoded_image);
}
$logaction = new Actionlog();
if ($request->input('asset_acceptance') == 'accepted') {
$logaction_msg = 'accepted';
$accepted = 'accepted';
$return_msg = trans('admin/users/message.accepted');
} else {
$logaction_msg = 'declined';
$accepted = 'rejected';
$return_msg = trans('admin/users/message.declined');
}
$logaction->item_id = $findlog->item_id;
$logaction->item_type = $findlog->item_type;
// Asset
if (($findlog->item_id != '') && ($findlog->item_type == Asset::class)) {
if ($request->input('asset_acceptance') != 'accepted') {
DB::table('assets')
->where('id', $findlog->item_id)
->update(['assigned_to' => null]);
}
}
$logaction->target_id = $findlog->target_id;
$logaction->target_type = User::class;
$logaction->note = e($request->input('note'));
$logaction->updated_at = date('Y-m-d H:i:s');
if (isset($sig_filename)) {
$logaction->accept_signature = $sig_filename;
}
$log = $logaction->logaction($logaction_msg);
$update_checkout = DB::table('action_logs')
->where('id', $findlog->id)
->update(['accepted_id' => $logaction->id]);
if (($findlog->item_id != '') && ($findlog->item_type == Asset::class)) {
$affected_asset = $logaction->item;
$affected_asset->accepted = $accepted;
$affected_asset->save();
}
if ($update_checkout) {
return redirect()->to('account/view-assets')->with('success', $return_msg);
} else {
return redirect()->to('account/view-assets')->with('error', 'Something went wrong ');
}
}
}
@@ -68,8 +68,6 @@ class AccessoriesTransformer
$array = [];
foreach ($accessory_users as $user) {
\Log::debug(print_r($user->pivot, true));
\Log::debug(print_r($user->pivot, true));
$array[] = [
'assigned_pivot_id' => $user->pivot->id,
@@ -55,20 +55,35 @@ class ActionlogsTransformer
}
}
$file_url = '';
if($actionlog->filename!='') {
if ($actionlog->present()->actionType() == 'accepted') {
$file_url = route('log.storedeula.download', ['filename' => $actionlog->filename]);
} else {
if ($actionlog->itemType() == 'asset') {
$file_url = route('show/assetfile', ['assetId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
} elseif ($actionlog->itemType() == 'license') {
$file_url = route('show.licensefile', ['licenseId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
} elseif ($actionlog->itemType() == 'user') {
$file_url = route('show/userfile', ['userId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
}
}
}
$array = [
$array = [
'id' => (int) $actionlog->id,
'icon' => $icon,
'file' => ($actionlog->filename!='') ?
'file' => ($actionlog->filename!='')
?
[
'url' => route('show/assetfile', ['assetId' => $actionlog->item->id, 'fileId' => $actionlog->id]),
'url' => $file_url,
'filename' => $actionlog->filename,
'inlineable' => (bool) Helper::show_file_inline($actionlog->filename),
] : null,
'item' => ($actionlog->item) ? [
'id' => (int) $actionlog->item->id,
'name' => ($actionlog->itemType()=='user') ? $actionlog->filename : e($actionlog->item->getDisplayNameAttribute()),
'name' => ($actionlog->itemType()=='user') ? e($actionlog->item->getFullNameAttribute()) : e($actionlog->item->getDisplayNameAttribute()),
'type' => e($actionlog->itemType()),
] : null,
'location' => ($actionlog->location) ? [
@@ -96,10 +111,10 @@ class ActionlogsTransformer
'signature_file' => ($actionlog->accept_signature) ? route('log.signature.view', ['filename' => $actionlog->accept_signature ]) : null,
'log_meta' => ((isset($clean_meta)) && (is_array($clean_meta))) ? $clean_meta: null,
'action_date' => ($actionlog->action_date) ? Helper::getFormattedDateObject($actionlog->action_date, 'datetime'): Helper::getFormattedDateObject($actionlog->created_at, 'datetime'),
'stored_eula_file' => ($actionlog->stored_eula_file) ? route('log.storedeula.download', ['filename' => $actionlog->stored_eula_file]) : null,
];
//\Log::info("Clean Meta is: ".print_r($clean_meta,true));
//dd($array);
return $array;
}
+22 -7
View File
@@ -94,25 +94,40 @@ class AssetsTransformer
$fields_array = [];
foreach ($asset->model->fieldset->fields as $field) {
if ($field->isFieldDecryptable($asset->{$field->convertUnicodeDbSlug()})) {
$decrypted = Helper::gracefulDecrypt($field, $asset->{$field->convertUnicodeDbSlug()});
if ($field->isFieldDecryptable($asset->{$field->db_column})) {
$decrypted = Helper::gracefulDecrypt($field, $asset->{$field->db_column});
$value = (Gate::allows('superadmin')) ? $decrypted : strtoupper(trans('admin/custom_fields/general.encrypted'));
if ($field->format == 'DATE'){
if (Gate::allows('superadmin')){
$value = Helper::getFormattedDateObject($value, 'date', false);
} else {
$value = strtoupper(trans('admin/custom_fields/general.encrypted'));
}
}
$fields_array[$field->name] = [
'field' => e($field->convertUnicodeDbSlug()),
'field' => e($field->db_column),
'value' => e($value),
'field_format' => $field->format,
'element' => $field->element,
];
} else {
$value = $asset->{$field->db_column};
if (($field->format == 'DATE') && (!is_null($value)) && ($value!='')){
$value = Helper::getFormattedDateObject($value, 'date', false);
}
$fields_array[$field->name] = [
'field' => e($field->convertUnicodeDbSlug()),
'value' => e($asset->{$field->convertUnicodeDbSlug()}),
'field' => e($field->db_column),
'value' => e($value),
'field_format' => $field->format,
'element' => $field->element,
];
}
$array['custom_fields'] = $fields_array;
}
} else {
@@ -39,7 +39,7 @@ class ComponentsAssetsTransformer
if ($asset->model->fieldset) {
foreach ($asset->model->fieldset->fields as $field) {
$fields_array = [$field->name => $asset->{$field->convertUnicodeDbSlug()}];
$fields_array = [$field->name => $asset->{$field->db_column}];
$array += $fields_array;
}
}
@@ -46,7 +46,7 @@ class CustomFieldsTransformer
'field_values' => ($field->field_values) ? e($field->field_values) : null,
'field_values_array' => ($field->field_values) ? explode("\r\n", e($field->field_values)) : null,
'type' => e($field->element),
'required' => $field->pivot ? $field->pivot->required : false,
'required' => (($field->pivot) && ($field->pivot->required=='1')) ? true : false,
'created_at' => Helper::getFormattedDateObject($field->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($field->updated_at, 'datetime'),
];
@@ -9,14 +9,14 @@ use Illuminate\Database\Eloquent\Collection;
class DepreciationsTransformer
{
public function transformDepreciations(Collection $depreciations)
public function transformDepreciations(Collection $depreciations, $total)
{
$array = [];
foreach ($depreciations as $depreciation) {
$array[] = self::transformDepreciation($depreciation);
}
return (new DatatablesTransformer)->transformDatatables($array);
return (new DatatablesTransformer)->transformDatatables($array, $total);
}
public function transformDepreciation(Depreciation $depreciation)
@@ -27,8 +27,7 @@ class DepreciationsTransformer
'months' => $depreciation->months.' '.trans('general.months'),
'depreciation_min' => $depreciation->depreciation_min,
'created_at' => Helper::getFormattedDateObject($depreciation->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($depreciation->updated_at, 'datetime'),
'depreciation_min' =>($depreciation->depreciation_min),
'updated_at' => Helper::getFormattedDateObject($depreciation->updated_at, 'datetime')
];
$permissions_array['available_actions'] = [
@@ -40,4 +39,4 @@ class DepreciationsTransformer
return $array;
}
}
}
@@ -63,6 +63,10 @@ class UsersTransformer
'accessories_count' => (int) $user->accessories_count,
'consumables_count' => (int) $user->consumables_count,
'company' => ($user->company) ? ['id' => (int) $user->company->id, 'name'=> e($user->company->name)] : null,
'created_by' => ($user->createdBy) ? [
'id' => (int) $user->createdBy->id,
'name'=> e($user->createdBy->present()->fullName),
] : null,
'created_at' => Helper::getFormattedDateObject($user->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($user->updated_at, 'datetime'),
'last_login' => Helper::getFormattedDateObject($user->last_login, 'datetime'),
+1 -1
View File
@@ -130,7 +130,7 @@ class AssetImporter extends ItemImporter
//-- user_id is a property of the abstract class Importer, which this class inherits from and it's setted by
//-- the class that needs to use it (command importer or GUI importer inside the project).
if (isset($target)) {
$asset->fresh()->checkOut($target, $this->user_id);
$asset->fresh()->checkOut($target, $this->user_id, date('Y-m-d H:i:s'));
}
return;
+15
View File
@@ -2,7 +2,9 @@
namespace App\Importer;
use App\Models\Asset;
use App\Models\Department;
use App\Models\Setting;
use App\Models\User;
use App\Notifications\WelcomeNotification;
@@ -60,6 +62,13 @@ class UserImporter extends ItemImporter
if ($this->shouldUpdateField($user_department)) {
$this->item['department_id'] = $this->createOrFetchDepartment($user_department);
}
if (is_null($this->item['username']) || $this->item['username'] == "") {
$user_full_name = $this->item['first_name'] . ' ' . $this->item['last_name'];
$user_formatted_array = User::generateFormattedNameFromFullName($user_full_name, Setting::getSettings()->username_format);
$this->item['username'] = $user_formatted_array['username'];
}
$user = User::where('username', $this->item['username'])->first();
if ($user) {
if (! $this->updating) {
@@ -71,6 +80,12 @@ class UserImporter extends ItemImporter
$this->log('Updating User');
$user->update($this->sanitizeItemForUpdating($user));
$user->save();
// 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' => $user->location_id]);
// \Log::debug('UserImporter.php Updated User ' . print_r($user, true));
return;
}
+7 -12
View File
@@ -24,10 +24,13 @@ use Illuminate\Support\Facades\Notification;
class CheckoutableListener
{
/**
* Notify the user about the checked out checkoutable
* Notify the user about the checked out checkoutable and add a record to the
* checkout_requests table.
*/
public function onCheckedOut($event)
{
/**
* When the item wasn't checked out to a user, we can't send notifications
*/
@@ -58,14 +61,12 @@ class CheckoutableListener
*/
public function onCheckedIn($event)
{
\Log::debug('checkin fired');
\Log::debug('onCheckedIn in the Checkoutable listener fired');
/**
* When the item wasn't checked out to a user, we can't send notifications
*/
if (! $event->checkedOutTo instanceof User) {
\Log::debug('checked out to not a user');
return;
}
@@ -81,16 +82,14 @@ class CheckoutableListener
$acceptance->delete();
}
}
\Log::debug('checked out to a user');
// Use default locale
if (! $event->checkedOutTo->locale) {
\Log::debug('Use default settings locale');
Notification::locale(Setting::getSettings()->locale)->send(
$this->getNotifiables($event),
$this->getCheckinNotification($event)
);
} else {
\Log::debug('Use user locale? I do not think this works as expected yet');
// \Log::debug(print_r($this->getNotifiables($event), true));
Notification::send(
$this->getNotifiables($event),
$this->getCheckinNotification($event)
@@ -151,10 +150,6 @@ class CheckoutableListener
private function getCheckinNotification($event)
{
// $model = get_class($event->checkoutable);
$notificationClass = null;
switch (get_class($event->checkoutable)) {
+22 -1
View File
@@ -22,24 +22,44 @@ use App\Models\LicenseSeat;
class LogListener
{
/**
* These onBlah methods are used by the subscribe() method further down in this file.
* This one creates an action_logs entry for the checkin
* @param CheckoutableCheckedIn $event
* @return void
*
*/
public function onCheckoutableCheckedIn(CheckoutableCheckedIn $event)
{
$event->checkoutable->logCheckin($event->checkedOutTo, $event->note, $event->action_date);
}
/**
* These onBlah methods are used by the subscribe() method further down in this file.
* This one creates an action_logs entry for the checkout
*
* @param CheckoutableCheckedOut $event
* @return void
*
*/
public function onCheckoutableCheckedOut(CheckoutableCheckedOut $event)
{
$event->checkoutable->logCheckout($event->note, $event->checkedOutTo, $event->checkoutable->last_checkout);
}
/**
* These onBlah methods are used by the subscribe() method further down in this file.
* This creates the entry in the action_logs table for the accept/decline action
*/
public function onCheckoutAccepted(CheckoutAccepted $event)
{
\Log::error('event passed to the onCheckoutAccepted listener:');
$logaction = new Actionlog();
$logaction->item()->associate($event->acceptance->checkoutable);
$logaction->target()->associate($event->acceptance->assignedTo);
$logaction->accept_signature = $event->acceptance->signature_filename;
$logaction->stored_eula_file = $event->acceptance->stored_eula_file;
$logaction->filename = $event->acceptance->stored_eula_file;
$logaction->action_type = 'accepted';
// TODO: log the actual license seat that was checked out
@@ -47,6 +67,7 @@ class LogListener
$logaction->item()->associate($event->acceptance->checkoutable->license);
}
\Log::debug('New onCheckoutAccepted Listener fired. logaction: '.print_r($logaction, true));
$logaction->save();
}
+15
View File
@@ -310,6 +310,21 @@ class Accessory extends SnipeModel
return null;
}
/**
* Check how many items within an accessory are checked out
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v5.0]
* @return int
*/
public function numCheckedOut()
{
$checkedout = 0;
$checkedout = $this->users->count();
return $checkedout;
}
/**
* Check how many items of an accessory remain
*
+1 -1
View File
@@ -25,7 +25,7 @@ class Actionlog extends SnipeModel
protected $table = 'action_logs';
public $timestamps = true;
protected $fillable = ['created_at', 'item_type', 'user_id', 'item_id', 'action_type', 'note', 'target_id', 'target_type', 'stored_eula', 'stored_eula_file'];
protected $fillable = ['created_at', 'item_type', 'user_id', 'item_id', 'action_type', 'note', 'target_id', 'target_type', 'stored_eula'];
use Searchable;
+28 -1
View File
@@ -1147,6 +1147,31 @@ class Asset extends Depreciable
}
/**
* Query builder scope for Archived assets counting
*
* This is primarily used for the tab counters so that IF the admin
* has chosen to not display archived assets in their regular lists
* and views, it will return the correct number.
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeAssetsForShow($query)
{
if (Setting::getSettings()->show_archived_in_list!=1) {
return $query->whereHas('assetstatus', function ($query) {
$query->where('archived', '=', 0);
});
} else {
return $query;
}
}
/**
* Query builder scope for Archived assets
*
@@ -1187,7 +1212,9 @@ class Asset extends Depreciable
public function scopeRequestableAssets($query)
{
return Company::scopeCompanyables($query->where('requestable', '=', 1))
$table = $query->getModel()->getTable();
return Company::scopeCompanyables($query->where($table.'.requestable', '=', 1))
->whereHas('assetstatus', function ($query) {
$query->where(function ($query) {
$query->where('deployable', '=', 1)
+14
View File
@@ -162,6 +162,20 @@ class AssetMaintenance extends Model implements ICompanyableChild
* -----------------------------------------------
**/
/**
* Query builder scope to order on a supplier
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param string $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeOrderBySupplier($query, $order)
{
return $query->leftJoin('suppliers as suppliers_maintenances', 'asset_maintenances.supplier_id', '=', 'suppliers_maintenances.id')
->orderBy('suppliers_maintenances.name', $order);
}
/**
* Query builder scope to order on admin user
*
+18 -1
View File
@@ -20,7 +20,7 @@ class AssetModel extends SnipeModel
use HasFactory;
use SoftDeletes;
protected $presenter = \App\Presenters\AssetModelPresenter::class;
use Requestable, Presentable;
use Loggable, Requestable, Presentable;
protected $table = 'models';
protected $hidden = ['user_id', 'deleted_at'];
@@ -181,6 +181,23 @@ class AssetModel extends SnipeModel
return false;
}
/**
* Get uploads for this model
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function uploads()
{
return $this->hasMany('\App\Models\Actionlog', 'item_id')
->where('item_type', '=', AssetModel::class)
->where('action_type', '=', 'uploaded')
->whereNotNull('filename')
->orderBy('created_at', 'desc');
}
/**
* -----------------------------------------------
* BEGIN QUERY SCOPES
+7 -3
View File
@@ -57,20 +57,24 @@ class CheckoutAcceptance extends Model
}
/**
* Accept the checkout acceptance
* Add a record to the checkout_acceptance table ONLY.
* Do not add stuff here that doesn't have a corresponding column in the
* checkout_acceptances table or you'll get an error.
*
* @param string $signature_filename
*/
public function accept($signature_filename)
public function accept($signature_filename, $eula = null, $filename = null)
{
$this->accepted_at = now();
$this->signature_filename = $signature_filename;
$this->stored_eula = $eula;
$this->stored_eula_file = $filename;
$this->save();
/**
* Update state for the checked out item
*/
$this->checkoutable->acceptedCheckout($this->assignedTo, $signature_filename);
$this->checkoutable->acceptedCheckout($this->assignedTo, $signature_filename, $filename);
}
/**
+15
View File
@@ -276,6 +276,21 @@ class Consumable extends SnipeModel
}
}
/**
* Check how many items within a consumable are checked out
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v5.0]
* @return int
*/
public function numCheckedOut()
{
$checkedout = 0;
$checkedout = $this->users->count();
return $checkedout;
}
/**
* Checks the number of available consumables
*
+2 -2
View File
@@ -111,7 +111,7 @@ class CustomField extends Model
// Column already exists on the assets table - nothing to do here.
// This *shouldn't* happen in the wild.
if (Schema::hasColumn(self::$table_name, $custom_field->convertUnicodeDbSlug())) {
if (Schema::hasColumn(self::$table_name, $custom_field->db_column)) {
return false;
}
@@ -156,7 +156,7 @@ class CustomField extends Model
// Drop the assets column if we've deleted it from custom fields
self::deleting(function ($custom_field) {
return Schema::table(self::$table_name, function ($table) use ($custom_field) {
$table->dropColumn($custom_field->convertUnicodeDbSlug());
$table->dropColumn($custom_field->db_column);
});
});
}
+3 -8
View File
@@ -66,16 +66,11 @@ class Depreciable extends SnipeModel
/**
* @return float|int
*/
public function getLinearDepreciatedValue()
public function getLinearDepreciatedValue() // TODO - for testing it might be nice to have an optional $relative_to param here, defaulted to 'now'
{
$numerator= (($this->purchase_cost-($this->purchase_cost*12/($this->get_depreciation()->months))));
$denominator=$this->get_depreciation()->months/12;
$deprecation_per_year= $numerator/$denominator;
$deprecation_per_month= $deprecation_per_year/12;
$months_remaining = $this->time_until_depreciated()->m + 12 * $this->time_until_depreciated()->y; //UGlY
$months_depreciated=$this->get_depreciation()->months-$months_remaining;
$current_value = $this->purchase_cost-($deprecation_per_month*$months_depreciated);
$current_value = round(($months_remaining / $this->get_depreciation()->months) * $this->purchase_cost, 2);
if($this->get_depreciation()->depreciation_min > $current_value) {
+9 -7
View File
@@ -37,7 +37,7 @@ class Ldap extends Model
public static function connectToLdap()
{
$ldap_host = Setting::getSettings()->ldap_server;
$ldap_version = Setting::getSettings()->ldap_version;
$ldap_version = Setting::getSettings()->ldap_version ?: 3;
$ldap_server_cert_ignore = Setting::getSettings()->ldap_server_cert_ignore;
$ldap_use_tls = Setting::getSettings()->ldap_tls;
@@ -64,8 +64,8 @@ class Ldap extends Model
ldap_set_option($connection, LDAP_OPT_NETWORK_TIMEOUT, 20);
if (Setting::getSettings()->ldap_client_tls_cert && Setting::getSettings()->ldap_client_tls_key) {
ldap_set_option($connection, LDAP_OPT_X_TLS_CERTFILE, Setting::get_client_side_cert_path());
ldap_set_option($connection, LDAP_OPT_X_TLS_KEYFILE, Setting::get_client_side_key_path());
ldap_set_option(null, LDAP_OPT_X_TLS_CERTFILE, Setting::get_client_side_cert_path());
ldap_set_option(null, LDAP_OPT_X_TLS_KEYFILE, Setting::get_client_side_key_path());
}
if ($ldap_use_tls=='1') {
@@ -275,9 +275,10 @@ class Ldap extends Model
* @since [v3.0]
* @param $base_dn
* @param $count
* @param $filter
* @return array|bool
*/
public static function findLdapUsers($base_dn = null, $count = -1)
public static function findLdapUsers($base_dn = null, $count = -1, $filter = null)
{
$ldapconn = self::connectToLdap();
self::bindAdminToLdap($ldapconn);
@@ -285,7 +286,9 @@ class Ldap extends Model
if (is_null($base_dn)) {
$base_dn = Setting::getSettings()->ldap_basedn;
}
$filter = Setting::getSettings()->ldap_filter;
if($filter === null) {
$filter = Setting::getSettings()->ldap_filter;
}
// Set up LDAP pagination for very large databases
$page_size = 500;
@@ -304,14 +307,13 @@ class Ldap extends Model
// HUGE thanks to this article: https://stackoverflow.com/questions/68275972/how-to-get-paged-ldap-queries-in-php-8-and-read-more-than-1000-entries
// which helped me wrap my head around paged results!
\Log::info("ldap conn is: ".$ldapconn." basedn is: $base_dn, filter is: $filter - count is: $count. page size is: $page_size"); //FIXME - remove
// if a $count is set and it's smaller than $page_size then use that as the page size
$ldap_controls = [];
//if($count == -1) { //count is -1 means we have to employ paging to query the entire directory
$ldap_controls = [['oid' => LDAP_CONTROL_PAGEDRESULTS, 'iscritical' => false, 'value' => ['size'=> $count == -1||$count>$page_size ? $page_size : $count, 'cookie' => $cookie]]];
//}
$search_results = ldap_search($ldapconn, $base_dn, $filter, [], 0, /* $page_size */ -1, -1, LDAP_DEREF_NEVER, $ldap_controls); // TODO - I hate the @, and I hate that we get a full page even if we ask for 10 records. Can we use an ldap_control?
\Log::info("did the search run? I guess so if you got here!");
\Log::debug("did the search run? I guess so if you got here!");
if (! $search_results) {
return redirect()->route('users.index')->with('error', trans('admin/users/message.error.ldap_could_not_search').ldap_error($ldapconn)); // TODO this is never called in any routed context - only from the Artisan command. So this redirect will never work.
}
+18
View File
@@ -103,6 +103,7 @@ class Location extends SnipeModel
return $this->hasMany(\App\Models\User::class, 'location_id');
}
public function assets()
{
return $this->hasMany(\App\Models\Asset::class, 'location_id')
@@ -129,6 +130,23 @@ class Location extends SnipeModel
return $this->hasMany(\App\Models\Asset::class, 'rtd_location_id');
}
public function consumables()
{
return $this->hasMany(\App\Models\Consumable::class, 'location_id');
}
public function components()
{
return $this->hasMany(\App\Models\Component::class, 'location_id');
}
public function accessories()
{
return $this->hasMany(\App\Models\Accessory::class, 'location_id');
}
public function parent()
{
return $this->belongsTo(self::class, 'parent_id', 'id')
+1
View File
@@ -218,6 +218,7 @@ class Setting extends Model
*/
public static function fileSizeConvert($bytes): string
{
$result = 0;
$bytes = floatval($bytes);
$arBytes = [
0 => [
+5 -11
View File
@@ -42,7 +42,7 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig
);
$config['validations'][$core.'emails'] = 'nullable|array'; // emails are not required in Snipe-IT...
$config['validations'][$core.'emails.*.value'] = 'required|email'; // ...but if you give us one, it better be an email address
$config['validations'][$core.'emails.*.value'] = 'email'; // ...(had to remove the recommended 'required' here)
$mappings['emails'] = [[
"value" => AttributeMapping::eloquent("email"),
@@ -58,7 +58,7 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig
//phone
$config['validations'][$core.'phoneNumbers'] = 'nullable|array';
$config['validations'][$core.'phoneNumbers.*.value'] = 'required';
$config['validations'][$core.'phoneNumbers.*.value'] = 'string'; // another one where want to say 'we don't _need_ a phone number, but if you have one it better have a value.
$mappings['phoneNumbers'] = [[
"value" => AttributeMapping::eloquent("phone"),
@@ -69,10 +69,10 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig
//address
$config['validations'][$core.'addresses'] = 'nullable|array';
$config['validations'][$core.'addresses.*.streetAddress'] = 'required';
$config['validations'][$core.'addresses.*.streetAddress'] = 'string';
$config['validations'][$core.'addresses.*.locality'] = 'string';
$config['validations'][$core.'addresses.*.region'] = 'string';
$config['validations'][$core.'addresses.*.postalCode'] = 'string';
$config['validations'][$core.'addresses.*.region'] = 'nullable|string';
$config['validations'][$core.'addresses.*.postalCode'] = 'nullable|string';
$config['validations'][$core.'addresses.*.country'] = 'string';
$mappings['addresses'] = [[
@@ -118,7 +118,6 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig
'employeeNumber' => AttributeMapping::eloquent('employee_num'),
'department' =>(new AttributeMapping())->setAdd( // FIXME parent?
function ($value, &$object) {
\Log::error("Department-Add: $value"); //FIXME
$department = Department::where("name", $value)->first();
if ($department) {
$object->department_id = $department->id;
@@ -126,7 +125,6 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig
}
)->setReplace(
function ($value, &$object) {
\Log::error("Department-Replace: $value"); //FIXME
$department = Department::where("name", $value)->first();
if ($department) {
$object->department_id = $department->id;
@@ -134,7 +132,6 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig
}
)->setRead(
function (&$object) {
\Log::error("Weird department reader firing..."); //FIXME
return $object->department ? $object->department->name : null;
}
),
@@ -145,7 +142,6 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig
// NOTE: you could probably do a 'plain' Eloquent mapping here, but we don't for future-proofing
'value' => (new AttributeMapping())->setAdd(
function ($value, &$object) {
\Log::error("Manager-Add: $value"); //FIXME
$manager = User::find($value);
if ($manager) {
$object->manager_id = $manager->id;
@@ -153,7 +149,6 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig
}
)->setReplace(
function ($value, &$object) {
\Log::error("Manager-Replace: $value"); //FIXME
$manager = User::find($value);
if ($manager) {
$object->manager_id = $manager->id;
@@ -161,7 +156,6 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig
}
)->setRead(
function (&$object) {
\Log::error("Weird manager reader firing..."); //FIXME
return $object->manager_id;
}
),
+1 -1
View File
@@ -184,7 +184,7 @@ class Supplier extends SnipeModel
*/
public function addhttp($url)
{
if (! preg_match('~^(?:f|ht)tps?://~i', $url)) {
if (($url!='') && (! preg_match('~^(?:f|ht)tps?://~i', $url))) {
$url = 'http://'.$url;
}
+2 -1
View File
@@ -17,8 +17,9 @@ trait Acceptable
* @param User $acceptedBy
* @param string $signature
*/
public function acceptedCheckout(User $acceptedBy, $signature)
public function acceptedCheckout(User $acceptedBy, $signature, $filename = null)
{
\Log::debug('acceptedCheckout in Acceptable trait fired, tho it doesn\'t do anything?');
}
/**
+29
View File
@@ -561,6 +561,18 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
return false;
}
/**
* Get the admin user who created this user
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v6.0.5]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function createdBy()
{
return $this->belongsTo(\App\Models\User::class, 'created_by')->withTrashed();
}
/**
* Check whether two-factor authorization is required and the user has activated it
* and enrolled a device
@@ -685,6 +697,23 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
return $query->leftJoin('departments as departments_users', 'users.department_id', '=', 'departments_users.id')->orderBy('departments_users.name', $order);
}
/**
* Query builder scope to order on admin user
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param string $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeOrderByCreatedBy($query, $order)
{
// Left join here, or it will only return results with parents
return $query->leftJoin('users as admin_user', 'users.created_by', '=', 'admin_user.id')
->orderBy('admin_user.first_name', $order)
->orderBy('admin_user.last_name', $order);
}
/**
* Query builder scope to order on company
*
@@ -54,7 +54,6 @@ class CheckinAssetNotification extends Notification
* has the corresponding checkbox checked.
*/
if ($this->item->checkin_email() && $this->target instanceof User && $this->target->email != '') {
\Log::debug('use email');
$notifyBy[] = 'mail';
}
+23 -8
View File
@@ -18,22 +18,37 @@ class AssetObserver
public function updating(Asset $asset)
{
$attributes = $asset->getAttributes();
$attributesOriginal = $asset->getOriginal();
$attributesOriginal = $asset->getRawOriginal();
$same_checkout_counter = false;
$same_checkin_counter = false;
if (array_key_exists('checkout_counter', $attributes) && array_key_exists('checkout_counter', $attributesOriginal)){
$same_checkout_counter = (($attributes['checkout_counter'] == $attributesOriginal['checkout_counter']));
}
if (array_key_exists('checkin_counter', $attributes) && array_key_exists('checkin_counter', $attributesOriginal)){
$same_checkin_counter = (($attributes['checkin_counter'] == $attributesOriginal['checkin_counter']));
}
// If the asset isn't being checked out or audited, log the update.
// (Those other actions already create log entries.)
if (($attributes['assigned_to'] == $attributesOriginal['assigned_to'])
if (($attributes['assigned_to'] == $attributesOriginal['assigned_to'])
&& ($same_checkout_counter) && ($same_checkin_counter)
&& ((isset( $attributes['next_audit_date']) ? $attributes['next_audit_date'] : null) == (isset($attributesOriginal['next_audit_date']) ? $attributesOriginal['next_audit_date']: null))
&& ($attributes['last_checkout'] == $attributesOriginal['last_checkout']))
&& ($attributes['last_checkout'] == $attributesOriginal['last_checkout']))
{
$changed = [];
foreach ($asset->getOriginal() as $key => $value) {
if ($asset->getOriginal()[$key] != $asset->getAttributes()[$key]) {
$changed[$key]['old'] = $asset->getOriginal()[$key];
foreach ($asset->getRawOriginal() as $key => $value) {
if ($asset->getRawOriginal()[$key] != $asset->getAttributes()[$key]) {
$changed[$key]['old'] = $asset->getRawOriginal()[$key];
$changed[$key]['new'] = $asset->getAttributes()[$key];
}
}
}
if (empty($changed)){
return;
}
$logAction = new Actionlog();
$logAction->item_type = Asset::class;
+1 -1
View File
@@ -248,7 +248,7 @@ class AssetAuditPresenter extends Presenter
foreach ($fields as $field) {
$layout[] = [
'field' => 'custom_fields.'.$field->convertUnicodeDbSlug(),
'field' => 'custom_fields.'.$field->db_column,
'searchable' => true,
'sortable' => true,
'visible' => false,
+1 -1
View File
@@ -263,7 +263,7 @@ class AssetPresenter extends Presenter
// name can break the listings page. - snipe
foreach ($fields as $field) {
$layout[] = [
'field' => 'custom_fields.'.$field->convertUnicodeDbSlug(),
'field' => 'custom_fields.'.$field->db_column,
'searchable' => true,
'sortable' => true,
'switchable' => true,
@@ -48,13 +48,7 @@ class DepreciationReportPresenter extends Presenter
"sortable" => true,
"title" => trans('general.asset_model'),
"visible" => true,
], [
"field" => "model",
"searchable" => true,
"sortable" => true,
"title" => trans('admin/hardware/form.model'),
"visible" => true,
], [
], [
"field" => "model_number",
"searchable" => true,
"sortable" => true,
+8
View File
@@ -90,6 +90,14 @@ class LocationPresenter extends Presenter
'title' => trans('admin/locations/table.address'),
'visible' => true,
],
[
'field' => 'address2',
'searchable' => true,
'sortable' => true,
'switchable' => true,
'title' => trans('admin/locations/table.address'),
'visible' => false,
],
[
'field' => 'city',
'searchable' => true,
+8
View File
@@ -285,6 +285,14 @@ class UserPresenter extends Presenter
'visible' => true,
'formatter' => 'trueFalseFormatter',
],
[
'field' => 'created_by',
'searchable' => false,
'sortable' => true,
'title' => trans('general.created_by'),
'visible' => false,
'formatter' => 'usersLinkObjFormatter',
],
[
'field' => 'created_at',
'searchable' => true,
+11 -1
View File
@@ -75,12 +75,22 @@ class RouteServiceProvider extends ServiceProvider
/**
* Configure the rate limiters for the application.
*
* https://laravel.com/docs/8.x/routing#rate-limiting
*
* @return void
*/
protected function configureRateLimiting()
{
// Rate limiter for API calls
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip());
return Limit::perMinute(config('app.api_throttle_per_minute'))->by(optional($request->user())->id ?: $request->ip());
});
// Rate limiter for forgotten password requests
RateLimiter::for('forgotten_password', function (Request $request) {
return Limit::perMinute(config('auth.password_reset.max_attempts_per_min'))->by(optional($request->user())->id ?: $request->ip());
});
}
}
@@ -36,6 +36,11 @@ class SettingsServiceProvider extends ServiceProvider
// Model paths and URLs
\App::singleton('eula_pdf_path', function () {
return 'eula_pdf_path/';
});
\App::singleton('assets_upload_path', function () {
return 'assets/';
});
+3 -3
View File
@@ -130,11 +130,12 @@ class Saml
$this->clearData();
}
\Log::debug('Trying to create a new OneLogin_Saml2_Auth object ');
try {
$this->_auth = new OneLogin_Saml2_Auth($this->_settings);
} catch (Exception $e) {
\Log::error('Trying OneLogin_Saml2_Auth failed. Setting SAML enabled to false. OneLogin_Saml2_Auth error message is: '. $e->getMessage());
if ( $this->isEnabled() ) { // $this->loadSettings() initializes this to true if SAML is enabled by settings.
\Log::warning('Trying OneLogin_Saml2_Auth failed. Setting SAML enabled to false. OneLogin_Saml2_Auth error message is: '. $e->getMessage());
}
$this->_enabled = false;
}
}
@@ -157,7 +158,6 @@ class Saml
$this->_enabled = $setting->saml_enabled == '1';
if ($this->isEnabled()) {
\Log::debug('SAML is enabled according to loadSettings()');
//Let onelogin/php-saml know to use 'X-Forwarded-*' headers if it is from a trusted proxy
OneLogin_Saml2_Utils::setProxyVars(request()->isFromTrustedProxy());
+6 -6
View File
@@ -11,13 +11,13 @@
"license": "AGPL-3.0-or-later",
"type": "project",
"repositories": [
{
"type": "vcs",
"url": "https://github.com/grokability/laravel-scim-server"
}
{
"type": "vcs",
"url": "https://github.com/grokability/laravel-scim-server"
}
],
"require": {
"php": ">=7.4 <8.1",
"php": ">=7.4 <8.3",
"ext-curl": "*",
"ext-fileinfo": "*",
"ext-json": "*",
@@ -127,4 +127,4 @@
"discard-changes": true,
"process-timeout": 3000
}
}
}
Generated
+469 -292
View File
File diff suppressed because it is too large Load Diff
+24
View File
@@ -430,4 +430,28 @@ return [
'api_throttle_per_minute' => env('API_THROTTLE_PER_MINUTE', 120),
/*
|--------------------------------------------------------------------------
| Allow Web-Based Purge
|--------------------------------------------------------------------------
|
| This sets whether or not to allow superadmins to purge deleted data
|
*/
'allow_purge' => env('ALLOW_DATA_PURGE', false),
/*
|--------------------------------------------------------------------------
| Allow Backup Deletion
|--------------------------------------------------------------------------
|
| This sets whether or not to allow superadmins to delete backups
|
*/
'allow_backup_delete' => env('ALLOW_BACKUP_DELETE', false),
];
+16 -3
View File
@@ -98,14 +98,27 @@ return [
'email' => 'auth.emails.password',
'table' => 'password_resets',
'expire' => env('RESET_PASSWORD_LINK_EXPIRES', 900),
'throttle' => 60,
'throttle' => [
'max_attempts' => env('LOGIN_MAX_ATTEMPTS', 5),
'lockout_duration' => env('LOGIN_LOCKOUT_DURATION', 60),
]
],
],
/*
|--------------------------------------------------------------------------
| Resetting Password Requests
|--------------------------------------------------------------------------
| This sets the throttle for forgotten password requests
|
*/
'password_reset' => [
'max_attempts_per_min' => env('PASSWORD_RESET_MAX_ATTEMPTS_PER_MIN', 50),
],
/*
|--------------------------------------------------------------------------
| Password Confirmation Timeout
@@ -117,6 +130,6 @@ return [
|
*/
'password_timeout' => 10800,
'password_timeout' => env('PASSWORD_CONFIRM_TIMEOUT', 10800),
];
+248
View File
@@ -0,0 +1,248 @@
<?php
return array(
/*
|--------------------------------------------------------------------------
| Settings
|--------------------------------------------------------------------------
|
| Set some default values. It is possible to add all defines that can be set
| in dompdf_config.inc.php. You can also override the entire config file.
|
*/
'show_warnings' => false, // Throw an Exception on warnings from dompdf
'orientation' => 'portrait',
/*
* Dejavu Sans font is missing glyphs for converted entities, turn it off if you need to show and £.
*/
'convert_entities' => false,
'defines' => array(
/**
* The location of the DOMPDF font directory
*
* The location of the directory where DOMPDF will store fonts and font metrics
* Note: This directory must exist and be writable by the webserver process.
* *Please note the trailing slash.*
*
* Notes regarding fonts:
* Additional .afm font metrics can be added by executing load_font.php from command line.
*
* Only the original "Base 14 fonts" are present on all pdf viewers. Additional fonts must
* be embedded in the pdf file or the PDF may not display correctly. This can significantly
* increase file size unless font subsetting is enabled. Before embedding a font please
* review your rights under the font license.
*
* Any font specification in the source HTML is translated to the closest font available
* in the font directory.
*
* The pdf standard "Base 14 fonts" are:
* Courier, Courier-Bold, Courier-BoldOblique, Courier-Oblique,
* Helvetica, Helvetica-Bold, Helvetica-BoldOblique, Helvetica-Oblique,
* Times-Roman, Times-Bold, Times-BoldItalic, Times-Italic,
* Symbol, ZapfDingbats.
*/
"font_dir" => storage_path('fonts'), // advised by dompdf (https://github.com/dompdf/dompdf/pull/782)
/**
* The location of the DOMPDF font cache directory
*
* This directory contains the cached font metrics for the fonts used by DOMPDF.
* This directory can be the same as DOMPDF_FONT_DIR
*
* Note: This directory must exist and be writable by the webserver process.
*/
"font_cache" => storage_path('fonts'),
/**
* The location of a temporary directory.
*
* The directory specified must be writeable by the webserver process.
* The temporary directory is required to download remote images and when
* using the PFDLib back end.
*/
"temp_dir" => sys_get_temp_dir(),
/**
* ==== IMPORTANT ====
*
* dompdf's "chroot": Prevents dompdf from accessing system files or other
* files on the webserver. All local files opened by dompdf must be in a
* subdirectory of this directory. DO NOT set it to '/' since this could
* allow an attacker to use dompdf to read any files on the server. This
* should be an absolute path.
* This is only checked on command line call by dompdf.php, but not by
* direct class use like:
* $dompdf = new DOMPDF(); $dompdf->load_html($htmldata); $dompdf->render(); $pdfdata = $dompdf->output();
*/
"chroot" => realpath(base_path()),
/**
* Whether to enable font subsetting or not.
*/
"enable_font_subsetting" => false,
/**
* The PDF rendering backend to use
*
* Valid settings are 'PDFLib', 'CPDF' (the bundled R&OS PDF class), 'GD' and
* 'auto'. 'auto' will look for PDFLib and use it if found, or if not it will
* fall back on CPDF. 'GD' renders PDFs to graphic files. {@link
* Canvas_Factory} ultimately determines which rendering class to instantiate
* based on this setting.
*
* Both PDFLib & CPDF rendering backends provide sufficient rendering
* capabilities for dompdf, however additional features (e.g. object,
* image and font support, etc.) differ between backends. Please see
* {@link PDFLib_Adapter} for more information on the PDFLib backend
* and {@link CPDF_Adapter} and lib/class.pdf.php for more information
* on CPDF. Also see the documentation for each backend at the links
* below.
*
* The GD rendering backend is a little different than PDFLib and
* CPDF. Several features of CPDF and PDFLib are not supported or do
* not make any sense when creating image files. For example,
* multiple pages are not supported, nor are PDF 'objects'. Have a
* look at {@link GD_Adapter} for more information. GD support is
* experimental, so use it at your own risk.
*
* @link http://www.pdflib.com
* @link http://www.ros.co.nz/pdf
* @link http://www.php.net/image
*/
"pdf_backend" => "CPDF",
/**
* PDFlib license key
*
* If you are using a licensed, commercial version of PDFlib, specify
* your license key here. If you are using PDFlib-Lite or are evaluating
* the commercial version of PDFlib, comment out this setting.
*
* @link http://www.pdflib.com
*
* If pdflib present in web server and auto or selected explicitely above,
* a real license code must exist!
*/
//"DOMPDF_PDFLIB_LICENSE" => "your license key here",
/**
* html target media view which should be rendered into pdf.
* List of types and parsing rules for future extensions:
* http://www.w3.org/TR/REC-html40/types.html
* screen, tty, tv, projection, handheld, print, braille, aural, all
* Note: aural is deprecated in CSS 2.1 because it is replaced by speech in CSS 3.
* Note, even though the generated pdf file is intended for print output,
* the desired content might be different (e.g. screen or projection view of html file).
* Therefore allow specification of content here.
*/
"default_media_type" => "screen",
/**
* The default paper size.
*
* North America standard is "letter"; other countries generally "a4"
*
* @see CPDF_Adapter::PAPER_SIZES for valid sizes ('letter', 'legal', 'A4', etc.)
*/
"default_paper_size" => "a4",
/**
* The default font family
*
* Used if no suitable fonts can be found. This must exist in the font folder.
* @var string
*/
"default_font" => "serif",
/**
* Image DPI setting
*
* This setting determines the default DPI setting for images and fonts. The
* DPI may be overridden for inline images by explictly setting the
* image's width & height style attributes (i.e. if the image's native
* width is 600 pixels and you specify the image's width as 72 points,
* the image will have a DPI of 600 in the rendered PDF. The DPI of
* background images can not be overridden and is controlled entirely
* via this parameter.
*
* For the purposes of DOMPDF, pixels per inch (PPI) = dots per inch (DPI).
* If a size in html is given as px (or without unit as image size),
* this tells the corresponding size in pt.
* This adjusts the relative sizes to be similar to the rendering of the
* html page in a reference browser.
*
* In pdf, always 1 pt = 1/72 inch
*
* Rendering resolution of various browsers in px per inch:
* Windows Firefox and Internet Explorer:
* SystemControl->Display properties->FontResolution: Default:96, largefonts:120, custom:?
* Linux Firefox:
* about:config *resolution: Default:96
* (xorg screen dimension in mm and Desktop font dpi settings are ignored)
*
* Take care about extra font/image zoom factor of browser.
*
* In images, <img> size in pixel attribute, img css style, are overriding
* the real image dimension in px for rendering.
*
* @var int
*/
"dpi" => 96,
/**
* Enable inline PHP
*
* If this setting is set to true then DOMPDF will automatically evaluate
* inline PHP contained within <script type="text/php"> ... </script> tags.
*
* Enabling this for documents you do not trust (e.g. arbitrary remote html
* pages) is a security risk. Set this option to false if you wish to process
* untrusted documents.
*
* @var bool
*/
"enable_php" => false,
/**
* Enable inline Javascript
*
* If this setting is set to true then DOMPDF will automatically insert
* JavaScript code contained within <script type="text/javascript"> ... </script> tags.
*
* @var bool
*/
"enable_javascript" => true,
/**
* Enable remote file access
*
* If this setting is set to true, DOMPDF will access remote sites for
* images and CSS files as required.
* This is required for part of test case www/test/image_variants.html through www/examples.php
*
* Attention!
* This can be a security risk, in particular in combination with DOMPDF_ENABLE_PHP and
* allowing remote access to dompdf.php or on allowing remote html code to be passed to
* $dompdf = new DOMPDF(, $dompdf->load_html(...,
* This allows anonymous users to download legally doubtful internet content which on
* tracing back appears to being downloaded by your server, or allows malicious php code
* in remote html pages to be executed by your server with your account privileges.
*
* @var bool
*/
"enable_remote" => true,
/**
* A ratio applied to the fonts height to be more like browsers' line height
*/
"font_height_ratio" => 1.1,
/**
* Use the more-than-experimental HTML5 Lib parser
*/
"enable_html5_parser" => false,
),
);
+158
View File
@@ -0,0 +1,158 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Class Namespace
|--------------------------------------------------------------------------
|
| This value sets the root namespace for Livewire component classes in
| your application. This value affects component auto-discovery and
| any Livewire file helper commands, like `artisan make:livewire`.
|
| After changing this item, run: `php artisan livewire:discover`.
|
*/
'class_namespace' => 'App\\Http\\Livewire',
/*
|--------------------------------------------------------------------------
| View Path
|--------------------------------------------------------------------------
|
| This value sets the path for Livewire component views. This affects
| file manipulation helper commands like `artisan make:livewire`.
|
*/
'view_path' => resource_path('views/livewire'),
/*
|--------------------------------------------------------------------------
| Layout
|--------------------------------------------------------------------------
| The default layout view that will be used when rendering a component via
| Route::get('/some-endpoint', SomeComponent::class);. In this case the
| the view returned by SomeComponent will be wrapped in "layouts.app"
|
*/
'layout' => 'layouts.app',
/*
|--------------------------------------------------------------------------
| Livewire Assets URL
|--------------------------------------------------------------------------
|
| This value sets the path to Livewire JavaScript assets, for cases where
| your app's domain root is not the correct path. By default, Livewire
| will load its JavaScript assets from the app's "relative root".
|
| Examples: "/assets", "myurl.com/app".
|
*/
'asset_url' => env('APP_URL'),
/*
|--------------------------------------------------------------------------
| Livewire App URL
|--------------------------------------------------------------------------
|
| This value should be used if livewire assets are served from CDN.
| Livewire will communicate with an app through this url.
|
| Examples: "https://my-app.com", "myurl.com/app".
|
*/
'app_url' => null,
/*
|--------------------------------------------------------------------------
| Livewire Endpoint Middleware Group
|--------------------------------------------------------------------------
|
| This value sets the middleware group that will be applied to the main
| Livewire "message" endpoint (the endpoint that gets hit everytime
| a Livewire component updates). It is set to "web" by default.
|
*/
'middleware_group' => 'web',
/*
|--------------------------------------------------------------------------
| Livewire Temporary File Uploads Endpoint Configuration
|--------------------------------------------------------------------------
|
| Livewire handles file uploads by storing uploads in a temporary directory
| before the file is validated and stored permanently. All file uploads
| are directed to a global endpoint for temporary storage. The config
| items below are used for customizing the way the endpoint works.
|
*/
'temporary_file_upload' => [
'disk' => env('PRIVATE_FILESYSTEM_DISK', 'local'), // Example: 'local', 's3' Default: 'default'
'rules' => null, // Example: ['file', 'mimes:png,jpg'] Default: ['required', 'file', 'max:12288'] (12MB)
'directory' => null, // Example: 'tmp' Default 'livewire-tmp'
'middleware' => null, // Example: 'throttle:5,1' Default: 'throttle:60,1'
'preview_mimes' => [ // Supported file types for temporary pre-signed file URLs.
'png', 'gif', 'bmp', 'svg', 'wav', 'mp4',
'mov', 'avi', 'wmv', 'mp3', 'm4a',
'jpg', 'jpeg', 'mpga', 'webp', 'wma',
],
'max_upload_time' => 5, // Max duration (in minutes) before an upload gets invalidated.
],
/*
|--------------------------------------------------------------------------
| Manifest File Path
|--------------------------------------------------------------------------
|
| This value sets the path to the Livewire manifest file.
| The default should work for most cases (which is
| "<app_root>/bootstrap/cache/livewire-components.php"), but for specific
| cases like when hosting on Laravel Vapor, it could be set to a different value.
|
| Example: for Laravel Vapor, it would be "/tmp/storage/bootstrap/cache/livewire-components.php".
|
*/
'manifest_path' => null,
/*
|--------------------------------------------------------------------------
| Back Button Cache
|--------------------------------------------------------------------------
|
| This value determines whether the back button cache will be used on pages
| that contain Livewire. By disabling back button cache, it ensures that
| the back button shows the correct state of components, instead of
| potentially stale, cached data.
|
| Setting it to "false" (default) will disable back button cache.
|
*/
'back_button_cache' => false,
/*
|--------------------------------------------------------------------------
| Render On Redirect
|--------------------------------------------------------------------------
|
| This value determines whether Livewire will render before it's redirected
| or not. Setting it to "false" (default) will mean the render method is
| skipped when redirecting. And "true" will mean the render method is
| run before redirecting. Browsers bfcache can store a potentially
| stale view if render is skipped on redirect.
|
*/
'render_on_redirect' => false,
];
+5 -5
View File
@@ -1,10 +1,10 @@
<?php
return array (
'app_version' => 'v6.0.1',
'full_app_version' => 'v6.0.1 - build 7750-gb2e7572fe',
'build_version' => '7750',
'app_version' => 'v6.0.6',
'full_app_version' => 'v6.0.6 - build 8300-gdf1e2687d',
'build_version' => '8300',
'prerelease_version' => '',
'hash_version' => 'gb2e7572fe',
'full_hash' => 'v6.0.1-29-gb2e7572fe',
'hash_version' => 'gdf1e2687d',
'full_hash' => 'v6.0.6-172-gdf1e2687d',
'branch' => 'master',
);
@@ -0,0 +1,48 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use App\Models\Actionlog;
class RemoveStoredEulaField extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
$actionlog_eulas = Actionlog::whereNotNull('stored_eula_file')->get();
foreach ($actionlog_eulas as $eula_file) {
$eula_file->filename = $eula_file->stored_eula_file;
$eula_file->save();
}
$actionlog_bad_action_type = Actionlog::where('item_id', '=', 0)->whereNull('target_type')->whereNull('action_type')->whereNull('target_type')->get();
foreach ($actionlog_bad_action_type as $bad_action_type) {
$bad_action_type->delete();
}
Schema::table('action_logs', function (Blueprint $table) {
$table->dropColumn('stored_eula_file');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('action_logs', function (Blueprint $table) {
$table->string('stored_eula_file')->nullable()->default(null);
});
}
}
@@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddUserIdToUsers extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->integer('created_by')->after('activated')->nullable()->default(null);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
if (Schema::hasColumn('users', 'created_by')) {
$table->dropColumn('created_by');
}
});
}
}

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