Compare commits

...

422 Commits

Author SHA1 Message Date
snipe 3e222b674a Merge branch 'develop'
# Conflicts:
#	resources/views/hardware/view.blade.php
2017-09-22 17:04:43 -07:00
snipe e316444c63 Show suppliers link - force cache break? 2017-09-22 17:03:57 -07:00
snipe b29d7beb3a Merge branch 'develop'
# Conflicts:
#	.gitignore
#	Dockerfile
#	README.md
#	app/Http/Controllers/AccessoriesController.php
#	app/Http/Controllers/AssetMaintenancesController.php
#	app/Http/Controllers/AssetsController.php
#	app/Http/Controllers/ConsumablesController.php
#	app/Http/Controllers/GroupsController.php
#	app/Http/Controllers/LicensesController.php
#	app/Http/Controllers/ReportsController.php
#	app/Http/Controllers/UsersController.php
#	app/Http/routes.php
#	app/Models/Depreciation.php
#	app/Models/Location.php
#	config/version.php
#	resources/views/account/view-assets.blade.php
#	resources/views/hardware/edit.blade.php
#	resources/views/hardware/view.blade.php
#	resources/views/partials/modals.blade.php
#	resources/views/reports/custom.blade.php
#	snipeit.sh
2017-09-22 16:12:18 -07:00
snipe f0a49fefd7 Bumped version 2017-09-22 15:50:24 -07:00
snipe 998c4a5fe5 Make model number nullable 2017-09-22 04:43:28 -07:00
snipe 626a6408d0 Additional Danish and Polish translations 2017-09-18 19:12:37 -07:00
snipe 126a5671fe Set timeout for LDAP server 2017-09-18 19:11:38 -07:00
snipe aff104fa5d Bumped version for beta 2017-09-18 18:10:43 -07:00
Daniel Meltzer a5764351f7 Migrate weird assigned_type issues, Issue #3972 (#3973)
For a while, prior to 987536930, we did not null assigned_type on
checkin.  This migration manually nulls all assigned_type fields if
assigned_to is unset.  Add a test to AssetTest for this as well...kind
of.  We need to extract an Asset::checkin() method for 4.1 that mirrors
Asset::checkOut() to really test this.

This also fixes a separate (but related) issue.  The Asset importer did
not set assigned_type when importing and creating users.  In this
instance, we assume that if assigned_to is set and assigned_type is not,
then the item was checked out to a user and update the DB accordingly.
Also add a check in ImporterTest for this issue.
2017-09-18 16:40:13 -07:00
snipe 348becbbec Production assets generated 2017-09-18 13:01:54 -07:00
Daniel Meltzer 922d6937ae Custom field import repair (#3968)
* There is no notes field on accessories.  Fixes Importer Test.

* Fix notification test.  We should see a checkout not allowed exception when trying to check out to a location if the asset requires acceptance.

* Fix Custom field import.

Add a test for custom field import, and fix a few issues related to
importing custom fields.  This will restore v3 functionality.

* Add UI support for mapping custom fields.

This still requires the field mappings to be created/assigned in
advance, but will fetch all custom field names and allow them to be
selected when setting up custom field mappings.

This commit also updates laravel-mix to v1.4.3 and other node
dependencies to fix some build issues.

* Fix some requestable asset page/assetloc issues.  I'd love to know why laravel expections relationships to be in lower case... but thats a question for another day.
2017-09-18 12:29:08 -07:00
snipe c53dae4b72 Possible fix for #3919 - allow later versions of mcrypted base64 keys 2017-09-14 16:43:41 -07:00
snipe 17ad7f7800 Merge branch 'master' of github.com:snipe/snipe-it 2017-09-14 14:14:45 -07:00
snipe 6232a077b5 Fix more enum fuckery 2017-09-14 14:06:53 -07:00
snipe e7d72beb88 Also check for $snipeSettings in the first place
Since the preflight also uses this basic blade
2017-09-12 13:08:43 -07:00
snipe 01e3f4a4db Use site name if provided in the settings table for basic template 2017-09-12 13:01:51 -07:00
snipe 1b76880b0e Add @imanghafoori1 as a contributor 2017-09-12 12:30:21 -07:00
Iman ed4ea7f1f4 No new feature,No bug fix, Only refactoring (#3949)
* No change in logic !

Just exchanging the if and else code blocks and negating condition.

* remove unneeded else{} block

* Re-indented the code
2017-09-12 12:28:42 -07:00
snipe 81e358a01d Small maintenance fixes 2017-09-08 17:49:01 -07:00
snipe 6c283de60a Check for status_id key - related to #3928
TODO: Fix for model number
2017-09-08 17:24:28 -07:00
snipe 4e7a6c0ccf Fixes #3928 - adds correct key generation and passport install 2017-09-08 17:23:19 -07:00
snipe eba145503b Bumped version 2017-09-06 19:02:05 -07:00
snipe ae8c9d6afc Updated translations 2017-09-06 18:05:32 -07:00
snipe faeca4139d Added new languages, commented out ones with 0% translated 2017-09-06 17:51:11 -07:00
snipe 47909b93f7 Fixed deleted users/restore users view 2017-09-06 17:11:43 -07:00
snipe 472658b2fe Fixes #3924 - missing/donked language string 2017-09-06 17:11:23 -07:00
snipe 42a03a0436 Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-09-06 16:25:07 -07:00
Daniel Meltzer ae0573b3da Fix asset create (#3929)
* Fix accidental commit of ImporterTest.

* Move the name() method to the presenter

This fixes some weird collisions between laravels voodoo and our
presenter voodoo that confused php.  It's also probably a cleaner place
to put it.  Should fix #3927

* Add missing parenthesis

* Add heading to tables on locations/view page.
2017-09-06 16:24:43 -07:00
snipe 34f816097e Fixed missing quotation mark 2017-09-06 15:43:07 -07:00
snipe c651c9f1ed Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-09-05 18:35:43 -07:00
snipe 7c390cee2c Bumped version 2017-09-05 18:35:39 -07:00
Daniel Meltzer 987536930c Assorted fixes (#3923)
* Fix some n+1 problems

* Use route in notification dropdown to make sure we link to correct page

* Work on better UI support for checkout to non-user.  Fix links on index bootstrap table, work towards eliminating assignedUser

* Remove Asset::assigneduser() relationship.  Instead add a checkedOutToUser() method and/or port to using assignedTo()

* Adjust string to fit new reality

* Fix #3780.  Move the consumables getDataView method to the ApiController.  Not entirely RESTful, but it's a weird method that probably doesn't need its own controller and the functionality would be strange to stack on the userscontroller...

* Fix file uploads to assets and restore the delete route.

* Add asset maintence edit action to index.

* Suppliers asset list should link to the related asset, not to the supplier with same ID.

* Asset models page should use polymorphic formatter on assigned to to better handle assorted item types.

* Comment out more assigneduser fallacy until we figure out the query builder approach to searching for location text.
2017-09-05 17:54:58 -07:00
snipe 10f322198f Move audited count to top of table 2017-08-31 21:31:07 -07:00
snipe 761371509d Use notifiables for slack audit notification 2017-08-31 21:30:38 -07:00
snipe 3518ea7e7d Fixes #606 - email notifications for expected checkins 2017-08-31 21:18:05 -07:00
snipe c92eed2b3e Small HTML email tweaks 2017-08-31 21:17:02 -07:00
snipe 0054ce3071 Fixes #3907 2017-08-31 13:45:48 -07:00
snipe b0f74466bb Removed dd 2017-08-31 11:15:52 -07:00
snipe b4a0484295 Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-08-31 11:15:03 -07:00
Daniel Meltzer bb874012d9 Progress towards better email notifications (#3911)
Working mail from notification.  Still requires testing/cleaning

Add tests around checkout notification.

This also removes the ability to check out an asset to a location|asset
that requires acceptance/a Eula.  For 4.1 we may think about how to
support such a thing, but at present it seems to make sense to only alow
such assets to be checked out to users, who can be responsible for the
items.
2017-08-31 11:14:21 -07:00
snipe bb8583eb14 Remove lower casing for LDAP array re: #3910 2017-08-31 11:00:08 -07:00
snipe 8d2c229bc3 Move LDAP validation into form request 2017-08-31 10:44:00 -07:00
snipe 48e6208214 Fixes #3907 - do not require username on user if LDAP import 2017-08-31 10:43:36 -07:00
snipe 22233e3ba6 Bulk asset audit form (needs more testing) 2017-08-29 16:00:22 -07:00
KeenRivals fd515654ff Fix broken user's manual link (#3902)
snipe-it-manual.readme.io goes to a 404 page
2017-08-29 13:50:57 -07:00
snipe e439f15a64 Fixed some date math for auditing 2017-08-28 17:20:20 -07:00
snipe 42175782a5 Only pull logo if there is a value 2017-08-26 17:43:00 -07:00
snipe c7a21e0e4d Production asset build 2017-08-26 17:39:59 -07:00
snipe d98ffd94f9 Localized modal titles with correct headers 2017-08-26 16:16:41 -07:00
Brady Wetherington 6ad5da44f3 Formalize modals (#3898)
* Refactor Modal JS into standalone file, remove duplicated JS and HTML

* Finish fixing Bulk-checkout and checkout
2017-08-26 16:06:52 -07:00
snipe 479f422e68 Added default if no audit settings are in place 2017-08-26 15:27:50 -07:00
snipe e10cdd57a5 Removed old getassetloist method 2017-08-26 15:22:04 -07:00
snipe bf157773c8 Also related to #3888 2017-08-26 15:21:38 -07:00
snipe fba3949530 Fixes #3888 - broken preview of existing assets 2017-08-26 15:21:10 -07:00
snipe abc3dea8ac Fixed wonky datepicker on bulk checkout 2017-08-26 14:16:16 -07:00
snipe 51d74ac06d Auduting improvements 2017-08-25 18:40:20 -07:00
snipe af835d6efc Additional setting validation for new fields 2017-08-25 17:59:01 -07:00
snipe a7a10455ae Bumped version 2017-08-25 13:27:58 -07:00
snipe bd02b9ed62 Audit tweaks 2017-08-25 10:18:18 -07:00
snipe 16f57e16cb Fixes #1190 - added basic audit workflow 2017-08-25 10:04:19 -07:00
snipe af6f208c43 Reordered settings nav 2017-08-25 10:03:05 -07:00
snipe 52270fa4db Derp 2017-08-25 08:30:48 -07:00
snipe bf3731d65c Set default min password to 10 2017-08-25 08:23:23 -07:00
snipe 233ebf06ee ANOTHER fix for enum fuckery 2017-08-25 07:36:44 -07:00
snipe e27f6a483d Updated translations 2017-08-25 07:32:57 -07:00
snipe 19670f9dd8 Remove assigned_to constraint 2017-08-25 06:30:10 -07:00
snipe 1448229cd2 Fixes location user route 2017-08-25 06:30:00 -07:00
snipe 4721cab928 Grr. 2017-08-25 06:08:19 -07:00
snipe 08f3e78d26 Merge branch 'checkout-to-location-v2' of https://github.com/dmeltzer/snipe-it into dmeltzer-checkout-to-location-v2
# Conflicts:
#	app/Http/Controllers/Api/UsersController.php
#	app/Http/Transformers/LocationsTransformer.php
#	resources/views/locations/view.blade.php
#	routes/api.php
#	tests/_data/dump.sql
2017-08-25 06:04:22 -07:00
snipe 62227ec27d Link to location in user view 2017-08-25 05:48:32 -07:00
snipe 10711245ba Fixes #3792 - parent/child locations in API 2017-08-25 05:32:12 -07:00
snipe 29a7c8577d Fixes #3849 - fillable for accessories 2017-08-25 03:48:07 -07:00
snipe dfb1ff81e6 Fixes settings problem in unit tests 2017-08-25 03:40:56 -07:00
snipe 021e723acf Fixed typo 2017-08-25 03:27:41 -07:00
snipe 14c0c314aa Make sure payload is always passed, even if null 2017-08-25 03:27:31 -07:00
snipe d23ea70b08 Added auth check back to asset store 2017-08-25 03:26:50 -07:00
snipe 1b047c768b Added fullName() presenter for locations 2017-08-25 03:26:10 -07:00
snipe e6323e0a1b Version bump for beta 2 2017-08-24 23:32:33 -07:00
snipe 73ce5f98bb Removed some logging to make test debugging less verbose 2017-08-24 23:20:51 -07:00
Brady Wetherington a37cb616eb Add Error DIV's to all modals (#3886) 2017-08-24 22:43:05 -07:00
snipe 659d953f3f Fixed custom error message for status labels 2017-08-24 22:40:07 -07:00
Brady Wetherington c1dcc22217 Refactor and improve Modal support for Assets (#3884) 2017-08-24 22:24:02 -07:00
snipe 6a67426140 Create travis user? I don’t know wqhy it’s still looking for a travis user 2017-08-24 17:21:50 -07:00
snipe 4ba474cf73 Fixes asset test 2017-08-24 16:52:27 -07:00
snipe fb6caa35ff Only increment if settings table has a value
(This should only ever come up in the CI tests)
2017-08-23 14:07:01 -07:00
snipe a5870c888e Removed incrementer from non-asset event listeners 2017-08-23 13:59:59 -07:00
snipe f35f8477d3 Maybe the travis user isn’t created automatically anymore? 2017-08-23 13:42:17 -07:00
snipe d0637d38f3 More travis fixes 2017-08-23 13:32:30 -07:00
snipe 7141968d64 Trying to fix travis. Again. Always. 2017-08-23 13:22:01 -07:00
snipe 0f7b7d8e6a Add @zwerch as a contributor 2017-08-23 13:13:50 -07:00
snipe ca78b3ed7c Fixes models on create asset 2017-08-23 13:08:42 -07:00
snipe 2d2cae10b9 Fixed wonky “maintained” badge 2017-08-23 12:07:00 -07:00
Robin Temme 5347b19910 Update Maintained Badge (#3877)
The maintenance badge was outdated and displayed "no!". As I guess this was not it's intended purpose, I changed it to the new path, and it now displays "yes".
2017-08-23 12:05:29 -07:00
snipe 5e9331f5ae Fixed typo. (English is hard. Let’s go shopping!) 2017-08-23 04:00:10 -07:00
snipe 6e30fa6922 Fixes custom fields in asset listing where no custom fields were assigned 2017-08-23 03:28:13 -07:00
snipe 58b3f0519d Add empty errors array 2017-08-23 00:31:37 -07:00
snipe f119c69698 Possible fix for #3852 2017-08-22 22:46:02 -07:00
snipe 57f4c986af Enforce password complexity rules on new account password change 2017-08-22 22:41:35 -07:00
snipe 2958630923 Fixed some settings text 2017-08-22 22:11:26 -07:00
snipe 72dacda4f9 Trying again to resolve doctrine/php7 issue 2017-08-22 21:58:42 -07:00
snipe 9c2b986bb0 Fixes doctrine/etc compatibility issue
See: https://github.com/laravel/framework/issues/20490
2017-08-22 21:51:50 -07:00
snipe 06c5bce3c7 Fixes #3865 - employee number mislabeled in list output 2017-08-22 21:40:35 -07:00
snipe a0cbca85bf Fixes for API calls for password complexity stuff 2017-08-22 21:15:35 -07:00
snipe 9bda62d295 ADDED: Password rules for complexity, min length, rejecting common passwords 2017-08-22 20:32:39 -07:00
snipe 1d7e243d0a Fixes #3790 - parent display on locations index 2017-08-22 15:02:31 -07:00
snipe 63bc2ec09f Fixes #3802 - make id an (int) in API repsonse 2017-08-22 14:53:48 -07:00
snipe d5cadeab1a Fixes #3854 - more fillable fields for supplier API 2017-08-22 14:30:39 -07:00
snipe 31516abef9 Fixes #3858 - use transformer for single listing categories 2017-08-22 14:26:08 -07:00
snipe d2535582f3 Fixes #3853 - added notes/zip to suppliers API response 2017-08-22 14:18:21 -07:00
snipe eaaea303f4 Fixes #3860 - return JSON instead of redirect in API delete dept call 2017-08-22 14:15:13 -07:00
snipe 8c5312b931 Fixes #3866 - weird API behavior in status label types 2017-08-22 14:10:54 -07:00
snipe 4ef6e292d1 Fixes #3868 - model_number/notes in models API call 2017-08-22 13:56:51 -07:00
snipe 6310670835 Fixes #3869 - asset maintenances API endpoints 2017-08-22 13:52:06 -07:00
snipe 15bb30acd6 Fixes #3873 - show groups correctly on user listing page 2017-08-22 12:29:46 -07:00
snipe 148d41d8dc Removes erroneous else 2017-08-22 12:22:32 -07:00
snipe 71c1c74164 Fixes #3085 - adds “change password” functionality back to user accounts 2017-08-22 12:09:04 -07:00
snipe 9c02526a37 Make fields nullable in settings 2017-08-22 10:41:59 -07:00
snipe 25dc26aac3 Added 30 as page selector value for label printing 2017-08-21 22:31:37 -07:00
snipe afc763ebac Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-08-21 22:31:04 -07:00
snipe 6a73ec6537 First stab at a recrypter for legacy mcrypt conversion 2017-08-21 22:30:56 -07:00
Ryan McGuire 481143b891 Fixes for Red Hat Enterprise Linux 7 and CentOS 6 (#3846)
* Changes for Red Hat Enterprise Linux.

RHEL uses "rhel" in the ID field in /etc/os-release. We'll leave
"redhat" in the script just in case.

Also, RHEL uses a two digit version number in the VERSION_ID field. So
instead of looking for just "7", look for anything that starts with "7".
This should fix RHEL installations as well as not break anything
with CentOS.

* Fixes issue #3079.

"lsb_release -s -r" returns a two digit version number (at least on recent CentOS releases) while the script is looking for a single digit version. We'll change the script so that it only looks for the version starting with 6. This fixes recent releases of CentOS, while also not breaking previous versions that may have used a single digit.
2017-08-18 15:12:09 -07:00
Brady Wetherington cef67695cd New Dockerfile fixes to add support for the new barcode library (#3856) 2017-08-16 13:10:25 -07:00
snipe 4576cb6f56 Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-08-10 14:38:08 -07:00
snipe 56f88d2c22 Fixes #3836 - Adds supplier to licenses column 2017-08-10 14:38:04 -07:00
gibsonjoshua55 c1d1cb8122 Address #3840 and fixes group transformation in UsersTransformer (#3841)
Removes the incorrect variable access in UsersTransformer of a users's
groups and adds an array of groups' ids and names to the return array.
2017-08-10 13:37:54 -07:00
snipe ac8f46c93c Bumped version for beta release 2017-08-09 19:01:07 -07:00
snipe 101a09b421 Removed chart (for now) 2017-08-09 19:00:54 -07:00
snipe cb1e3b7978 Fixed encryption warning on custom fields 2017-08-09 18:40:45 -07:00
snipe de18e2a887 Only bcrypt passwords on user save if the password value is passed 2017-08-08 14:41:58 -07:00
snipe 241bf0cd4b Allow port number to be configured via env 2017-08-08 12:36:44 -07:00
snipe 7da4fe4524 Fixes #3825 - allows fillables through location API 2017-08-08 12:36:28 -07:00
snipe 9bfd345774 Use Company transformer with payload 2017-08-03 19:55:08 -07:00
snipe df87c82ddc Fixes #3805 - add/update/delete methods for User API 2017-08-03 19:50:18 -07:00
snipe 3e8b7d9c94 Check for overall asset delete permissions before checking to see if the user can delete that specific asset 2017-08-03 19:49:41 -07:00
snipe 7adfab9d9f Fixes #3632 and #3817 - set archived to default 0 so imported assets will be included in expiring reports 2017-08-03 16:04:47 -07:00
Jason Spriggs 7c4ee54f8b Fix #3803 - Return asset object instead of just id (#3811) 2017-08-01 20:01:11 -07:00
snipe 03f9d01aab Fixes #3775 - added missing created_at and updated_at fields 2017-07-29 17:01:03 -07:00
snipe 5b420fb4b9 Fixes #3779 - corrects presenter used for Consumables 2017-07-29 16:44:51 -07:00
snipe a2d63dd3e4 Fixes #3776 - adds Company to Dept UI 2017-07-29 16:42:17 -07:00
snipe 0408509fdc Fixes #3777 - correct response for two_factor_actived for user API 2017-07-29 16:25:42 -07:00
snipe 5e47c18d68 Fixes #3786 - checkin/checkout to components UI 2017-07-29 16:13:17 -07:00
snipe b3293a7a5f Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-07-29 15:46:38 -07:00
snipe 4e5cf531f7 Fixes #3799 - use transformers on show() method as well 2017-07-29 15:46:10 -07:00
Donald M f0bbe38c71 fixes #3725 in develop branch (#3800)
added button for create Asset Model to index.blade.php in develop branch.
2017-07-29 15:33:16 -07:00
snipe ccb7556281 Fixes javascript error when custom fields exist but do not belong to any fieldsets or models 2017-07-26 17:06:58 -07:00
snipe ee7348d0d5 Better fix for javascript formatter for employee number 2017-07-26 16:47:47 -07:00
snipe 7d6bf4ac24 Fixes stupid javascript for employee_number 2017-07-26 16:26:47 -07:00
snipe cb903ab9fd Fixes manager user->name to username in Users API 2017-07-26 08:51:16 -07:00
snipe 66d8308163 More compact payload for users API on location and manager 2017-07-26 08:47:54 -07:00
snipe 847262e989 Fixes #3774 - fixes for inconsistent API responses (‘’ vs null) and adds escaping 2017-07-25 23:40:30 -07:00
snipe 59006964d1 Fixes #3771 - adds username to API response on Asset API 2017-07-25 22:11:50 -07:00
snipe ac29b142dc Adds max thumbnail width to asset listings, settings 2017-07-25 19:36:38 -07:00
snipe 978a906513 Fixes undefined error when validation fails on asset save 2017-07-25 19:32:09 -07:00
snipe dfa0714d44 Fixes #3770 - account update not saving correctly 2017-07-25 12:28:11 -07:00
snipe 0fbf9236f4 Fixes #3742 - add employee number to asset listing
Also removes asset report, since it’s basically the exact same output as the asset listing
2017-07-25 01:17:23 -07:00
snipe c64ca76b3d Fixes API route 2017-07-25 01:16:31 -07:00
snipe 73052d3fc1 Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-07-25 00:24:26 -07:00
snipe ae0b639d0c Added link to AGPL 2017-07-25 00:24:22 -07:00
Jan Felix Wiebe 5cc84ca137 Use correct array when deleting users with location (#3769) 2017-07-24 23:15:15 -07:00
snipe 29f1cf2b48 Increase depreciation max 2017-07-19 19:41:21 -07:00
snipe 7510f9f128 Fixes #3753 - use route direction instead of URL 2017-07-17 16:42:39 -07:00
snipe 7c6143bbb8 Fixes #3754 - incorrect language translation location for supplier 2017-07-17 16:39:19 -07:00
snipe 346156bae1 Added colored icons to indicate status types versus status labels 2017-07-17 16:19:52 -07:00
snipe 3eea1a23f8 Slug the filename
So upoloads with weird characters like parens don’t get hoarked when trying to delete
2017-07-14 02:38:13 -07:00
snipe 1fda4593c1 Update @gibsonjoshua55 as a contributor 2017-07-12 20:41:20 -07:00
snipe 6b5a0983ee Added model validation to custom fieldsets 2017-07-12 19:34:45 -07:00
snipe ad12a5ce11 Added store/update methods to custom fields API 2017-07-12 19:34:34 -07:00
snipe ec09ea53db Changed custom fieldset API routes to resource routes for consistency 2017-07-12 19:24:21 -07:00
snipe 5abe72ce02 Added whether the field is required to the custom fieldsets transformer 2017-07-12 19:23:54 -07:00
snipe 3e3276334b Added escaping to API output 2017-07-12 19:23:15 -07:00
snipe b13e04095e Removed commented code 2017-07-12 19:22:58 -07:00
gibsonjoshua55 3cfcc43efa Adds basic GET api support for CustomFieldsets (#3697)
* Adds basic GET api support for CustomFieldsets

Currently there is not support for getting what fields a given fieldset contains
from the API.  This commit creates a new API Controller for CustomFieldsets as
well as Transformers for CustomFields CustomFieldsets.  Additionally, the api
route has been updated so that a show method can be access from
http://myapp/api/v1/fieldsets/{id}

* CustomFieldsetsTransformer only returns id and name of model

* Added index api method for CustomFieldsets

* Removes copy/paste error in CustomFieldsetController (including search)

* Added id to CustomFieldsetsTransformers

* Adds custom_fieldset_id as a field when storing and updating AssetModels

* Removed uncessesary parameter from CustomFieldsetsController.index

* Cleaned up CustomFieldset API
2017-07-12 17:51:22 -07:00
Daniel Meltzer f432f98e12 Importer tests + Fixes (#3733)
* Fix Bug in User::generateFormattedNameFromFullName

In a name "John Doe", this method would split it into "John" and " Doe",
Leaving a space in the last name when importing to the database.  Strip
this space.

* Cleanup/fix some item mapping.

Also make some changes to the importer schema to allow for unit testing.
Generate a default item mapping, and then merge that with any custom
mappings.

* Beginning work on importer unit tests.

* Strip out testrun branches from importer.  It added a lot of complexity and was not terribly useful with web importer as it stood, might reconsider down the road however.

* Normalize the mapped keys when using custom field mappings.

* Add test for custom asset import mapping.

* Make all unit tests inherit from a new custom base.

This baseclass currently calls Artisan::migrate() and seeds a Settings
instance.  This fixes unit tests after the autoincrement bits.

* Store requestable as a boolean.  Fixes some import oddities

* Work on tests for accessory importer.

* Test for custom mapping of accessory import, also adjust the internal field for purchase date.

* Update default locale fallback for currency detection

* Fix Reassignable in consumable as well.

* More importer tests and fixes.
2017-07-11 20:37:02 -07:00
Sorvani f56862c684 change CentOS 7 to pull from git (#3734)
The package setup for CentOS 7 already installs git so use it for the install. This makes later updates easier for the end users. They can simply use git pull like the instructions say for updating.
2017-07-11 20:28:31 -07:00
snipe 9bcfe0748b Make custom fields into their own JSON array 2017-07-08 18:44:28 -07:00
snipe de5e7bd9ba Removed null formatter 2017-07-08 17:04:52 -07:00
snipe 635299cd74 Decrypt encrypted fields 2017-07-08 17:04:40 -07:00
snipe 20376daec4 Fix encryption on first save 2017-07-08 17:04:24 -07:00
snipe 50e1570543 Added additional models for #3702 2017-07-08 14:49:43 -07:00
snipe eb94c4333d Fixes #3702 - Added artisan command to walk through special characters and unescape them in the DB 2017-07-08 14:47:43 -07:00
snipe a49fd16916 Fixed delete file settings route 2017-07-08 13:42:05 -07:00
snipe 0cc9c214aa Added tooltip for undeployable items 2017-07-08 13:39:07 -07:00
snipe c48bcb7ed1 Added tooltips for checkin/checkout 2017-07-08 13:36:37 -07:00
snipe 09de201027 Removed question mark on delete title 2017-07-08 13:36:25 -07:00
snipe 6ce2127d75 Fixes incorrect link on dashboard 2017-07-08 13:36:06 -07:00
snipe e79260a0d4 Fixes #3732 - broken tooltips and weird select2 option text behavior
The solve here was a few things - first, load jquery-ui before bootstrap. They have conflicting tooltips. Second, initiate the tooltips in the wenzhixin/bootstrap-table formatter using `data-tooltip=“true”`, and thirdly, add some JS that tells BS table to inititalize tooltips within the table using that `data-tooltip=“true”` business
2017-07-08 13:21:13 -07:00
snipe 932e25ca9b Only add an update log message if the asset isn’t being checked in or out 2017-07-08 03:38:39 -07:00
snipe b02148f59e Updated formatter for location display 2017-07-08 02:24:30 -07:00
snipe 6046063666 Updated LDAP icon 2017-07-08 02:24:20 -07:00
snipe fd57617c8e Check that the LDAP extension is loaded and functions are available 2017-07-08 01:48:29 -07:00
snipe 44569558e9 Remove admin label 2017-07-08 01:41:07 -07:00
snipe d2f6c8af11 Require first name field if LDAP is enabled 2017-07-08 01:40:56 -07:00
snipe 814bf18a4b Updated phpinfo title 2017-07-08 00:23:28 -07:00
snipe 33557f3792 Nicer formatting for phpinfo output 2017-07-08 00:22:30 -07:00
snipe c2927c4a2e Added phpinfo page if debugging is enabled 2017-07-08 00:09:39 -07:00
snipe ab2b2f3043 Updated UI for Admin Settings 2017-07-07 23:44:48 -07:00
snipe 0e598702f8 Fixed error field name in settings > login note 2017-07-07 19:56:14 -07:00
snipe 9894edb008 Added login note to settings 2017-07-07 19:54:10 -07:00
snipe c2e8803d1e Addec clone button back to models, assets, licenses, etc 2017-07-07 18:45:49 -07:00
snipe 7e1f7297b3 Settings tweaks 2017-07-07 18:06:31 -07:00
snipe 3401f3dfb9 Added @uberbrady as code owner of custom fields API too 2017-07-07 17:10:23 -07:00
snipe 31cabaa4db Fixes #3724 - adds edit/delete button back to companies listing 2017-07-07 17:10:06 -07:00
snipe 06c04bf271 Created a contibuting md so GH would stop whining at me
(even though it’s documented elsewhere)
2017-07-07 16:37:11 -07:00
snipe 4c39be1f3c First stab at a code owners doc
More info:
https://github.com/blog/2392-introducing-code-owners
https://help.github.com/articles/about-codeowners/
2017-07-07 16:36:45 -07:00
snipe c8c279588f Updated language strings 2017-07-07 13:14:51 -07:00
snipe 8aa920ca3a Update composer 2017-07-07 12:59:59 -07:00
snipe 0242283a11 Updated composer 2017-06-23 18:56:42 -07:00
snipe 9e0c5e50b6 Merge branch 'develop' of github.com:snipe/snipe-it into develop
# Conflicts:
#	composer.lock
2017-06-23 18:55:18 -07:00
snipe 95d1612234 Updated composer 2017-06-23 18:52:21 -07:00
Daniel Meltzer 61c6160b98 Importer mapping - v1 (#3677)
* Move importer to an inline-template, allows for translations and easier passing of data from laravel to vue.

* Pull the modal out into a dedicated partial, move importer to views/importer.

* Add document of CSV->importer mappings.  Reorganize some code.

Progress.

* Add header_row and first_row to imports table, and process upon uploading a file

* Use an expandable table row instead of a modal for import processing.  This should allow for field mapping interaction easier.

* Fix import processing after moving method.

* Frontend importer mapping improvements.

Invert display so we show found columns and allow users to select an
importer field to map to.  Also implement sample data based on first row
of csv.

* Update select2.  Maintain selected items properly.

* Backend support for importing.  Only works on the web importer currently.  Definitely needs testing and polish.

* We no longer use vue-modal plugin.

* Add a column to track field mappings to the imports table.

* Cleanup/rename methods+refactor

* Save field mappings and import type when attempting an import, and repopulate these values when returning to the page.

* Update debugbar to fix a bug in the debugbar code.

* Fix asset tag detection.

Also rename findMatch to be a bit clearer as to what it does.
  Remove logging to file of imports for http imports because
it eats an incredible amouint of memory.

This commit also moves imports out of the hardware namespace and into
their own webcontroller and route prefix, remove dead code from
AssetController as a result.

* Dynamically limit options for select2 based on import type selected, and group them by item type.

* Add user importer.

Still need to implement emailing of passwords to new users, and probably
test a bit more.

This also bumps the memory limit for web imports up as well, I need to
profile memory usage here before too long.

* Query the db to find user matches rather than search the array.  Performance is much much better.

* Speed/memory improvements in importers.

Move to querying the db rather than maintaining an array for all
importers.  Also only store the id of items when we import, rather than
the full model.  It saves a decent amount of memory.

* Remove grouping of items in select2

With the values being set dynamically, the grouping is redundant.  It
also caused a regression with automatically guessing/matching field
names.  This is starting to get close.

* Remove debug line on every create.

* Switch migration to be text field instead of json field for compatibility with older mysql/mariadb

* Fix asset import regression matching email address.

* Rearrange travis order in attempt to fix null settings.

* Use auth::id instead of fetching it off the user.  Fixes a null object reference during seeding.
2017-06-21 16:37:37 -07:00
Daniel Meltzer d12159c042 Fix travis with new observer code (#3683)
* Rearrange travis order in attempt to fix null settings.

* Use auth::id instead of fetching it off the user.  Fixes a null object reference during seeding.
2017-06-20 20:38:13 -07:00
snipe e009bb956d Possible fix for travis donkery 2017-06-20 19:48:57 -07:00
snipe 25e99194ce Fixes #3681 - corrected fieldname for bulk asset delete 2017-06-20 14:41:30 -07:00
snipe 274f3511f5 Fixes new setup migration for auto-increment 2017-06-20 12:23:32 -07:00
snipe 5b9bcd8fa2 Add next auto-increment to settings form 2017-06-20 12:23:16 -07:00
snipe 4bde058192 Save next_auto_tag_base in settings on edit 2017-06-20 12:19:05 -07:00
snipe ffba9789b7 Fixed typo in variable name 2017-06-20 12:13:36 -07:00
snipe 1052be670d Increase size of state field 2017-06-15 21:04:10 -07:00
snipe 770092f23f Added save/update/delete observers
This should make it easier to handle action logging between the GUI and the API
2017-06-15 20:54:14 -07:00
snipe 99f65cbf69 Hopefully fixes #3203 and #3439 2017-06-15 19:42:43 -07:00
Daniel Meltzer 5d4920c741 [WIP] Improvements to unit tests. (#3574)
* Improvemenets to unit tests.

* Break up modelfactory into multiple files, populate many states.
* Begin testing validation at the unit test level, test relationships.
* Add tests for Asset::availableForCheckout.
* Model factories now generate all needed relationships on demand,
  which allows us to unit test with a empty database.
* To faciliate the empty database, we move to using sqlite in memory as
  the unit testing database.

* Fix bug with logs of checkouts to non users.

* Fix location finding for assets.  Also Fix location show page to show users associated with location.  Still need some work to show assets.

* More test and generator improvements

* More unit test fixes. PermissionsTest is borked still.

* More Updates

* Rewrite permissionstest.  Check that we have access on the model level rather than via web requests.  Also test delete permissions.

* Fix seeders.

* Make the default asset model factory generate assets that are rtd for testing.

* Save progress.

* Rebase tests, fix department unit test, update database for functional tests.

* Update functional and api tests to use new modelfactory signatures.
2017-06-12 17:39:03 -07:00
Daniel Meltzer 54279f22a3 Update DB to fix tests. 2017-06-12 18:24:20 -05:00
Daniel Meltzer dfea47a272 Fix location view display. Migrate to api controller methods and fix missing bits to make this happen. Show manager on the location view page. 2017-06-12 18:24:20 -05:00
Daniel Meltzer f0d78091d2 Add a manager field to locations.
This is round one of the rethink of checkout-to-everything.  A location
now has a manager field, and the manager (by default) be responsible for
assets checked out to the location.
2017-06-12 18:23:50 -05:00
snipe 966a736602 Patches #3640 to develop 2017-06-12 15:31:11 -07:00
Daniel Nemanic 30a9704625 Update UsersController.php (#3640)
If a user is disabled in your Active Directory, it should be deactivated in the licensing too.

The standard state is now deactivated for synced accounts.
Maybe we can change this throw a Setting for a standard state.

The codes comes from this site:
http://www.netvision.com/ad_useraccountcontrol.php
2017-06-12 15:29:55 -07:00
Daniel Meltzer 30487bfee7 Fix importer vue issues. (#3655)
We currently depend on a "vue-strap" module to provide the modal dialog.
The default npm vue-strap is not compatible with vue2, so we need to use
a fork.  Update package.json to reflect this.  Probably makes sense to
move away from vue-strap in all my copious amounts of free time.
2017-06-12 15:24:49 -07:00
snipe 3046d7d33c Fixes #3644 - broken datepicker 2017-06-09 18:53:19 -07:00
snipe 0aa76bd946 PHPStorm lag strikes again 2017-06-09 16:49:55 -07:00
snipe 26d7fffae8 Added in/out string to general 2017-06-09 16:47:28 -07:00
snipe 14f3868b46 Update all controllers to use laravel 5 return view method 2017-06-09 16:44:03 -07:00
snipe a5cd4a0a22 Use updated view method for laravel 5 2017-06-09 16:31:25 -07:00
snipe ad816264e9 WIP import mapper #3639
@dmeltzer, I’m not sure how much extra work this will be to integrate.
2017-06-09 16:29:42 -07:00
snipe c2494fe0e5 Removed social buttons for BS styles 2017-06-09 14:59:23 -07:00
snipe 02edb74cdf Style updates 2017-06-09 14:58:43 -07:00
snipe 408bb6476f Removed some unneeded styles 2017-06-09 14:57:57 -07:00
snipe ee5b5acffb Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-06-09 12:44:49 -07:00
snipe e387673e74 Fixes #3651 - backups not working 2017-06-09 12:44:11 -07:00
Ben 17ce4ea08b Fixes #3649 (#3650)
Fixes issue #3649 with gohilurvish’s recommended fix.
2017-06-09 12:23:32 -07:00
snipe 0bc709206f Fixes #3652 - missing groups UI element in user edit view 2017-06-09 12:19:12 -07:00
snipe e9dd119b9c Fixes some vue styles 2017-06-09 02:06:10 -07:00
snipe 269997a1fb Push v3.6.5 changes into v4 2017-06-09 00:35:23 -07:00
snipe 041b794e1f Fixes #3634 - use new routes for groups 2017-06-08 20:24:26 -07:00
snipe da2d9b2374 Fixes presenter issue on user history 2017-06-08 19:09:42 -07:00
snipe a59db7062d Fix license datatable on license view 2017-06-08 18:59:53 -07:00
snipe 58b2834c54 Fixed case for userloc 2017-06-08 18:46:07 -07:00
snipe 2aaa635345 Fixes crash on asset detail view 2017-06-08 18:26:55 -07:00
snipe 8269aec71a Removed erroneous file 2017-06-08 17:51:30 -07:00
snipe d62896f945 Fixes #3414 - bulk update for asset models 2017-06-08 17:48:48 -07:00
snipe a717ca683c Fixes #3648 - missing endif in blade 2017-06-08 16:16:49 -07:00
snipe d7827fedd9 Fixed dashboard size element 2017-06-06 15:19:19 -07:00
snipe fbcc40a145 Commented out dashboard chart until proper data provided 2017-06-06 02:51:29 -07:00
snipe 12a7309ecd Note that the chart doesn’t work, to clear things up 2017-06-06 02:40:50 -07:00
snipe 9caf045930 Production assets 2017-06-06 02:36:02 -07:00
snipe 1c056d1a59 Updated asset urls 2017-06-06 02:35:26 -07:00
snipe 240a07b108 Formatting for error pages 2017-06-06 02:32:04 -07:00
snipe c977dda5bb Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-06-06 01:45:25 -07:00
snipe 03411a3ae8 Removed poop class, added comment to webpack file 2017-06-06 01:44:17 -07:00
snipe 01cc00c832 Fixing webpack. Again 2017-06-06 01:39:53 -07:00
snipe 9338b37b74 Try to fix the datepicker :(
Webpack has fucked everything. I hate everything.
2017-06-06 00:51:41 -07:00
snipe 9cd2881ad0 Initiate datepicker 2017-06-06 00:29:52 -07:00
snipe 64b483b686 Updated build css output
I don't know why I need to do this. :(
2017-06-06 00:06:29 -07:00
snipe 1f7266274d Updated manifest 2017-06-06 00:06:01 -07:00
snipe 4e5b2d1fe9 Updated font awesome 2017-06-06 00:05:47 -07:00
snipe ada2ac06f2 Minified all.css 2017-06-06 00:05:22 -07:00
snipe 9d948e8d23 Removed erroneous bower dir 2017-06-06 00:04:55 -07:00
snipe 4062228092 Updated contribs 2017-06-05 23:54:13 -07:00
Wyatt 3e67cdc501 Allows a null location value for importing LDAP users (#3598)
* Allows a null location value for importing LDAP users

* Forgot you need to set the variable to null..
2017-06-01 21:20:40 -07:00
snipe be42a0add1 Add @steveelwood as a contributor 2017-06-01 21:03:05 -07:00
snipe 6cadde23d7 Add @manassesferreira as a contributor 2017-06-01 21:00:47 -07:00
snipe a6c1f7b30b Add @n8felton as a contributor 2017-06-01 20:59:15 -07:00
snipe 1b5b0e9d19 Add @jasonspriggs as a contributor 2017-06-01 20:58:50 -07:00
snipe 2a226fd3f9 Update @pakkua80 as a contributor 2017-06-01 20:58:26 -07:00
snipe 043182593d Add @BrettFagerlund as a contributor 2017-06-01 20:57:55 -07:00
snipe 08dc07b46b Apply PR #3620 to develop (oracle linux support) 2017-06-01 20:55:30 -07:00
Lee Thoong Ching 9a9b6ae228 Update snipeit.sh (#3620)
To support Oracle Linux ( equivalent to redhat which check os version and type )
2017-06-01 20:54:23 -07:00
snipe 2d3ea4eec6 Apply PR #3616 (Docker updates) 2017-06-01 20:53:01 -07:00
morph027 7c8dc9fe2d docker: use ubuntu:xenial with php7.0 (#3616)
Nice, thanks! I'll patch this over to develop as well.
2017-06-01 20:50:09 -07:00
snipe 74aaadcdc5 Fixes #3583 - incorrect 404 status code, use curl for checking .env 2017-06-01 20:41:23 -07:00
snipe 0238dd59a3 Fixes #3600 - wrong route for hardware 2017-06-01 20:34:01 -07:00
snipe 461ca53289 Fixes #3603 - Depreciation report crashes 2017-06-01 20:31:44 -07:00
snipe ccc0063556 Fixes #3604 - company view not displaying assets on page load 2017-06-01 20:28:09 -07:00
snipe 66145a625c Upgraded laravel mix 2017-05-31 13:57:34 -07:00
snipe cc5192c91e Updated asset url 2017-05-31 13:57:23 -07:00
snipe de5334e525 Updated with production assets 2017-05-31 13:27:17 -07:00
snipe b797604627 Fixed &%#!@@!ing ES that prevented npm run production from working 2017-05-31 13:26:48 -07:00
snipe 293981148c Few more stabs at this dumb uglify error 2017-05-31 12:56:09 -07:00
snipe 66eaff739a More npm/css/js updates 2017-05-31 12:34:05 -07:00
snipe 8b5cb6e8c2 Added build directory for misc laravel mix crap 2017-05-31 12:01:45 -07:00
snipe 7b4b2d79cf Moved CSS/JS/etc assets up one level 2017-05-31 10:31:56 -07:00
snipe c3af13298e Added webpack.mix.js
Everything is terrible
2017-05-31 10:28:53 -07:00
snipe 312fd27d11 Removed weird temp file 2017-05-31 10:28:07 -07:00
snipe 1b55d38c63 Attempts at un-fscking package.json for laravel mix 2017-05-31 10:26:27 -07:00
snipe 1992906790 Use laravel mix asset call 2017-05-31 09:41:52 -07:00
snipe b0fc2489f6 Almost fixes user history table
Something is still fucky here
2017-05-31 09:39:52 -07:00
snipe b13726880e Fixes #3601 - HTML instead of username for manager in user view 2017-05-31 09:39:30 -07:00
snipe 25dca80644 Fixes #3602 - actions missing from suppliers in v4 2017-05-31 06:52:37 -07:00
snipe 748aba3c48 Add assets dashboard feature
- also a really broken sample graph
2017-05-31 05:23:54 -07:00
snipe c9484fa30b Updated compiled assets 2017-05-31 05:23:26 -07:00
snipe d950ddbda7 Changed go button to primary class 2017-05-31 05:23:09 -07:00
snipe fd0165b4b8 New compiled assets 2017-05-31 03:32:29 -07:00
snipe fd0da6ecf0 Ignore the icon column in exports 2017-05-31 02:03:09 -07:00
snipe 7b1265cb89 Cache totals for later dashboard use 2017-05-31 02:02:55 -07:00
snipe 92052442e3 Include department in user info 2017-05-31 01:17:30 -07:00
snipe 71b668e1a3 Removed extra else to make Codacy happy 2017-05-23 15:53:39 -07:00
snipe 3c167c9d33 Remove debugging frowny-face 2017-05-23 15:06:43 -07:00
snipe 9f87f72c96 Updated route name for activity report API call 2017-05-23 14:33:36 -07:00
snipe 5e0cc93ba2 Use new formatters in bootstrap table 2017-05-23 14:33:19 -07:00
snipe 3724442318 Exclude some BS table calls if it’s just a simple ajax table with no sorting/searching 2017-05-23 14:32:58 -07:00
snipe 610a773620 Use activity report for view-assets 2017-05-23 14:32:21 -07:00
snipe a1c7d2922e Tweaks to dashboard API calls 2017-05-23 14:32:02 -07:00
snipe 8ab29c628f Added icon to presenter 2017-05-23 14:31:44 -07:00
snipe 4ada5eaa94 Added targetType method 2017-05-23 14:31:14 -07:00
snipe 5499735f3a Actionlogs API transformer 2017-05-23 14:31:04 -07:00
snipe 40e11b6661 Removed old getActivityReportDataTable() method, since we’re using the API now 2017-05-23 14:30:55 -07:00
snipe b1fa25b73e Added filter to report by user_id for activity 2017-05-23 14:30:29 -07:00
snipe 452c52a3ab Changed variable name for consistency 2017-05-23 14:30:07 -07:00
snipe 76926c97c1 Updated dashboard to use new API activity report and added category summary 2017-05-23 09:25:45 -07:00
snipe 6775c39a5e Added simple_view to use compact, no pagination view of tables 2017-05-23 09:25:20 -07:00
snipe ce856bdb0a Moves activity report into API routes 2017-05-23 09:24:53 -07:00
snipe 52f24f7587 Reports API controller 2017-05-23 09:24:36 -07:00
snipe fba7f1ccf6 Fixes #3605 - missing table close tag causing page layout bonking 2017-05-23 03:20:50 -07:00
snipe ed46dee646 Dept tests 2017-05-23 03:03:30 -07:00
snipe 332076bbe5 Fixed location test method name 2017-05-23 03:03:25 -07:00
snipe 9d45375b8a Added dept to user edit/create/bulk edit views 2017-05-23 02:51:09 -07:00
snipe d3b07411da Added depts to bootstrap-table javascript formatters 2017-05-23 02:50:51 -07:00
snipe d17d3a2ef0 Dept views 2017-05-23 02:50:27 -07:00
snipe dd8511c66a Dept strings 2017-05-23 02:50:16 -07:00
snipe f57ebc664e Added dept management to permissions 2017-05-23 02:50:08 -07:00
snipe f285bd3c29 Added Dept field to users table presenter 2017-05-23 02:49:51 -07:00
snipe aeca549bab Dept search in User query scopes 2017-05-23 02:49:27 -07:00
snipe e0d2cbef20 Allow manager to be null for dept 2017-05-23 02:49:00 -07:00
snipe 96e8109d01 Allow location/company/manager to be null via validation 2017-05-23 02:48:51 -07:00
snipe b223630f72 Added dept to User API transformer 2017-05-23 02:48:03 -07:00
snipe e9c39add4f Added dept helper reference in create/edit/bulk edit users 2017-05-23 02:47:49 -07:00
snipe 7ec1724308 Create, edit and destroy for depts 2017-05-23 02:47:25 -07:00
snipe 811ddd2f67 Include depts in returned list, sort by dept 2017-05-23 02:46:55 -07:00
snipe cefb20d46f Set dept manager ID for dept 2017-05-23 02:46:25 -07:00
snipe bb323db685 Load relationships in query 2017-05-23 02:46:03 -07:00
snipe eb3aa99e4f Added destroy method to dept 2017-05-23 02:45:51 -07:00
snipe a7592de304 Added helper for dept list 2017-05-23 02:37:37 -07:00
snipe 64f17cecbf Updated department transformer 2017-05-23 02:37:30 -07:00
snipe e2f2f9e154 Additional methods for Department web UI 2017-05-23 01:09:13 -07:00
snipe 8caf6623f1 Filter by dept for user display 2017-05-23 01:09:03 -07:00
snipe 6c623866c0 Additional API methods for departments 2017-05-23 01:08:55 -07:00
snipe 659e60fd12 Department controllers and transformer 2017-05-22 21:32:33 -07:00
snipe ae329f4160 Department model 2017-05-22 21:32:22 -07:00
snipe e314de3594 Department migration 2017-05-22 21:32:12 -07:00
snipe b0479923b1 Add link to departments 2017-05-22 21:31:58 -07:00
snipe e3a5accace Departments routes 2017-05-22 21:31:47 -07:00
snipe b81dd18576 Fixed delete_at 2017-05-19 03:00:19 -07:00
snipe dac4b58892 Show warning on deleted items 2017-05-19 02:58:55 -07:00
snipe 71fd430f8e Fixes issue with older, deleted asset tags caching QR codes 2017-05-19 02:51:35 -07:00
snipe 5265821bcc Bumped version 2017-05-18 22:24:03 -07:00
snipe cb494a74ca Merge branch 'master' of github.com:snipe/snipe-it 2017-05-18 22:20:57 -07:00
snipe c526ffbf68 Bumped version 2017-05-18 22:20:52 -07:00
snipe 6f5fe83a91 Fixed missing language string in asset display 2017-05-18 22:20:43 -07:00
snipe 0c43e64160 Licenses detail view 2017-05-18 22:10:45 -07:00
snipe 708385e23a Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-05-16 12:32:05 -07:00
Jason Spriggs 0ab37af7ab Add in location parent and child information into API requests (#3582)
* Add location hierarchy to LocationsTransformer

* Add in parent_id
2017-05-16 12:30:11 -07:00
snipe 891660d4ea Fixes #3580 - reduce minimim username size to 1 2017-05-16 12:26:38 -07:00
snipe dcfc434075 Added suppliers back to new side menu (oops) 2017-05-15 20:55:53 -07:00
snipe 0c8308f5a4 Fixes for ordering on asset listing 2017-05-15 20:55:39 -07:00
snipe 1bd798c4d2 Removed Brady’s email address 2017-05-15 19:51:05 -07:00
snipe 23be188a49 Fixes #3579 2017-05-15 19:28:26 -07:00
snipe fdd88af44a Fixes #3556 2017-05-15 19:14:55 -07:00
Nate Felton 5a3816c907 Fixing a regression for RHEL 6 with snipe/snipe-it#2993 (#3572) 2017-05-12 17:19:41 -07:00
snipe c8796cf045 Only prompt for checkin if there is an assigned user 2017-05-10 03:37:30 -07:00
snipe f4095c6dd0 Bumped version 2017-05-09 15:32:34 -07:00
snipe ee2c67a65f Added missing logging back in 2017-05-09 15:30:45 -07:00
snipe 5614578710 Don’t make the item clickable if it’s been deleted 2017-05-09 15:30:19 -07:00
snipe 07882110fa Cleanup dashboard controller
We ajax this data in now
2017-05-09 00:38:45 -07:00
snipe 7a05467dbf Fixed missing password routes 2017-05-09 00:37:37 -07:00
snipe b7843ea565 Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-05-08 20:07:03 -07:00
snipe 4f9a253103 Fixes #3546 - increases size of field values in custom fields for listboxes 2017-05-08 20:06:52 -07:00
snipe 322817b8b1 Bumped version 2017-05-08 20:02:52 -07:00
Daniel Meltzer 82dc06ae19 Remove php7 feature (#3548)
...
2017-05-08 18:19:34 -07:00
Daniel Meltzer 38372f2b37 Remove php7 specific feature (#3547)
Not sure how this got in... I don't remember writing it (but I guess I did!)
2017-05-08 18:19:15 -07:00
Daniel Meltzer e9b056f66c Importer fixes v2 (#3524)
* Pave the imports table

* Format error response if file is the wrong type.

* If a custom field doesn't exist, don't insert a blank string into the custom fields table

* CustomField::db_column_name can return the stored name in the db.  It's slugified when that value is set initially.  This fixes a weird issue where _1 was replaced with _xx
2017-05-03 12:14:35 -07:00
snipe f6be7caaeb Updated composer to prevent ambiguous warnings 2017-04-27 18:50:00 -07:00
snipe d7f6d8e997 Fix for completely erroneous DBAL error
This should not work, but somehow does.

¯\_(ツ)_/¯
(╯° °)╯︵ ┻━┻

I hate computers.
2017-04-27 16:56:15 -07:00
snipe 841e3efe96 Add passport commands to boot() to allow us to call them via PHP 2017-04-27 07:09:46 -07:00
snipe 8ba19aa855 Fixes explode for trusted proxy 2017-04-27 07:09:23 -07:00
snipe 5ad9e8585d New composer options 2017-04-27 05:24:30 -07:00
snipe 68e831d555 Fixes #3514 - removed debugging code that was forcing 404 2017-04-27 05:22:03 -07:00
snipe 6fbf45554b Updated phpunit, removed post install and post update commands to see if that fixes upgrade issues 2017-04-27 02:28:22 -07:00
snipe 07f8c9dc5e Added additional mail markdown config variables 2017-04-27 02:27:57 -07:00
snipe e088eea2f7 Pull out weird query scope that breaks stuff when querying large datasets 2017-04-26 22:40:20 -07:00
snipe f4cdeaa956 Fixes #3514 - move tinker requirement out of dev 2017-04-25 07:46:56 -07:00
snipe 59a4e161ff Fixes checkout buttons on licenses list 2017-04-24 21:37:20 -07:00
snipe 6d53a5f58d Updated test for new JSON 2017-04-22 19:31:22 -05:00
snipe 54a2c46101 Fixes #3491 - adds supplier info to assets listing 2017-04-22 19:14:28 -05:00
snipe 08ef78356d Update Crowdin configuration file 2017-04-06 20:59:25 -07:00
Manasses Ferreira 47ac59abef We noted that the barcode folder was not being created. (what is done now in the entrypoint.sh) At the same time, a wrong directory was being created. (which explains the deleted line in Dockerfile) (#3456) 2017-03-31 13:48:50 -07:00
snipe 265a896211 Bumped version 2017-02-22 22:38:33 -08:00
snipe f7e4fca70d Add model_number to accessory search 2017-02-22 22:34:56 -08:00
snipe bb4c443cd9 Added notes to custom report 2017-02-03 02:20:56 -08:00
snipe 7b1d2ee050 Fixed typo 2017-01-17 11:57:24 -08:00
snipe b3f70a046f Don’t require superadmin for checkin and delete user 2017-01-17 09:19:14 -08:00
morph027 734e87f85f Installer fine tuning (#2993)
* used shellcheck to lint snipeit.sh

* do not depend on lsb-release command

* add lsb codename

* really use perms()

* more fixes

* quiet apt

* silent logging using log()

* start mysql if not running

* added curl to ubuntu

* added logfile to log function

* update apt index after adding mariadb repo

* fixed typo

* review fixes
2017-01-10 23:07:06 -08:00
snipe f371c5fd62 Merge branch 'master' of github.com:snipe/snipe-it 2017-01-10 19:02:18 -08:00
snipe 4b3edbd2f5 Fixed #3130 - model ID not being saved weith model info on modal for create asset 2017-01-10 19:02:13 -08:00
Byron Wolfman 1f3106b9da Use debian base container and clean up apt-get (#3011)
* Use debian base container and clean up apt-get

Attempt to slim down the docker image by replacing ubuntu:trusty with debian:jessie and clean up after apt-get invocation. Building against the 3.6.0 commit shows a healthy reduction of 44MB, or 9%, compared to the ubuntu-based image.

* Use debian:jessie-slim for an even smaller image

If we're using a debian base image for sizing reasons, we may as well go the full distance and use debian-slim.
2017-01-10 16:22:06 -08:00
snipe 9fd3a9a82d Removed logging 2017-01-06 03:12:49 -08:00
snipe a6e6991a2d Removed second number_format 2017-01-06 03:11:27 -08:00
snipe 93ba0717d8 Removed number_format 2017-01-06 03:02:38 -08:00
snipe a8839e0ef4 Fixes #3104, #2914 and #2918 - auto-increment incorrectly generating next ID 2017-01-06 02:52:10 -08:00
snipe 3e4152c966 Bumped version 2017-01-06 00:04:26 -08:00
snipe 1bf34d73f5 Use correct authorize rule in middleware for user delete 2017-01-06 00:02:46 -08:00
snipe d1e360d64d Fix logic to use gate instead of asking if superuser 2017-01-06 00:02:19 -08:00
snipe 3b5b19848c Added oauth keys to gitignore 2017-01-06 00:01:55 -08:00
snipe 93ba90e837 Merge remote-tracking branch 'origin/develop' 2016-12-12 19:24:00 -08:00
snipe fc70d79a17 Merge remote-tracking branch 'origin/develop' 2016-12-12 19:07:07 -08:00
snipe 65016a2383 Merge remote-tracking branch 'origin/develop' 2016-12-05 16:12:41 -08:00
snipe dbcb2ccb46 Merge remote-tracking branch 'origin/develop' 2016-12-05 15:09:49 -08:00
snipe 2afcfcc87c Set DB_SSL to false for config 2016-12-03 17:32:44 -08:00
snipe 1afef9416a Merge remote-tracking branch 'origin/develop'
# Conflicts:
#	config/version.php
2016-12-03 17:15:02 -08:00
snipe 4049143ebf Bumped version 2016-12-01 06:11:03 -08:00
snipe 4df53bdf8d Merge remote-tracking branch 'origin/develop'
# Conflicts:
#	config/version.php
#	resources/views/account/view-assets.blade.php
2016-12-01 06:10:50 -08:00
snipe d49a1ea304 More graceful error message if log doesn’t exist 2016-12-01 06:05:14 -08:00
snipe 521f4facd5 Bumped version 2016-12-01 05:56:24 -08:00
snipe b4653dfc15 Ignore npm log 2016-12-01 05:55:29 -08:00
1754 changed files with 60166 additions and 99176 deletions
+92 -1
View File
@@ -491,7 +491,8 @@
"avatar_url": "https://avatars3.githubusercontent.com/u/2527115?v=3",
"profile": "https://github.com/pakkua80",
"contributions": [
"doc"
"doc",
"code"
]
},
{
@@ -646,6 +647,96 @@
"contributions": [
"code"
]
},
{
"login": "BrettFagerlund",
"name": "Brett",
"avatar_url": "https://avatars2.githubusercontent.com/u/10522541?v=3",
"profile": "https://github.com/BrettFagerlund",
"contributions": [
"test"
]
},
{
"login": "jasonspriggs",
"name": "Jason Spriggs",
"avatar_url": "https://avatars2.githubusercontent.com/u/16108587?v=3",
"profile": "http://jasonspriggs.com",
"contributions": [
"code"
]
},
{
"login": "n8felton",
"name": "Nate Felton",
"avatar_url": "https://avatars2.githubusercontent.com/u/1134568?v=3",
"profile": "http://n8felton.wordpress.com",
"contributions": [
"code"
]
},
{
"login": "manassesferreira",
"name": "Manasses Ferreira",
"avatar_url": "https://avatars2.githubusercontent.com/u/14036694?v=3",
"profile": "http://homepages.dcc.ufmg.br/~manassesferreira",
"contributions": [
"code"
]
},
{
"login": "steveelwood",
"name": "Steve",
"avatar_url": "https://avatars0.githubusercontent.com/u/15913949?v=3",
"profile": "https://github.com/steveelwood",
"contributions": [
"test"
]
},
{
"login": "matc",
"name": "matc",
"avatar_url": "https://avatars1.githubusercontent.com/u/3361683?v=3",
"profile": "http://twitter.com/matc",
"contributions": [
"test"
]
},
{
"login": "VanillaNinjaD",
"name": "Cole R. Davis",
"avatar_url": "https://avatars3.githubusercontent.com/u/7405702?v=3",
"profile": "http://www.davisracingteam.com",
"contributions": [
"test"
]
},
{
"login": "gibsonjoshua55",
"name": "gibsonjoshua55",
"avatar_url": "https://avatars2.githubusercontent.com/u/10167681?v=3",
"profile": "https://github.com/gibsonjoshua55",
"contributions": [
"code"
]
},
{
"login": "zwerch",
"name": "Robin Temme",
"avatar_url": "https://avatars2.githubusercontent.com/u/2809241?v=4",
"profile": "https://github.com/zwerch",
"contributions": [
"code"
]
},
{
"login": "imanghafoori1",
"name": "Iman",
"avatar_url": "https://avatars0.githubusercontent.com/u/6961695?v=4",
"profile": "https://github.com/imanghafoori1",
"contributions": [
"code"
]
}
]
}
+1 -1
View File
@@ -15,7 +15,7 @@ FILESYSTEM_DISK=local
DB_CONNECTION=mysql
DB_HOST=localhost
DB_DATABASE=snipeit_unit
DB_USERNAME=travis
DB_USERNAME=root
DB_PASSWORD=null
# --------------------------------------------
+3 -2
View File
@@ -1,7 +1,8 @@
APP_ENV=local
APP_ENV=testing
APP_DEBUG=true
APP_URL=http://snipe-it.localapp
DB_CONNECTION=mysql
DB_CONNECTION=sqlite_testing
DB_DEFAULT=sqlite_testing
DB_HOST=localhost
DB_DATABASE=snipeittests
DB_USERNAME=snipeit
+22
View File
@@ -0,0 +1,22 @@
# Code ownership for pull request reviews, per
# the feature detailed here:
# https://github.com/blog/2392-introducing-code-owners
# https://help.github.com/articles/about-codeowners/
# These owners will be the default owners for everything in the repo.
* @snipe
# Order is important. The last matching pattern has the most precedence.
# So if a pull request only touches javascript files, only these owners
# will be requested to review.
# For example:
# *.js @octocat @github/js
app/Importer/* @dmeltzer
app/Http/Controllers/CustomFields* @uberbrady
app/Http/Controllers/Api/CustomFields* @uberbrady
resources/views/custom_fields/* @uberbrady
docker/* @uberbrady
+8 -2
View File
@@ -6,6 +6,9 @@ sudo: false
# see http://about.travis-ci.org/docs/user/languages/php/ for more hints
language: php
services:
- mysql
# list any PHP version you want to test against
php:
- 5.6
@@ -15,16 +18,19 @@ php:
before_script:
- phantomjs --webdriver=4444 &
- sleep 4
- mysql -e "create database IF NOT EXISTS snipeit_unit;" -utravis
- mysql -e 'CREATE DATABASE snipeit_unit;'
- mysql -e 'CREATE USER "travis'@'localhost";'
- mysql -e 'GRANT ALL PRIVILEGES ON * . * TO "travis'@'localhost";'
- mysql -e 'FLUSH PRIVILEGES;'
- composer self-update
- composer install -n --prefer-source
- chmod -R 777 storage
- php artisan migrate --env=testing-ci --database=mysql --force
- ./vendor/bin/codecept build
- php artisan --env=testing-ci key:generate
- php artisan --env=testing-ci snipeit:travisci-install
- php artisan --env=testing-ci db:seed --database=mysql --force
- php artisan --env=testing-ci snipeit:create-admin --first_name=Alison --last_name=Foobar --email=me@example.com --username=snipe --password=password
- php artisan --env=testing-ci snipeit:travisci-install
- php artisan --env=testing-ci passport:install
- php artisan serve --env=testing-ci --port=8000 --host=localhost &
- sleep 5
+6
View File
@@ -0,0 +1,6 @@
### Contributing
Please see the documentation on [contributing and developing for Snipe-IT](https://snipe-it.readme.io/docs/contributing).
Please note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.
+28 -14
View File
@@ -1,14 +1,19 @@
FROM debian:jessie-slim
FROM ubuntu:xenial
MAINTAINER Brady Wetherington <uberbrady@gmail.com>
RUN apt-get update && apt-get install -y \
apache2 \
apache2-bin \
libapache2-mod-php5 \
php5-curl \
php5-ldap \
php5-mysql \
php5-mcrypt \
php5-gd \
libapache2-mod-php7.0 \
php7.0-curl \
php7.0-ldap \
php7.0-mysql \
php7.0-mcrypt \
php7.0-gd \
php7.0-xml \
php7.0-mbstring \
php7.0-zip \
php7.0-bcmath \
patch \
curl \
vim \
@@ -17,13 +22,14 @@ mysql-client \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
RUN php5enmod mcrypt
RUN php5enmod gd
RUN phpenmod mcrypt
RUN phpenmod gd
RUN phpenmod bcmath
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php5/apache2/php.ini
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php5/cli/php.ini
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php/7.0/apache2/php.ini
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php/7.0/cli/php.ini
RUN useradd --uid 1000 --gid 50 docker
RUN useradd -m --uid 1000 --gid 50 docker
RUN echo export APACHE_RUN_USER=docker >> /etc/apache2/envvars
RUN echo export APACHE_RUN_GROUP=staff >> /etc/apache2/envvars
@@ -66,7 +72,9 @@ RUN \
RUN cd /tmp;curl -sS https://getcomposer.org/installer | php;mv /tmp/composer.phar /usr/local/bin/composer
# Get dependencies
RUN cd /var/www/html;composer install
USER docker
RUN cd /var/www/html;composer install && rm -rf /home/docker/.composer/cache
USER root
############### APPLICATION INSTALL/INIT #################
@@ -86,7 +94,13 @@ VOLUME ["/var/lib/snipeit"]
COPY docker/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
# Add Tini
ENV TINI_VERSION v0.14.0
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
RUN chmod +x /tini
ENTRYPOINT ["/tini", "--"]
CMD ["/entrypoint.sh"]
EXPOSE 80
EXPOSE 443
+14 -12
View File
@@ -1,5 +1,5 @@
[![Build Status](https://travis-ci.org/snipe/snipe-it.svg?branch=develop)](https://travis-ci.org/snipe/snipe-it) [![Stories in Ready](https://badge.waffle.io/snipe/snipe-it.png?label=ready+for+dev&amp;title=Ready+for+development)](http://waffle.io/snipe/snipe-it) [![Maintenance](https://img.shields.io/maintenance/yes/2016.svg)]() [![Crowdin](https://d322cqt584bo4o.cloudfront.net/snipe-it/localized.png)](https://crowdin.com/project/snipe-it) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/snipe/snipe-it?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![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/snipeyhead.svg?style=social)](https://twitter.com/snipeyhead) [![Zenhub](https://raw.githubusercontent.com/ZenHubIO/support/master/zenhub-badge.png)](https://zenhub.io) [![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-69-orange.svg?style=flat-square)](#contributors)
[![Build Status](https://travis-ci.org/snipe/snipe-it.svg?branch=develop)](https://travis-ci.org/snipe/snipe-it) [![Stories in Ready](https://badge.waffle.io/snipe/snipe-it.png?label=ready+for+dev&amp;title=Ready+for+development)](http://waffle.io/snipe/snipe-it) [![Maintenance](https://img.shields.io/maintenance/yes/2017.svg)]() [![Crowdin](https://d322cqt584bo4o.cloudfront.net/snipe-it/localized.png)](https://crowdin.com/project/snipe-it) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/snipe/snipe-it?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![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/snipeyhead.svg?style=social)](https://twitter.com/snipeyhead) [![Zenhub](https://raw.githubusercontent.com/ZenHubIO/support/master/zenhub-badge.png)](https://zenhub.io) [![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-79-orange.svg?style=flat-square)](#contributors)
## Snipe-IT - Open Source Asset Management System
@@ -55,17 +55,19 @@ Please see the [translations documentation](https://snipe-it.readme.io/docs/tran
Thanks goes to all of these wonderful people ([emoji key](https://github.com/kentcdodds/all-contributors#emoji-key)) who have helped Snipe-IT get this far:
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
| [<img src="https://avatars3.githubusercontent.com/u/197404?v=3" width="110px;"/><br /><sub>snipe</sub>](http://www.snipe.net)<br />[💻](https://github.com/snipe/snipe-it/commits?author=snipe) 🚇 [📖](https://github.com/snipe/snipe-it/commits?author=snipe) [⚠️](https://github.com/snipe/snipe-it/commits?author=snipe) [🐛](https://github.com/snipe/snipe-it/issues?q=author%3Asnipe) 🎨 👀 | [<img src="https://avatars0.githubusercontent.com/u/36335?v=3" width="110px;"/><br /><sub>Brady Wetherington</sub>](http://www.uberbrady.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=uberbrady) [📖](https://github.com/snipe/snipe-it/commits?author=uberbrady) 🚇 👀 | [<img src="https://avatars0.githubusercontent.com/u/3803132?v=3" width="110px;"/><br /><sub>Daniel Meltzer</sub>](https://github.com/dmeltzer)<br />[💻](https://github.com/snipe/snipe-it/commits?author=dmeltzer) [⚠️](https://github.com/snipe/snipe-it/commits?author=dmeltzer) [📖](https://github.com/snipe/snipe-it/commits?author=dmeltzer) | [<img src="https://avatars0.githubusercontent.com/u/1609106?v=3" width="110px;"/><br /><sub>Michael T</sub>](http://www.tuckertechonline.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mtucker6784) | [<img src="https://avatars2.githubusercontent.com/u/3274937?v=3" width="110px;"/><br /><sub>madd15</sub>](https://github.com/madd15)<br />[📖](https://github.com/snipe/snipe-it/commits?author=madd15) 💬 | [<img src="https://avatars2.githubusercontent.com/u/894126?v=3" width="110px;"/><br /><sub>Vincent Sposato</sub>](https://github.com/vsposato)<br />[💻](https://github.com/snipe/snipe-it/commits?author=vsposato) | [<img src="https://avatars0.githubusercontent.com/u/1639757?v=3" width="110px;"/><br /><sub>Andrea Bergamasco</sub>](https://github.com/vjandrea)<br />[💻](https://github.com/snipe/snipe-it/commits?author=vjandrea) |
| [<img src="https://avatars3.githubusercontent.com/u/197404?v=3" width="110px;"/><br /><sub>snipe</sub>](http://www.snipe.net)<br />[💻](https://github.com/snipe/snipe-it/commits?author=snipe "Code") [🚇](#infra-snipe "Infrastructure (Hosting, Build-Tools, etc)") [📖](https://github.com/snipe/snipe-it/commits?author=snipe "Documentation") [⚠️](https://github.com/snipe/snipe-it/commits?author=snipe "Tests") [🐛](https://github.com/snipe/snipe-it/issues?q=author%3Asnipe "Bug reports") [🎨](#design-snipe "Design") [👀](#review-snipe "Reviewed Pull Requests") | [<img src="https://avatars0.githubusercontent.com/u/36335?v=3" width="110px;"/><br /><sub>Brady Wetherington</sub>](http://www.uberbrady.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=uberbrady "Code") [📖](https://github.com/snipe/snipe-it/commits?author=uberbrady "Documentation") [🚇](#infra-uberbrady "Infrastructure (Hosting, Build-Tools, etc)") [👀](#review-uberbrady "Reviewed Pull Requests") | [<img src="https://avatars0.githubusercontent.com/u/3803132?v=3" width="110px;"/><br /><sub>Daniel Meltzer</sub>](https://github.com/dmeltzer)<br />[💻](https://github.com/snipe/snipe-it/commits?author=dmeltzer "Code") [⚠️](https://github.com/snipe/snipe-it/commits?author=dmeltzer "Tests") [📖](https://github.com/snipe/snipe-it/commits?author=dmeltzer "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/1609106?v=3" width="110px;"/><br /><sub>Michael T</sub>](http://www.tuckertechonline.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mtucker6784 "Code") | [<img src="https://avatars2.githubusercontent.com/u/3274937?v=3" width="110px;"/><br /><sub>madd15</sub>](https://github.com/madd15)<br />[📖](https://github.com/snipe/snipe-it/commits?author=madd15 "Documentation") [💬](#question-madd15 "Answering Questions") | [<img src="https://avatars2.githubusercontent.com/u/894126?v=3" width="110px;"/><br /><sub>Vincent Sposato</sub>](https://github.com/vsposato)<br />[💻](https://github.com/snipe/snipe-it/commits?author=vsposato "Code") | [<img src="https://avatars0.githubusercontent.com/u/1639757?v=3" width="110px;"/><br /><sub>Andrea Bergamasco</sub>](https://github.com/vjandrea)<br />[💻](https://github.com/snipe/snipe-it/commits?author=vjandrea "Code") |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| [<img src="https://avatars0.githubusercontent.com/u/10640152?v=3" width="110px;"/><br /><sub>Karol</sub>](https://github.com/kpawelski)<br />🌍 [💻](https://github.com/snipe/snipe-it/commits?author=kpawelski) | [<img src="https://avatars3.githubusercontent.com/u/600106?v=3" width="110px;"/><br /><sub>morph027</sub>](http://blog.morph027.de/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=morph027) | [<img src="https://avatars3.githubusercontent.com/u/22935755?v=3" width="110px;"/><br /><sub>fvleminckx</sub>](https://github.com/fvleminckx)<br />🚇 | [<img src="https://avatars2.githubusercontent.com/u/15633547?v=3" width="110px;"/><br /><sub>itsupportcmsukorg</sub>](https://github.com/itsupportcmsukorg)<br />[💻](https://github.com/snipe/snipe-it/commits?author=itsupportcmsukorg) [🐛](https://github.com/snipe/snipe-it/issues?q=author%3Aitsupportcmsukorg) | [<img src="https://avatars3.githubusercontent.com/u/12373799?v=3" width="110px;"/><br /><sub>Frank</sub>](https://override.io)<br />[💻](https://github.com/snipe/snipe-it/commits?author=base-zero) | [<img src="https://avatars0.githubusercontent.com/u/10137?v=3" width="110px;"/><br /><sub>Deleted user</sub>](https://github.com/ghost)<br />🌍 | [<img src="https://avatars1.githubusercontent.com/u/10802313?v=3" width="110px;"/><br /><sub>tiagom62</sub>](https://github.com/tiagom62)<br />[💻](https://github.com/snipe/snipe-it/commits?author=tiagom62) 🚇 |
| [<img src="https://avatars3.githubusercontent.com/u/2389047?v=3" width="110px;"/><br /><sub>Ryan Stafford</sub>](https://github.com/rystaf)<br />[💻](https://github.com/snipe/snipe-it/commits?author=rystaf) | [<img src="https://avatars2.githubusercontent.com/u/10345935?v=3" width="110px;"/><br /><sub>Eammon Hanlon</sub>](https://github.com/ehanlon)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ehanlon) | [<img src="https://avatars0.githubusercontent.com/u/441924?v=3" width="110px;"/><br /><sub>zjean</sub>](https://github.com/zjean)<br />[💻](https://github.com/snipe/snipe-it/commits?author=zjean) | [<img src="https://avatars0.githubusercontent.com/u/12660103?v=3" width="110px;"/><br /><sub>Matthias Frei</sub>](http://www.frei.media)<br />[💻](https://github.com/snipe/snipe-it/commits?author=FREImedia) | [<img src="https://avatars0.githubusercontent.com/u/3767518?v=3" width="110px;"/><br /><sub>opsydev</sub>](https://github.com/opsydev)<br />[💻](https://github.com/snipe/snipe-it/commits?author=opsydev) | [<img src="https://avatars1.githubusercontent.com/u/82290?v=3" width="110px;"/><br /><sub>Daniel Dreier</sub>](http://www.ddreier.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ddreier) | [<img src="https://avatars0.githubusercontent.com/u/23448?v=3" width="110px;"/><br /><sub>Nikolai Prokoschenko</sub>](http://rassie.org)<br />[💻](https://github.com/snipe/snipe-it/commits?author=rassie) |
| [<img src="https://avatars0.githubusercontent.com/u/13452757?v=3" width="110px;"/><br /><sub>Drew</sub>](https://github.com/YetAnotherCodeMonkey)<br />[💻](https://github.com/snipe/snipe-it/commits?author=YetAnotherCodeMonkey) | [<img src="https://avatars0.githubusercontent.com/u/1342320?v=3" width="110px;"/><br /><sub>Walter</sub>](https://github.com/merid14)<br />[💻](https://github.com/snipe/snipe-it/commits?author=merid14) | [<img src="https://avatars3.githubusercontent.com/u/11254614?v=3" width="110px;"/><br /><sub>Petr Baloun</sub>](https://github.com/balous)<br />[💻](https://github.com/snipe/snipe-it/commits?author=balous) | [<img src="https://avatars0.githubusercontent.com/u/6117660?v=3" width="110px;"/><br /><sub>reidblomquist</sub>](https://github.com/reidblomquist)<br />[📖](https://github.com/snipe/snipe-it/commits?author=reidblomquist) | [<img src="https://avatars0.githubusercontent.com/u/539914?v=3" width="110px;"/><br /><sub>Mathieu Kooiman</sub>](https://github.com/mathieuk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mathieuk) | [<img src="https://avatars3.githubusercontent.com/u/6606421?v=3" width="110px;"/><br /><sub>csayre</sub>](https://github.com/csayre)<br />[📖](https://github.com/snipe/snipe-it/commits?author=csayre) | [<img src="https://avatars1.githubusercontent.com/u/768488?v=3" width="110px;"/><br /><sub>Adam Dunson</sub>](https://github.com/adamdunson)<br />[💻](https://github.com/snipe/snipe-it/commits?author=adamdunson) |
| [<img src="https://avatars0.githubusercontent.com/u/5547470?v=3" width="110px;"/><br /><sub>Hereward</sub>](https://github.com/thehereward)<br />[💻](https://github.com/snipe/snipe-it/commits?author=thehereward) | [<img src="https://avatars0.githubusercontent.com/u/5802977?v=3" width="110px;"/><br /><sub>swoopdk</sub>](https://github.com/swoopdk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=swoopdk) | [<img src="https://avatars1.githubusercontent.com/u/3470403?v=3" width="110px;"/><br /><sub>Abdullah Alansari</sub>](https://linkedin.com/in/ahimta)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Ahimta) | [<img src="https://avatars0.githubusercontent.com/u/796443?v=3" width="110px;"/><br /><sub>Micael Rodrigues</sub>](https://github.com/MicaelRodrigues)<br />[💻](https://github.com/snipe/snipe-it/commits?author=MicaelRodrigues) | [<img src="https://avatars0.githubusercontent.com/u/614564?v=3" width="110px;"/><br /><sub>Patrick Gallagher</sub>](http://macadmincorner.com)<br />[📖](https://github.com/snipe/snipe-it/commits?author=patgmac) | [<img src="https://avatars3.githubusercontent.com/u/7165922?v=3" width="110px;"/><br /><sub>Miliamber</sub>](https://github.com/Miliamber)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Miliamber) | [<img src="https://avatars3.githubusercontent.com/u/861766?v=3" width="110px;"/><br /><sub>hawk554</sub>](https://github.com/hawk554)<br />[💻](https://github.com/snipe/snipe-it/commits?author=hawk554) |
| [<img src="https://avatars1.githubusercontent.com/u/1695622?v=3" width="110px;"/><br /><sub>Justin Kerr</sub>](http://jbirdkerr.net)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jbirdkerr) | [<img src="https://avatars3.githubusercontent.com/u/11426176?v=3" width="110px;"/><br /><sub>Ira W. Snyder</sub>](http://www.irasnyder.com/devel/)<br />[📖](https://github.com/snipe/snipe-it/commits?author=irasnyd) | [<img src="https://avatars2.githubusercontent.com/u/2475759?v=3" width="110px;"/><br /><sub>Aladin Alaily</sub>](https://github.com/aalaily)<br />[💻](https://github.com/snipe/snipe-it/commits?author=aalaily) | [<img src="https://avatars0.githubusercontent.com/u/10247644?v=3" width="110px;"/><br /><sub>Chase Hansen</sub>](https://github.com/kobie-chasehansen)<br />[💻](https://github.com/snipe/snipe-it/commits?author=kobie-chasehansen) 💬 [🐛](https://github.com/snipe/snipe-it/issues?q=author%3Akobie-chasehansen) | [<img src="https://avatars2.githubusercontent.com/u/13545400?v=3" width="110px;"/><br /><sub>IDM Helpdesk</sub>](https://github.com/IDM-Helpdesk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=IDM-Helpdesk) | [<img src="https://avatars2.githubusercontent.com/u/614439?v=3" width="110px;"/><br /><sub>Kai</sub>](http://balticer.de)<br />[💻](https://github.com/snipe/snipe-it/commits?author=balticer) | [<img src="https://avatars1.githubusercontent.com/u/8762511?v=3" width="110px;"/><br /><sub>Michael Daniels</sub>](http://www.michaeldaniels.me)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mdaniels5757) |
| [<img src="https://avatars3.githubusercontent.com/u/1532660?v=3" width="110px;"/><br /><sub>Tom Castleman</sub>](http://tomcastleman.me)<br />[💻](https://github.com/snipe/snipe-it/commits?author=tomcastleman) | [<img src="https://avatars3.githubusercontent.com/u/10723243?v=3" width="110px;"/><br /><sub>Daniel Nemanic</sub>](https://github.com/DanielNemanic)<br />[💻](https://github.com/snipe/snipe-it/commits?author=DanielNemanic) | [<img src="https://avatars0.githubusercontent.com/u/150648?v=3" width="110px;"/><br /><sub>SouthWolf</sub>](https://github.com/southwolf)<br />[💻](https://github.com/snipe/snipe-it/commits?author=southwolf) | [<img src="https://avatars2.githubusercontent.com/u/131616?v=3" width="110px;"/><br /><sub>Ivar Nesje</sub>](https://github.com/ivarne)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ivarne) | [<img src="https://avatars1.githubusercontent.com/u/62333?v=3" width="110px;"/><br /><sub>Jérémy Benoist</sub>](http://www.j0k3r.net)<br />[📖](https://github.com/snipe/snipe-it/commits?author=j0k3r) | [<img src="https://avatars2.githubusercontent.com/u/724344?v=3" width="110px;"/><br /><sub>Chris Leathley</sub>](https://github.com/cleathley)<br />🚇 | [<img src="https://avatars0.githubusercontent.com/u/972498?v=3" width="110px;"/><br /><sub>splaer</sub>](https://github.com/splaer)<br />[🐛](https://github.com/snipe/snipe-it/issues?q=author%3Asplaer) [💻](https://github.com/snipe/snipe-it/commits?author=splaer) |
| [<img src="https://avatars1.githubusercontent.com/u/967362?v=3" width="110px;"/><br /><sub>Joe Ferguson</sub>](http://www.joeferguson.me)<br />[💻](https://github.com/snipe/snipe-it/commits?author=svpernova09) | [<img src="https://avatars3.githubusercontent.com/u/6108682?v=3" width="110px;"/><br /><sub>diwanicki</sub>](https://github.com/diwanicki)<br />[💻](https://github.com/snipe/snipe-it/commits?author=diwanicki) [📖](https://github.com/snipe/snipe-it/commits?author=diwanicki) | [<img src="https://avatars3.githubusercontent.com/u/2527115?v=3" width="110px;"/><br /><sub>Lee Thoong Ching</sub>](https://github.com/pakkua80)<br />[📖](https://github.com/snipe/snipe-it/commits?author=pakkua80) | [<img src="https://avatars1.githubusercontent.com/u/461491?v=3" width="110px;"/><br /><sub>Marek Šuppa</sub>](http://shu.io)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mrshu) | [<img src="https://avatars1.githubusercontent.com/u/8693762?v=3" width="110px;"/><br /><sub>Juan J. Martinez</sub>](https://github.com/mizar1616)<br />🌍 | [<img src="https://avatars1.githubusercontent.com/u/1458388?v=3" width="110px;"/><br /><sub>R Ryan Dial</sub>](https://github.com/rrdial)<br />🌍 | [<img src="https://avatars2.githubusercontent.com/u/2871745?v=3" width="110px;"/><br /><sub>Andrej Manduch</sub>](https://github.com/burlito)<br />[📖](https://github.com/snipe/snipe-it/commits?author=burlito) |
| [<img src="https://avatars0.githubusercontent.com/u/8341172?v=3" width="110px;"/><br /><sub>Jay Richards</sub>](http://www.cordeos.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=technogenus) | [<img src="https://avatars2.githubusercontent.com/u/7295127?v=3" width="110px;"/><br /><sub>Alexander Innes</sub>](https://necurity.co.uk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=leostat) | [<img src="https://avatars2.githubusercontent.com/u/334485?v=3" width="110px;"/><br /><sub>Danny Garcia</sub>](https://buzzedword.codes)<br />[💻](https://github.com/snipe/snipe-it/commits?author=buzzedword) | [<img src="https://avatars2.githubusercontent.com/u/366855?v=3" width="110px;"/><br /><sub>archpoint</sub>](https://github.com/archpoint)<br />[💻](https://github.com/snipe/snipe-it/commits?author=archpoint) | [<img src="https://avatars1.githubusercontent.com/u/67991?v=3" width="110px;"/><br /><sub>Jake McGraw</sub>](http://www.jakemcgraw.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jakemcgraw) | [<img src="https://avatars1.githubusercontent.com/u/1714374?v=3" width="110px;"/><br /><sub>FleischKarussel</sub>](https://github.com/FleischKarussel)<br />[📖](https://github.com/snipe/snipe-it/commits?author=FleischKarussel) | [<img src="https://avatars3.githubusercontent.com/u/319644?v=3" width="110px;"/><br /><sub>Dylan Yi</sub>](https://github.com/feeva)<br />[💻](https://github.com/snipe/snipe-it/commits?author=feeva) |
| [<img src="https://avatars2.githubusercontent.com/u/857740?v=3" width="110px;"/><br /><sub>Gil Rutkowski</sub>](http://FlashingCursor.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=flashingcursor) | [<img src="https://avatars3.githubusercontent.com/u/129360?v=3" width="110px;"/><br /><sub>Desmond Morris</sub>](http://www.desmondmorris.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=desmondmorris) | [<img src="https://avatars2.githubusercontent.com/u/52936?v=3" width="110px;"/><br /><sub>Nick Peelman</sub>](http://peelman.us)<br />[💻](https://github.com/snipe/snipe-it/commits?author=peelman) | [<img src="https://avatars0.githubusercontent.com/u/53161?v=3" width="110px;"/><br /><sub>Abraham Vegh</sub>](https://abrahamvegh.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=abrahamvegh) | [<img src="https://avatars0.githubusercontent.com/u/2818680?v=3" width="110px;"/><br /><sub>Mohamed Rashid</sub>](https://github.com/rashivkp)<br />[📖](https://github.com/snipe/snipe-it/commits?author=rashivkp) | [<img src="https://avatars3.githubusercontent.com/u/1509456?v=3" width="110px;"/><br /><sub>Kasey</sub>](http://hinchk.github.io)<br />[💻](https://github.com/snipe/snipe-it/commits?author=HinchK) |
| [<img src="https://avatars0.githubusercontent.com/u/10640152?v=3" width="110px;"/><br /><sub>Karol</sub>](https://github.com/kpawelski)<br />[🌍](#translation-kpawelski "Translation") [💻](https://github.com/snipe/snipe-it/commits?author=kpawelski "Code") | [<img src="https://avatars3.githubusercontent.com/u/600106?v=3" width="110px;"/><br /><sub>morph027</sub>](http://blog.morph027.de/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=morph027 "Code") | [<img src="https://avatars3.githubusercontent.com/u/22935755?v=3" width="110px;"/><br /><sub>fvleminckx</sub>](https://github.com/fvleminckx)<br />[🚇](#infra-fvleminckx "Infrastructure (Hosting, Build-Tools, etc)") | [<img src="https://avatars2.githubusercontent.com/u/15633547?v=3" width="110px;"/><br /><sub>itsupportcmsukorg</sub>](https://github.com/itsupportcmsukorg)<br />[💻](https://github.com/snipe/snipe-it/commits?author=itsupportcmsukorg "Code") [🐛](https://github.com/snipe/snipe-it/issues?q=author%3Aitsupportcmsukorg "Bug reports") | [<img src="https://avatars3.githubusercontent.com/u/12373799?v=3" width="110px;"/><br /><sub>Frank</sub>](https://override.io)<br />[💻](https://github.com/snipe/snipe-it/commits?author=base-zero "Code") | [<img src="https://avatars0.githubusercontent.com/u/10137?v=3" width="110px;"/><br /><sub>Deleted user</sub>](https://github.com/ghost)<br />[🌍](#translation-ghost "Translation") | [<img src="https://avatars1.githubusercontent.com/u/10802313?v=3" width="110px;"/><br /><sub>tiagom62</sub>](https://github.com/tiagom62)<br />[💻](https://github.com/snipe/snipe-it/commits?author=tiagom62 "Code") [🚇](#infra-tiagom62 "Infrastructure (Hosting, Build-Tools, etc)") |
| [<img src="https://avatars3.githubusercontent.com/u/2389047?v=3" width="110px;"/><br /><sub>Ryan Stafford</sub>](https://github.com/rystaf)<br />[💻](https://github.com/snipe/snipe-it/commits?author=rystaf "Code") | [<img src="https://avatars2.githubusercontent.com/u/10345935?v=3" width="110px;"/><br /><sub>Eammon Hanlon</sub>](https://github.com/ehanlon)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ehanlon "Code") | [<img src="https://avatars0.githubusercontent.com/u/441924?v=3" width="110px;"/><br /><sub>zjean</sub>](https://github.com/zjean)<br />[💻](https://github.com/snipe/snipe-it/commits?author=zjean "Code") | [<img src="https://avatars0.githubusercontent.com/u/12660103?v=3" width="110px;"/><br /><sub>Matthias Frei</sub>](http://www.frei.media)<br />[💻](https://github.com/snipe/snipe-it/commits?author=FREImedia "Code") | [<img src="https://avatars0.githubusercontent.com/u/3767518?v=3" width="110px;"/><br /><sub>opsydev</sub>](https://github.com/opsydev)<br />[💻](https://github.com/snipe/snipe-it/commits?author=opsydev "Code") | [<img src="https://avatars1.githubusercontent.com/u/82290?v=3" width="110px;"/><br /><sub>Daniel Dreier</sub>](http://www.ddreier.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ddreier "Code") | [<img src="https://avatars0.githubusercontent.com/u/23448?v=3" width="110px;"/><br /><sub>Nikolai Prokoschenko</sub>](http://rassie.org)<br />[💻](https://github.com/snipe/snipe-it/commits?author=rassie "Code") |
| [<img src="https://avatars0.githubusercontent.com/u/13452757?v=3" width="110px;"/><br /><sub>Drew</sub>](https://github.com/YetAnotherCodeMonkey)<br />[💻](https://github.com/snipe/snipe-it/commits?author=YetAnotherCodeMonkey "Code") | [<img src="https://avatars0.githubusercontent.com/u/1342320?v=3" width="110px;"/><br /><sub>Walter</sub>](https://github.com/merid14)<br />[💻](https://github.com/snipe/snipe-it/commits?author=merid14 "Code") | [<img src="https://avatars3.githubusercontent.com/u/11254614?v=3" width="110px;"/><br /><sub>Petr Baloun</sub>](https://github.com/balous)<br />[💻](https://github.com/snipe/snipe-it/commits?author=balous "Code") | [<img src="https://avatars0.githubusercontent.com/u/6117660?v=3" width="110px;"/><br /><sub>reidblomquist</sub>](https://github.com/reidblomquist)<br />[📖](https://github.com/snipe/snipe-it/commits?author=reidblomquist "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/539914?v=3" width="110px;"/><br /><sub>Mathieu Kooiman</sub>](https://github.com/mathieuk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mathieuk "Code") | [<img src="https://avatars3.githubusercontent.com/u/6606421?v=3" width="110px;"/><br /><sub>csayre</sub>](https://github.com/csayre)<br />[📖](https://github.com/snipe/snipe-it/commits?author=csayre "Documentation") | [<img src="https://avatars1.githubusercontent.com/u/768488?v=3" width="110px;"/><br /><sub>Adam Dunson</sub>](https://github.com/adamdunson)<br />[💻](https://github.com/snipe/snipe-it/commits?author=adamdunson "Code") |
| [<img src="https://avatars0.githubusercontent.com/u/5547470?v=3" width="110px;"/><br /><sub>Hereward</sub>](https://github.com/thehereward)<br />[💻](https://github.com/snipe/snipe-it/commits?author=thehereward "Code") | [<img src="https://avatars0.githubusercontent.com/u/5802977?v=3" width="110px;"/><br /><sub>swoopdk</sub>](https://github.com/swoopdk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=swoopdk "Code") | [<img src="https://avatars1.githubusercontent.com/u/3470403?v=3" width="110px;"/><br /><sub>Abdullah Alansari</sub>](https://linkedin.com/in/ahimta)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Ahimta "Code") | [<img src="https://avatars0.githubusercontent.com/u/796443?v=3" width="110px;"/><br /><sub>Micael Rodrigues</sub>](https://github.com/MicaelRodrigues)<br />[💻](https://github.com/snipe/snipe-it/commits?author=MicaelRodrigues "Code") | [<img src="https://avatars0.githubusercontent.com/u/614564?v=3" width="110px;"/><br /><sub>Patrick Gallagher</sub>](http://macadmincorner.com)<br />[📖](https://github.com/snipe/snipe-it/commits?author=patgmac "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/7165922?v=3" width="110px;"/><br /><sub>Miliamber</sub>](https://github.com/Miliamber)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Miliamber "Code") | [<img src="https://avatars3.githubusercontent.com/u/861766?v=3" width="110px;"/><br /><sub>hawk554</sub>](https://github.com/hawk554)<br />[💻](https://github.com/snipe/snipe-it/commits?author=hawk554 "Code") |
| [<img src="https://avatars1.githubusercontent.com/u/1695622?v=3" width="110px;"/><br /><sub>Justin Kerr</sub>](http://jbirdkerr.net)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jbirdkerr "Code") | [<img src="https://avatars3.githubusercontent.com/u/11426176?v=3" width="110px;"/><br /><sub>Ira W. Snyder</sub>](http://www.irasnyder.com/devel/)<br />[📖](https://github.com/snipe/snipe-it/commits?author=irasnyd "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/2475759?v=3" width="110px;"/><br /><sub>Aladin Alaily</sub>](https://github.com/aalaily)<br />[💻](https://github.com/snipe/snipe-it/commits?author=aalaily "Code") | [<img src="https://avatars0.githubusercontent.com/u/10247644?v=3" width="110px;"/><br /><sub>Chase Hansen</sub>](https://github.com/kobie-chasehansen)<br />[💻](https://github.com/snipe/snipe-it/commits?author=kobie-chasehansen "Code") [💬](#question-kobie-chasehansen "Answering Questions") [🐛](https://github.com/snipe/snipe-it/issues?q=author%3Akobie-chasehansen "Bug reports") | [<img src="https://avatars2.githubusercontent.com/u/13545400?v=3" width="110px;"/><br /><sub>IDM Helpdesk</sub>](https://github.com/IDM-Helpdesk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=IDM-Helpdesk "Code") | [<img src="https://avatars2.githubusercontent.com/u/614439?v=3" width="110px;"/><br /><sub>Kai</sub>](http://balticer.de)<br />[💻](https://github.com/snipe/snipe-it/commits?author=balticer "Code") | [<img src="https://avatars1.githubusercontent.com/u/8762511?v=3" width="110px;"/><br /><sub>Michael Daniels</sub>](http://www.michaeldaniels.me)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mdaniels5757 "Code") |
| [<img src="https://avatars3.githubusercontent.com/u/1532660?v=3" width="110px;"/><br /><sub>Tom Castleman</sub>](http://tomcastleman.me)<br />[💻](https://github.com/snipe/snipe-it/commits?author=tomcastleman "Code") | [<img src="https://avatars3.githubusercontent.com/u/10723243?v=3" width="110px;"/><br /><sub>Daniel Nemanic</sub>](https://github.com/DanielNemanic)<br />[💻](https://github.com/snipe/snipe-it/commits?author=DanielNemanic "Code") | [<img src="https://avatars0.githubusercontent.com/u/150648?v=3" width="110px;"/><br /><sub>SouthWolf</sub>](https://github.com/southwolf)<br />[💻](https://github.com/snipe/snipe-it/commits?author=southwolf "Code") | [<img src="https://avatars2.githubusercontent.com/u/131616?v=3" width="110px;"/><br /><sub>Ivar Nesje</sub>](https://github.com/ivarne)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ivarne "Code") | [<img src="https://avatars1.githubusercontent.com/u/62333?v=3" width="110px;"/><br /><sub>Jérémy Benoist</sub>](http://www.j0k3r.net)<br />[📖](https://github.com/snipe/snipe-it/commits?author=j0k3r "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/724344?v=3" width="110px;"/><br /><sub>Chris Leathley</sub>](https://github.com/cleathley)<br />[🚇](#infra-cleathley "Infrastructure (Hosting, Build-Tools, etc)") | [<img src="https://avatars0.githubusercontent.com/u/972498?v=3" width="110px;"/><br /><sub>splaer</sub>](https://github.com/splaer)<br />[🐛](https://github.com/snipe/snipe-it/issues?q=author%3Asplaer "Bug reports") [💻](https://github.com/snipe/snipe-it/commits?author=splaer "Code") |
| [<img src="https://avatars1.githubusercontent.com/u/967362?v=3" width="110px;"/><br /><sub>Joe Ferguson</sub>](http://www.joeferguson.me)<br />[💻](https://github.com/snipe/snipe-it/commits?author=svpernova09 "Code") | [<img src="https://avatars3.githubusercontent.com/u/6108682?v=3" width="110px;"/><br /><sub>diwanicki</sub>](https://github.com/diwanicki)<br />[💻](https://github.com/snipe/snipe-it/commits?author=diwanicki "Code") [📖](https://github.com/snipe/snipe-it/commits?author=diwanicki "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/2527115?v=3" width="110px;"/><br /><sub>Lee Thoong Ching</sub>](https://github.com/pakkua80)<br />[📖](https://github.com/snipe/snipe-it/commits?author=pakkua80 "Documentation") [💻](https://github.com/snipe/snipe-it/commits?author=pakkua80 "Code") | [<img src="https://avatars1.githubusercontent.com/u/461491?v=3" width="110px;"/><br /><sub>Marek Šuppa</sub>](http://shu.io)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mrshu "Code") | [<img src="https://avatars1.githubusercontent.com/u/8693762?v=3" width="110px;"/><br /><sub>Juan J. Martinez</sub>](https://github.com/mizar1616)<br />[🌍](#translation-mizar1616 "Translation") | [<img src="https://avatars1.githubusercontent.com/u/1458388?v=3" width="110px;"/><br /><sub>R Ryan Dial</sub>](https://github.com/rrdial)<br />[🌍](#translation-rrdial "Translation") | [<img src="https://avatars2.githubusercontent.com/u/2871745?v=3" width="110px;"/><br /><sub>Andrej Manduch</sub>](https://github.com/burlito)<br />[📖](https://github.com/snipe/snipe-it/commits?author=burlito "Documentation") |
| [<img src="https://avatars0.githubusercontent.com/u/8341172?v=3" width="110px;"/><br /><sub>Jay Richards</sub>](http://www.cordeos.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=technogenus "Code") | [<img src="https://avatars2.githubusercontent.com/u/7295127?v=3" width="110px;"/><br /><sub>Alexander Innes</sub>](https://necurity.co.uk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=leostat "Code") | [<img src="https://avatars2.githubusercontent.com/u/334485?v=3" width="110px;"/><br /><sub>Danny Garcia</sub>](https://buzzedword.codes)<br />[💻](https://github.com/snipe/snipe-it/commits?author=buzzedword "Code") | [<img src="https://avatars2.githubusercontent.com/u/366855?v=3" width="110px;"/><br /><sub>archpoint</sub>](https://github.com/archpoint)<br />[💻](https://github.com/snipe/snipe-it/commits?author=archpoint "Code") | [<img src="https://avatars1.githubusercontent.com/u/67991?v=3" width="110px;"/><br /><sub>Jake McGraw</sub>](http://www.jakemcgraw.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jakemcgraw "Code") | [<img src="https://avatars1.githubusercontent.com/u/1714374?v=3" width="110px;"/><br /><sub>FleischKarussel</sub>](https://github.com/FleischKarussel)<br />[📖](https://github.com/snipe/snipe-it/commits?author=FleischKarussel "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/319644?v=3" width="110px;"/><br /><sub>Dylan Yi</sub>](https://github.com/feeva)<br />[💻](https://github.com/snipe/snipe-it/commits?author=feeva "Code") |
| [<img src="https://avatars2.githubusercontent.com/u/857740?v=3" width="110px;"/><br /><sub>Gil Rutkowski</sub>](http://FlashingCursor.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=flashingcursor "Code") | [<img src="https://avatars3.githubusercontent.com/u/129360?v=3" width="110px;"/><br /><sub>Desmond Morris</sub>](http://www.desmondmorris.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=desmondmorris "Code") | [<img src="https://avatars2.githubusercontent.com/u/52936?v=3" width="110px;"/><br /><sub>Nick Peelman</sub>](http://peelman.us)<br />[💻](https://github.com/snipe/snipe-it/commits?author=peelman "Code") | [<img src="https://avatars0.githubusercontent.com/u/53161?v=3" width="110px;"/><br /><sub>Abraham Vegh</sub>](https://abrahamvegh.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=abrahamvegh "Code") | [<img src="https://avatars0.githubusercontent.com/u/2818680?v=3" width="110px;"/><br /><sub>Mohamed Rashid</sub>](https://github.com/rashivkp)<br />[📖](https://github.com/snipe/snipe-it/commits?author=rashivkp "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/1509456?v=3" width="110px;"/><br /><sub>Kasey</sub>](http://hinchk.github.io)<br />[💻](https://github.com/snipe/snipe-it/commits?author=HinchK "Code") | [<img src="https://avatars2.githubusercontent.com/u/10522541?v=3" width="110px;"/><br /><sub>Brett</sub>](https://github.com/BrettFagerlund)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=BrettFagerlund "Tests") |
| [<img src="https://avatars2.githubusercontent.com/u/16108587?v=3" width="110px;"/><br /><sub>Jason Spriggs</sub>](http://jasonspriggs.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jasonspriggs "Code") | [<img src="https://avatars2.githubusercontent.com/u/1134568?v=3" width="110px;"/><br /><sub>Nate Felton</sub>](http://n8felton.wordpress.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=n8felton "Code") | [<img src="https://avatars2.githubusercontent.com/u/14036694?v=3" width="110px;"/><br /><sub>Manasses Ferreira</sub>](http://homepages.dcc.ufmg.br/~manassesferreira)<br />[💻](https://github.com/snipe/snipe-it/commits?author=manassesferreira "Code") | [<img src="https://avatars0.githubusercontent.com/u/15913949?v=3" width="110px;"/><br /><sub>Steve</sub>](https://github.com/steveelwood)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=steveelwood "Tests") | [<img src="https://avatars1.githubusercontent.com/u/3361683?v=3" width="110px;"/><br /><sub>matc</sub>](http://twitter.com/matc)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=matc "Tests") | [<img src="https://avatars3.githubusercontent.com/u/7405702?v=3" width="110px;"/><br /><sub>Cole R. Davis</sub>](http://www.davisracingteam.com)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=VanillaNinjaD "Tests") | [<img src="https://avatars2.githubusercontent.com/u/10167681?v=3" width="110px;"/><br /><sub>gibsonjoshua55</sub>](https://github.com/gibsonjoshua55)<br />[💻](https://github.com/snipe/snipe-it/commits?author=gibsonjoshua55 "Code") |
| [<img src="https://avatars2.githubusercontent.com/u/2809241?v=4" width="110px;"/><br /><sub>Robin Temme</sub>](https://github.com/zwerch)<br />[💻](https://github.com/snipe/snipe-it/commits?author=zwerch "Code") | [<img src="https://avatars0.githubusercontent.com/u/6961695?v=4" width="110px;"/><br /><sub>Iman</sub>](https://github.com/imanghafoori1)<br />[💻](https://github.com/snipe/snipe-it/commits?author=imanghafoori1 "Code") |
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
+85
View File
@@ -0,0 +1,85 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class FixDoubleEscape extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'snipeit:unescape';
/**
* The console command description.
*
* @var string
*/
protected $description = 'This should be run to fix some double-escaping issues from earlier versions of Snipe-IT.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$tables = [
'\App\Models\Asset' => ['name'],
'\App\Models\License' => ['name'],
'\App\Models\Consumable' => ['name'],
'\App\Models\Accessory' => ['name'],
'\App\Models\Component' => ['name'],
'\App\Models\Company' => ['name'],
'\App\Models\Manufacturer' => ['name'],
'\App\Models\Supplier' => ['name'],
'\App\Models\Statuslabel' => ['name'],
'\App\Models\Depreciation' => ['name'],
'\App\Models\AssetModel' => ['name'],
'\App\Models\Group' => ['name'],
'\App\Models\Department' => ['name'],
'\App\Models\Location' => ['name'],
'\App\Models\User' => ['first_name', 'last_name'],
];
$count = array();
foreach ($tables as $classname => $fields) {
$count[$classname] = array();
$count[$classname]['classname'] = 0;
foreach($fields as $field) {
$count[$classname]['classname']++;
$count[$classname][$field] = 0;
foreach($classname::where("$field",'LIKE','%&%')->get() as $row) {
$this->info('Updating '.$field.' for '.$classname);
$row->{$field} = html_entity_decode($row->{$field});
$row->save();
$count[$classname][$field]++;
}
}
}
$this->info('Update complete');
}
}
+4 -4
View File
@@ -90,11 +90,11 @@ class LdapSync extends Command
LOG::debug('Location ID '.$this->option('location_id').' passed');
LOG::debug('Importing to '.$location->name.' ('.$location->id.')');
} else {
$location = new Location;
}
$location = NULL;
}
if (!isset($location)) {
LOG::debug('That location is invalid, so no location will be assigned by default.');
LOG::debug('That location is invalid or a location was not provided, so no location will be assigned by default.');
}
// Grab subsets based on location-specific DNs, and overwrite location for these users.
@@ -109,7 +109,7 @@ class LdapSync extends Command
// Delete located users from the general group.
foreach ($results as $key => $generic_entry) {
if (in_array($generic_entry[$ldap_result_username][0], $location_users)) {
if (in_array($generic_entry[$ldap_result_username][0], $usernames)) {
unset($results[$key]);
}
}
@@ -1,398 +0,0 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use League\Csv\Reader;
use App\Models\User;
use App\Models\Supplier;
use App\Models\License;
use App\Models\LicenseSeat;
use App\Models\Asset;
class LicenseImportCommand extends Command
{
/**
* The console command name.
*
* @var string
*/
protected $name = 'snipeit:license-import';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Import Licenses from CSV';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function fire()
{
$filename = $this->argument('filename');
if (!$this->option('testrun')=='true') {
$this->comment('======= Importing Licenses from '.$filename.' =========');
} else {
$this->comment('====== TEST ONLY License Import for '.$filename.' ====');
$this->comment('============== NO DATA WILL BE WRITTEN ==============');
}
if (! ini_get("auto_detect_line_endings")) {
ini_set("auto_detect_line_endings", '1');
}
$csv = Reader::createFromPath($this->argument('filename'));
$csv->setNewline("\r\n");
$csv->setOffset(1);
$duplicates = '';
// Loop through the records
$nbInsert = $csv->each(function ($row) use ($duplicates) {
$status_id = 1;
// Let's just map some of these entries to more user friendly words
if (array_key_exists('0', $row)) {
$user_name = trim($row[0]);
} else {
$user_name = '';
}
if (array_key_exists('1', $row)) {
$user_email = trim($row[1]);
} else {
$user_email = '';
}
if (array_key_exists('2', $row)) {
$user_username = trim($row[2]);
} else {
$user_username = '';
}
if (array_key_exists('3', $row)) {
$user_license_name = trim($row[3]);
} else {
$user_license_name = '';
}
if (array_key_exists('4', $row)) {
$user_license_serial = trim($row[4]);
} else {
$user_license_serial = '';
}
if (array_key_exists('5', $row)) {
$user_licensed_to_name = trim($row[5]);
} else {
$user_licensed_to_name = '';
}
if (array_key_exists('6', $row)) {
$user_licensed_to_email = trim($row[6]);
} else {
$user_licensed_to_email = '';
}
if (array_key_exists('7', $row)) {
$user_license_seats = trim($row[7]);
} else {
$user_license_seats = '';
}
if (array_key_exists('8', $row)) {
$user_license_reassignable = trim($row[8]);
if ($user_license_reassignable!='') {
if ((strtolower($user_license_reassignable)=='yes') || (strtolower($user_license_reassignable)=='true') || ($user_license_reassignable=='1')) {
$user_license_reassignable = 1;
}
} else {
$user_license_reassignable = 0;
}
} else {
$user_license_reassignable = 0;
}
if (array_key_exists('9', $row)) {
$user_license_supplier = trim($row[9]);
} else {
$user_license_supplier = '';
}
if (array_key_exists('10', $row)) {
$user_license_maintained = trim($row[10]);
if ($user_license_maintained!='') {
if ((strtolower($user_license_maintained)=='yes') || (strtolower($user_license_maintained)=='true') || ($user_license_maintained=='1')) {
$user_license_maintained = 1;
}
} else {
$user_license_maintained = 0;
}
} else {
$user_license_maintained = '';
}
if (array_key_exists('11', $row)) {
$user_license_notes = trim($row[11]);
} else {
$user_license_notes = '';
}
if (array_key_exists('12', $row)) {
if ($row[12]!='') {
$user_license_purchase_date = date("Y-m-d 00:00:01", strtotime($row[12]));
} else {
$user_license_purchase_date = '';
}
} else {
$user_license_purchase_date = 0;
}
if (array_key_exists('13', $row)) {
$user_licensed_to_asset = trim($row[13]);
} else {
$user_licensed_to_asset = '';
}
// A number was given instead of a name
if (is_numeric($user_name)) {
$this->comment('User '.$user_name.' is not a name - assume this user already exists');
$user_username = '';
// No name was given
} elseif ($user_name=='') {
$this->comment('No user data provided - skipping user creation, just adding license');
$first_name = '';
$last_name = '';
$user_username = '';
} else {
$name = explode(" ", $user_name);
$first_name = $name[0];
$email_last_name = '';
$email_prefix = $first_name;
if (!array_key_exists(1, $name)) {
$last_name='';
$email_last_name = $last_name;
$email_prefix = $first_name;
} else {
$last_name = str_replace($first_name, '', $user_name);
if ($this->option('email_format')=='filastname') {
$email_last_name.=str_replace(' ', '', $last_name);
$email_prefix = $first_name[0].$email_last_name;
} elseif ($this->option('email_format')=='firstname.lastname') {
$email_last_name.=str_replace(' ', '', $last_name);
$email_prefix = $first_name.'.'.$email_last_name;
} elseif ($this->option('email_format')=='firstname') {
$email_last_name.=str_replace(' ', '', $last_name);
$email_prefix = $first_name;
}
}
$user_username = $email_prefix;
// Generate an email based on their name if no email address is given
if ($user_email=='') {
if ($first_name=='Unknown') {
$status_id = 7;
}
$email = strtolower($email_prefix).'@'.$this->option('domain');
$user_email = str_replace("'", '', $email);
}
}
$this->comment('Full Name: '.$user_name);
$this->comment('First Name: '.$first_name);
$this->comment('Last Name: '.$last_name);
$this->comment('Username: '.$user_username);
$this->comment('Email: '.$user_email);
$this->comment('License Name: '.$user_license_name);
$this->comment('Serial No: '.$user_license_serial);
$this->comment('Licensed To Name: '.$user_licensed_to_name);
$this->comment('Licensed To Email: '.$user_licensed_to_email);
$this->comment('Seats: '.$user_license_seats);
$this->comment('Reassignable: '.$user_license_reassignable);
$this->comment('Supplier: '.$user_license_supplier);
$this->comment('Maintained: '.$user_license_maintained);
$this->comment('Notes: '.$user_license_notes);
$this->comment('Purchase Date: '.$user_license_purchase_date);
$this->comment('Asset ID: '.$user_licensed_to_asset);
$this->comment('------------- Action Summary ----------------');
if ($user_username!='') {
if ($user = User::where('username', $user_username)->whereNotNull('username')->first()) {
$this->comment('User '.$user_username.' already exists');
} else {
$user = new \App\Models\User;
$password = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 20);
$user->first_name = $first_name;
$user->last_name = $last_name;
$user->username = $user_username;
$user->email = $user_email;
$user->permissions = '{user":1}';
$user->password = bcrypt($password);
$user->activated = 1;
if ($user->save()) {
$this->comment('User '.$first_name.' created');
} else {
$this->error('ERROR CREATING User '.$first_name.' '.$last_name);
$this->error($user->getErrors());
}
$this->comment('User '.$first_name.' created');
}
} else {
$user = new User;
$user->user_id = null;
}
// Check for the supplier match and create it if it doesn't exist
if ($supplier = Supplier::where('name', $user_license_supplier)->first()) {
$this->comment('Supplier '.$user_license_supplier.' already exists');
} else {
$supplier = new Supplier();
$supplier->name = e($user_license_supplier);
$supplier->user_id = 1;
if ($supplier->save()) {
$this->comment('Supplier '.$user_license_supplier.' was created');
} else {
$this->comment('Something went wrong! Supplier '.$user_license_supplier.' was NOT created');
}
}
// Add the license
$license = new License();
$license->name = e($user_license_name);
if ($user_license_purchase_date!='') {
$license->purchase_date = $user_license_purchase_date;
} else {
$license->purchase_date = null;
}
$license->serial = e($user_license_serial);
$license->seats = e($user_license_seats);
$license->supplier_id = $supplier->id;
$license->user_id = 1;
if ($user_license_purchase_date!='') {
$license->purchase_date = $user_license_purchase_date;
} else {
$license->purchase_date = null;
}
$license->license_name = $user_licensed_to_name;
$license->license_email = $user_licensed_to_email;
$license->notes = e($user_license_notes);
if ($license->save()) {
$this->comment('License '.$user_license_name.' with serial number '.$user_license_serial.' was created');
$license_seat_created = 0;
for ($x = 0; $x < $user_license_seats; $x++) {
// Create the license seat entries
$license_seat = new LicenseSeat();
$license_seat->license_id = $license->id;
// Only assign the first seat to the user
if ($x==0) {
$license_seat->assigned_to = $user->id;
} else {
$license_seat->assigned_to = null;
}
if($user_licensed_to_asset) {
$asset = Asset::where('asset_tag', $user_licensed_to_asset)->first();
if($asset) {
$license_seat->asset_id = $asset->id;
}
}
if ($license_seat->save()) {
$license_seat_created++;
}
}
if ($license_seat_created > 0) {
$this->comment($license_seat_created.' seats were created');
} else {
$this->comment('Something went wrong! NO seats for '.$user_license_name.' were created');
}
} else {
$this->comment('Something went wrong! License '.$user_license_name.' was NOT created');
}
$this->comment('=====================================');
return true;
});
}
/**
* Get the console command arguments.
*
* @return array
*/
protected function getArguments()
{
return array(
array('filename', InputArgument::REQUIRED, 'File for the CSV import.'),
);
}
/**
* Get the console command options.
*
* @return array
*/
protected function getOptions()
{
return array(
array('domain', null, InputOption::VALUE_REQUIRED, 'Email domain for generated email addresses.', null),
array('email_format', null, InputOption::VALUE_REQUIRED, 'The format of the email addresses that should be generated. Options are firstname.lastname, firstname, filastname', null),
array('testrun', null, InputOption::VALUE_REQUIRED, 'Test the output without writing to the database or not.', null),
);
}
}
+3 -5
View File
@@ -72,7 +72,6 @@ class ObjectImportCommand extends Command
$classString = "App\\Importer\\{$class}Importer";
$importer = new $classString($filename);
$importer->setCallbacks([$this, 'log'], [$this, 'progress'], [$this, 'errorCallback'])
->setTestRun($this->option('testrun'))
->setUserId($this->option('user_id'))
->setUpdating($this->option('update'))
->setUsernameFormat($this->option('username_format'));
@@ -80,10 +79,10 @@ class ObjectImportCommand extends Command
$logFile = $this->option('logfile');
\Log::useFiles($logFile);
if ($this->option('testrun')) {
$this->comment('====== TEST ONLY Asset Import for '.$filename.' ====');
$this->comment('====== TEST ONLY Item Import for '.$filename.' ====');
$this->comment('============== NO DATA WILL BE WRITTEN ==============');
} else {
$this->comment('======= Importing Assets from '.$filename.' =========');
$this->comment('======= Importing Items from '.$filename.' =========');
}
$importer->import();
@@ -173,9 +172,8 @@ class ObjectImportCommand extends Command
return array(
array('email_format', null, InputOption::VALUE_REQUIRED, 'The format of the email addresses that should be generated. Options are firstname.lastname, firstname, filastname', null),
array('username_format', null, InputOption::VALUE_REQUIRED, 'The format of the username that should be generated. Options are firstname.lastname, firstname, filastname, email', null),
array('testrun', null, InputOption::VALUE_NONE, 'If set, will parse and output data without adding to database', null),
array('logfile', null, InputOption::VALUE_REQUIRED, 'The path to log output to. storage/logs/importer.log by default', storage_path('logs/importer.log') ),
array('item-type', null, InputOption::VALUE_REQUIRED, 'Item Type To import. Valid Options are Asset, Consumable, Or Accessory', 'Asset'),
array('item-type', null, InputOption::VALUE_REQUIRED, 'Item Type To import. Valid Options are Asset, Consumable, Accessory, License, or User', 'Asset'),
array('web-importer', null, InputOption::VALUE_NONE, 'Internal: packages output for use with the web importer'),
array('user_id', null, InputOption::VALUE_REQUIRED, 'ID of user creating items', 1),
array('update', null, InputOption::VALUE_NONE, 'If a matching item is found, update item information'),
+8 -3
View File
@@ -2,9 +2,6 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use DB;
use App\Models\Accessory;
use App\Models\Asset;
use App\Models\AssetModel;
@@ -12,14 +9,18 @@ use App\Models\Category;
use App\Models\Company;
use App\Models\Component;
use App\Models\Consumable;
use App\Models\Department;
use App\Models\Depreciation;
use App\Models\Group;
use App\Models\Import;
use App\Models\License;
use App\Models\LicenseSeat;
use App\Models\Location;
use App\Models\Manufacturer;
use App\Models\Statuslabel;
use App\Models\Supplier;
use DB;
use Illuminate\Console\Command;
class PaveIt extends Command
{
@@ -63,6 +64,7 @@ class PaveIt extends Command
Company::getQuery()->delete();
Component::getQuery()->delete();
Consumable::getQuery()->delete();
Department::getQuery()->delete();
Depreciation::getQuery()->delete();
License::getQuery()->delete();
LicenseSeat::getQuery()->delete();
@@ -72,6 +74,7 @@ class PaveIt extends Command
Statuslabel::getQuery()->delete();
Supplier::getQuery()->delete();
Group::getQuery()->delete();
Import::getQuery()->delete();
DB::statement('delete from accessories_users');
DB::statement('delete from asset_logs');
@@ -107,6 +110,7 @@ class PaveIt extends Command
\DB::statement('drop table IF EXISTS custom_fields');
\DB::statement('drop table IF EXISTS custom_fieldsets');
\DB::statement('drop table IF EXISTS depreciations');
\DB::statement('drop table IF EXISTS departments');
\DB::statement('drop table IF EXISTS groups');
\DB::statement('drop table IF EXISTS history');
\DB::statement('drop table IF EXISTS components');
@@ -131,6 +135,7 @@ class PaveIt extends Command
\DB::statement('drop table IF EXISTS throttle');
\DB::statement('drop table IF EXISTS users_groups');
\DB::statement('drop table IF EXISTS users');
\DB::statement('drop table IF EXISTS imports');
}
}
}
+164
View File
@@ -0,0 +1,164 @@
<?php
namespace App\Console\Commands;
use App\Models\CustomField;
use Illuminate\Console\Command;
use App\LegacyEncrypter\McryptEncrypter;
use App\Models\Setting;
use App\Models\Asset;
use Illuminate\Support\Facades\Storage;
class RecryptFromMcrypt extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'snipeit:legacy-recrypt';
/**
* The console command description.
*
* @var string
*/
protected $description = 'This command allows upgrading users to de-encrypt their deprecated mcrypt encrypted fields and re-encrypt them using the current OpenSSL encryption.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
// Check and see if they have a legacy app key listed in their .env
// If not, we can try to use the current APP_KEY if looks like it's old
$legacy_key = env('LEGACY_APP_KEY');
$key_parts = explode(':', $legacy_key);
$errors = array();
if (!$legacy_key) {
$this->error('ERROR: You do not have a LEGACY_APP_KEY set in your .env file. Please locate your old APP_KEY and ADD a line to your .env file like: LEGACY_APP_KEY=YOUR_OLD_APP_KEY');
return false;
}
// Do some basic legacy app key length checks
if (strlen($legacy_key) == 32) {
$legacy_length_check = true;
} elseif (array_key_exists('1', $key_parts) && (strlen($key_parts[1])==44)) {
$legacy_length_check = true;
} else {
$legacy_length_check = false;
}
// Check that the app key is 32 characters
if ($legacy_length_check === true) {
$this->comment('INFO: Your LEGACY_APP_KEY looks correct. Okay to continue.');
} else {
$this->error('ERROR: Your LEGACY_APP_KEY is not the correct length (32 characters or base64 followed by 44 characters for later versions). Please locate your old APP_KEY and use that as your LEGACY_APP_KEY in your .env file to continue.');
return false;
}
$this->error('================================!!!! WARNING !!!!================================');
$this->error('================================!!!! WARNING !!!!================================');
$this->comment("This tool will attempt to decrypt your old Snipe-IT (mcrypt, now deprecated) encrypted data and re-encrypt it using OpenSSL. \n\nYou should only continue if you have backed up any and all old APP_KEYs and have backed up your data.");
if ($this->confirm("Are you SURE you wish to continue?")) {
$backup_file = 'backups/env-backups/'.'app_key-'.date('Y-m-d-gis');
try {
Storage::disk('local')->put($backup_file, 'APP_KEY: '.config('app.key'));
Storage::disk('local')->append($backup_file, 'LEGACY_APP_KEY: '.$legacy_key);
} catch (\Exception $e) {
$this->info('WARNING: Could not backup app keys');
}
$mcrypter = new McryptEncrypter($legacy_key);
$settings = Setting::getSettings();
if ($settings->ldap_password=='') {
$this->comment('INFO: No LDAP password found. Skipping... ');
}
$custom_fields = CustomField::where('field_encrypted','=', 1)->get();
$this->comment('INFO: Retrieving encrypted custom fields...');
$query = Asset::withTrashed();
foreach ($custom_fields as $custom_field) {
$this->comment('FIELD TO RECRYPT: '.$custom_field->name .' ('.$custom_field->db_column.')');
$query->orWhereNotNull($custom_field->db_column);
}
// Get all assets with a value in any of the fields that were encrypted
$assets = $query->get();
$bar = $this->output->createProgressBar(count($assets));
foreach ($custom_fields as $encrypted_field) {
// Try to decrypt the payload using the legacy app key
try {
$decrypted_field = $mcrypter->decrypt($encrypted_field);
$this->comment($decrypted_field);
} catch (\Exception $e) {
$errors[] = ' - ERROR: Could not decrypt field ['.$encrypted_field->name.']: '.$e->getMessage();
}
$bar->advance();
}
foreach ($assets as $asset) {
foreach ($custom_fields as $encrypted_field) {
// Make sure the value isn't null
if ($asset->{$encrypted_field}!='') {
// Try to decrypt the payload using the legacy app key
try {
$decrypted_field = $mcrypter->decrypt($asset->{$encrypted_field});
$asset->{$encrypted_field} = \Crypt::encrypt($decrypted_field);
$this->comment($decrypted_field);
} catch (\Exception $e) {
$errors[] = ' - ERROR: Could not decrypt field ['.$encrypted_field->name.']: '.$e->getMessage();
}
}
}
$asset->save();
$bar->advance();
}
$bar->finish();
if (count($errors) > 0) {
$this->comment("\n\n");
$this->error("The decrypter encountered some errors: \n");
foreach ($errors as $error) {
$this->error($error);
}
}
}
}
}
@@ -0,0 +1,64 @@
<?php
namespace App\Console\Commands;
use App\Models\Asset;
use Illuminate\Console\Command;
use App\Notifications\ExpectedCheckinNotification;
use Carbon\Carbon;
class SendExpectedCheckinAlerts extends Command
{
/**
* The console command name.
*
* @var string
*/
protected $name = 'snipeit:expected-checkin';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Check for overdue or upcoming expected checkins.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function fire()
{
$whenNotify = Carbon::now()->addDays(7);
$assets = Asset::with('assignedTo')->whereNotNull('expected_checkin')->where('expected_checkin', '<=', $whenNotify)->get();
$this->info($whenNotify.' is deadline');
$this->info($assets->count().' assets');
foreach ($assets as $asset) {
if ($asset->assignedTo && $asset->checkoutOutToUser()) {
$asset->assignedTo->notify((new ExpectedCheckinNotification($asset)));
//$this->info($asset);
}
}
}
}
+4 -1
View File
@@ -17,13 +17,15 @@ class Kernel extends ConsoleKernel
Commands\CreateAdmin::class,
Commands\SendExpirationAlerts::class,
Commands\SendInventoryAlerts::class,
Commands\LicenseImportCommand::class,
Commands\SendExpectedCheckinAlerts::class,
Commands\ObjectImportCommand::class,
Commands\Versioning::class,
Commands\SystemBackup::class,
Commands\DisableLDAP::class,
Commands\Purge::class,
Commands\LdapSync::class,
Commands\FixDoubleEscape::class,
Commands\RecryptFromMcrypt::class
];
/**
@@ -37,6 +39,7 @@ class Kernel extends ConsoleKernel
$schedule->command('snipeit:inventory-alerts')->daily();
$schedule->command('snipeit:expiring-alerts')->daily();
$schedule->command('snipeit:expected-checkins')->daily();
$schedule->command('snipeit:backup')->weekly();
$schedule->command('backup:clean')->daily();
}
+12
View File
@@ -0,0 +1,12 @@
<?php
namespace App\Exceptions;
use Exception;
class CheckoutNotAllowed extends Exception
{
public function __toString()
{
"A checkout is not allowed under these circumstances";
}
}
+2 -2
View File
@@ -80,7 +80,7 @@ class Handler extends ExceptionHandler
}
}
// Try to parse 500 Errors ina bit nicer way when debug is enabled.
// Try to parse 500 Errors in a bit nicer way when debug is enabled.
if (config('app.debug')) {
return response()->json(Helper::formatStandardApiResponse('error', null, "An Error has occured! " . $e->getMessage()), 500);
}
@@ -91,7 +91,7 @@ class Handler extends ExceptionHandler
if ($this->isHttpException($e) && (isset($statusCode)) && ($statusCode == '404' )) {
return response()->view('layouts/basic', [
'content' => view('errors/404')
]);
],$statusCode);
}
return parent::render($request, $e);
+22 -3
View File
@@ -4,6 +4,7 @@ namespace App\Helpers;
use DB;
use App\Models\Statuslabel;
use App\Models\Location;
use App\Models\Department;
use App\Models\AssetModel;
use App\Models\Company;
use App\Models\User;
@@ -184,6 +185,25 @@ class Helper
return $category_list;
}
/**
* Get the list of categories in an array to make a dropdown menu
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.5]
* @return Array
*/
public static function departmentList()
{
$departments = Department::orderBy('name', 'asc')
->whereNull('deleted_at')
->orderBy('name', 'asc');
return array('' => trans('general.select_department')) + $departments->pluck('name', 'id')->toArray();
}
/**
* Get the list of suppliers in an array to make a dropdown menu
*
@@ -663,12 +683,11 @@ class Helper
public static function formatStandardApiResponse($status, $payload = null, $messages = null) {
$array['status'] = $status;
($payload) ? $array['payload'] = $payload : '';
$array['messages'] = $messages;
if (($messages) && (count($messages) > 0)) {
$array['messages'] = $messages;
}
($payload) ? $array['payload'] = $payload : $array['payload'] = null;
return $array;
}
+7 -15
View File
@@ -39,7 +39,7 @@ class AccessoriesController extends Controller
public function index(Request $request)
{
$this->authorize('index', Accessory::class);
return View::make('accessories/index');
return view('accessories/index');
}
@@ -53,7 +53,7 @@ class AccessoriesController extends Controller
{
$this->authorize('create', Accessory::class);
// Show the page
return View::make('accessories/edit')
return view('accessories/edit')
->with('item', new Accessory)
->with('category_list', Helper::categoryList('accessory'))
->with('company_list', Helper::companyList())
@@ -90,7 +90,6 @@ class AccessoriesController extends Controller
// Was the accessory created?
if ($accessory->save()) {
$accessory->logCreate();
// Redirect to the new accessory page
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.create.success'));
}
@@ -108,13 +107,12 @@ class AccessoriesController extends Controller
{
// Check if the accessory exists
if (is_null($item = Accessory::find($accessoryId))) {
// Redirect to the blogs management page
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
}
$this->authorize($item);
return View::make('accessories/edit', compact('item'))
return view('accessories/edit', compact('item'))
->with('category_list', Helper::categoryList('accessory'))
->with('company_list', Helper::companyList())
->with('location_list', Helper::locationsList())
@@ -131,9 +129,7 @@ class AccessoriesController extends Controller
*/
public function update(Request $request, $accessoryId = null)
{
// Check if the accessory exists
if (is_null($accessory = Accessory::find($accessoryId))) {
// Redirect to the accessory index page
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
}
@@ -154,7 +150,6 @@ class AccessoriesController extends Controller
// Was the accessory updated?
if ($accessory->save()) {
// Redirect to the updated accessory page
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.update.success'));
}
return redirect()->back()->withInput()->withErrors($accessory->getErrors());
@@ -169,9 +164,7 @@ class AccessoriesController extends Controller
*/
public function destroy(Request $request, $accessoryId)
{
// Check if the blog post exists
if (is_null($accessory = Accessory::find($accessoryId))) {
// Redirect to the blogs management page
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.not_found'));
}
@@ -182,7 +175,6 @@ class AccessoriesController extends Controller
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.assoc_users', array('count'=> $accessory->hasUsers())));
}
$accessory->delete();
// Redirect to the locations management page
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.delete.success'));
}
@@ -203,7 +195,7 @@ class AccessoriesController extends Controller
$accessory = Accessory::find($accessoryID);
$this->authorize('view', $accessory);
if (isset($accessory->id)) {
return View::make('accessories/view', compact('accessory'));
return view('accessories/view', compact('accessory'));
}
// Prepare the error message
$error = trans('admin/accessories/message.does_not_exist', compact('id'));
@@ -230,7 +222,7 @@ class AccessoriesController extends Controller
$this->authorize('checkout', $accessory);
// Get the dropdown of users and then pass it to the checkout view
return View::make('accessories/checkout', compact('accessory'))->with('users_list', Helper::usersList());
return view('accessories/checkout', compact('accessory'))->with('users_list', Helper::usersList());
}
@@ -268,7 +260,7 @@ class AccessoriesController extends Controller
'assigned_to' => $request->get('assigned_to')
]);
$logaction = $accessory->logCheckout(e(Input::get('note')));
$logaction = $accessory->logCheckout(e(Input::get('note')), $user);
DB::table('accessories_users')->where('assigned_to', '=', $accessory->assigned_to)->where('accessory_id', '=', $accessory->id)->first();
@@ -316,7 +308,7 @@ class AccessoriesController extends Controller
$accessory = Accessory::find($accessory_user->accessory_id);
$this->authorize('checkin', $accessory);
return View::make('accessories/checkin', compact('accessory'))->with('backto', $backto);
return view('accessories/checkin', compact('accessory'))->with('backto', $backto);
}
@@ -0,0 +1,227 @@
<?php
namespace App\Http\Controllers\Api;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Transformers\AssetMaintenancesTransformer;
use App\Models\Asset;
use App\Models\AssetMaintenance;
use App\Models\Company;
use Auth;
use Carbon\Carbon;
use Gate;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Input;
/**
* This controller handles all actions related to Asset Maintenance for
* the Snipe-IT Asset Management application.
*
* @version v2.0
*/
class AssetMaintenancesController extends Controller
{
/**
* Generates the JSON response for asset maintenances listing view.
*
* @see AssetMaintenancesController::getIndex() method that generates view
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
* @since [v1.8]
* @return String JSON
*/
public function index(Request $request)
{
$maintenances = AssetMaintenance::with('asset', 'supplier', 'asset.company', 'admin');
if (Input::has('search')) {
$maintenances = $maintenances->TextSearch(e($request->input('search')));
}
$offset = request('offset', 0);
$limit = request('limit', 50);
$allowed_columns = ['id','title','asset_maintenance_time','asset_maintenance_type','cost','start_date','completion_date','notes','user_id'];
$order = Input::get('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array(Input::get('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
switch ($sort) {
case 'user_id':
$maintenances = $maintenances->OrderAdmin($order);
break;
default:
$maintenances = $maintenances->orderBy($sort, $order);
break;
}
$maintenances = $maintenances->skip($offset)->take($limit)->get();
return (new AssetMaintenancesTransformer())->transformAssetMaintenances($maintenances, $maintenances->count());
}
/**
* Validates and stores the new asset maintenance
*
* @see AssetMaintenancesController::getCreate() method for the form
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
* @since [v1.8]
* @return String JSON
*/
public function store(Request $request)
{
// create a new model instance
$assetMaintenance = new AssetMaintenance();
$assetMaintenance->supplier_id = $request->input('supplier_id');
$assetMaintenance->is_warranty = $request->input('is_warranty');
$assetMaintenance->cost = e($request->input('cost'));
$assetMaintenance->notes = e($request->input('notes'));
$asset = Asset::find(e($request->input('asset_id')));
if (!Company::isCurrentUserHasAccess($asset)) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot add a maintenance for that asset'));
}
// Save the asset maintenance data
$assetMaintenance->asset_id = $request->input('asset_id');
$assetMaintenance->asset_maintenance_type = $request->input('asset_maintenance_type');
$assetMaintenance->title = $request->input('title');
$assetMaintenance->start_date = $request->input('start_date');
$assetMaintenance->completion_date = $request->input('completion_date');
$assetMaintenance->user_id = Auth::id();
if (( $assetMaintenance->completion_date !== null )
&& ( $assetMaintenance->start_date !== "" )
&& ( $assetMaintenance->start_date !== "0000-00-00" )
) {
$startDate = Carbon::parse($assetMaintenance->start_date);
$completionDate = Carbon::parse($assetMaintenance->completion_date);
$assetMaintenance->asset_maintenance_time = $completionDate->diffInDays($startDate);
}
// Was the asset maintenance created?
if ($assetMaintenance->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $assetMaintenance, trans('admin/asset_maintenances/message.create.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $assetMaintenance->getErrors()));
}
/**
* Validates and stores an update to an asset maintenance
*
* @author A. Gianotto <snipe@snipe.net>
* @param int $assetMaintenanceId
* @param int $request
* @version v1.0
* @since [v4.0]
* @return String JSON
*/
public function update(Request $request, $assetMaintenanceId = null)
{
// Check if the asset maintenance exists
$assetMaintenance = AssetMaintenance::findOrFail($assetMaintenanceId);
if (!Company::isCurrentUserHasAccess($assetMaintenance->asset)) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot edit a maintenance for that asset'));
}
$assetMaintenance->supplier_id = e($request->input('supplier_id'));
$assetMaintenance->is_warranty = e($request->input('is_warranty'));
$assetMaintenance->cost = Helper::ParseFloat(e($request->input('cost')));
$assetMaintenance->notes = e($request->input('notes'));
$asset = Asset::find(request('asset_id'));
if (!Company::isCurrentUserHasAccess($asset)) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot edit a maintenance for that asset'));
}
// Save the asset maintenance data
$assetMaintenance->asset_id = $request->input('asset_id');
$assetMaintenance->asset_maintenance_type = $request->input('asset_maintenance_type');
$assetMaintenance->title = $request->input('title');
$assetMaintenance->start_date = $request->input('start_date');
$assetMaintenance->completion_date = $request->input('completion_date');
if (( $assetMaintenance->completion_date == null )
) {
if (( $assetMaintenance->asset_maintenance_time !== 0 )
|| ( !is_null($assetMaintenance->asset_maintenance_time) )
) {
$assetMaintenance->asset_maintenance_time = null;
}
}
if (( $assetMaintenance->completion_date !== null )
&& ( $assetMaintenance->start_date !== "" )
&& ( $assetMaintenance->start_date !== "0000-00-00" )
) {
$startDate = Carbon::parse($assetMaintenance->start_date);
$completionDate = Carbon::parse($assetMaintenance->completion_date);
$assetMaintenance->asset_maintenance_time = $completionDate->diffInDays($startDate);
}
// Was the asset maintenance created?
if ($assetMaintenance->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $assetMaintenance, trans('admin/asset_maintenances/message.edit.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $assetMaintenance->getErrors()));
}
/**
* Delete an asset maintenance
*
* @author A. Gianotto <snipe@snipe.net>
* @param int $assetMaintenanceId
* @version v1.0
* @since [v4.0]
* @return String JSON
*/
public function destroy($assetMaintenanceId)
{
// Check if the asset maintenance exists
$assetMaintenance = AssetMaintenance::findOrFail($assetMaintenanceId);
if (!Company::isCurrentUserHasAccess($assetMaintenance->asset)) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot delete a maintenance for that asset'));
}
$assetMaintenance->delete();
return response()->json(Helper::formatStandardApiResponse('success', $assetMaintenance, trans('admin/asset_maintenances/message.delete.success')));
}
/**
* View an asset maintenance
*
* @author A. Gianotto <snipe@snipe.net>
* @param int $assetMaintenanceId
* @version v1.0
* @since [v4.0]
* @return String JSON
*/
public function show($assetMaintenanceId)
{
$assetMaintenance = AssetMaintenance::findOrFail($assetMaintenanceId);
if (!Company::isCurrentUserHasAccess($assetMaintenance->asset)) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot view a maintenance for that asset'));
}
return (new AssetMaintenancesTransformer())->transformAssetMaintenance($assetMaintenance);
}
}
@@ -76,7 +76,7 @@ class AssetModelsController extends Controller
$assetmodel->fill($request->all());
if ($assetmodel->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $assetmodel, trans('admin/assetmodels/message.create.success')));
return response()->json(Helper::formatStandardApiResponse('success', $assetmodel, trans('admin/models/message.create.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $assetmodel->getErrors()));
@@ -127,6 +127,7 @@ class AssetModelsController extends Controller
$this->authorize('edit', AssetModel::class);
$assetmodel = AssetModel::findOrFail($id);
$assetmodel->fill($request->all());
$assetmodel->fieldset_id = $request->get("custom_fieldset_id");
if ($assetmodel->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $assetmodel, trans('admin/assetmodels/message.update.success')));
+74 -12
View File
@@ -31,6 +31,7 @@ use TCPDF;
use Validator;
use View;
/**
* This class controls all actions related to assets for
* the Snipe-IT Asset Management application.
@@ -83,9 +84,8 @@ class AssetsController extends Controller
}
$assets = Company::scopeCompanyables(Asset::select('assets.*'))->with(
'assetLoc', 'assetstatus', 'defaultLoc', 'assetlog', 'company',
'model.category', 'model.manufacturer', 'model.fieldset', 'assigneduser');
'assetloc', 'assetstatus', 'defaultLoc', 'assetlog', 'company',
'model.category', 'model.manufacturer', 'model.fieldset','supplier');
// If we should search on everything
if (($request->has('search')) && (count($filter) == 0)) {
$assets->TextSearch($request->input('search'));
@@ -96,6 +96,7 @@ class AssetsController extends Controller
}
}
// These are used by the API to query against specific ID numbers
if ($request->has('status_id')) {
$assets->where('status_id', '=', $request->input('status_id'));
}
@@ -112,6 +113,10 @@ class AssetsController extends Controller
$assets->ByLocationId($request->input('location_id'));
}
if ($request->has('supplier_id')) {
$assets->where('assets.supplier_id', '=', $request->input('supplier_id'));
}
if ($request->has('company_id')) {
$assets->where('assets.company_id', '=', $request->input('company_id'));
}
@@ -125,9 +130,9 @@ class AssetsController extends Controller
$offset = request('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'assets.created_at';
$assets->orderBy($sort, $order);
// This is used by the sidenav, mostly
switch ($request->input('status')) {
case 'Deleted':
$assets->withTrashed()->Deleted();
@@ -154,7 +159,10 @@ class AssetsController extends Controller
switch ($sort) {
// This handles all of the pivot sorting (versus the assets.* fields in the allowed_columns array)
$column_sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'assets.created_at';
switch ($request->input('sort')) {
case 'model':
$assets->OrderModels($order);
break;
@@ -176,15 +184,17 @@ class AssetsController extends Controller
case 'status_label':
$assets->OrderStatus($order);
break;
case 'supplier':
$assets->OrderSupplier($order);
break;
case 'assigned_to':
$assets->OrderAssigned($order);
break;
default:
$assets->orderBy($sort, $order);
$assets->orderBy($column_sort, $order);
break;
}
$total = $assets->count();
$assets = $assets->skip($offset)->take($limit)->get();
return (new AssetsTransformer)->transformAssets($assets, $total);
@@ -220,7 +230,8 @@ class AssetsController extends Controller
*/
public function store(AssetRequest $request)
{
// $this->authorize('create', Asset::class);
$this->authorize('create', Asset::class);
$asset = new Asset();
$asset->model()->associate(AssetModel::find((int) $request->get('model_id')));
@@ -266,8 +277,9 @@ class AssetsController extends Controller
if (isset($target)) {
$asset->checkOut($target, Auth::user(), date('Y-m-d H:i:s'), '', 'Checked out on asset creation', e($request->get('name')));
}
return response()->json(Helper::formatStandardApiResponse('success', $asset->id, trans('admin/hardware/message.create.success')));
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.create.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $asset->getErrors()), 200);
}
@@ -331,7 +343,7 @@ class AssetsController extends Controller
}
if ($asset->save()) {
$asset->logCreate();
if ($request->get('assigned_user')) {
$target = User::find(request('assigned_user'));
} elseif ($request->get('assigned_asset')) {
@@ -362,7 +374,10 @@ class AssetsController extends Controller
*/
public function destroy($id)
{
$this->authorize('delete', Asset::class);
if ($asset = Asset::find($id)) {
$this->authorize('delete', $asset);
DB::table('assets')
@@ -479,5 +494,52 @@ class AssetsController extends Controller
}
return response()->json(Helper::formatStandardApiResponse('success', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkin.error')));
}
/**
* Mark an asset as audited
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $id
* @since [v4.0]
* @return JsonResponse
*/
public function audit(Request $request) {
$this->authorize('audit', Asset::class);
$rules = array(
'asset_tag' => 'required',
'location_id' => 'exists:locations,id|nullable|numeric',
'next_audit_date' => 'date|nullable'
);
$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) {
return response()->json(Helper::formatStandardApiResponse('error', null, $validator->errors()->all()));
}
$asset = Asset::where('asset_tag','=', $request->input('asset_tag'))->first();
if ($asset) {
$asset->next_audit_date = $request->input('next_audit_date');
if ($asset->save()) {
$log = $asset->logAudit(request('note'),request('location_id'));
return response()->json(Helper::formatStandardApiResponse('success', [
'asset_tag'=> e($asset->asset_tag),
'note'=> e($request->input('note')),
'next_audit_date' => Helper::getFormattedDateObject($log->calcNextAuditDate())
], trans('admin/hardware/message.audit.success')));
}
}
return response()->json(Helper::formatStandardApiResponse('error', ['asset_tag'=> e($request->input('asset_tag'))], 'Asset with tag '.$request->input('asset_tag').' not found'));
}
}
@@ -22,7 +22,7 @@ class CategoriesController extends Controller
$this->authorize('view', Category::class);
$allowed_columns = ['id', 'name','category_type','use_default_eula','require_acceptance','checkin_email'];
$categories = Category::select(['id', 'name','category_type','use_default_eula','require_acceptance','checkin_email'])
$categories = Category::select(['id', 'created_at', 'updated_at', 'name','category_type','use_default_eula','require_acceptance','checkin_email'])
->withCount('assets', 'accessories', 'consumables', 'components');
if ($request->has('search')) {
@@ -75,7 +75,8 @@ class CategoriesController extends Controller
{
$this->authorize('view', Category::class);
$category = Category::findOrFail($id);
return $category;
return (new CategoriesTransformer)->transformCategory($category);
}
@@ -2,7 +2,7 @@
namespace App\Http\Controllers\Api;
use App\Http\Transformers\DatatablesTransformer;
use App\Http\Transformers\CompaniesTransformer;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Helpers\Helper;
@@ -23,7 +23,10 @@ class CompaniesController extends Controller
$allowed_columns = ['id','name'];
$companies = Company::withCount('assets','licenses','accessories','consumables','components','users');
$companies = Company::withCount('assets','licenses','accessories','consumables','components','users')
->withCount('users')->withCount('users')->withCount('assets')
->withCount('licenses')->withCount('accessories')
->withCount('consumables')->withCount('components');
if ($request->has('search')) {
$companies->TextSearch($request->input('search'));
@@ -37,7 +40,7 @@ class CompaniesController extends Controller
$total = $companies->count();
$companies = $companies->skip($offset)->take($limit)->get();
return (new DatatablesTransformer)->transformDatatables($companies, $total);
return (new CompaniesTransformer)->transformCompanies($companies, $total);
}
@@ -57,7 +60,7 @@ class CompaniesController extends Controller
$company->fill($request->all());
if ($company->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $company, trans('admin/companies/message.create.success')));
return response()->json(Helper::formatStandardApiResponse('success', (new CompaniesTransformer)->transformCompany($company), trans('admin/companies/message.create.success')));
}
return response()
->json(Helper::formatStandardApiResponse('error', null, $company->getErrors()));
@@ -76,7 +79,8 @@ class CompaniesController extends Controller
{
$this->authorize('view', Company::class);
$company = Company::findOrFail($id);
return $company;
return (new CompaniesTransformer)->transformCompany($company);
}
@@ -97,7 +101,7 @@ class CompaniesController extends Controller
if ($company->save()) {
return response()
->json(Helper::formatStandardApiResponse('success', $company, trans('admin/companies/message.update.success')));
->json(Helper::formatStandardApiResponse('success', (new CompaniesTransformer)->transformCompany($company), trans('admin/companies/message.update.success')));
}
return response()
@@ -148,4 +148,47 @@ class ConsumablesController extends Controller
$consumable->delete();
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/consumables/message.delete.success')));
}
/**
* Returns a JSON response containing details on the users associated with this consumable.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see ConsumablesController::getView() method that returns the form.
* @since [v1.0]
* @param int $consumableId
* @return array
*/
public function getDataView($consumableId)
{
//$consumable = Consumable::find($consumableID);
$consumable = Consumable::with(array('consumableAssignments'=>
function ($query) {
$query->orderBy('created_at', 'DESC');
},
'consumableAssignments.admin'=> function ($query) {
},
'consumableAssignments.user'=> function ($query) {
},
))->find($consumableId);
// $consumable->load('consumableAssignments.admin','consumableAssignments.user');
if (!Company::isCurrentUserHasAccess($consumable)) {
return ['total' => 0, 'rows' => []];
}
$this->authorize('view', Component::class);
$rows = array();
foreach ($consumable->consumableAssignments as $consumable_assignment) {
$rows[] = [
'name' => $consumable_assignment->user->present()->nameUrl(),
'created_at' => ($consumable_assignment->created_at->format('Y-m-d H:i:s')=='-0001-11-30 00:00:00') ? '' : $consumable_assignment->created_at->format('Y-m-d H:i:s'),
'admin' => ($consumable_assignment->admin) ? $consumable_assignment->admin->present()->nameUrl() : '',
];
}
$consumableCount = $consumable->users->count();
$data = array('total' => $consumableCount, 'rows' => $rows);
return $data;
}
}
@@ -2,9 +2,11 @@
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Transformers\CustomFieldsTransformer;
use App\Models\CustomField;
use App\Models\CustomFieldset;
use Illuminate\Http\Request;
class CustomFieldsController extends Controller
{
@@ -16,6 +18,15 @@ class CustomFieldsController extends Controller
* @since [v3.0]
* @return Array
*/
public function index()
{
$this->authorize('index', CustomFields::class);
$fields = CustomField::get();
$total = count($fields);
return (new CustomFieldsTransformer)->transformCustomFields($fields, $total);
}
public function postReorder(Request $request, $id)
{
$fieldset = CustomFieldset::find($id);
@@ -0,0 +1,147 @@
<?php
namespace App\Http\Controllers\Api;
use View;
use App\Models\CustomFieldset;
use App\Models\CustomField;
use Input;
use Validator;
use Redirect;
use App\Models\AssetModel;
use Lang;
use Auth;
use Illuminate\Http\Request;
use Log;
use App\Http\Controllers\Controller;
use App\Helpers\Helper;
use App\Http\Transformers\CustomFieldsTransformer;
use App\Http\Transformers\CustomFieldsetsTransformer;
use App\Http\Requests\AssetRequest;
/**
* This controller handles all actions related to Custom Asset Fieldsets for
* the Snipe-IT Asset Management application.
*
* @todo Improve documentation here.
* @todo Check for raw DB queries and try to convert them to query builder statements
* @version v2.0
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
* @author [Josh Gibson]
*/
class CustomFieldsetsController extends Controller
{
/**
* Shows the given fieldset and its fields
* @author [A. Gianotto] [<snipe@snipe.net>]
* @author [Josh Gibson]
* @param int $id
* @since [v1.8]
* @return View
*/
public function index()
{
$this->authorize('index', CustomFieldset::class);
$fieldsets = CustomFieldset::withCount(['fields', 'models'])->get();
$total = count($fieldsets);
return (new CustomFieldsetsTransformer)->transformCustomFieldsets($fieldsets, $total);
}
/**
* Shows the given fieldset and its fields
* @author [A. Gianotto] [<snipe@snipe.net>]
* @author [Josh Gibson]
* @param int $id
* @since [v1.8]
* @return View
*/
public function show($id)
{
$this->authorize('show', CustomFieldset::class);
if ($fieldset = CustomFieldset::find($id)) {
return (new CustomFieldsetsTransformer)->transformCustomFieldset($fieldset);
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/custom_fields/message.fieldset.does_not_exist')), 200);
}
/**
* Update the specified resource in storage.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
$this->authorize('edit', CustomFieldset::class);
$fieldset = CustomFieldset::findOrFail($id);
$fieldset->fill($request->all());
if ($fieldset->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $fieldset, trans('admin/custom_fields/message.fieldset.update.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $fieldset->getErrors()));
}
/**
* Store a newly created resource in storage.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$this->authorize('create', CustomFieldset::class);
$fieldset = new CustomFieldset;
$fieldset->fill($request->all());
if ($fieldset->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $fieldset, trans('admin/custom_fields/message.fieldset.create.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $fieldset->getErrors()));
}
/**
* Delete a custom fieldset.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return Redirect
*/
public function destroy($id)
{
$this->authorize('delete', CustomFieldset::class);
$fieldset = CustomFieldset::findOrFail($id);
$modelsCount = $fieldset->models->count();
$fieldsCount = $fieldset->fields->count();
if (($modelsCount > 0) || ($fieldsCount > 0) ){
return response()->json(Helper::formatStandardApiResponse('error', null, 'Fieldset is in use.'));
}
if ($fieldset->delete()) {
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/custom_fields/message.fieldset.delete.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, 'Unspecified error'));
}
}
@@ -0,0 +1,113 @@
<?php
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Department;
use App\Http\Transformers\DepartmentsTransformer;
use App\Helpers\Helper;
use Auth;
class DepartmentsController extends Controller
{
/**
* Display a listing of the resource.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
{
$this->authorize('view', Department::class);
$allowed_columns = ['id','name'];
$departments = Department::select([
'id',
'name',
'location_id',
'company_id',
'manager_id',
'created_at',
'updated_at'
])->with('users')->with('location')->with('manager')->with('company')->withCount('users');
if ($request->has('search')) {
$departments = $departments->TextSearch($request->input('search'));
}
$offset = $request->input('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
$departments->orderBy($sort, $order);
$total = $departments->count();
$departments = $departments->skip($offset)->take($limit)->get();
return (new DepartmentsTransformer)->transformDepartments($departments, $total);
}
/**
* Store a newly created resource in storage.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$this->authorize('create', Department::class);
$department = new Department;
$department->fill($request->all());
$department->user_id = Auth::user()->id;
$department->manager_id = ($request->has('manager_id' ) ? $request->input('manager_id') : null);
if ($department->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $department, trans('admin/departments/message.create.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $department->getErrors()));
}
/**
* Display the specified resource.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
$this->authorize('view', Department::class);
$department = Department::findOrFail($id);
return (new DepartmentsTransformer)->transformDepartment($department);
}
/**
* Validates and deletes selected location.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $locationId
* @since [v1.0]
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy($id)
{
$department = Department::findOrFail($id);
if ($department->users->count() > 0) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/departments/message.assoc_users')));
}
$department->delete();
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/departments/message.delete.success')));
}
}
@@ -22,7 +22,7 @@ class GroupsController extends Controller
$this->authorize('view', Group::class);
$allowed_columns = ['id','name','created_at'];
$groups = Group::select('id','name','permissions')->withCount('users');
$groups = Group::select('id','name','permissions','created_at','updated_at')->withCount('users');
if ($request->has('search')) {
$groups = $groups->TextSearch($request->input('search'));
+15 -8
View File
@@ -11,6 +11,7 @@ use App\Models\Import;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Session;
use League\Csv\Reader;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
class ImportController extends Controller
@@ -29,7 +30,7 @@ class ImportController extends Controller
}
/**
* Store a newly created resource in storage.
* Process and store a CSV upload file.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
@@ -45,7 +46,6 @@ class ImportController extends Controller
$results = [];
$import = new Import;
foreach ($files as $file) {
if (!in_array($file->getMimeType(), array(
'application/vnd.ms-excel',
'text/csv',
@@ -53,11 +53,11 @@ class ImportController extends Controller
'text/comma-separated-values',
'text/tsv'))) {
$results['error']='File type must be CSV';
return $results;
return response()->json(Helper::formatStandardApiResponse('error', null, $results['error']), 500);
}
$date = date('Y-m-d-his');
$fixed_filename = str_replace(' ', '-', $file->getClientOriginalName());
$fixed_filename = str_slug($file->getClientOriginalName());
try {
$file->move($path, $date.'-'.$fixed_filename);
} catch (FileException $exception) {
@@ -66,17 +66,21 @@ class ImportController extends Controller
$results['error'].= ' ' . $exception->getMessage();
}
return response()->json(Helper::formatStandardApiResponse('error', null, $results['error']), 500);
}
$file_name = date('Y-m-d-his').'-'.$fixed_filename;
$import->file_path = $file_name;
$import->filesize = filesize($path.'/'.$file_name);
//TODO: is there a lighter way to do this?
$reader = Reader::createFromPath("{$path}/{$file_name}");
$import->header_row = $reader->fetchOne(0);
// Grab the first row to display via ajax as the user picks fields
$import->first_row = $reader->fetchOne(1);
$import->save();
$results[] = $import;
}
$results = (new ImportsTransformer)->transformImports($results);
return [
'files' => $results
'files' => $results,
];
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.feature_disabled')), 500);
@@ -91,7 +95,7 @@ class ImportController extends Controller
{
$this->authorize('create', Asset::class);
$errors = $request->import(Import::find($import_id));
$redirectTo = "hardware";
$redirectTo = "hardware.index";
switch ($request->get('import-type')) {
case "asset":
$redirectTo = "hardware.index";
@@ -108,6 +112,9 @@ class ImportController extends Controller
case "license":
$redirectTo = "licenses.index";
break;
case "user":
$redirectTo = "users.index";
break;
}
if ($errors) { //Failure
@@ -132,7 +139,7 @@ class ImportController extends Controller
try {
unlink(config('app.private_uploads').'/imports/'.$import->file_path);
$import->delete();
return response()->json(Helper::formatStandardApiResponse('success', null, trans('message.import.file_delete_success')));
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/hardware/message.import.file_delete_success')));
} catch (\Exception $e) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.import.file_delete_error')), 500);
}
@@ -21,7 +21,7 @@ class LicensesController extends Controller
public function index(Request $request)
{
$this->authorize('view', License::class);
$licenses = Company::scopeCompanyables(License::with('company', 'licenseSeatsRelation', 'manufacturer'));
$licenses = Company::scopeCompanyables(License::with('company', 'licenseSeatsRelation', 'manufacturer', 'supplier'));
if ($request->has('search')) {
$licenses = $licenses->TextSearch($request->input('search'));
@@ -59,6 +59,10 @@ class LicensesController extends Controller
$licenses->where('manufacturer_id','=',$request->input('manufacturer_id'));
}
if ($request->has('supplier_id')) {
$licenses->where('supplier_id','=',$request->input('supplier_id'));
}
if ($request->has('depreciation_id')) {
$licenses->where('depreciation_id','=',$request->input('depreciation_id'));
}
@@ -69,22 +73,26 @@ class LicensesController extends Controller
$offset = request('offset', 0);
$limit = request('limit', 50);
$allowed_columns = ['id','name','purchase_cost','expiration_date','purchase_order','order_number','notes','purchase_date','serial','manufacturer','company','license_name','license_email'];
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
switch ($sort) {
switch ($request->input('sort')) {
case 'manufacturer':
$licenses = $licenses->OrderManufacturer($order);
break;
case 'supplier':
$licenses = $licenses->OrderSupplier($order);
break;
case 'company':
$licenses = $licenses->OrderCompany($order);
break;
default:
$allowed_columns = ['id','name','purchase_cost','expiration_date','purchase_order','order_number','notes','purchase_date','serial','company','license_name','license_email'];
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
$licenses = $licenses->orderBy($sort, $order);
break;
}
$total = $licenses->count();
$licenses = $licenses->skip($offset)->take($limit)->get();
@@ -117,7 +125,13 @@ class LicensesController extends Controller
*/
public function show($id)
{
//
$license = License::find($id);
if (isset($license->id)) {
$license = $license->load('assignedusers', 'licenseSeats.user', 'licenseSeats.asset');
$this->authorize('view', $license);
return (new LicensesTransformer)->transformLicense($license);
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/licenses/message.does_not_exist')), 200);
}
@@ -21,7 +21,7 @@ class LocationsController extends Controller
{
$this->authorize('view', Location::class);
$allowed_columns = ['id','name','address','address2','city','state','country','zip','created_at',
'updated_at'];
'updated_at','parent_id', 'manager_id'];
$locations = Location::select([
'locations.id',
@@ -33,6 +33,7 @@ class LocationsController extends Controller
'locations.zip',
'locations.country',
'locations.parent_id',
'locations.manager_id',
'locations.created_at',
'locations.updated_at',
'locations.currency'
@@ -70,7 +71,7 @@ class LocationsController extends Controller
$location->fill($request->all());
if ($location->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $location, trans('admin/locations/message.create.success')));
return response()->json(Helper::formatStandardApiResponse('success', (new LocationsTransformer)->transformLocation($location), trans('admin/locations/message.create.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $location->getErrors()));
@@ -108,7 +109,7 @@ class LocationsController extends Controller
$location->fill($request->all());
if ($location->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $location, trans('admin/locations/message.update.success')));
return response()->json(Helper::formatStandardApiResponse('success', (new LocationsTransformer)->transformLocation($location), trans('admin/locations/message.update.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $location->getErrors()));
@@ -77,7 +77,7 @@ class ManufacturersController extends Controller
{
$this->authorize('view', Manufacturer::class);
$manufacturer = Manufacturer::findOrFail($id);
return $manufacturer;
return (new ManufacturersTransformer)->transformManufacturer($manufacturer);
}
@@ -0,0 +1,60 @@
<?php
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Actionlog;
use App\Http\Transformers\ActionlogsTransformer;
class ReportsController extends Controller
{
/**
* Returns Activity Report JSON.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return View
*/
public function index(Request $request)
{
$actionlogs = Actionlog::with('item', 'user', 'target','location');
if ($request->has('search')) {
$actionlogs = $actionlogs->TextSearch(e($request->input('search')));
}
if (($request->has('target_type')) && ($request->has('target_id'))) {
$actionlogs = $actionlogs->where('target_id','=',$request->input('target_id'))
->where('target_type','=',"App\\Models\\".ucwords($request->input('target_type')));
}
if (($request->has('item_type')) && ($request->has('item_id'))) {
$actionlogs = $actionlogs->where('item_id','=',$request->input('item_id'))
->where('item_type','=',"App\\Models\\".ucwords($request->input('item_type')));
}
if ($request->has('action_type')) {
$actionlogs = $actionlogs->where('action_type','=',$request->input('action_type'))->orderBy('created_at', 'desc');
}
$allowed_columns = [
'id',
'created_at'
];
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$offset = request('offset', 0);
$limit = request('limit', 50);
$total = $actionlogs->count();
$actionlogs = $actionlogs->orderBy($sort, $order);
$actionlogs = $actionlogs->skip($offset)->take($limit)->get();
return (new ActionlogsTransformer)->transformActionlogs($actionlogs, $total);
}
}
@@ -4,6 +4,7 @@ namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Ldap;
class SettingsController extends Controller
{
@@ -73,4 +74,28 @@ class SettingsController extends Controller
{
//
}
public function getLdapTest()
{
\Log::debug('Preparing to test LDAP connection');
try {
$connection = Ldap::connectToLdap();
try {
\Log::debug('attempting to bind to LDAP for LDAP test');
Ldap::bindAdminToLdap($connection);
return response()->json(['message' => 'It worked!'], 200);
} catch (\Exception $e) {
\Log::debug('Bind failed');
return response()->json(['message' => $e->getMessage()], 400);
//return response()->json(['message' => $e->getMessage()], 500);
}
} catch (\Exception $e) {
\Log::debug('Connection failed');
return response()->json(['message' => $e->getMessage()], 600);
}
}
}
@@ -53,9 +53,20 @@ class StatuslabelsController extends Controller
public function store(Request $request)
{
$this->authorize('create', Statuslabel::class);
$request->except('deployable', 'pending','archived');
if (!$request->has('type')) {
return response()->json(Helper::formatStandardApiResponse('error', null, ["type" => ["Status label type is required."]]));
}
$statuslabel = new Statuslabel;
$statuslabel->fill($request->all());
$statusType = Statuslabel::getStatuslabelTypesForDB($request->input('type'));
$statuslabel->deployable = $statusType['deployable'];
$statuslabel->pending = $statusType['pending'];
$statuslabel->archived = $statusType['archived'];
if ($statuslabel->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $statuslabel, trans('admin/statuslabels/message.create.success')));
}
@@ -75,7 +86,7 @@ class StatuslabelsController extends Controller
{
$this->authorize('view', Statuslabel::class);
$statuslabel = Statuslabel::findOrFail($id);
return $statuslabel;
return (new StatuslabelsTransformer)->transformStatuslabel($statuslabel);
}
@@ -92,8 +103,20 @@ class StatuslabelsController extends Controller
{
$this->authorize('edit', Statuslabel::class);
$statuslabel = Statuslabel::findOrFail($id);
$request->except('deployable', 'pending','archived');
if (!$request->has('type')) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'Status label type is required.'));
}
$statuslabel->fill($request->all());
$statusType = Statuslabel::getStatuslabelTypesForDB($request->input('type'));
$statuslabel->deployable = $statusType['deployable'];
$statuslabel->pending = $statusType['pending'];
$statuslabel->archived = $statusType['archived'];
if ($statuslabel->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $statuslabel, trans('admin/statuslabels/message.update.success')));
}
@@ -6,7 +6,7 @@ use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Helpers\Helper;
use App\Models\Supplier;
use App\Http\Transformers\DatatablesTransformer;
use App\Http\Transformers\SuppliersTransformer;
class SuppliersController extends Controller
{
@@ -23,7 +23,7 @@ class SuppliersController extends Controller
$allowed_columns = ['id','name','address','phone','contact','fax','email'];
$suppliers = Supplier::select(
array('id','name','address','address2','city','state','country','fax', 'phone','email','contact')
array('id','name','address','address2','city','state','country','fax', 'phone','email','contact','created_at','updated_at','deleted_at')
)->withCount('assets')->withCount('licenses')->whereNull('deleted_at');
@@ -39,8 +39,7 @@ class SuppliersController extends Controller
$total = $suppliers->count();
$suppliers = $suppliers->skip($offset)->take($limit)->get();
return (new DatatablesTransformer)->transformDatatables($suppliers, $total);
return $suppliers;
return (new SuppliersTransformer)->transformSuppliers($suppliers, $total);
}
@@ -77,7 +76,7 @@ class SuppliersController extends Controller
{
$this->authorize('view', Supplier::class);
$supplier = Supplier::findOrFail($id);
return $supplier;
return (new SuppliersTransformer)->transformSupplier($supplier);
}
+78 -9
View File
@@ -7,6 +7,9 @@ use App\Http\Controllers\Controller;
use App\Http\Transformers\UsersTransformer;
use App\Models\Company;
use App\Models\User;
use App\Helpers\Helper;
use App\Http\Requests\SaveUserRequest;
use App\Models\Asset;
class UsersController extends Controller
{
@@ -38,8 +41,9 @@ class UsersController extends Controller
'users.company_id',
'users.last_login',
'users.deleted_at',
'users.department_id',
'users.activated'
])->with('manager', 'groups', 'userloc', 'company', 'throttle','assets','licenses','accessories','consumables')
])->with('manager', 'groups', 'userloc', 'company', 'department','throttle','assets','licenses','accessories','consumables')
->withCount('assets','licenses','accessories','consumables');
$users = Company::scopeCompanyables($users);
@@ -48,8 +52,22 @@ class UsersController extends Controller
$users = $users->TextSearch($request->input('search'));
}
if (($request->has('deleted')) && ($request->input('deleted')=='true')) {
$users = $users->GetDeleted();
}
if ($request->has('company_id')) {
$users = $users->where('company_id','=',$request->input('company_id'));
$users = $users->where('company_id', '=', $request->input('company_id'));
}
if ($request->has('location_id')) {
$users = $users->where('location_id', '=', $request->input('location_id'));
}
if ($request->has('department_id')) {
$users = $users->where('department_id','=',$request->input('department_id'));
}
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
@@ -63,6 +81,9 @@ class UsersController extends Controller
case 'location':
$users = $users->OrderLocation($order);
break;
case 'department':
$users = $users->OrderDepartment($order);
break;
default:
$allowed_columns =
[
@@ -75,9 +96,9 @@ class UsersController extends Controller
$users = $users->orderBy($sort, $order);
break;
}
$userCount = $users->count();
$total = $users->count();
$users = $users->skip($offset)->take($limit)->get();
return (new UsersTransformer)->transformUsers($users, $userCount);
return (new UsersTransformer)->transformUsers($users, $total);
}
@@ -89,9 +110,17 @@ class UsersController extends Controller
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
public function store(SaveUserRequest $request)
{
//
$this->authorize('view', User::class);
$user = new User;
$user->fill($request->all());
$user->password = bcrypt($request->input('password'));
if ($user->save()) {
return response()->json(Helper::formatStandardApiResponse('success', (new UsersTransformer)->transformUser($user), trans('admin/users/message.create.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $user->getErrors()));
}
/**
@@ -118,9 +147,22 @@ class UsersController extends Controller
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
public function update(SaveUserRequest $request, $id)
{
//
$this->authorize('edit', User::class);
$user = User::findOrFail($id);
$user->fill($request->all());
if ($request->has('password')) {
$user->password = bcrypt($request->input('password'));
}
if ($user->save()) {
return response()->json(Helper::formatStandardApiResponse('success', (new UsersTransformer)->transformUser($user), trans('admin/users/message.success.update')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $user->getErrors()));
}
/**
@@ -133,6 +175,33 @@ class UsersController extends Controller
*/
public function destroy($id)
{
//
$this->authorize('delete', User::class);
$user = User::findOrFail($id);
$this->authorize('delete', $user);
if ($user->assets()->count() > 0) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.error.delete_has_assets')));
}
if ($user->delete()) {
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.success.delete')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.error.delete')));
}
/**
* Return JSON containing a list of assets assigned to a user.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @param $userId
* @return string JSON
*/
public function assets($id)
{
$this->authorize('view', User::class);
$assets = Asset::where('assigned_to', '=', $id)->with('model')->get();
return response()->json($assets);
}
}
@@ -59,7 +59,7 @@ class AssetMaintenancesController extends Controller
*/
public function index()
{
return View::make('asset_maintenances/index');
return view('asset_maintenances/index');
}
@@ -160,7 +160,7 @@ class AssetMaintenancesController extends Controller
] + AssetMaintenance::getImprovementOptions();
// Mark the selected asset, if it came in
// Render the view
return View::make('asset_maintenances/edit')
return view('asset_maintenances/edit')
->with('asset_list', Helper::detailedAssetList())
->with('selectedAsset', request('asset_id'))
->with('supplier_list', Helper::suppliersList())
@@ -259,7 +259,7 @@ class AssetMaintenancesController extends Controller
// Get Supplier List
// Render the view
return View::make('asset_maintenances/edit')
return view('asset_maintenances/edit')
->with('asset_list', Helper::detailedAssetList())
->with('selectedAsset', null)
->with('supplier_list', Helper::suppliersList())
@@ -384,6 +384,6 @@ class AssetMaintenancesController extends Controller
return static::getInsufficientPermissionsRedirect();
}
return View::make('asset_maintenances/view')->with('assetMaintenance', $assetMaintenance);
return view('asset_maintenances/view')->with('assetMaintenance', $assetMaintenance);
}
}
+73 -4
View File
@@ -40,7 +40,7 @@ class AssetModelsController extends Controller
*/
public function index()
{
return View::make('models/index');
return view('models/index');
}
/**
@@ -53,7 +53,7 @@ class AssetModelsController extends Controller
public function create()
{
// Show the page
return View::make('models/edit')
return view('models/edit')
->with('category_list', Helper::categoryList('asset'))
->with('depreciation_list', Helper::depreciationList())
->with('manufacturer_list', Helper::manufacturerList())
@@ -297,7 +297,7 @@ class AssetModelsController extends Controller
$model = AssetModel::withTrashed()->find($modelId);
if (isset($model->id)) {
return View::make('models/view', compact('model'));
return view('models/view', compact('model'));
}
// Prepare the error message
$error = trans('admin/models/message.does_not_exist', compact('id'));
@@ -347,7 +347,7 @@ class AssetModelsController extends Controller
public function getCustomFields($modelId)
{
$model = AssetModel::find($modelId);
return View::make("models.custom_fields_form")->with("model", $model);
return view("models.custom_fields_form")->with("model", $model);
}
@@ -394,4 +394,73 @@ class AssetModelsController extends Controller
return $data;
}
/**
* Returns a view that allows the user to bulk edit model attrbutes
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.7]
* @return \Illuminate\Contracts\View\View
*/
public function postBulkEdit(Request $request)
{
$models_raw_array = Input::get('ids');
$models = AssetModel::whereIn('id', $models_raw_array)->get();
$nochange = ['NC' => 'No Change'];
$fieldset_list = $nochange + Helper::customFieldsetList();
$depreciation_list = $nochange + Helper::depreciationList();
$category_list = $nochange + Helper::categoryList('asset');
$manufacturer_list = $nochange + Helper::manufacturerList();
return view('models/bulk-edit', compact('models'))
->with('manufacturer_list', $manufacturer_list)
->with('category_list', $category_list)
->with('fieldset_list', $fieldset_list)
->with('depreciation_list', $depreciation_list);
}
/**
* Returns a view that allows the user to bulk edit model attrbutes
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.7]
* @return \Illuminate\Contracts\View\View
*/
public function postBulkEditSave(Request $request)
{
$models_raw_array = Input::get('ids');
$update_array = array();
if (($request->has('manufacturer_id') && ($request->input('manufacturer_id')!='NC'))) {
$update_array['manufacturer_id'] = $request->input('manufacturer_id');
}
if (($request->has('category_id') && ($request->input('category_id')!='NC'))) {
$update_array['category_id'] = $request->input('category_id');
}
if ($request->input('fieldset_id')!='NC') {
$update_array['fieldset_id'] = $request->input('fieldset_id');
}
if ($request->input('depreciation_id')!='NC') {
$update_array['depreciation_id'] = $request->input('depreciation_id');
}
if (count($update_array) > 0) {
AssetModel::whereIn('id', $models_raw_array)->update($update_array);
return redirect()->route('models.index')
->with('success', trans('admin/models/message.bulkedit.success'));
}
return redirect()->route('models.index')
->with('warning', trans('admin/models/message.bulkedit.error'));
}
}
+119 -117
View File
@@ -12,6 +12,7 @@ use App\Models\Asset;
use App\Models\AssetModel;
use App\Models\Company;
use App\Models\CustomField;
use App\Models\Import;
use App\Models\Location;
use App\Models\Setting;
use App\Models\User;
@@ -74,7 +75,7 @@ class AssetsController extends Controller
} else {
$company = null;
}
return View::make('hardware/index')->with('company',$company);
return view('hardware/index')->with('company',$company);
}
/**
@@ -115,9 +116,9 @@ class AssetsController extends Controller
->with('statuslabel_list', Helper::statusLabelList())
->with('location_list', Helper::locationsList())
->with('item', new Asset)
->with('manufacturer', Helper::manufacturerList())
->with('category', Helper::categoryList('asset'))
->with('statuslabel_types', Helper::statusTypeList())
->with('manufacturer', Helper::manufacturerList()) //handled in modal now?
->with('category', Helper::categoryList('asset')) //handled in modal now?
->with('statuslabel_types', Helper::statusTypeList()) //handled in modal now?
->with('users_list', Helper::usersList())
->with('assets_list', Helper::assetsList())
->with('locations_list', Helper::locationsList());
@@ -209,9 +210,21 @@ class AssetsController extends Controller
// FIXME: No idea why this is returning a Builder error on db_column_name.
// Need to investigate and fix. Using static method for now.
$model = AssetModel::find($request->get('model_id'));
if ($model->fieldset) {
foreach ($model->fieldset->fields as $field) {
$asset->{$field->convertUnicodeDbSlug()} = e($request->input($field->convertUnicodeDbSlug()));
if ($field->field_encrypted=='1') {
if (Gate::allows('admin')) {
$asset->{$field->convertUnicodeDbSlug()} = \Crypt::encrypt($request->input($field->convertUnicodeDbSlug()));
}
} else {
$asset->{$field->convertUnicodeDbSlug()} = $request->input($field->convertUnicodeDbSlug());
}
}
}
@@ -254,11 +267,11 @@ class AssetsController extends Controller
//Handles company checks and permissions.
$this->authorize($item);
return View::make('hardware/edit', compact('item'))
return view('hardware/edit', compact('item'))
->with('model_list', Helper::modelList())
->with('supplier_list', Helper::suppliersList())
->with('company_list', Helper::companyList())
->with('location_list', Helper::locationsList())
->with('locations_list', Helper::locationsList())
->with('statuslabel_list', Helper::statusLabelList())
->with('assigned_to', Helper::usersList())
->with('manufacturer', Helper::manufacturerList())
@@ -358,7 +371,7 @@ class AssetsController extends Controller
}
} else {
$asset->{$field->convertUnicodeDbSlug()} = e($request->input($field->convertUnicodeDbSlug()));
$asset->{$field->convertUnicodeDbSlug()} = $request->input($field->convertUnicodeDbSlug());
}
}
}
@@ -367,7 +380,7 @@ class AssetsController extends Controller
if ($asset->save()) {
// Redirect to the new asset page
\Session::flash('success', trans('admin/hardware/message.update.success'));
return response()->json(['redirect_url' => route("hardware.show", $assetId)]);
return response()->json(['redirect_url' => route("view/hardware", $assetId)]);
}
\Input::flash();
\Session::flash('errors', $asset->getErrors());
@@ -399,6 +412,13 @@ class AssetsController extends Controller
$asset->delete();
$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;
$log = $logaction->logaction('deleted');
// Redirect to the asset management page
return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.delete.success'));
}
@@ -423,7 +443,7 @@ class AssetsController extends Controller
$this->authorize('checkout', $asset);
// Get the dropdown of users and then pass it to the checkout view
return View::make('hardware/checkout', compact('asset'))
return view('hardware/checkout', compact('asset'))
->with('users_list', Helper::usersList())
->with('assets_list', Helper::assetsList())
->with('locations_list', Helper::locationsList());
@@ -460,19 +480,19 @@ class AssetsController extends Controller
$admin = Auth::user();
if ((Input::has('checkout_at')) && (Input::get('checkout_at')!= date("Y-m-d"))) {
$checkout_at = e(Input::get('checkout_at'));
$checkout_at = Input::get('checkout_at');
} else {
$checkout_at = date("Y-m-d H:i:s");
}
if (Input::has('expected_checkin')) {
$expected_checkin = e(Input::get('expected_checkin'));
$expected_checkin = Input::get('expected_checkin');
} else {
$expected_checkin = '';
}
if ($asset->checkOut($target, $admin, $checkout_at, $expected_checkin, e(Input::get('note')), e(Input::get('name')))) {
if ($asset->checkOut($target, $admin, $checkout_at, $expected_checkin, e(Input::get('note')), Input::get('name'))) {
// Redirect to the new asset page
return redirect()->to("hardware")->with('success', trans('admin/hardware/message.checkout.success'));
return redirect()->route("hardware.index")->with('success', trans('admin/hardware/message.checkout.success'));
}
// Redirect to the asset management page with error
@@ -498,7 +518,7 @@ class AssetsController extends Controller
}
$this->authorize('checkin', $asset);
return View::make('hardware/checkin', compact('asset'))->with('statusLabel_list', Helper::statusLabelList())->with('backto', $backto);
return view('hardware/checkin', compact('asset'))->with('statusLabel_list', Helper::statusLabelList())->with('backto', $backto);
}
@@ -524,17 +544,18 @@ class AssetsController extends Controller
$this->authorize('checkin', $asset);
$admin = Auth::user();
$user = $asset->assignedUser;
if($asset->assignedType() == Asset::USER) {
$user = $asset->assignedTo;
}
if (is_null($target = $asset->assignedTo)) {
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkin.already_checked_in'));
}
// This is just used for the redirect
$return_to = $asset->assigned_to;
$asset->expected_checkin = null;
$asset->last_checkout = null;
$asset->assigned_to = null;
$asset->assignedTo()->disassociate($asset);
$asset->assigned_type = null;
$asset->accepted = null;
$asset->name = e(Input::get('name'));
@@ -553,7 +574,7 @@ class AssetsController extends Controller
$data['item_serial'] = $asset->serial;
$data['note'] = $logaction->note;
if ((($asset->checkin_email()=='1')) && (isset($user)) && (!config('app.lock_passwords'))) {
if ((($asset->checkin_email()=='1')) && (isset($user)) && (!empty($user->email)) && (!config('app.lock_passwords'))) {
Mail::send('emails.checkin-asset', $data, function ($m) use ($user) {
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
@@ -562,13 +583,13 @@ class AssetsController extends Controller
}
if ($backto=='user') {
return redirect()->to("admin/users/".$return_to.'/view')->with('success', trans('admin/hardware/message.checkin.success'));
return redirect()->to("admin/users/".$user->id.'/view')->with('success', trans('admin/hardware/message.checkin.success'));
}
return redirect()->to("hardware")->with('success', trans('admin/hardware/message.checkin.success'));
return redirect()->route("hardware.index")->with('success', trans('admin/hardware/message.checkin.success'));
}
// Redirect to the asset management page with error
return redirect()->to("hardware")->with('error', trans('admin/hardware/message.checkin.error'));
return redirect()->route("hardware.index")->with('error', trans('admin/hardware/message.checkin.error'));
}
@@ -582,15 +603,16 @@ class AssetsController extends Controller
*/
public function show($assetId = null)
{
$asset = Asset::withTrashed()->find($assetId);
$settings = Setting::getSettings();
$this->authorize('view', $asset);
$settings = Setting::getSettings();
$audit_log = Actionlog::where('action_type','=','audit')->where('item_id','=',$assetId)->where('item_type','=',Asset::class)->orderBy('created_at','DESC')->first();
if (isset($asset->id)) {
if ($asset->userloc) {
$use_currency = $asset->userloc->currency;
} elseif ($asset->assetloc) {
if (isset($asset)) {
if (!is_null($asset->assetloc)) {
$use_currency = $asset->assetloc->currency;
} else {
@@ -606,10 +628,11 @@ class AssetsController extends Controller
'url' => route('qr_code/hardware', $asset->id)
);
return View::make('hardware/view', compact('asset', 'qr_code', 'settings'))->with('use_currency', $use_currency);
return view('hardware/view', compact('asset', 'qr_code', 'settings'))
->with('use_currency', $use_currency)->with('audit_log',$audit_log);
}
return redirect()->route('hardware')->with('error', trans('admin/hardware/message.does_not_exist', compact('id')));
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist', compact('id')));
}
/**
@@ -627,7 +650,7 @@ class AssetsController extends Controller
if ($settings->qr_code == '1') {
$asset = Asset::find($assetId);
$size = Helper::barcodeDimensions($settings->barcode_type);
$qr_file = public_path().'/uploads/barcodes/qr-'.str_slug($asset->asset_tag).'.png';
$qr_file = public_path().'/uploads/barcodes/qr-'.str_slug($asset->asset_tag).'-'.str_slug($asset->id).'.png';
if (isset($asset->id,$asset->asset_tag)) {
@@ -675,56 +698,6 @@ class AssetsController extends Controller
}
/**
* Get the Asset import upload page.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @return View
*/
public function getImportUpload()
{
$this->authorize('create', Asset::class);
return View::make('hardware/import');
}
/**
* Process the uploaded file
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @return Redirect
*/
public function postProcessImportFile(ItemImportRequest $request)
{
$this->authorize('create', Asset::class);
$errors = $request->import();
// We use hardware instead of asset in the url
$redirectTo = "hardware";
switch (request('import-type')) {
case "asset":
$redirectTo = "hardware.index";
break;
case "accessory":
$redirectTo = "accessories.index";
break;
case "consumable":
$redirectTo = "consumables.index";
break;
case "component":
$redirectTo = "components.index";
break;
}
if ($errors) { //Failure
return redirect()->back()->with('import_errors', json_decode(json_encode($errors)))->with('error', trans('admin/hardware/message.import.error'));
}
return redirect()->to(route($redirectTo))->with('success', trans('admin/hardware/message.import.success'));
}
/**
* Returns a view that presents a form to clone an asset.
*
@@ -749,16 +722,18 @@ class AssetsController extends Controller
$asset->serial = '';
$asset->assigned_to = '';
return View::make('hardware/edit')
return view('hardware/edit')
->with('supplier_list', Helper::suppliersList())
->with('model_list', Helper::modelList())
->with('statuslabel_list', Helper::statusLabelList())
->with('statuslabel_types', Helper::statusTypeList())
->with('assigned_to', Helper::usersList())
->with('item', $asset)
->with('location_list', Helper::locationsList())
->with('locations_list', Helper::locationsList())
->with('manufacturer', Helper::manufacturerList())
->with('category', Helper::categoryList('asset'))
->with('users_list', Helper::usersList())
->with('assets_list', Helper::assetsList())
->with('company_list', Helper::companyList());
}
@@ -772,7 +747,7 @@ class AssetsController extends Controller
public function getImportHistory()
{
$this->authorize('checkout', Asset::class);
return View::make('hardware/history');
return view('hardware/history');
}
/**
@@ -918,7 +893,7 @@ class AssetsController extends Controller
}
}
}
return View::make('hardware/history')->with('status', $status);
return view('hardware/history')->with('status', $status);
}
/**
@@ -937,7 +912,7 @@ class AssetsController extends Controller
if (isset($asset->id)) {
// Restore the asset
Asset::withTrashed()->where('id', $assetId)->restore();
return redirect()->route('hardware')->with('success', trans('admin/hardware/message.restore.success'));
return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.restore.success'));
}
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
}
@@ -956,7 +931,7 @@ class AssetsController extends Controller
{
if (!$asset = Asset::find($assetId)) {
return redirect()->route('hardware')->with('error', trans('admin/hardware/message.does_not_exist'));
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
}
$this->authorize('update', $asset);
@@ -990,7 +965,7 @@ class AssetsController extends Controller
* @since [v1.0]
* @return View
*/
public function getDeleteFile($assetId = null, $fileId = null)
public function deleteFile($assetId = null, $fileId = null)
{
$asset = Asset::find($assetId);
$this->authorize('update', $asset);
@@ -1013,7 +988,7 @@ class AssetsController extends Controller
$error = trans('admin/hardware/message.does_not_exist', compact('id'));
// Redirect to the hardware management page
return redirect()->route('hardware')->with('error', $error);
return redirect()->route('hardware.index')->with('error', $error);
}
/**
@@ -1046,7 +1021,7 @@ class AssetsController extends Controller
$error = trans('admin/hardware/message.does_not_exist', compact('id'));
// Redirect to the hardware management page
return redirect()->route('hardware')->with('error', $error);
return redirect()->route('hardware.index')->with('error', $error);
}
/**
@@ -1078,7 +1053,7 @@ class AssetsController extends Controller
if ($request->input('bulk_actions')=='labels') {
$count = 0;
return View::make('hardware/labels')
return view('hardware/labels')
->with('assets', Asset::find($asset_ids))
->with('settings', Setting::getSettings())
->with('count', $count)
@@ -1091,11 +1066,11 @@ class AssetsController extends Controller
$assets->each(function($asset) {
$this->authorize('delete',$asset);
});
return View::make('hardware/bulk-delete')->with('assets', $assets);
return view('hardware/bulk-delete')->with('assets', $assets);
// Bulk edit
} elseif ($request->input('bulk_actions')=='edit') {
return View::make('hardware/bulk')
return view('hardware/bulk')
->with('assets', request('ids'))
->with('supplier_list', Helper::suppliersList())
->with('statuslabel_list', Helper::statusLabelList())
@@ -1172,20 +1147,10 @@ class AssetsController extends Controller
$update_array['requestable'] = e(Input::get('requestable'));
}
if (DB::table('assets')
DB::table('assets')
->where('id', $key)
->update($update_array)) {
$logAction = new Actionlog();
$logAction->item_type = Asset::class;
$logAction->item_id = $key;
$logAction->created_at = date("Y-m-d H:i:s");
->update($update_array);
if (Input::has('rtd_location_id')) {
$logAction->location_id = e(Input::get('rtd_location_id'));
}
$logAction->user_id = Auth::user()->id;
$logAction->logaction('update');
}
} // endforeach
return redirect()->to("hardware")->with('success', trans('admin/hardware/message.update.success'));
// no values given, nothing to update
@@ -1206,23 +1171,17 @@ class AssetsController extends Controller
public function postBulkDelete()
{
$this->authorize('delete', Asset::class);
if (Input::has('bulk_edit')) {
$assets = Asset::find(Input::get('bulk_edit'));
if (Input::has('ids')) {
$assets = Asset::find(Input::get('ids'));
foreach ($assets as $asset) {
$update_array['deleted_at'] = date('Y-m-d H:i:s');
$update_array['assigned_to'] = null;
if (DB::table('assets')
DB::table('assets')
->where('id', $asset->id)
->update($update_array)) {
$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('deleted');
}
->update($update_array);
} // endforeach
return redirect()->to("hardware")->with('success', trans('admin/hardware/message.delete.success'));
@@ -1237,7 +1196,7 @@ class AssetsController extends Controller
$this->authorize('checkout', Asset::class);
// Filter out assets that are not deployable.
$assets_list = Company::scopeCompanyables(Asset::RTD()->get(), 'assets.company_id')->pluck('detailed_name', 'id')->toArray();
return View::make('hardware/bulk-checkout')
return view('hardware/bulk-checkout')
->with('users_list', Helper::usersList())
->with('assets_list', $assets_list);
}
@@ -1286,4 +1245,47 @@ class AssetsController extends Controller
// Redirect to the asset management page with error
return redirect()->to("hardware/bulk-checkout")->with('error', trans('admin/hardware/message.checkout.error'))->withErrors($errors);
}
public function quickScan(Request $request)
{
$this->authorize('audit', Asset::class);
$dt = Carbon::now()->addMonths(12)->toDateString();
return view('hardware/quickscan')->with('next_audit_date', $dt)->with('locations_list', Helper::locationsList());
}
public function audit(Request $request, $id)
{
$this->authorize('audit', Asset::class);
$dt = Carbon::now()->addMonths(12)->toDateString();
$asset = Asset::findOrFail($id);
return view('hardware/audit')->with('asset', $asset)->with('next_audit_date', $dt)->with('locations_list', Helper::locationsList());
}
public function auditStore(Request $request, $id)
{
$this->authorize('audit', Asset::class);
$rules = array(
'location_id' => 'exists:locations,id|nullable|numeric',
'next_audit_date' => 'date|nullable'
);
$validator = \Validator::make($request->all(), $rules);
if ($validator->fails()) {
return response()->json(Helper::formatStandardApiResponse('error', null, $validator->errors()->all()));
}
$asset = Asset::findOrFail($id);
$asset->next_audit_date = $request->input('next_audit_date');
if ($asset->save()) {
$asset->logAudit(request('note'),request('location_id'));
return redirect()->to("hardware")->with('success', trans('admin/hardware/message.audit.success'));
}
}
}
@@ -55,7 +55,7 @@ class LoginController extends Controller
if (Auth::check()) {
return redirect()->intended('dashboard');
}
return View::make('auth.login');
return view('auth.login');
}
@@ -198,7 +198,7 @@ class LoginController extends Controller
$user->two_factor_secret
);
return View::make('auth.two_factor_enroll')->with('google2fa_url', $google2fa_url);
return view('auth.two_factor_enroll')->with('google2fa_url', $google2fa_url);
}
@@ -210,7 +210,7 @@ class LoginController extends Controller
*/
public function getTwoFactorAuth()
{
return View::make('auth.two_factor');
return view('auth.two_factor');
}
/**
@@ -38,7 +38,7 @@ class CategoriesController extends Controller
public function index()
{
// Show the page
return View::make('categories/index');
return view('categories/index');
}
@@ -54,7 +54,7 @@ class CategoriesController extends Controller
{
// Show the page
$category_types= Helper::categoryTypeList();
return View::make('categories/edit')->with('item', new Category)
return view('categories/edit')->with('item', new Category)
->with('category_types', $category_types);
}
@@ -105,7 +105,7 @@ class CategoriesController extends Controller
}
$category_types= Helper::categoryTypeList();
return View::make('categories/edit', compact('item'))
return view('categories/edit', compact('item'))
->with('category_types', $category_types);
}
@@ -201,7 +201,7 @@ class CategoriesController extends Controller
$category_type = $category->category_type;
$category_type_route = $category->category_type.'s';
}
return View::make('categories/view', compact('category'))
return view('categories/view', compact('category'))
->with('category_type',$category_type)
->with('category_type_route',$category_type_route);
}
+4 -4
View File
@@ -27,7 +27,7 @@ final class CompaniesController extends Controller
*/
public function index()
{
return View::make('companies/index')->with('companies', Company::all());
return view('companies/index')->with('companies', Company::all());
}
/**
@@ -39,7 +39,7 @@ final class CompaniesController extends Controller
*/
public function create()
{
return View::make('companies/edit')->with('item', new Company);
return view('companies/edit')->with('item', new Company);
}
/**
@@ -77,7 +77,7 @@ final class CompaniesController extends Controller
return redirect()->route('companies.index')
->with('error', trans('admin/companies/message.does_not_exist'));
}
return View::make('companies/edit')->with('item', $item);
return view('companies/edit')->with('item', $item);
}
/**
@@ -145,7 +145,7 @@ final class CompaniesController extends Controller
return redirect()->route('companies.index')
->with('error', trans('admin/companies/message.not_found'));
} else {
return View::make('companies/view')->with('company',$company);
return view('companies/view')->with('company',$company);
}
}
+6 -18
View File
@@ -2,7 +2,6 @@
namespace App\Http\Controllers;
use App\Helpers\Helper;
use App\Models\Actionlog;
use App\Models\Company;
use App\Models\Component;
use App\Models\CustomField;
@@ -12,7 +11,6 @@ use App\Models\Asset;
use Auth;
use Config;
use DB;
use DeepCopyTest\H;
use Input;
use Lang;
use Mail;
@@ -44,7 +42,7 @@ class ComponentsController extends Controller
public function index()
{
$this->authorize('view', Component::class);
return View::make('components/index');
return view('components/index');
}
@@ -60,7 +58,7 @@ class ComponentsController extends Controller
{
$this->authorize('create', Component::class);
// Show the page
return View::make('components/edit')
return view('components/edit')
->with('item', new Component)
->with('category_list', Helper::categoryList('component'))
->with('company_list', Helper::companyList())
@@ -79,10 +77,7 @@ class ComponentsController extends Controller
public function store()
{
$this->authorize('create', Component::class);
// create a new model instance
$component = new Component();
// Update the component data
$component->name = Input::get('name');
$component->category_id = Input::get('category_id');
$component->location_id = Input::get('location_id');
@@ -95,10 +90,7 @@ class ComponentsController extends Controller
$component->qty = Input::get('qty');
$component->user_id = Auth::id();
// Was the component created?
if ($component->save()) {
$component->logCreate();
// Redirect to the new component page
return redirect()->route('components.index')->with('success', trans('admin/components/message.create.success'));
}
return redirect()->back()->withInput()->withErrors($component->getErrors());
@@ -115,15 +107,13 @@ class ComponentsController extends Controller
*/
public function edit($componentId = null)
{
// Check if the component exists
if (is_null($item = Component::find($componentId))) {
// Redirect to the blogs management page
return redirect()->route('components.index')->with('error', trans('admin/components/message.does_not_exist'));
}
$this->authorize('update', $item);
return View::make('components/edit', compact('item'))
return view('components/edit', compact('item'))
->with('category_list', Helper::categoryList('component'))
->with('company_list', Helper::companyList())
->with('location_list', Helper::locationsList());
@@ -141,9 +131,7 @@ class ComponentsController extends Controller
*/
public function update($componentId = null)
{
// Check if the blog post exists
if (is_null($component = Component::find($componentId))) {
// Redirect to the blogs management page
return redirect()->route('components.index')->with('error', trans('admin/components/message.does_not_exist'));
}
@@ -215,7 +203,7 @@ class ComponentsController extends Controller
if (isset($component->id)) {
$this->authorize('view', $component);
return View::make('components/view', compact('component'));
return view('components/view', compact('component'));
}
// Prepare the error message
$error = trans('admin/components/message.does_not_exist', compact('id'));
@@ -240,7 +228,7 @@ class ComponentsController extends Controller
return redirect()->route('components.index')->with('error', trans('admin/components/message.not_found'));
}
$this->authorize('checkout', $component);
return View::make('components/checkout', compact('component'))->with('assets_list', Helper::detailedAssetList());
return view('components/checkout', compact('component'))->with('assets_list', Helper::detailedAssetList());
}
/**
@@ -295,7 +283,7 @@ class ComponentsController extends Controller
'asset_id' => $asset_id
]);
$component->logCheckout(e(Input::get('note')), $asset_id);
$component->logCheckout(e(Input::get('note')), $asset);
return redirect()->route('components.index')->with('success', trans('admin/components/message.checkout.success'));
}
+9 -69
View File
@@ -3,7 +3,6 @@
namespace App\Http\Controllers;
use App\Helpers\Helper;
use App\Models\Actionlog;
use App\Models\Company;
use App\Models\Consumable;
use App\Models\Setting;
@@ -40,7 +39,7 @@ class ConsumablesController extends Controller
public function index()
{
$this->authorize('index', Consumable::class);
return View::make('consumables/index');
return view('consumables/index');
}
@@ -56,7 +55,7 @@ class ConsumablesController extends Controller
{
$this->authorize('create', Consumable::class);
// Show the page
return View::make('consumables/edit')
return view('consumables/edit')
->with('item', new Consumable)
->with('category_list', Helper::categoryList('consumable'))
->with('company_list', Helper::companyList())
@@ -91,10 +90,7 @@ class ConsumablesController extends Controller
$consumable->qty = Input::get('qty');
$consumable->user_id = Auth::id();
// Was the consumable created?
if ($consumable->save()) {
$consumable->logCreate();
// Redirect to the new consumable page
return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.create.success'));
}
@@ -113,15 +109,13 @@ class ConsumablesController extends Controller
*/
public function edit($consumableId = null)
{
// Check if the consumable exists
if (is_null($item = Consumable::find($consumableId))) {
// Redirect to the blogs management page
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist'));
}
$this->authorize($item);
return View::make('consumables/edit', compact('item'))
return view('consumables/edit', compact('item'))
->with('category_list', Helper::categoryList('consumable'))
->with('company_list', Helper::companyList())
->with('location_list', Helper::locationsList())
@@ -175,9 +169,7 @@ class ConsumablesController extends Controller
*/
public function destroy($consumableId)
{
// Check if the blog post exists
if (is_null($consumable = Consumable::find($consumableId))) {
// Redirect to the blogs management page
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.not_found'));
}
$this->authorize($consumable);
@@ -200,13 +192,9 @@ class ConsumablesController extends Controller
$consumable = Consumable::find($consumableId);
$this->authorize($consumable);
if (isset($consumable->id)) {
return View::make('consumables/view', compact('consumable'));
return view('consumables/view', compact('consumable'));
}
// Prepare the error message
$error = trans('admin/consumables/message.does_not_exist', compact('id'));
// Redirect to the user management page
return redirect()->route('consumables')->with('error', $error);
return redirect()->route('consumables')->with('error', trans('admin/consumables/message.does_not_exist', compact('id')));
}
/**
@@ -220,14 +208,11 @@ class ConsumablesController extends Controller
*/
public function getCheckout($consumableId)
{
// Check if the consumable exists
if (is_null($consumable = Consumable::find($consumableId))) {
// Redirect to the consumable management page with error
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.not_found'));
}
$this->authorize('checkout', $consumable);
// Get the dropdown of users and then pass it to the checkout view
return View::make('consumables/checkout', compact('consumable'))->with('users_list', Helper::usersList());
return view('consumables/checkout', compact('consumable'))->with('users_list', Helper::usersList());
}
/**
@@ -241,9 +226,7 @@ class ConsumablesController extends Controller
*/
public function postCheckout($consumableId)
{
// Check if the consumable exists
if (is_null($consumable = Consumable::find($consumableId))) {
// Redirect to the consumable management page with error
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.not_found'));
}
@@ -252,13 +235,13 @@ class ConsumablesController extends Controller
$admin_user = Auth::user();
$assigned_to = e(Input::get('assigned_to'));
// Check if the user exists
// Check if the user exists
if (is_null($user = User::find($assigned_to))) {
// Redirect to the consumable management page with error
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.user_does_not_exist'));
}
// Update the consumable data
// Update the consumable data
$consumable->assigned_to = e(Input::get('assigned_to'));
$consumable->users()->attach($consumable->id, [
@@ -267,7 +250,7 @@ class ConsumablesController extends Controller
'assigned_to' => e(Input::get('assigned_to'))
]);
$logaction = $consumable->logCheckout(e(Input::get('note')));
$logaction = $consumable->logCheckout(e(Input::get('note')), $user);
$data['log_id'] = $logaction->id;
$data['eula'] = $consumable->getEula();
$data['first_name'] = $user->first_name;
@@ -290,47 +273,4 @@ class ConsumablesController extends Controller
}
/**
* Returns a JSON response containing details on the users associated with this consumable.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see ConsumablesController::getView() method that returns the form.
* @since [v1.0]
* @param int $consumableId
* @return array
*/
public function getDataView($consumableId)
{
//$consumable = Consumable::find($consumableID);
$consumable = Consumable::with(array('consumableAssigments'=>
function ($query) {
$query->orderBy('created_at', 'DESC');
},
'consumableAssigments.admin'=> function ($query) {
},
'consumableAssigments.user'=> function ($query) {
},
))->find($consumableId);
// $consumable->load('consumableAssigments.admin','consumableAssigments.user');
if (!Company::isCurrentUserHasAccess($consumable)) {
return ['total' => 0, 'rows' => []];
}
$this->authorize('view', Component::class);
$rows = array();
foreach ($consumable->consumableAssigments as $consumable_assignment) {
$rows[] = [
'name' => $consumable_assignment->user->present()->nameUrl(),
'created_at' => ($consumable_assignment->created_at->format('Y-m-d H:i:s')=='-0001-11-30 00:00:00') ? '' : $consumable_assignment->created_at->format('Y-m-d H:i:s'),
'admin' => ($consumable_assignment->admin) ? $consumable_assignment->admin->present()->nameUrl() : '',
];
}
$consumableCount = $consumable->users->count();
$data = array('total' => $consumableCount, 'rows' => $rows);
return $data;
}
}
@@ -39,7 +39,7 @@ class CustomFieldsController extends Controller
$fieldsets = CustomFieldset::with("fields", "models")->get();
$fields = CustomField::with("fieldset")->get();
return View::make("custom_fields.index")->with("custom_fieldsets", $fieldsets)->with("custom_fields", $fields);
return view("custom_fields.index")->with("custom_fieldsets", $fieldsets)->with("custom_fields", $fields);
}
@@ -57,7 +57,7 @@ class CustomFieldsController extends Controller
public function create()
{
return View::make("custom_fields.fields.edit")->with('field', new CustomField());
return view("custom_fields.fields.edit")->with('field', new CustomField());
}
@@ -155,7 +155,7 @@ class CustomFieldsController extends Controller
public function edit($id)
{
$field = CustomField::find($id);
return View::make("custom_fields.fields.edit")->with('field', $field);
return view("custom_fields.fields.edit")->with('field', $field);
}
@@ -49,7 +49,7 @@ class CustomFieldsetsController extends Controller
}
}
return View::make("custom_fields.fieldsets.view")->with("custom_fieldset", $cfset)->with("maxid", $maxid+1)->with("custom_fields_list", $custom_fields_list);
return view("custom_fields.fieldsets.view")->with("custom_fieldset", $cfset)->with("maxid", $maxid+1)->with("custom_fields_list", $custom_fields_list);
}
@@ -62,7 +62,7 @@ class CustomFieldsetsController extends Controller
*/
public function create()
{
return View::make("custom_fields.fieldsets.edit");
return view("custom_fields.fieldsets.edit");
}
+10 -43
View File
@@ -30,53 +30,20 @@ class DashboardController extends Controller
// Show the page
if (Auth::user()->hasAccess('admin')) {
$asset_stats['total'] = Asset::Hardware()->count();
$asset_stats=null;
$asset_stats['rtd']['total'] = Asset::Hardware()->RTD()->count();
$counts['asset'] = \App\Models\Asset::count();
$counts['accessory'] = \App\Models\Accessory::count();
$counts['license'] = \App\Models\License::assetcount();
$counts['consumable'] = \App\Models\Consumable::count();
$counts['grand_total'] = $counts['asset'] + $counts['accessory'] + $counts['license'] + $counts['consumable'];
if ($asset_stats['rtd']['total'] > 0) {
$asset_stats['rtd']['percent'] = round(($asset_stats['rtd']['total']/$asset_stats['total']) * 100);
} else {
$asset_stats['rtd']['percent'] = 0;
if ((!file_exists(storage_path().'/oauth-private.key')) || (!file_exists(storage_path().'/oauth-public.key'))) {
\Artisan::call('passport:install');
\Artisan::call('migrate', ['--force' => true]);
}
$asset_stats['pending']['total'] = Asset::Hardware()->Pending()->count();
if ($asset_stats['pending']['total'] > 0) {
$asset_stats['pending']['percent'] = round(($asset_stats['pending']['total']/$asset_stats['total']) * 100);
} else {
$asset_stats['pending']['percent'] = 0;
}
$asset_stats['deployed']['total'] = Asset::Hardware()->Deployed()->count();
if ($asset_stats['deployed']['total'] > 0) {
$asset_stats['deployed']['percent'] = round(($asset_stats['deployed']['total']/$asset_stats['total']) * 100);
} else {
$asset_stats['deployed']['percent'] = 0;
}
$asset_stats['undeployable']['total'] = Asset::Hardware()->Undeployable()->count();
if ($asset_stats['undeployable']['total'] > 0) {
$asset_stats['undeployable']['percent'] = round(($asset_stats['undeployable']['total']/$asset_stats['total']) * 100);
} else {
$asset_stats['undeployable']['percent'] = 0;
}
$asset_stats['archived']['total'] = Asset::Hardware()->Archived()->count();
if ($asset_stats['archived']['total'] > 0) {
$asset_stats['archived']['percent'] = round(($asset_stats['archived']['total']/$asset_stats['total']) * 100);
} else {
$asset_stats['archived']['percent'] = 0;
}
return View::make('dashboard')->with('asset_stats', $asset_stats);
return view('dashboard')->with('asset_stats', $asset_stats)->with('counts', $counts);
} else {
// Redirect to the profile page
return redirect()->intended('account/view-assets');
@@ -0,0 +1,164 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Department;
use App\Helpers\Helper;
use Auth;
class DepartmentsController extends Controller
{
public function __construct()
{
$this->middleware('auth');
parent::__construct();
}
/**
* Returns a view that invokes the ajax tables which actually contains
* the content for the assets listing, which is generated in getDatatable.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see AssetController::getDatatable() method that generates the JSON response
* @since [v4.0]
* @return View
*/
public function index(Request $request)
{
$this->authorize('index', Department::class);
if ($request->has('company_id')) {
$company = Company::find($request->input('company_id'));
} else {
$company = null;
}
return view('departments/index')->with('company',$company);
}
/**
* Store a newly created resource in storage.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$this->authorize('create', Department::class);
$department = new Department;
$department->fill($request->all());
$department->user_id = Auth::user()->id;
$department->manager_id = ($request->has('manager_id' ) ? $request->input('manager_id') : null);
if ($department->save()) {
return redirect()->route("departments.index")->with('success', trans('admin/departments/message.create.success'));
}
return redirect()->back()->withInput()->withErrors($department->getErrors());
}
/**
* Returns a view that invokes the ajax tables which actually contains
* the content for the department detail page.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $id
* @since [v4.0]
* @return \Illuminate\Contracts\View\View
*/
public function show($id)
{
$department = Department::find($id);
if (isset($department->id)) {
return view('departments/view', compact('department'));
}
return redirect()->route('departments.index')->with('error', trans('admin/departments/message.does_not_exist', compact('id')));
}
/**
* Returns a form view used to create a new department.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see DepartmentsController::postCreate() method that validates and stores the data
* @since [v4.0]
* @return \Illuminate\Contracts\View\View
*/
public function create()
{
return view('departments/edit')->with('item', new Department)
->with('manager_list', Helper::managerList())
->with('location_list', Helper::locationsList())
->with('company_list', Helper::companyList());
}
/**
* Validates and deletes selected department.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $locationId
* @since [v4.0]
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy($id)
{
if (is_null($department = Department::find($id))) {
return redirect()->to(route('departments.index'))->with('error', trans('admin/departments/message.not_found'));
}
if ($department->users->count() > 0) {
return redirect()->to(route('departments.index'))->with('error', trans('admin/departments/message.assoc_users'));
}
$department->delete();
return redirect()->back()->with('success', trans('admin/departments/message.delete.success'));
}
/**
* Makes a form view to edit location information.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see LocationsController::postCreate() method that validates and stores
* @param int $locationId
* @since [v1.0]
* @return \Illuminate\Contracts\View\View
*/
public function edit($id = null)
{
if (is_null($item = Department::find($id))) {
return redirect()->back()->with('error', trans('admin/locations/message.does_not_exist'));
}
return view('departments/edit', compact('item'))
->with('manager_list', Helper::managerList())
->with('location_list', Helper::locationsList())
->with('company_list', Helper::companyList());
}
public function update(Request $request, $id) {
$this->authorize('create', Department::class);
if (is_null($department = Department::find($id))) {
return redirect()->to('admin/settings/departments')->with('error', trans('admin/departments/message.does_not_exist'));
}
$department->fill($request->all());
$department->manager_id = ($request->has('manager_id' ) ? $request->input('manager_id') : null);
if ($department->save()) {
return redirect()->route("departments.index")->with('success', trans('admin/departments/message.update.success'));
}
return redirect()->back()->withInput()->withErrors($department->getErrors());
}
}
@@ -32,7 +32,7 @@ class DepreciationsController extends Controller
public function index()
{
// Show the page
return View::make('depreciations/index', compact('depreciations'));
return view('depreciations/index', compact('depreciations'));
}
@@ -47,7 +47,7 @@ class DepreciationsController extends Controller
public function create()
{
// Show the page
return View::make('depreciations/edit')->with('item', new Depreciation);
return view('depreciations/edit')->with('item', new Depreciation);
}
@@ -94,7 +94,7 @@ class DepreciationsController extends Controller
return redirect()->route('depreciations.index')->with('error', trans('admin/depreciations/message.does_not_exist'));
}
return View::make('depreciations/edit', compact('item'));
return view('depreciations/edit', compact('item'));
}
+13 -13
View File
@@ -28,10 +28,10 @@ class GroupsController extends Controller
* @since [v1.0]
* @return \Illuminate\Contracts\View\View
*/
public function getIndex()
public function index()
{
// Show the page
return View::make('groups/index', compact('groups'));
return view('groups/index', compact('groups'));
}
/**
@@ -42,7 +42,7 @@ class GroupsController extends Controller
* @since [v1.0]
* @return \Illuminate\Contracts\View\View
*/
public function getCreate()
public function create()
{
$group = new Group;
// Get all the available permissions
@@ -51,7 +51,7 @@ class GroupsController extends Controller
$selectedPermissions = Input::old('permissions', $groupPermissions);
// Show the page
return View::make('groups/edit', compact('permissions', 'selectedPermissions', 'groupPermissions'))->with('group', $group);
return view('groups/edit', compact('permissions', 'selectedPermissions', 'groupPermissions'))->with('group', $group);
}
/**
@@ -62,7 +62,7 @@ class GroupsController extends Controller
* @since [v1.0]
* @return \Illuminate\Http\RedirectResponse
*/
public function postCreate()
public function store()
{
// create a new group instance
$group = new Group();
@@ -84,13 +84,13 @@ class GroupsController extends Controller
* @since [v1.0]
* @return \Illuminate\Contracts\View\View
*/
public function getEdit($id = null)
public function edit($id = null)
{
$group = Group::find($id);
$permissions = config('permissions');
$groupPermissions = $group->decodePermissions();
$selected_array = Helper::selectedPermissionsArray($permissions, $groupPermissions);
return View::make('groups/edit', compact('group', 'permissions', 'selected_array', 'groupPermissions'));
return view('groups.edit', compact('group', 'permissions', 'selected_array', 'groupPermissions'));
}
/**
@@ -102,7 +102,7 @@ class GroupsController extends Controller
* @since [v1.0]
* @return \Illuminate\Http\RedirectResponse
*/
public function postEdit($id = null)
public function update($id = null)
{
$permissions = config('permissions');
if (!$group = Group::find($id)) {
@@ -113,11 +113,11 @@ class GroupsController extends Controller
if (!config('app.lock_passwords')) {
if ($group->save()) {
return redirect()->to("admin/groups")->with('success', trans('admin/groups/message.success.update'));
return redirect()->route('groups.index')->with('success', trans('admin/groups/message.success.update'));
}
return redirect()->back()->withInput()->withErrors($group->getErrors());
}
return redirect()->route('groups')->with('error', trans('general.feature_disabled'));
return redirect()->route('groups.index')->with('error', trans('general.feature_disabled'));
}
/**
@@ -129,7 +129,7 @@ class GroupsController extends Controller
* @since [v1.0]
* @return \Illuminate\Http\RedirectResponse
*/
public function getDelete($id = null)
public function destroy($id = null)
{
if (!config('app.lock_passwords')) {
if (!$group = Group::find($id)) {
@@ -137,9 +137,9 @@ class GroupsController extends Controller
}
$group->delete();
// Redirect to the group management page
return redirect()->route('groups')->with('success', trans('admin/groups/message.success.delete'));
return redirect()->route('groups.index')->with('success', trans('admin/groups/message.success.delete'));
}
return redirect()->route('groups')->with('error', trans('general.feature_disabled'));
return redirect()->route('groups.index')->with('error', trans('general.feature_disabled'));
}
}
@@ -0,0 +1,18 @@
<?php
namespace App\Http\Controllers;
use App\Http\Transformers\ImportsTransformer;
use App\Models\Import;
use Illuminate\Http\Request;
class ImportsController extends Controller
{
public function index()
{
$this->authorize('create', Asset::class);
$imports = Import::latest()->get();
$imports = (new ImportsTransformer)->transformImports($imports);
return view('importer/import')->with('imports', $imports);
}
}
+15 -18
View File
@@ -43,7 +43,7 @@ class LicensesController extends Controller
public function index()
{
$this->authorize('view', License::class);
return View::make('licenses/index');
return view('licenses/index');
}
@@ -64,7 +64,7 @@ class LicensesController extends Controller
'0' => 'No'
];
return View::make('licenses/edit')
return view('licenses/edit')
//->with('license_options',$license_options)
->with('depreciation_list', Helper::depreciationList())
->with('supplier_list', Helper::suppliersList())
@@ -113,10 +113,7 @@ class LicensesController extends Controller
$license->termination_date = $request->input('termination_date');
$license->user_id = Auth::id();
// Was the license created?
if ($license->save()) {
$license->logCreate();
// Save the license seat data
return redirect()->route("licenses.index")->with('success', trans('admin/licenses/message.create.success'));
}
return redirect()->back()->withInput()->withErrors($license->getErrors());
@@ -145,7 +142,7 @@ class LicensesController extends Controller
'0' => 'No'
];
return View::make('licenses/edit', compact('item'))
return view('licenses/edit', compact('item'))
->with('depreciation_list', Helper::depreciationList())
->with('supplier_list', Helper::suppliersList())
->with('company_list', Helper::companyList())
@@ -167,15 +164,12 @@ class LicensesController extends Controller
*/
public function update(Request $request, $licenseId = null)
{
// Check if the license exists
if (is_null($license = License::find($licenseId))) {
// Redirect to the blogs management page
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist'));
}
$this->authorize('update', $license);
// Update the license data
$license->company_id = Company::getIdForCurrentUser($request->input('company_id'));
$license->depreciation_id = $request->input('depreciation_id');
$license->expiration_date = $request->input('expiration_date');
@@ -259,7 +253,7 @@ class LicensesController extends Controller
}
$this->authorize('checkout', $licenseSeat);
return View::make('licenses/checkout', compact('licenseSeat'))
return view('licenses/checkout', compact('licenseSeat'))
->with('users_list', Helper::usersList())
->with('asset_list', Helper::detailedAssetList());
}
@@ -297,22 +291,22 @@ class LicensesController extends Controller
// Ooops.. something went wrong
return redirect()->back()->withInput()->withErrors($validator);
}
$target = null;
if ($assigned_to!='') {
// Check if the user exists
if (is_null($is_assigned_to = User::find($assigned_to))) {
if (is_null($target = User::find($assigned_to))) {
// Redirect to the asset management page with error
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.user_does_not_exist'));
}
}
if ($asset_id!='') {
if (is_null($asset = Asset::find($asset_id))) {
if (is_null($target = Asset::find($asset_id))) {
// Redirect to the asset management page with error
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.asset_does_not_exist'));
}
if (($asset->assigned_to!='') && (($asset->assigned_to!=$assigned_to)) && ($assigned_to!='')) {
if (($target->assigned_to!='') && (($target->assigned_to!=$assigned_to)) && ($target!='')) {
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.owner_doesnt_match_asset'));
}
}
@@ -338,7 +332,7 @@ class LicensesController extends Controller
// Was the asset updated?
if ($licenseSeat->save()) {
$licenseSeat->logCheckout($request->input('note'));
$licenseSeat->logCheckout($request->input('note'), $target);
$data['license_id'] =$licenseSeat->license_id;
$data['note'] = $request->input('note');
@@ -369,7 +363,7 @@ class LicensesController extends Controller
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found'));
}
$this->authorize('checkin', $licenseseat);
return View::make('licenses/checkin', compact('licenseseat'))->with('backto', $backTo);
return view('licenses/checkin', compact('licenseseat'))->with('backto', $backTo);
}
@@ -446,11 +440,14 @@ class LicensesController extends Controller
*/
public function show($licenseId = null)
{
$license = License::find($licenseId);
$license = $license->load('assignedusers', 'licenseSeats.user', 'licenseSeats.asset');
if (isset($license->id)) {
$license = $license->load('assignedusers', 'licenseSeats.user', 'licenseSeats.asset');
$this->authorize('view', $license);
return View::make('licenses/view', compact('license'));
return view('licenses/view', compact('license'));
}
$error = trans('admin/licenses/message.does_not_exist', compact('id'));
return redirect()->route('licenses.index')->with('error', $error);
@@ -475,7 +472,7 @@ class LicensesController extends Controller
$license->serial = null;
// Show the page
return View::make('licenses/edit')
return view('licenses/edit')
->with('depreciation_list', Helper::depreciationList())
->with('supplier_list', Helper::suppliersList())
->with('item', $license)
+11 -81
View File
@@ -41,7 +41,7 @@ class LocationsController extends Controller
$locations = Location::orderBy('created_at', 'DESC')->with('parent', 'assets', 'assignedassets')->get();
// Show the page
return View::make('locations/index', compact('locations'));
return view('locations/index', compact('locations'));
}
@@ -61,9 +61,10 @@ class LocationsController extends Controller
$location_options = Location::flattenLocationsArray($location_options_array);
$location_options = array('' => 'Top Level') + $location_options;
return View::make('locations/edit')
return view('locations/edit')
->with('location_options', $location_options)
->with('item', new Location);
->with('item', new Location)
->with('manager_list', Helper::managerList());
}
@@ -88,6 +89,7 @@ class LocationsController extends Controller
$location->state = Input::get('state');
$location->country = Input::get('country');
$location->zip = Input::get('zip');
$location->manager_id = Input::get('manager_id');
$location->user_id = Auth::id();
if ($location->save()) {
@@ -154,7 +156,10 @@ class LocationsController extends Controller
$location_options = Location::flattenLocationsArray($location_options_array);
$location_options = array('' => 'Top Level') + $location_options;
return View::make('locations/edit', compact('item'))->with('location_options', $location_options);
return view('locations/edit', compact('item'))
->with('location_options', $location_options)
->with('manager_list', Helper::managerList());
}
@@ -185,6 +190,7 @@ class LocationsController extends Controller
$location->country = Input::get('country');
$location->zip = Input::get('zip');
$location->ldap_ou = Input::get('ldap_ou');
$location->manager_id = Input::get('manager_id');
// Was the location updated?
if ($location->save()) {
@@ -232,8 +238,6 @@ class LocationsController extends Controller
* the content for the locations detail page.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see LocationsController::getDataViewUsers() method that returns JSON for location users
* @see LocationsController::getDataViewAssets() method that returns JSON for location assets
* @param int $locationId
* @since [v1.0]
* @return \Illuminate\Contracts\View\View
@@ -243,7 +247,7 @@ class LocationsController extends Controller
$location = Location::find($locationId);
if (isset($location->id)) {
return View::make('locations/view', compact('location'));
return view('locations/view', compact('location'));
}
// Prepare the error message
$error = trans('admin/locations/message.does_not_exist', compact('id'));
@@ -252,78 +256,4 @@ class LocationsController extends Controller
return redirect()->route('locations.index')->with('error', $error);
}
/**
* Returns a JSON response that contains the users association with the
* selected location, to be used by the location detail view.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see LocationsController::getView() method that creates the display view
* @param $locationID
* @return array
* @internal param int $locationId
* @since [v1.8]
*/
public function getDataViewUsers($locationID)
{
$location = Location::find($locationID);
$users = User::where('location_id', '=', $location->id);
if (Input::has('search')) {
$users = $users->TextSearch(e(Input::get('search')));
}
$users = $users->get();
$rows = array();
foreach ($users as $user) {
$rows[] = array(
'name' => (string)link_to_route('users.show', e($user->present()->fullName()), ['user'=>$user->id])
);
}
$data = array('total' => $users->count(), 'rows' => $rows);
return $data;
}
/**
* Returns a JSON response that contains the assets association with the
* selected location, to be used by the location detail view.
*
* @todo This is broken for accessories and consumables.
* @todo This is a very naive implementation. Should clean this up with query scopes.
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see LocationsController::getView() method that creates the display view
* @param int $locationID
* @since [v1.8]
* @return array
*/
public function getDataViewAssets($locationID)
{
$location = Location::find($locationID)->load('assignedassets.model');
$assets = Asset::AssetsByLocation($location);
if (Input::has('search')) {
$assets = $assets->TextSearch(e(Input::get('search')));
}
$assets = $assets->get();
$rows = array();
foreach ($assets as $asset) {
$rows[] = [
'name' => (string)link_to_route('hardware.show', e($asset->present()->name()), ['hardware' => $asset->id]),
'asset_tag' => e($asset->asset_tag),
'serial' => e($asset->serial),
'model' => e($asset->model->name),
];
}
$data = array('total' => $assets->count(), 'rows' => $rows);
return $data;
}
}
@@ -33,7 +33,7 @@ class ManufacturersController extends Controller
*/
public function index()
{
return View::make('manufacturers/index', compact('manufacturers'));
return view('manufacturers/index', compact('manufacturers'));
}
@@ -47,7 +47,7 @@ class ManufacturersController extends Controller
*/
public function create()
{
return View::make('manufacturers/edit')->with('item', new Manufacturer);
return view('manufacturers/edit')->with('item', new Manufacturer);
}
@@ -95,7 +95,7 @@ class ManufacturersController extends Controller
return redirect()->route('manufacturers.index')->with('error', trans('admin/manufacturers/message.does_not_exist'));
}
// Show the page
return View::make('manufacturers/edit', compact('item'));
return view('manufacturers/edit', compact('item'));
}
@@ -172,7 +172,7 @@ class ManufacturersController extends Controller
$manufacturer = Manufacturer::find($manufacturerId);
if (isset($manufacturer->id)) {
return View::make('manufacturers/view', compact('manufacturer'));
return view('manufacturers/view', compact('manufacturer'));
}
// Prepare the error message
$error = trans('admin/manufacturers/message.does_not_exist', compact('id'));
+32
View File
@@ -0,0 +1,32 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Helpers\Helper;
class ModalController extends Controller
{
function location() {
return view('modals.location');
}
function model() {
return view('modals.model')
->with('manufacturer', Helper::manufacturerList())
->with('category', Helper::categoryList('asset'));
}
function statuslabel() {
return view('modals.statuslabel')->with('statuslabel_types', Helper::statusTypeList());
}
function supplier() {
return view('modals.supplier');
}
function user() {
return view('modals.user');
}
}
+59 -2
View File
@@ -4,12 +4,13 @@ namespace App\Http\Controllers;
use Image;
use Input;
use Redirect;
use App\Models\Location;
use View;
use Auth;
use App\Helpers\Helper;
use App\Models\Setting;
use Gate;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
/**
* This controller handles all actions related to User Profiles for
@@ -30,7 +31,7 @@ class ProfileController extends Controller
{
$user = Auth::user();
$location_list = Helper::locationsList();
return View::make('account/profile', compact('user'))->with('location_list', $location_list);
return view('account/profile', compact('user'))->with('location_list', $location_list);
}
/**
@@ -87,4 +88,60 @@ class ProfileController extends Controller
public function api() {
return view('account/api');
}
/**
* User change email page.
*
* @return View
*/
public function password()
{
$user = Auth::user();
return view('account/change-password', compact('user'));
}
/**
* Users change password form processing page.
*
* @return Redirect
*/
public function passwordSave(Request $request)
{
if (config('app.lock_passwords')) {
return redirect()->route('account.password.index')->with('error', Lang::get('admin/users/table.lock_passwords'));
}
$user = Auth::user();
if ($user->ldap_import=='1') {
return redirect()->route('account.password.index')->with('error', Lang::get('admin/users/message.error.password_ldap'));
}
$rules = array(
'current_password' => 'required',
'password' => Setting::passwordComplexityRulesSaving('store'),
'password_confirm' => 'required|same:password',
);
$validator = \Validator::make($request->all(), $rules);
$validator->after(function($validator) use ($request, $user) {
if (!Hash::check($request->input('current_password'), $user->password)) {
$validator->errors()->add('current_password', trans('validation.hashed_pass'));
}
});
if (!$validator->fails()) {
$user->password = Hash::make($request->input('password'));
$user->save();
return redirect()->route('account.password.index')->with('success', 'Password updated!');
}
return redirect()->back()->withInput()->withErrors($validator);
}
}
+31 -71
View File
@@ -6,21 +6,14 @@ use App\Models\Accessory;
use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\AssetMaintenance;
use App\Models\AssetModel;
use App\Models\Company;
use App\Models\CustomField;
use App\Models\License;
use App\Models\Location;
use App\Models\Setting;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Support\Facades\Lang;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\View;
use Input;
use League\Csv\Reader;
use Redirect;
use Symfony\Component\HttpFoundation\StreamedResponse;
/**
@@ -42,8 +35,7 @@ class ReportsController extends Controller
public function getAccessoryReport()
{
$accessories = Accessory::orderBy('created_at', 'DESC')->with('company')->get();
return View::make('reports/accessories', compact('accessories'));
return view('reports/accessories', compact('accessories'));
}
/**
@@ -98,7 +90,7 @@ class ReportsController extends Controller
public function getAssetsReport()
{
$settings = \App\Models\Setting::first();
return View::make('reports/asset', compact('assets'))->with('settings', $settings);
return view('reports/asset', compact('assets'))->with('settings', $settings);
}
@@ -194,10 +186,10 @@ class ReportsController extends Controller
{
// Grab all the assets
$assets = Asset::with('model', 'assignedTo', 'assetstatus', 'defaultLoc', 'assetlog', 'company')
$assets = Asset::with( 'assignedTo', 'assetstatus', 'defaultLoc', 'assetloc', 'assetlog', 'company', 'model.category', 'model.depreciation')
->orderBy('created_at', 'DESC')->get();
return View::make('reports/depreciation', compact('assets'));
return view('reports/depreciation', compact('assets'));
}
/**
@@ -279,6 +271,20 @@ class ReportsController extends Controller
}
/**
* Displays audit report.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return View
*/
public function audit()
{
return view('reports/audit');
}
/**
* Displays activity report.
*
@@ -289,55 +295,9 @@ class ReportsController extends Controller
public function getActivityReport()
{
return View::make('reports/activity');
return view('reports/activity');
}
/**
* Returns Activity Report JSON.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
public function getActivityReportDataTable()
{
$activitylogs = Company::scopeCompanyables(Actionlog::with('item', 'user', 'target'))->orderBy('created_at', 'DESC');
if (Input::has('search')) {
$activitylogs = $activitylogs->TextSearch(e(Input::get('search')));
}
if (Input::has('offset')) {
$offset = e(Input::get('offset'));
} else {
$offset = 0;
}
if (Input::has('limit')) {
$limit = e(Input::get('limit'));
} else {
$limit = 50;
}
$allowed_columns = ['created_at'];
$order = Input::get('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array(Input::get('sort'), $allowed_columns) ? e(Input::get('sort')) : 'created_at';
$activityCount = $activitylogs->count();
$activitylogs = $activitylogs->offset($offset)->limit($limit)->get();
$rows = array();
foreach ($activitylogs as $activity) {
$rows[] = $activity->present()->forDataTable();
}
$data = array('total'=>$activityCount, 'rows'=>$rows);
return $data;
}
/**
* Displays license report
@@ -353,7 +313,7 @@ class ReportsController extends Controller
->with('company')
->get();
return View::make('reports/licenses', compact('licenses'));
return view('reports/licenses', compact('licenses'));
}
/**
@@ -417,7 +377,7 @@ class ReportsController extends Controller
public function getCustomReport()
{
$customfields = CustomField::get();
return View::make('reports/custom')->with('customfields', $customfields);
return view('reports/custom')->with('customfields', $customfields);
}
/**
@@ -430,7 +390,7 @@ class ReportsController extends Controller
*/
public function postCustom()
{
$assets = Asset::orderBy('created_at', 'DESC')->with('company', 'assigneduser', 'assetloc', 'defaultLoc', 'assigneduser.userloc', 'model', 'supplier', 'assetstatus', 'model.manufacturer')->get();
$assets = Asset::orderBy('created_at', 'DESC')->with('company', 'assignedTo', 'assetloc', 'defaultLoc', 'model', 'supplier', 'assetstatus', 'model.manufacturer')->get();
$customfields = CustomField::get();
$rows = [ ];
@@ -503,7 +463,7 @@ class ReportsController extends Controller
}
if (e(Input::get('notes')) == '1') {
$header[] = 'Notes';
$header[] = trans('general.notes');
}
@@ -592,8 +552,8 @@ class ReportsController extends Controller
if (e(Input::get('username')) == '1') {
// Only works if we're checked out to a user, not anything else.
if ($asset->assigneduser) {
$row[] = '"' .e($asset->assigneduser->username). '"';
if ($asset->checkedOutToUser()) {
$row[] = '"' .e($asset->assignedTo->username). '"';
} else {
$row[] = ''; // Empty string if unassigned
}
@@ -601,8 +561,8 @@ class ReportsController extends Controller
if (e(Input::get('employee_num')) == '1') {
// Only works if we're checked out to a user, not anything else.
if ($asset->assigneduser) {
$row[] = '"' .e($asset->assigneduser->employee_num). '"';
if ($asset->checkedOutToUser()) {
$row[] = '"' .e($asset->assignedTo->employee_num). '"';
} else {
$row[] = ''; // Empty string if unassigned
}
@@ -644,9 +604,9 @@ class ReportsController extends Controller
if (e(Input::get('notes')) == '1') {
if ($asset->notes) {
$row[] = '"' .$asset->notes. '"';
$row[] = '"' .$asset->notes . '"';
} else {
$row[] = ''; // Empty string if unassigned
$row[] = '';
}
}
@@ -690,7 +650,7 @@ class ReportsController extends Controller
->orderBy('created_at', 'DESC')
->get();
return View::make('reports/asset_maintenances', compact('assetMaintenances'));
return view('reports/asset_maintenances', compact('assetMaintenances'));
}
@@ -765,7 +725,7 @@ class ReportsController extends Controller
{
$assetsForReport = Asset::notYetAccepted()->with('company')->get();
return View::make('reports/unaccepted_assets', compact('assetsForReport'));
return view('reports/unaccepted_assets', compact('assetsForReport'));
}
/**
+555 -149
View File
@@ -20,6 +20,7 @@ use Auth;
use App\Models\User;
use App\Http\Requests\SetupUserRequest;
use App\Http\Requests\ImageUploadRequest;
use App\Http\Requests\SettingsLdapRequest;
/**
* This controller handles all actions related to Settings for
@@ -65,15 +66,24 @@ class SettingsController extends Controller
$start_settings['url_config'] = url('/');
$start_settings['real_url'] = $pageURL;
// Curl the .env file to make sure it's not accessible via a browser
$ch = curl_init($protocol . $host.'/.env');
curl_setopt($ch, CURLOPT_HEADER, true); // we want headers
curl_setopt($ch, CURLOPT_NOBODY, true); // we don't need body
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$output = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$exposed_env = @file_get_contents($protocol . $host.'/.env');
if ($exposed_env) {
$start_settings['env_exposed'] = true;
} else {
if ($httpcode == 404 || $httpcode == 403) {
$start_settings['env_exposed'] = false;
} else {
$start_settings['env_exposed'] = true;
}
if (\App::Environment('production') && (config('app.debug')==true)) {
$start_settings['debug_exposed'] = true;
} else {
@@ -120,7 +130,7 @@ class SettingsController extends Controller
$start_settings['gd'] = extension_loaded('gd');
return View::make('setup/index')
return view('setup/index')
->with('step', 1)
->with('start_settings', $start_settings)
->with('section', 'Pre-Flight Check');
@@ -175,12 +185,14 @@ class SettingsController extends Controller
$settings->site_name = e(Input::get('site_name'));
$settings->alert_email = e(Input::get('email'));
$settings->alerts_enabled = 1;
$settings->pwd_secure_min = 10;
$settings->brand = 1;
$settings->locale = 'en';
$settings->default_currency = 'USD';
$settings->user_id = 1;
$settings->email_domain = e(Input::get('email_domain'));
$settings->email_format = e(Input::get('email_format'));
$settings->next_auto_tag_base = 1;
if ((!$user->isValid()) || (!$settings->isValid())) {
@@ -215,7 +227,7 @@ class SettingsController extends Controller
*/
public function getSetupUser()
{
return View::make('setup/user')
return view('setup/user')
->with('step', 3)
->with('section', 'Create a User');
}
@@ -230,7 +242,7 @@ class SettingsController extends Controller
public function getSetupDone()
{
return View::make('setup/done')
return view('setup/done')
->with('step', 4)
->with('section', 'Done!');
}
@@ -249,7 +261,14 @@ class SettingsController extends Controller
Artisan::call('migrate', ['--force' => true]);
$output = Artisan::output();
return View::make('setup/migrate')
if ((!file_exists(storage_path().'/oauth-private.key')) || (!file_exists(storage_path().'/oauth-public.key'))) {
Artisan::call('passport:install');
Artisan::call('migrate', ['--force' => true]);
}
return view('setup/migrate')
->with('output', $output)
->with('step', 2)
->with('section', 'Create Database Tables');
@@ -264,15 +283,15 @@ class SettingsController extends Controller
* @since [v1.0]
* @return View
*/
public function getIndex()
public function index()
{
$settings = Setting::all();
return View::make('settings/index', compact('settings'));
return view('settings/index', compact('settings'));
}
/**
* Return a form to allow a super admin to update settings.
* Return the admin settings page
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
@@ -281,77 +300,471 @@ class SettingsController extends Controller
public function getEdit()
{
$setting = Setting::first();
$is_gd_installed = extension_loaded('gd');
return View::make('settings/edit', compact('setting'))->with('is_gd_installed', $is_gd_installed);
return view('settings/general', compact('setting'));
}
/**
* Validate and process settings edit form.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return Redirect
*/
public function postEdit(ImageUploadRequest $request)
* Return a form to allow a super admin to update settings.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
public function getSettings()
{
$setting = Setting::first();
return view('settings/general', compact('setting'));
}
/**
* Return a form to allow a super admin to update settings.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
public function postSettings(Request $request)
{
if (is_null($setting = Setting::first())) {
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
}
$setting->full_multiple_companies_support = $request->input('full_multiple_companies_support', '0');
$setting->load_remote = $request->input('load_remote', '0');
$setting->email_domain = $request->input('email_domain');
$setting->email_format = $request->input('email_format');
$setting->username_format = $request->input('username_format');
$setting->require_accept_signature = $request->input('require_accept_signature');
$setting->login_note = $request->input('login_note');
$setting->default_eula_text = $request->input('default_eula_text');
$setting->thumbnail_max_h = $request->input('thumbnail_max_h');
if (Input::get('per_page')!='') {
$setting->per_page = $request->input('per_page');
} else {
$setting->per_page = 200;
}
if ($setting->save()) {
return redirect()->route('settings.index')
->with('success', trans('admin/settings/message.update.success'));
}
return redirect()->back()->withInput()->withErrors($setting->getErrors());
}
/**
* Return a form to allow a super admin to update settings.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
public function getBranding()
{
$setting = Setting::first();
return view('settings.branding', compact('setting'));
}
/**
* Return a form to allow a super admin to update settings.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
public function postBranding(ImageUploadRequest $request)
{
if (is_null($setting = Setting::first())) {
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
}
$setting->brand = $request->input('brand', '1');
$setting->header_color = $request->input('header_color');
// Only allow the site name and CSS to be changed if lock_passwords is false
// Because public demos make people act like dicks
if (!config('app.lock_passwords')) {
$setting->site_name = $request->input('site_name');
$setting->custom_css = $request->input('custom_css');
}
// If the user wants to clear the logo, reset the brand type
if ($request->input('clear_logo')=='1') {
$setting->logo = null;
$setting->brand = 1;
// If they are uploading an image, validate it and upload it
} elseif ($request->hasFile('image')) {
if (!config('app.lock_passwords')) {
$image = $request->file('image');
$file_name = "logo.".$image->getClientOriginalExtension();
$path = public_path('uploads');
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(null, 40, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path.'/'.$file_name);
} else {
$image->move($path, $file_name);
}
$setting->logo = $file_name;
}
}
if ($setting->save()) {
return redirect()->route('settings.index')
->with('success', trans('admin/settings/message.update.success'));
}
return redirect()->back()->withInput()->withErrors($setting->getErrors());
}
/**
* Return a form to allow a super admin to update settings.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
public function getSecurity()
{
$setting = Setting::first();
return view('settings.security', compact('setting'));
}
/**
* Return a form to allow a super admin to update settings.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
public function postSecurity(Request $request)
{
// Check if the asset exists
if (is_null($setting = Setting::first())) {
// Redirect to the asset management page with error
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
}
if (!config('app.lock_passwords')) {
$setting->site_name = e(Input::get('site_name'));
$setting->custom_css = e(Input::get('custom_css'));
if (Input::get('two_factor_enabled')=='') {
if ($request->input('two_factor_enabled')=='') {
$setting->two_factor_enabled = null;
} else {
$setting->two_factor_enabled = e(Input::get('two_factor_enabled'));
$setting->two_factor_enabled = $request->input('two_factor_enabled');
}
}
if (Input::get('per_page')!='') {
$setting->per_page = e(Input::get('per_page'));
} else {
$setting->per_page = 200;
$setting->pwd_secure_uncommon = (int) $request->input('pwd_secure_uncommon');
$setting->pwd_secure_min = (int) $request->input('pwd_secure_min');
$setting->pwd_secure_complexity = '';
if ($request->has('pwd_secure_complexity')) {
$setting->pwd_secure_complexity = implode('|', $request->input('pwd_secure_complexity'));
}
$setting->locale = e(Input::get('locale', 'en'));
$setting->qr_code = e(Input::get('qr_code', '0'));
$setting->full_multiple_companies_support = e(Input::get('full_multiple_companies_support', '0'));
$setting->alt_barcode = e(Input::get('alt_barcode'));
$setting->alt_barcode_enabled = e(Input::get('alt_barcode_enabled', '0'));
$setting->barcode_type = e(Input::get('barcode_type'));
$setting->load_remote = e(Input::get('load_remote', '0'));
$setting->default_currency = e(Input::get('default_currency', '$'));
$setting->qr_text = e(Input::get('qr_text'));
$setting->auto_increment_prefix = e(Input::get('auto_increment_prefix'));
$setting->auto_increment_assets = e(Input::get('auto_increment_assets', '0'));
$setting->zerofill_count = e(Input::get('zerofill_count'));
$setting->alert_interval = e(Input::get('alert_interval'));
$setting->alert_threshold = e(Input::get('alert_threshold'));
$setting->email_domain = e(Input::get('email_domain'));
$setting->email_format = e(Input::get('email_format'));
$setting->username_format = e(Input::get('username_format'));
$setting->require_accept_signature = e(Input::get('require_accept_signature'));
$setting->labels_per_page = e(Input::get('labels_per_page'));
$setting->labels_width = e(Input::get('labels_width'));
$setting->labels_height = e(Input::get('labels_height'));
$setting->labels_pmargin_left = e(Input::get('labels_pmargin_left'));
$setting->labels_pmargin_right = e(Input::get('labels_pmargin_right'));
$setting->labels_pmargin_top = e(Input::get('labels_pmargin_top'));
$setting->labels_pmargin_bottom = e(Input::get('labels_pmargin_bottom'));
$setting->labels_display_bgutter = e(Input::get('labels_display_bgutter'));
$setting->labels_display_sgutter = e(Input::get('labels_display_sgutter'));
$setting->labels_fontsize = e(Input::get('labels_fontsize'));
$setting->labels_pagewidth = e(Input::get('labels_pagewidth'));
$setting->labels_pageheight = e(Input::get('labels_pageheight'));
if ($setting->save()) {
return redirect()->route('settings.index')
->with('success', trans('admin/settings/message.update.success'));
}
return redirect()->back()->withInput()->withErrors($setting->getErrors());
}
/**
* Return a form to allow a super admin to update settings.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
public function getLocalization()
{
$setting = Setting::first();
return view('settings.localization', compact('setting'));
}
/**
* Return a form to allow a super admin to update settings.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
public function postLocalization(Request $request)
{
if (is_null($setting = Setting::first())) {
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
}
$setting->locale = $request->input('locale', 'en');
$setting->default_currency = $request->input('default_currency', '$');
$setting->date_display_format = $request->input('date_display_format');
$setting->time_display_format = $request->input('time_display_format');
if ($setting->save()) {
return redirect()->route('settings.index')
->with('success', trans('admin/settings/message.update.success'));
}
return redirect()->back()->withInput()->withErrors($setting->getErrors());
}
/**
* Return a form to allow a super admin to update settings.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
public function getAlerts()
{
$setting = Setting::first();
return view('settings.alerts', compact('setting'));
}
/**
* Return a form to allow a super admin to update settings.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
public function postAlerts(Request $request)
{
if (is_null($setting = Setting::first())) {
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
}
$alert_email = rtrim($request->input('alert_email'), ',');
$alert_email = trim($alert_email);
$setting->alert_email = $alert_email;
$setting->alerts_enabled = $request->input('alerts_enabled', '0');
$setting->alert_interval = $request->input('alert_interval');
$setting->alert_threshold = $request->input('alert_threshold');
$setting->audit_interval = $request->input('audit_interval');
$setting->audit_warning_days = $request->input('audit_warning_days');
if ($setting->save()) {
return redirect()->route('settings.index')
->with('success', trans('admin/settings/message.update.success'));
}
return redirect()->back()->withInput()->withErrors($setting->getErrors());
}
/**
* Return a form to allow a super admin to update settings.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
public function getSlack()
{
$setting = Setting::first();
return view('settings.slack', compact('setting'));
}
/**
* Return a form to allow a super admin to update settings.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
public function postSlack(Request $request)
{
if (is_null($setting = Setting::first())) {
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
}
$setting->slack_endpoint = $request->input('slack_endpoint');
$setting->slack_channel = $request->input('slack_channel');
$setting->slack_botname = $request->input('slack_botname');
if ($setting->save()) {
return redirect()->route('settings.index')
->with('success', trans('admin/settings/message.update.success'));
}
return redirect()->back()->withInput()->withErrors($setting->getErrors());
}
/**
* Return a form to allow a super admin to update settings.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
public function getAssetTags()
{
$setting = Setting::first();
return view('settings.asset_tags', compact('setting'));
}
/**
* Saves settings from form
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
public function postAssetTags(Request $request)
{
if (is_null($setting = Setting::first())) {
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
}
$setting->auto_increment_prefix = $request->input('auto_increment_prefix');
$setting->auto_increment_assets = $request->input('auto_increment_assets', '0');
$setting->zerofill_count = $request->input('zerofill_count');
$setting->next_auto_tag_base = $request->input('next_auto_tag_base');
if ($setting->save()) {
return redirect()->route('settings.index')
->with('success', trans('admin/settings/message.update.success'));
}
return redirect()->back()->withInput()->withErrors($setting->getErrors());
}
/**
* Return a form to allow a super admin to update settings.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
public function getBarcodes()
{
$setting = Setting::first();
$is_gd_installed = extension_loaded('gd');
return view('settings.barcodes', compact('setting'))->with('is_gd_installed',$is_gd_installed);
}
/**
* Saves settings from form
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
public function postBarcodes(Request $request)
{
if (is_null($setting = Setting::first())) {
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
}
$setting->qr_code = $request->input('qr_code', '0');
$setting->alt_barcode = $request->input('alt_barcode');
$setting->alt_barcode_enabled = $request->input('alt_barcode_enabled', '0');
$setting->barcode_type = $request->input('barcode_type');
$setting->qr_text = $request->input('qr_text');
if ($setting->save()) {
return redirect()->route('settings.index')
->with('success', trans('admin/settings/message.update.success'));
}
return redirect()->back()->withInput()->withErrors($setting->getErrors());
}
/**
* Return a form to allow a super admin to update settings.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return View
*/
public function getPhpInfo()
{
if (config('app.debug')=== true) {
return view('settings.phpinfo');
}
return redirect()->route('settings.index')
->with('error', 'PHP syetem debugging information is only available when debug is enabled in your .env file.');
}
/**
* Return a form to allow a super admin to update settings.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return View
*/
public function getLabels()
{
$setting = Setting::first();
return view('settings.labels', compact('setting'));
}
/**
* Saves settings from form
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return View
*/
public function postLabels(Request $request)
{
if (is_null($setting = Setting::first())) {
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
}
$setting->labels_per_page = $request->input('labels_per_page');
$setting->labels_width = $request->input('labels_width');
$setting->labels_height = $request->input('labels_height');
$setting->labels_pmargin_left = $request->input('labels_pmargin_left');
$setting->labels_pmargin_right = $request->input('labels_pmargin_right');
$setting->labels_pmargin_top = $request->input('labels_pmargin_top');
$setting->labels_pmargin_bottom = $request->input('labels_pmargin_bottom');
$setting->labels_display_bgutter = $request->input('labels_display_bgutter');
$setting->labels_display_sgutter = $request->input('labels_display_sgutter');
$setting->labels_fontsize = $request->input('labels_fontsize');
$setting->labels_pagewidth = $request->input('labels_pagewidth');
$setting->labels_pageheight = $request->input('labels_pageheight');
if (Input::has('labels_display_name')) {
@@ -372,96 +785,78 @@ class SettingsController extends Controller
$setting->labels_display_tag = 0;
}
$alert_email = rtrim(Input::get('alert_email'), ',');
$alert_email = trim($alert_email);
$setting->alert_email = e($alert_email);
$setting->alerts_enabled = e(Input::get('alerts_enabled', '0'));
$setting->header_color = e(Input::get('header_color'));
$setting->default_eula_text = e(Input::get('default_eula_text'));
$setting->slack_endpoint = e(Input::get('slack_endpoint'));
$setting->slack_channel = e(Input::get('slack_channel'));
$setting->slack_botname = e(Input::get('slack_botname'));
$setting->ldap_enabled = e(Input::get('ldap_enabled', '0'));
$setting->ldap_server = e(Input::get('ldap_server'));
$setting->ldap_server_cert_ignore = e(Input::get('ldap_server_cert_ignore', false));
$setting->ldap_uname = e(Input::get('ldap_uname'));
if (Input::has('ldap_pword')) {
$setting->ldap_pword = Crypt::encrypt(Input::get('ldap_pword'));
}
$setting->ldap_basedn = e(Input::get('ldap_basedn'));
$setting->ldap_filter = Input::get('ldap_filter');
$setting->ldap_username_field = Input::get('ldap_username_field');
$setting->ldap_lname_field = e(Input::get('ldap_lname_field'));
$setting->ldap_fname_field = e(Input::get('ldap_fname_field'));
$setting->ldap_auth_filter_query = Input::get('ldap_auth_filter_query');
$setting->ldap_version = e(Input::get('ldap_version'));
$setting->ldap_active_flag = e(Input::get('ldap_active_flag'));
$setting->ldap_emp_num = e(Input::get('ldap_emp_num'));
$setting->ldap_email = e(Input::get('ldap_email'));
$setting->ad_domain = e(Input::get('ad_domain'));
$setting->is_ad = e(Input::get('is_ad', '0'));
$setting->ldap_tls = e(Input::get('ldap_tls', '0'));
$setting->ldap_pw_sync = e(Input::get('ldap_pw_sync', '0'));
$setting->date_display_format = e(Input::get('date_display_format'));
$setting->time_display_format = e(Input::get('time_display_format'));
if ($request->input('clear_logo')=='1') {
$setting->logo = null;
$setting->brand = 1;
} elseif ($request->hasFile('image')) {
if (!config('app.lock_passwords')) {
$image = $request->file('image');
$file_name = "logo.".$image->getClientOriginalExtension();
$path = public_path('uploads');
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(null, 40, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path.'/'.$file_name);
} else {
$image->move($path, $file_name);
}
$setting->logo = $file_name;
}
}
if ($setting->save()) {
return redirect()->to("admin/settings/app")->with('success', trans('admin/settings/message.update.success'));
} else {
return redirect()->back()->withInput()->withErrors($setting->getErrors());
return redirect()->route('settings.index')
->with('success', trans('admin/settings/message.update.success'));
}
// Redirect to the setting management page
return redirect()->to("admin/settings/app/edit")->with('error', trans('admin/settings/message.update.error'));
return redirect()->back()->withInput()->withErrors($setting->getErrors());
}
public function getLdapTest()
/**
* Return a form to allow a super admin to update settings.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return View
*/
public function getLdapSettings()
{
$setting = Setting::first();
return view('settings.ldap', compact('setting'));
}
/**
* Saves settings from form
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return View
*/
public function postLdapSettings(Request $request)
{
try {
$connection = Ldap::connectToLdap();
try {
Ldap::bindAdminToLdap($connection);
return response()->json(['message' => 'It worked!'], 200);
} catch (\Exception $e) {
return response()->json(['message' => $e->getMessage()], 500);
}
return response()->json(['message' => 'It worked!'], 200);
} catch (\Exception $e) {
return response()->json(['message' => $e->getMessage()], 500);
if (is_null($setting = Setting::first())) {
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
}
$setting->ldap_enabled = $request->input('ldap_enabled', '0');
$setting->ldap_server = $request->input('ldap_server');
$setting->ldap_server_cert_ignore = $request->input('ldap_server_cert_ignore', false);
$setting->ldap_uname = $request->input('ldap_uname');
if (Input::has('ldap_pword')) {
$setting->ldap_pword = Crypt::encrypt($request->input('ldap_pword'));
}
$setting->ldap_basedn = $request->input('ldap_basedn');
$setting->ldap_filter = $request->input('ldap_filter');
$setting->ldap_username_field = $request->input('ldap_username_field');
$setting->ldap_lname_field = $request->input('ldap_lname_field');
$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_active_flag = $request->input('ldap_active_flag');
$setting->ldap_emp_num = $request->input('ldap_emp_num');
$setting->ldap_email = $request->input('ldap_email');
$setting->ad_domain = $request->input('ad_domain');
$setting->is_ad = $request->input('is_ad', '0');
$setting->ldap_tls = $request->input('ldap_tls', '0');
$setting->ldap_pw_sync = $request->input('ldap_pw_sync', '0');
if ($setting->save()) {
return redirect()->route('settings.index')
->with('success', trans('admin/settings/message.update.success'));
}
return redirect()->back()->withInput()->withErrors($setting->getErrors());
}
/**
* Show the listing of backups
*
@@ -495,7 +890,7 @@ class SettingsController extends Controller
}
return View::make('settings/backups', compact('path', 'files'));
return view('settings/backups', compact('path', 'files'));
}
@@ -511,10 +906,9 @@ class SettingsController extends Controller
{
if (!config('app.lock_passwords')) {
Artisan::call('backup:run');
return redirect()->to("admin/settings/backups")->with('success', trans('admin/settings/message.backup.generated'));
return redirect()->route('settings.backups.index')->with('success', trans('admin/settings/message.backup.generated'));
} else {
return redirect()->to("admin/settings/backups")->with('error', trans('general.feature_disabled'));
return redirect()->to("settings.backups.index")->with('error', trans('general.feature_disabled'));
}
@@ -538,11 +932,11 @@ class SettingsController extends Controller
} else {
// Redirect to the backup page
return redirect()->route('settings/backups')->with('error', trans('admin/settings/message.backup.file_not_found'));
return redirect()->route('settings.backups.index')->with('error', trans('admin/settings/message.backup.file_not_found'));
}
} else {
// Redirect to the backup page
return redirect()->route('settings/backups')->with('error', trans('general.feature_disabled'));
return redirect()->route('settings.backups.index')->with('error', trans('general.feature_disabled'));
}
@@ -564,17 +958,29 @@ class SettingsController extends Controller
$file = $path.'/'.$filename;
if (file_exists($file)) {
unlink($file);
return redirect()->route('settings/backups')->with('success', trans('admin/settings/message.backup.file_deleted'));
return redirect()->route('settings.backups.index')->with('success', trans('admin/settings/message.backup.file_deleted'));
} else {
return redirect()->route('settings/backups')->with('error', trans('admin/settings/message.backup.file_not_found'));
return redirect()->route('settings.backups.index')->with('error', trans('admin/settings/message.backup.file_not_found'));
}
} else {
return redirect()->route('settings/backups')->with('error', trans('general.feature_disabled'));
return redirect()->route('settings.backups.index')->with('error', trans('general.feature_disabled'));
}
}
/**
* Return a form to allow a super admin to update settings.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return View
*/
public function getPurge()
{
return view('settings.purge-form');
}
/**
* Purges soft-deletes
*
@@ -588,7 +994,7 @@ class SettingsController extends Controller
if (Input::get('confirm_purge')=='DELETE') {
Artisan::call('snipeit:purge', ['--force'=>'true','--no-interaction'=>true]);
$output = Artisan::output();
return View::make('settings/purge')
return view('settings/purge')
->with('output', $output)->with('success', trans('admin/settings/message.purge.success'));
} else {
return redirect()->back()->with('error', trans('admin/settings/message.purge.validation_failed'));
@@ -610,6 +1016,6 @@ class SettingsController extends Controller
* @return View
*/
public function api() {
return view('settings/api');
return view('settings.api');
}
}
@@ -32,7 +32,7 @@ class StatuslabelsController extends Controller
public function index()
{
return View::make('statuslabels/index', compact('statuslabels'));
return view('statuslabels/index', compact('statuslabels'));
}
public function show($id)
@@ -40,7 +40,7 @@ class StatuslabelsController extends Controller
$statuslabel = Statuslabel::find($id);
if (isset($statuslabel->id)) {
return View::make('statuslabels/view', compact('statuslabel'));
return view('statuslabels/view', compact('statuslabel'));
}
return redirect()->route('statuslabels.index')->with('error', trans('admin/locations/message.does_not_exist', compact('id')));
@@ -60,7 +60,7 @@ class StatuslabelsController extends Controller
$use_statuslabel_type = $item->getStatuslabelType();
$statuslabel_types = Helper::statusTypeList();
return View::make('statuslabels/edit', compact('statuslabel_types', 'item'))->with('use_statuslabel_type', $use_statuslabel_type);
return view('statuslabels/edit', compact('statuslabel_types', 'item'))->with('use_statuslabel_type', $use_statuslabel_type);
}
@@ -148,7 +148,7 @@ class StatuslabelsController extends Controller
$statuslabel_types = array('' => trans('admin/hardware/form.select_statustype')) + array('undeployable' => trans('admin/hardware/general.undeployable')) + array('pending' => trans('admin/hardware/general.pending')) + array('archived' => trans('admin/hardware/general.archived')) + array('deployable' => trans('admin/hardware/general.deployable'));
return View::make('statuslabels/edit', compact('item', 'statuslabel_types'))->with('use_statuslabel_type', $use_statuslabel_type);
return view('statuslabels/edit', compact('item', 'statuslabel_types'))->with('use_statuslabel_type', $use_statuslabel_type);
}
+4 -4
View File
@@ -35,7 +35,7 @@ class SuppliersController extends Controller
$suppliers = Supplier::orderBy('created_at', 'DESC')->get();
// Show the page
return View::make('suppliers/index', compact('suppliers'));
return view('suppliers/index', compact('suppliers'));
}
@@ -46,7 +46,7 @@ class SuppliersController extends Controller
*/
public function create()
{
return View::make('suppliers/edit')->with('item', new Supplier);
return view('suppliers/edit')->with('item', new Supplier);
}
@@ -126,7 +126,7 @@ class SuppliersController extends Controller
}
// Show the page
return View::make('suppliers/edit', compact('item'));
return view('suppliers/edit', compact('item'));
}
@@ -222,7 +222,7 @@ class SuppliersController extends Controller
$supplier = Supplier::find($supplierId);
if (isset($supplier->id)) {
return View::make('suppliers/view', compact('supplier'));
return view('suppliers/view', compact('supplier'));
}
// Prepare the error message
$error = trans('admin/suppliers/message.does_not_exist', compact('id'));
+75 -69
View File
@@ -12,9 +12,7 @@ use App\Models\Company;
use App\Models\Location;
use App\Models\License;
use App\Models\Setting;
use App\Models\Statuslabel;
use App\Http\Requests\SaveUserRequest;
use App\Http\Requests\UpdateUserRequest;
use Symfony\Component\HttpFoundation\StreamedResponse;
use App\Models\User;
use App\Models\Ldap;
@@ -23,7 +21,6 @@ use Config;
use Crypt;
use DB;
use HTML;
use Illuminate\Support\Facades\Log;
use Input;
use Lang;
use League\Csv\Reader;
@@ -61,7 +58,7 @@ class UsersController extends Controller
public function index()
{
$this->authorize('index', User::class);
return View::make('users/index');
return view('users/index');
}
/**
@@ -86,10 +83,11 @@ class UsersController extends Controller
$userPermissions = Helper::selectedPermissionsArray($permissions, Input::old('permissions', array()));
$permissions = $this->filterDisplayable($permissions);
return View::make('users/edit', compact('groups', 'userGroups', 'permissions', 'userPermissions'))
return view('users/edit', compact('groups', 'userGroups', 'permissions', 'userPermissions'))
->with('location_list', Helper::locationsList())
->with('manager_list', Helper::managerList())
->with('company_list', Helper::companyList())
->with('department_list', Helper::departmentList())
->with('user', new User);
}
@@ -120,6 +118,7 @@ class UsersController extends Controller
$user->jobtitle = $request->input('jobtitle');
$user->phone = $request->input('phone');
$user->location_id = $request->input('location_id', null);
$user->department_id = $request->input('department_id', null);
$user->company_id = Company::getIdForUser($request->input('company_id', null));
$user->manager_id = $request->input('manager_id', null);
$user->notes = $request->input('notes');
@@ -167,7 +166,7 @@ class UsersController extends Controller
* @since [v1.8]
* @return string JSON
*/
public function apiStore()
public function apiStore(SaveUserRequest $request)
{
$this->authorize('create', User::class);
@@ -175,12 +174,13 @@ class UsersController extends Controller
$inputs = Input::except('csrf_token', 'password_confirm', 'groups', 'email_user');
$inputs['activated'] = true;
$user->first_name = Input::get('first_name');
$user->last_name = Input::get('last_name');
$user->username = Input::get('username');
$user->email = Input::get('email');
if (Input::has('password')) {
$user->password = bcrypt(Input::get('password'));
$user->first_name = $request->input('first_name');
$user->last_name = $request->input('last_name');
$user->username = $request->input('username');
$user->email = $request->input('email');
$user->department_id = $request->input('department_id', null);
if ($request->has('password')) {
$user->password = bcrypt($request->input('password'));
}
$user->activated = true;
@@ -190,10 +190,10 @@ class UsersController extends Controller
if (Input::get('email_user') == 1) {
// Send the credentials through email
$data = array();
$data['email'] = e(Input::get('email'));
$data['first_name'] = e(Input::get('first_name'));
$data['last_name'] = e(Input::get('last_name'));
$data['password'] = e(Input::get('password'));
$data['email'] = $request->input('email');
$data['first_name'] = $request->input('first_name');
$data['last_name'] = $request->input('last_name');
$data['password'] = $request->input('password');
Mail::send('emails.send-login', $data, function ($m) use ($user) {
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
@@ -229,10 +229,10 @@ class UsersController extends Controller
return $output;
}
public function edit($id = null)
public function edit($id)
{
try {
// Get the user information
$user = User::find($id);
$this->authorize('update', $user);
$permissions = config('permissions');
@@ -243,19 +243,19 @@ class UsersController extends Controller
$user->permissions = $user->decodePermissions();
$userPermissions = Helper::selectedPermissionsArray($permissions, $user->permissions);
$permissions = $this->filterDisplayable($permissions);
} catch (UserNotFoundException $e) {
// Prepare the error message
$error = trans('admin/users/message.user_not_found', compact('id'));
// Redirect to the user management page
$error = trans('admin/users/message.user_not_found', compact('id'));
return redirect()->route('users.index')->with('error', $error);
}
// Show the page
return View::make('users/edit', compact('user', 'groups', 'userGroups', 'permissions', 'userPermissions'))
->with('location_list', Helper::locationsList())
->with('company_list', Helper::companyList())
->with('manager_list', Helper::managerList());
return view('users/edit', compact('user', 'groups', 'userGroups', 'permissions', 'userPermissions'))
->with('location_list', Helper::locationsList())
->with('department_list', Helper::departmentList())
->with('company_list', Helper::companyList())
->with('manager_list', Helper::managerList());
}
/**
@@ -267,7 +267,7 @@ class UsersController extends Controller
* @param int $id
* @return \Illuminate\Http\RedirectResponse
*/
public function update(UpdateUserRequest $request, $id = null)
public function update(SaveUserRequest $request, $id = null)
{
// We need to reverse the UI specific logic for our
// permissions here before we update the user.
@@ -306,14 +306,11 @@ class UsersController extends Controller
}
}
// Do we want to update the user password?
if ($request->has('password')) {
$user->password = bcrypt($request->input('password'));
}
if ($request->has('username')) {
$user->username = e($request->input('username'));
$user->username = $request->input('username');
}
$user->email = e($request->input('email'));
$user->email = $request->input('email');
// Update the user
@@ -329,6 +326,13 @@ class UsersController extends Controller
$user->company_id = Company::getIdForUser($request->input('company_id', null));
$user->manager_id = $request->input('manager_id', null);
$user->notes = $request->input('notes');
$user->department_id = $request->input('department_id', null);
// Do we want to update the user password?
if ($request->has('password')) {
$user->password = bcrypt($request->input('password'));
}
// Strip out the superuser permission if the user isn't a superadmin
$permissions_array = $request->input('permission');
@@ -366,15 +370,15 @@ class UsersController extends Controller
// Authorize takes care of many of our logic checks now.
$this->authorize('delete', User::class);
if ($user->assets()->count() > 0) {
// Check if we are not trying to delete ourselves
if ($user->id === Auth::user()->id) {
// Redirect to the user management page
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->assets()->count() . ' assets associated with them.');
}
if ($user->licenses()->count() > 0) {
// Redirect to the user management page
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->licenses()->count() . ' licenses associated with them.');
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->assets()->count() . ' assets associated with them.');
}
if ($user->accessories()->count() > 0) {
@@ -382,6 +386,11 @@ class UsersController extends Controller
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->accessories()->count() . ' accessories associated with them.');
}
if ($user->managedLocations()->count() > 0) {
// Redirect to the user management page
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->managedLocations()->count() . ' locations that they manage.');
}
// Delete the user
$user->delete();
@@ -419,15 +428,16 @@ class UsersController extends Controller
$users = User::whereIn('id', $user_raw_array)->with('groups', 'assets', 'licenses', 'accessories')->get();
if ($request->input('bulk_actions')=='edit') {
return View::make('users/bulk-edit', compact('users'))
return view('users/bulk-edit', compact('users'))
->with('location_list', Helper::locationsList())
->with('company_list', Helper::companyList())
->with('manager_list', Helper::managerList())
->with('manager_list', Helper::managerList())
->with('department_list', Helper::departmentList())
->with('groups', Group::pluck('name', 'id'));
}
return View::make('users/confirm-bulk-delete', compact('users', 'statuslabel_list'));
return view('users/confirm-bulk-delete', compact('users', 'statuslabel_list'));
}
}
@@ -448,12 +458,16 @@ class UsersController extends Controller
$user_raw_array = Input::get('ids');
$update_array = array();
$manager_conflict = false;
$users = User::whereIn('id', $user_raw_array)->where('id','!=',Auth::user()->id)->get();
if ($request->has('location_id')) {
$update_array['location_id'] = $request->input('location_id');
}
if ($request->has('department_id')) {
$update_array['department_id'] = $request->input('department_id');
}
if ($request->has('company_id')) {
$update_array['company_id'] = $request->input('company_id');
}
@@ -464,7 +478,7 @@ class UsersController extends Controller
// edited.
if (!array_key_exists($request->input('manager_id'), $user_raw_array)) {
$update_array['manager_id'] = $request->input('manager_id');
$manager_conflict = false;
} else {
$manager_conflict = true;
}
@@ -519,10 +533,7 @@ class UsersController extends Controller
if (($key = array_search(Auth::user()->id, $user_raw_array)) !== false) {
unset($user_raw_array[$key]);
}
if (!Auth::user()->isSuperUser()) {
return redirect()->route('users.index')->with('error', trans('admin/users/message.insufficient_permissions'));
}
if (!config('app.lock_passwords')) {
@@ -636,7 +647,7 @@ class UsersController extends Controller
if (isset($user->id)) {
$this->authorize('view', $user);
return View::make('users/view', compact('user', 'userlog'));
return view('users/view', compact('user', 'userlog'));
}
}
@@ -712,7 +723,7 @@ class UsersController extends Controller
$user->id = null;
// Get this user groups
$userGroups = $user_to_clone->groups()->lists('name', 'id');
$userGroups = $user_to_clone->groups()->pluck('name', 'id');
// Get all the available permissions
$permissions = config('permissions');
$clonedPermissions = $user_to_clone->decodePermissions();
@@ -720,10 +731,11 @@ class UsersController extends Controller
$userPermissions =Helper::selectedPermissionsArray($permissions, $clonedPermissions);
// Show the page
return View::make('users/edit', compact('permissions', 'userPermissions'))
return view('users/edit', compact('permissions', 'userPermissions'))
->with('location_list', Helper::locationsList())
->with('company_list', Helper::companyList())
->with('manager_list', Helper::managerList())
->with('department_list', Helper::departmentList())
->with('user', $user)
->with('groups', Group::pluck('name', 'id'))
->with('userGroups', $userGroups)
@@ -752,7 +764,7 @@ class UsersController extends Controller
$permissions = config('permissions');
$selectedPermissions = Input::old('permissions', array('superuser' => -1));
// Show the page
return View::make('users/import', compact('selectedGroups', 'permissions', 'selectedPermissions'));
return view('users/import', compact('selectedGroups', 'permissions', 'selectedPermissions'));
}
/**
@@ -822,7 +834,6 @@ class UsersController extends Controller
'permissions' => '{"user":1}',
'notes' => 'Imported user'
);
//dd($newuser);
DB::table('users')->insert($newuser);
@@ -914,7 +925,6 @@ class UsersController extends Controller
$user = User::find($userId);
$destinationPath = config('app.private_uploads').'/users';
// the license is valid
if (isset($user->id)) {
$this->authorize('update', $user);
$log = Actionlog::find($fileId);
@@ -982,7 +992,7 @@ class UsersController extends Controller
return redirect()->route('users.index')->with('error', $e->getMessage());
}
return View::make('users/ldap')
return view('users/ldap')
->with('location_list', Helper::locationsList());
}
@@ -1087,6 +1097,15 @@ class UsersController extends Controller
$item["ldap_location_override"] = isset($results[$i]["ldap_location_override"]) ? $results[$i]["ldap_location_override"]:"";
$item["location_id"] = isset($results[$i]["location_id"]) ? $results[$i]["location_id"]:"";
if( array_key_exists('useraccountcontrol', $results[$i]) ) {
$enabled_accounts = [
'512', '544', '66048', '66080', '262656', '262688', '328192', '328224'
];
$item['activated'] = ( in_array($results[$i]['useraccountcontrol'][0], $enabled_accounts) ) ? 1 : 0;
} else {
$item['activated'] = 0;
}
// User exists
$item["createorupdate"] = 'updated';
if (!$user = User::where('username', $item["username"])->first()) {
@@ -1096,12 +1115,13 @@ class UsersController extends Controller
}
// Create the user if they don't exist.
$user->first_name = e($item["firstname"]);
$user->last_name = e($item["lastname"]);
$user->username = e($item["username"]);
$user->email = e($item["email"]);
$user->first_name = $item["firstname"];
$user->last_name = $item["lastname"];
$user->username = $item["username"];
$user->email = $item["email"];
$user->employee_num = e($item["employee_number"]);
$user->activated = 1;
$user->activated = $item['activated'];
if ($item['ldap_location_override'] == true) {
$user->location_id = $item['location_id'];
} else if ($request->input('location_id')!='') {
@@ -1127,21 +1147,7 @@ class UsersController extends Controller
}
return redirect()->route('ldap/user')->with('success', "LDAP Import successful.")->with('summary', $summary);
}
/**
* Return JSON containing a list of assets assigned to a user.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @param $userId
* @return string JSON
*/
public function getAssetList($userId)
{
$this->authorize('view', User::class);
$assets = Asset::where('assigned_to', '=', $userId)->with('model')->get();
return response()->json($assets);
}
/**
* Exports users to CSV
@@ -53,7 +53,7 @@ class ViewAssetsController extends Controller
$userlog = $user->userlog->load('item', 'user', 'target');
if (isset($user->id)) {
return View::make('account/view-assets', compact('user', 'userlog'));
return view('account/view-assets', compact('user', 'userlog'));
} else {
// Prepare the error message
$error = trans('admin/users/message.user_not_found', compact('id'));
@@ -68,16 +68,16 @@ class ViewAssetsController extends Controller
public function getRequestableIndex()
{
$assets = Asset::with('model', 'defaultLoc', 'assetloc', 'assignedTo')->Hardware()->RequestableAssets()->get();
$models = AssetModel::with('category')->RequestableModels()->get();
$assets = Asset::with('model', 'defaultLoc', 'assetloc', 'assignedTo', 'requests')->Hardware()->RequestableAssets()->get();
$models = AssetModel::with('category', 'requests', 'assets')->RequestableModels()->get();
return View::make('account/requestable-assets', compact('user', 'assets', 'models'));
return view('account/requestable-assets', compact('user', 'assets', 'models'));
}
public function getRequestedIndex()
{
$requestedItems = CheckoutRequest::with('user', 'requestedItem')->get();
return View::make('admin/requested-assets', compact('requestedItems'));
return view('admin/requested-assets', compact('requestedItems'));
}
@@ -280,7 +280,7 @@ class ViewAssetsController extends Controller
{
$checkoutrequests = CheckoutRequest::all();
return View::make('account/requested-items', compact($checkoutrequests));
return view('account/requested-items', compact($checkoutrequests));
}
@@ -314,7 +314,7 @@ class ViewAssetsController extends Controller
} elseif (!Company::isCurrentUserHasAccess($item)) {
return redirect()->route('requestable-assets')->with('error', trans('general.insufficient_permissions'));
} else {
return View::make('account/accept-asset', compact('item'))->with('findlog', $findlog)->with('item', $item);
return view('account/accept-asset', compact('item'))->with('findlog', $findlog)->with('item', $item);
}
}
+17 -5
View File
@@ -32,22 +32,35 @@ class ItemImportRequest extends FormRequest
public function import(Import $import)
{
ini_set('max_execution_time', 600); //600 seconds = 10 minutes
ini_set('memory_limit', '500M');
$filename = config('app.private_uploads') . '/imports/' . $import->file_path;
$class = title_case($this->input('import-type'));
$import->import_type = $this->input('import-type');
$class = title_case($import->import_type);
$classString = "App\\Importer\\{$class}Importer";
$importer = new $classString($filename);
$import->field_map = request('column-mappings');
$import->save();
$fieldMappings=[];
if ($import->field_map) {
// We submit as csv field: column, but the importer is happier if we flip it here.
$fieldMappings = array_change_key_case(array_flip($import->field_map), CASE_LOWER);
// dd($fieldMappings);
}
$importer->setCallbacks([$this, 'log'], [$this, 'progress'], [$this, 'errorCallback'])
->setUserId(Auth::id())
->setUpdating($this->has('import-update'))
->setUsernameFormat('firstname.lastname');
->setUsernameFormat('firstname.lastname')
->setFieldMappings($fieldMappings);
// $logFile = storage_path('logs/importer.log');
// \Log::useFiles($logFile);
$importer->import();
return $this->errors;
}
public function log($string)
{
return; // FUTURE IMPLEMENTATION
// \Log::Info($string);
}
public function progress($count)
@@ -58,7 +71,6 @@ class ItemImportRequest extends FormRequest
public function errorCallback($item, $field, $errorString)
{
$this->errors[$item->name][$field] = $errorString;
// $this->errors[$item->name] = $errorString;
}
private $errors;
+34 -7
View File
@@ -3,6 +3,7 @@
namespace App\Http\Requests;
use App\Http\Requests\Request;
use App\Models\Setting;
class SaveUserRequest extends Request
{
@@ -23,12 +24,38 @@ class SaveUserRequest extends Request
*/
public function rules()
{
return [
'first_name' => 'required|string|min:1',
'email' => 'email',
'password' => 'required|min:6',
'password_confirm' => 'sometimes|required_with:password',
'username' => 'required|string|min:2|unique:users,username,NULL,deleted_at',
];
$rules = [];
switch($this->method())
{
// Brand new asset
case 'POST':
{
$rules['first_name'] = 'required|string|min:1';
$rules['username'] = 'required_unless:ldap_import,1|string|min:1';
$rules['password'] = Setting::passwordComplexityRulesSaving('store');
}
// Save all fields
case 'PUT':
$rules['first_name'] = 'required|string|min:1';
$rules['username'] = 'required_unless:ldap_import,1|string|min:1';
$rules['password'] = Setting::passwordComplexityRulesSaving('update');
// Save only what's passed
case 'PATCH':
{
$rules['password'] = Setting::passwordComplexityRulesSaving('update');
}
default:break;
}
$rules['password_confirm'] = 'sometimes|required_with:password';
return $rules;
}
}
+50
View File
@@ -0,0 +1,50 @@
<?php
namespace App\Http\Requests;
use App\Http\Requests\Request;
use Session;
class SettingsLdapRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
$rules = [
"ldap_server" => 'sometimes|required_if:ldap_enabled,1|url|nullable',
"ldap_uname" => 'sometimes|required_if:ldap_enabled,1|nullable',
"ldap_basedn" => 'sometimes|required_if:ldap_enabled,1|nullable',
"ldap_filter" => 'sometimes|required_if:ldap_enabled,1|nullable',
"ldap_username_field" => 'sometimes|required_if:ldap_enabled,1|nullable',
"ldap_fname_field" => 'sometimes|required_if:ldap_enabled,1|nullable',
"ldap_lname_field" => 'sometimes|required_if:ldap_enabled,1|nullable',
"ldap_auth_filter_query" => 'sometimes|required_if:ldap_enabled,1|nullable',
"ldap_version" => 'sometimes|required_if:ldap_enabled,1|nullable',
];
return $rules;
}
public function response(array $errors)
{
$this->session()->flash('errors', Session::get('errors', new \Illuminate\Support\ViewErrorBag)
->put('default', new \Illuminate\Support\MessageBag($errors)));
\Input::flash();
return parent::response($errors);
}
}
-32
View File
@@ -1,32 +0,0 @@
<?php
namespace App\Http\Requests;
use App\Http\Requests\Request;
class UpdateUserRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'first_name' => 'required|string|min:1',
'email' => 'email',
'password_confirm' => 'sometimes|required_with:password',
];
}
}
@@ -23,17 +23,17 @@ class AccessoriesTransformer
$array = [
'id' => $accessory->id,
'name' => e($accessory->name),
'company' => ($accessory->company) ? ['id' => $accessory->company->id,'name'=> e($accessory->company->name)] : '',
'manufacturer' => ($accessory->manufacturer) ? ['id' => $accessory->manufacturer->id,'name'=> e($accessory->manufacturer->name)] : '',
'company' => ($accessory->company) ? ['id' => $accessory->company->id,'name'=> e($accessory->company->name)] : null,
'manufacturer' => ($accessory->manufacturer) ? ['id' => $accessory->manufacturer->id,'name'=> e($accessory->manufacturer->name)] : null,
'model_number' => ($accessory->model_number) ? e($accessory->model_number) : null,
'category' => ($accessory->category) ? ['id' => $accessory->category->id,'name'=> e($accessory->category->name)] : '',
'location' => ($accessory->location) ? ['id' => $accessory->location->id,'name'=> e($accessory->location->name)] : '',
'category' => ($accessory->category) ? ['id' => $accessory->category->id,'name'=> e($accessory->category->name)] : null,
'location' => ($accessory->location) ? ['id' => $accessory->location->id,'name'=> e($accessory->location->name)] : null,
'notes' => ($accessory->notes) ? e($accessory->notes) : null,
'qty' => ($accessory->qty) ? e($accessory->qty) : null,
'qty' => ($accessory->qty) ? (int) $accessory->qty : null,
'purchase_date' => ($accessory->purchase_date) ? Helper::getFormattedDateObject($accessory->purchase_date, 'date') : null,
'purchase_cost' => ($accessory->purchase_cost) ? e($accessory->purchase_cost) : null,
'order_number' => ($accessory->order_number) ? e($accessory->order_number) : null,
'min_qty' => ($accessory->min_amt) ? e($accessory->min_amt) : null,
'min_qty' => ($accessory->min_amt) ? (int) $accessory->min_amt : null,
'remaining_qty' => $accessory->numRemaining(),
'created_at' => Helper::getFormattedDateObject($accessory->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($accessory->updated_at, 'datetime'),
@@ -0,0 +1,78 @@
<?php
namespace App\Http\Transformers;
use App\Models\Actionlog;
use App\Models\Setting;
use Gate;
use Illuminate\Database\Eloquent\Collection;
use App\Helpers\Helper;
class ActionlogsTransformer
{
public function transformActionlogs (Collection $actionlogs, $total)
{
$array = array();
$settings = Setting::getSettings();
foreach ($actionlogs as $actionlog) {
$array[] = self::transformActionlog($actionlog, $settings);
}
return (new DatatablesTransformer)->transformDatatables($array, $total);
}
public function transformActionlog (Actionlog $actionlog, $settings = null)
{
$array = [
'id' => (int) $actionlog->id,
'icon' => $actionlog->present()->icon(),
'image' => (method_exists($actionlog->item, 'getImageUrl')) ? $actionlog->item->getImageUrl() : null,
'item' => ($actionlog->item) ? [
'id' => (int) $actionlog->item->id,
'name' => e($actionlog->item->getDisplayNameAttribute()),
'type' => e($actionlog->itemType()),
] : null,
'location' => ($actionlog->location) ? [
'id' => (int) $actionlog->location->id,
'name' => e($actionlog->location->name)
] : null,
'created_at' => Helper::getFormattedDateObject($actionlog->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($actionlog->updated_at, 'datetime'),
'next_audit_date' => ($actionlog->itemType()=='asset') ? Helper::getFormattedDateObject($actionlog->calcNextAuditDate(), 'date'): null,
'days_to_next_audit' => $actionlog->daysUntilNextAudit($settings->audit_interval, $actionlog->item),
'action_type' => $actionlog->present()->actionType(),
'admin' => ($actionlog->user) ? [
'id' => (int) $actionlog->user->id,
'name' => e($actionlog->user->getFullNameAttribute()),
'first_name'=> e($actionlog->user->first_name),
'last_name'=> e($actionlog->user->last_name)
] : null,
'target' => ($actionlog->target) ? [
'id' => (int) $actionlog->target->id,
'name' => ($actionlog->targetType()=='user') ? e($actionlog->target->getFullNameAttribute()) : e($actionlog->target->getDisplayNameAttribute()),
'type' => e($actionlog->targetType()),
] : null,
'note' => e($actionlog->note),
];
return $array;
}
public function transformCheckedoutActionlog (Collection $accessories_users, $total)
{
$array = array();
foreach ($accessories_users as $user) {
$array[] = (new UsersTransformer)->transformUser($user);
}
return (new DatatablesTransformer)->transformDatatables($array, $total);
}
}
@@ -0,0 +1,54 @@
<?php
namespace App\Http\Transformers;
use App\Models\AssetMaintenance;
use Gate;
use Illuminate\Database\Eloquent\Collection;
use App\Helpers\Helper;
class AssetMaintenancesTransformer
{
public function transformAssetMaintenances (Collection $assetmaintenances, $total)
{
$array = array();
foreach ($assetmaintenances as $assetmaintenance) {
$array[] = self::transformAssetMaintenance($assetmaintenance);
}
return (new DatatablesTransformer)->transformDatatables($array, $total);
}
public function transformAssetMaintenance (AssetMaintenance $assetmaintenance)
{
$array = [
'id' => (int) $assetmaintenance->id,
'asset_name' => ($assetmaintenance->asset) ? ['id' => $assetmaintenance->asset->id,'name'=> e($assetmaintenance->asset->name)] : null,
'title' => ($assetmaintenance->title) ? e($assetmaintenance->title) : null,
'notes' => ($assetmaintenance->notes) ? e($assetmaintenance->notes) : null,
'supplier' => ($assetmaintenance->supplier) ? ['id' => $assetmaintenance->supplier->id,'name'=> e($assetmaintenance->supplier->name)] : null,
'cost' => Helper::formatCurrencyOutput($assetmaintenance->cost),
'asset_maintenance_type' => e($assetmaintenance->asset_maintenance_type),
'start_date' => Helper::getFormattedDateObject($assetmaintenance->start_date, 'datetime'),
'asset_maintenance_time' => $assetmaintenance->asset_maintenance_time,
'completion_date' => Helper::getFormattedDateObject($assetmaintenance->completion_date, 'datetime'),
'user_id' => ($assetmaintenance->admin) ? ['id' => $assetmaintenance->admin->id,'name'=> e($assetmaintenance->admin->getFullNameAttribute())] : null,
'created_at' => Helper::getFormattedDateObject($assetmaintenance->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($assetmaintenance->updated_at, 'datetime'),
];
$permissions_array['available_actions'] = [
'update' => (bool) Gate::allows('update', Asset::class),
'delete' => (bool) Gate::allows('delete', Asset::class),
];
$array += $permissions_array;
return $array;
}
}
@@ -4,6 +4,7 @@ namespace App\Http\Transformers;
use App\Models\AssetModel;
use Illuminate\Database\Eloquent\Collection;
use Gate;
use App\Helpers\Helper;
class AssetModelsTransformer
{
@@ -21,23 +22,38 @@ class AssetModelsTransformer
{
$array = [
'id' => $assetmodel->id,
'id' => (int) $assetmodel->id,
'name' => e($assetmodel->name),
'manufacturer' => ($assetmodel->manufacturer_id) ? $assetmodel->manufacturer : null,
'image' => ($assetmodel->image!='') ? url('/').'/uploads/models/'.e($assetmodel->image) : '',
'manufacturer' => ($assetmodel->manufacturer) ? [
'id' => (int) $assetmodel->manufacturer->id,
'name'=> e($assetmodel->manufacturer->name)
] : null,
'image' => ($assetmodel->image!='') ? url('/').'/uploads/models/'.e($assetmodel->image) : null,
'model_number' => e($assetmodel->model_number),
'depreciation' => ($assetmodel->depreciation) ? $assetmodel->depreciation : 'No',
'depreciation' => ($assetmodel->depreciation) ? [
'id' => (int) $assetmodel->depreciation->id,
'name'=> e($assetmodel->depreciation->name)
] : null,
'assets_count' => $assetmodel->assets_count,
'category' => ($assetmodel->category_id) ? $assetmodel->category : null,
'fieldset' => ($assetmodel->fieldset) ? $assetmodel->fieldset : null,
'category' => ($assetmodel->category) ? [
'id' => (int) $assetmodel->category->id,
'name'=> e($assetmodel->category->name)
] : null,
'fieldset' => ($assetmodel->fieldset) ? [
'id' => (int) $assetmodel->fieldset->id,
'name'=> e($assetmodel->fieldset->name)
] : null,
'eol' => ($assetmodel->eol > 0) ? $assetmodel->eol .' months': 'None',
'notes' => e($assetmodel->notes)
'notes' => e($assetmodel->notes),
'created_at' => Helper::getFormattedDateObject($assetmodel->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($assetmodel->updated_at, 'datetime'),
];
$permissions_array['available_actions'] = [
'update' => Gate::allows('admin') ? true : false,
'delete' => Gate::allows('admin') ? true : false,
'update' => Gate::allows('update', AssetModel::class) ? true : false,
'delete' => Gate::allows('delete', AssetModel::class) ? true : false,
'clone' => Gate::allows('create', AssetModel::class) ? true : false,
];
$array += $permissions_array;
+59 -14
View File
@@ -43,6 +43,10 @@ class AssetsTransformer
'id' => (int) $asset->model->manufacturer->id,
'name'=> e($asset->model->manufacturer->name)
] : null,
'supplier' => ($asset->supplier) ? [
'id' => (int) $asset->supplier->id,
'name'=> e($asset->supplier->name)
] : null,
'notes' => e($asset->notes),
'order_number' => e($asset->order_number),
'company' => ($asset->company) ? [
@@ -58,12 +62,7 @@ class AssetsTransformer
'name'=> e($asset->defaultLoc->name)
] : null,
'image' => ($asset->getImageUrl()) ? $asset->getImageUrl() : null,
'assigned_to' => ($asset->assigneduser) ? [
'id' => (int) $asset->assigneduser->id,
'name' => e($asset->assigneduser->getFullNameAttribute()),
'first_name'=> e($asset->assigneduser->first_name),
'last_name'=> e($asset->assigneduser->last_name)
] : null,
'assigned_to' => $this->transformAssignedTo($asset),
'warranty' => ($asset->warranty_months > 0) ? e($asset->warranty_months . ' ' . trans('admin/hardware/form.months')) : null,
'warranty_expires' => ($asset->warranty_months > 0) ? Helper::getFormattedDateObject($asset->warranty_expires, 'date') : null,
'created_at' => Helper::getFormattedDateObject($asset->created_at, 'datetime'),
@@ -75,22 +74,48 @@ class AssetsTransformer
'user_can_checkout' => (bool) $asset->availableForCheckout(),
];
if ($asset->model->fieldset) {
$fields_array = array();
foreach ($asset->model->fieldset->fields as $field) {
if ($field->isFieldDecryptable($asset->{$field->convertUnicodeDbSlug()})) {
$decrypted = \App\Helpers\Helper::gracefulDecrypt($field,$asset->{$field->convertUnicodeDbSlug()});
$value = (Gate::allows('superadmin')) ? $decrypted : strtoupper(trans('admin/custom_fields/general.encrypted'));
// $fields_array = [$field->convertUnicodeDbSlug() => $value];
$fields_array[$field->name] = [
'field' => $field->convertUnicodeDbSlug(),
'value' => $value
];
} else {
$fields_array[$field->name] = [
'field' => $field->convertUnicodeDbSlug(),
'value' => $asset->{$field->convertUnicodeDbSlug()}
];
//$fields_array = [$field->convertUnicodeDbSlug() => $asset->{$field->convertUnicodeDbSlug()}];
}
//array += $fields_array;
$array['custom_fields'] = $fields_array;
}
} else {
$array['custom_fields'] = array();
}
$permissions_array['available_actions'] = [
'checkout' => (bool) Gate::allows('checkout', Asset::class),
'checkin' => (bool) Gate::allows('checkin', Asset::class),
'clone' => Gate::allows('create', Asset::class) ? true : false,
'update' => (bool) Gate::allows('update', Asset::class),
'delete' => (bool) Gate::allows('delete', Asset::class),
];
$array += $permissions_array;
if ($asset->model->fieldset) {
foreach ($asset->model->fieldset->fields as $field) {
$fields_array = [$field->name => $asset->{$field->convertUnicodeDbSlug()}];
$array += $fields_array;
}
}
return $array;
}
@@ -98,4 +123,24 @@ class AssetsTransformer
{
return (new DatatablesTransformer)->transformDatatables($assets);
}
public function transformAssignedTo($asset)
{
if ($asset->checkedOutToUser()) {
return $asset->assignedTo ? [
'id' => (int) $asset->assignedTo->id,
'username' => e($asset->assignedTo->username),
'name' => e($asset->assignedTo->getFullNameAttribute()),
'first_name'=> e($asset->assignedTo->first_name),
'last_name'=> e($asset->assignedTo->last_name),
'employee_number' => e($asset->assignedTo->employee_num),
'type' => 'user'
] : null;
}
return $asset->assignedTo ? [
'id' => $asset->assignedTo->id,
'name' => $asset->assignedTo->display_name,
'type' => $asset->assignedType()
] : null;
}
}
@@ -4,6 +4,7 @@ namespace App\Http\Transformers;
use App\Models\Category;
use Illuminate\Database\Eloquent\Collection;
use Gate;
use App\Helpers\Helper;
class CategoriesTransformer
{
@@ -22,15 +23,18 @@ class CategoriesTransformer
if ($category) {
$array = [
'id' => e($category->id),
'id' => (int) $category->id,
'name' => e($category->name),
'type' => e($category->category_type),
'use_default_eula' => ($category->use_default_eula =='1') ? true : false,
'checkin_email' => ($category->checkin_email =='1') ? true : false,
'require_acceptance' => ($category->require_acceptance =='1') ? true : false,
'assets_count' => $category->assets_count,
'accessories_count' => $category->accessories_count,
'consumables_count' => $category->consumables_count,
'components_count' => $category->components_count,
'created_at' => Helper::getFormattedDateObject($category->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($category->updated_at, 'datetime'),
];
$permissions_array['available_actions'] = [
@@ -0,0 +1,53 @@
<?php
namespace App\Http\Transformers;
use App\Models\Company;
use Illuminate\Database\Eloquent\Collection;
use Gate;
use App\Helpers\Helper;
class CompaniesTransformer
{
public function transformCompanies (Collection $companies, $total)
{
$array = array();
foreach ($companies as $company) {
$array[] = self::transformCompany($company);
}
return (new DatatablesTransformer)->transformDatatables($array, $total);
}
public function transformCompany (Company $company = null)
{
if ($company) {
$array = [
'id' => (int) $company->id,
'name' => e($company->name),
"created_at" => Helper::getFormattedDateObject($company->created_at, 'datetime'),
"updated_at" => Helper::getFormattedDateObject($company->updated_at, 'datetime'),
"assets_count" => (int) $company->assets_count,
"licenses_count" => (int) $company->licenses_count,
"accessories_count" => (int) $company->accessories_count,
"consumables_count" => (int) $company->consumables_count,
"components_count" => (int) $company->components_count,
"users_count" => (int) $company->users_count
];
$permissions_array['available_actions'] = [
'update' => Gate::allows('update', Company::class) ? true : false,
'delete' => Gate::allows('delete', Company::class) ? true : false,
];
$array += $permissions_array;
return $array;
}
}
}
@@ -27,8 +27,8 @@ class ComponentsTransformer
'id' => (int) $component->location->id,
'name' => e($component->location->name)
] : null,
'qty' => number_format($component->qty),
'min_amt' => e($component->min_amt),
'qty' => ($component->qty!='') ? (int) $component->qty : null,
'min_amt' => ($component->min_amt!='') ? (int) $component->min_amt : null,
'category' => ($component->category) ? [
'id' => (int) $component->category->id,
'name' => e($component->category->name)
@@ -43,6 +43,7 @@ class ComponentsTransformer
] : null,
'created_at' => Helper::getFormattedDateObject($component->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($component->updated_at, 'datetime'),
'user_can_checkout' => ($component->numRemaining() > 0) ? 1 : 0,
];
$permissions_array['available_actions'] = [
@@ -21,20 +21,20 @@ class ConsumablesTransformer
public function transformConsumable (Consumable $consumable)
{
$array = [
'category' => ($consumable->category) ? ['id' => $consumable->category->id, 'name' => $consumable->category->name] : null,
'company' => ($consumable->company) ? ['id' => $consumable->company->id, 'name' => $consumable->company->name] : null,
'id' => $consumable->id,
'item_no' => $consumable->item_no,
'location' => ($consumable->location) ? ['id' => $consumable->location->id, 'name' => $consumable->location->name] : null,
'manufacturer' => ($consumable->manufacturer) ? ['id' => $consumable->manufacturer->id, 'name' => $consumable->manufacturer->name] : null,
'min_amt' => $consumable->min_amt,
'model_number' => $consumable->model_number,
'name' => $consumable->name,
'id' => (int) $consumable->id,
'category' => ($consumable->category) ? ['id' => $consumable->category->id, 'name' => e($consumable->category->name)] : null,
'company' => ($consumable->company) ? ['id' => (int) $consumable->company->id, 'name' => e($consumable->company->name)] : null,
'item_no' => e($consumable->item_no),
'location' => ($consumable->location) ? ['id' => (int) $consumable->location->id, 'name' => e($consumable->location->name)] : null,
'manufacturer' => ($consumable->manufacturer) ? ['id' => (int) $consumable->manufacturer->id, 'name' => e($consumable->manufacturer->name)] : null,
'min_amt' => (int) $consumable->min_amt,
'model_number' => e($consumable->model_number),
'name' => e($consumable->name),
'remaining' => $consumable->numRemaining(),
'order_number' => $consumable->order_number,
'order_number' => e($consumable->order_number),
'purchase_cost' => Helper::formatCurrencyOutput($consumable->purchase_cost),
'purchase_date' => Helper::getFormattedDateObject($consumable->purchase_date, 'date'),
'qty' => $consumable->qty,
'qty' => (int) $consumable->qty,
'created_at' => Helper::getFormattedDateObject($consumable->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($consumable->updated_at, 'datetime'),
];
@@ -0,0 +1,36 @@
<?php
namespace App\Http\Transformers;
use App\Models\CustomField;
use Illuminate\Database\Eloquent\Collection;
use App\Helpers\Helper;
use Gate;
class CustomFieldsTransformer
{
public function transformCustomFields (Collection $fields, $total)
{
$array = array();
foreach ($fields as $field) {
$array[] = self::transformCustomField($field);
}
return (new DatatablesTransformer)->transformDatatables($array, $total);
}
public function transformCustomField (CustomField $field)
{
$array = [
'name' => e($field->name),
'db_column_name' => e($field->db_column_name()),
'format' => e($field->format),
'required' => $field->pivot ? $field->pivot->required : false,
'created_at' => Helper::getFormattedDateObject($field->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($field->updated_at, 'datetime'),
];
return $array;
}
}
@@ -0,0 +1,47 @@
<?php
namespace App\Http\Transformers;
use App\Models\CustomFieldset;
use App\Models\CustomField;
use App\Models\AssetModel;
use Illuminate\Database\Eloquent\Collection;
use App\Helpers\Helper;
use Gate;
class CustomFieldsetsTransformer
{
public function transformCustomFieldsets (Collection $fieldsets, $total)
{
$array = array();
foreach ($fieldsets as $fieldset) {
$array[] = self::transformCustomFieldset($fieldset);
}
return (new DatatablesTransformer)->transformDatatables($array, $total);
}
public function transformCustomFieldset (CustomFieldset $fieldset)
{
$fields = $fieldset->fields;
$models = $fieldset->models;
$modelsArray = array();
foreach ($models as $model)
{
$modelsArray[] = [
'id' => $model->id,
'name' => e($model->name)
];
}
$array = [
'id' => (int) $fieldset->id,
'name' => e($fieldset->name),
'fields' => (new CustomFieldsTransformer)->transformCustomFields($fields, $fieldset->fields_count),
'models' => (new DatatablesTransformer)->transformDatatables($modelsArray, $fieldset->models_count),
'created_at' => Helper::getFormattedDateObject($fieldset->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($fieldset->updated_at, 'datetime'),
];
return $array;
}
}
@@ -0,0 +1,62 @@
<?php
namespace App\Http\Transformers;
use App\Models\Department;
use Illuminate\Database\Eloquent\Collection;
use Gate;
use App\Helpers\Helper;
class DepartmentsTransformer
{
public function transformDepartments (Collection $departments, $total)
{
$array = array();
foreach ($departments as $department) {
$array[] = self::transformDepartment($department);
}
return (new DatatablesTransformer)->transformDatatables($array, $total);
}
public function transformDepartment (Department $department = null)
{
if ($department) {
$array = [
'id' => (int) $department->id,
'name' => e($department->name),
'company' => ($department->company) ? [
'id' => (int) $department->company->id,
'name'=> e($department->company->name)
] : null,
'manager' => ($department->manager) ? [
'id' => (int) $department->manager->id,
'name' => e($department->manager->getFullNameAttribute()),
'first_name'=> e($department->manager->first_name),
'last_name'=> e($department->manager->last_name)
] : null,
'location' => ($department->location) ? [
'id' => (int) $department->location->id,
'name' => e($department->location->name)
] : null,
'users_count' => e($department->users_count),
'created_at' => Helper::getFormattedDateObject($department->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($department->updated_at, 'datetime'),
];
$permissions_array['available_actions'] = [
'update' => Gate::allows('update', Department::class) ? true : false,
'delete' => Gate::allows('delete', Department::class) ? true : false,
];
$array += $permissions_array;
return $array;
}
}
}
@@ -21,7 +21,7 @@ class DepreciationsTransformer
public function transformDepreciation (Depreciation $depreciation)
{
$array = [
'id' => e($depreciation->id),
'id' => (int) $depreciation->id,
'name' => e($depreciation->name),
'months' => $depreciation->months . ' '. trans('general.months'),
'created_at' => Helper::getFormattedDateObject($depreciation->created_at, 'datetime'),
+3 -2
View File
@@ -4,6 +4,7 @@ namespace App\Http\Transformers;
use App\Models\Group;
use Illuminate\Database\Eloquent\Collection;
use Gate;
use App\Helpers\Helper;
class GroupsTransformer
{
@@ -20,10 +21,10 @@ class GroupsTransformer
public function transformGroup (Group $group)
{
$array = [
'id' => e($group->id),
'id' => (int) $group->id,
'name' => e($group->name),
'permissions' => $group->permissions,
'users_count' => $group->users_count,
'users_count' => (int) $group->users_count,
'created_at' => Helper::getFormattedDateObject($group->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($group->updated_at, 'datetime'),
];
+7 -4
View File
@@ -20,12 +20,15 @@ class ImportsTransformer
public function transformImport(Import $import)
{
$array = [
'id' => $import->id,
'file_path' => $import->file_path,
'id' => (int) $import->id,
'file_path' => e($import->file_path),
'filesize' => Setting::fileSizeConvert($import->filesize),
'name' => $import->name,
'import_type' => $import->import_type,
'name' => e($import->name),
'import_type' => e($import->import_type),
'created_at' => $import->created_at->diffForHumans(),
'header_row' => $import->header_row,
'first_row' => $import->first_row,
'field_map' => $import->field_map,
];
@@ -21,32 +21,34 @@ class LicensesTransformer
public function transformLicense (License $license)
{
$array = [
'id' => $license->id,
'id' => (int) $license->id,
'name' => e($license->name),
'company' => ($license->company) ? ['id' => $license->company->id,'name'=> e($license->company->name)] : null,
'manufacturer' => ($license->manufacturer) ? ['id' => $license->manufacturer->id,'name'=> e($license->manufacturer->name)] : null,
'company' => ($license->company) ? ['id' => (int) $license->company->id,'name'=> e($license->company->name)] : null,
'manufacturer' => ($license->manufacturer) ? ['id' => (int) $license->manufacturer->id,'name'=> e($license->manufacturer->name)] : null,
'product_key' => e($license->serial),
'order_number' => e($license->order_number),
'purchase_order' => e($license->purchase_order),
'purchase_date' => Helper::getFormattedDateObject($license->purchase_date, 'date'),
'purchase_cost' => e($license->purchase_cost),
'depreciation' => ($license->depreciation) ? ['id' => $license->depreciation->id,'name'=> e($license->depreciation->name)] : null,
'depreciation' => ($license->depreciation) ? ['id' => (int) $license->depreciation->id,'name'=> e($license->depreciation->name)] : null,
'notes' => e($license->notes),
'expiration_date' => Helper::getFormattedDateObject($license->expiration_date, 'date'),
'total_seats' => e($license->seats),
'total_seats' => (int) $license->total_seats,
'remaining_qty' => $license->remaincount(),
'min_qty' => $license->remaincount(),
'license_name' => e($license->license_name),
'license_email' => e($license->license_email),
'maintained' => ($license->maintained == 1) ? true : false,
'supplier' => ($license->supplier) ? ['id' => $license->supplier->id,'name'=> e($license->supplier->name)] : null,
'supplier' => ($license->supplier) ? ['id' => (int) $license->supplier->id,'name'=> e($license->supplier->name)] : null,
'created_at' => Helper::getFormattedDateObject($license->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($license->updated_at, 'datetime'),
'user_can_checkout' => (bool) ($license->remaincount() > 0),
];
$permissions_array['available_actions'] = [
'checkout' => Gate::allows('checkout', License::class) ? true : false,
'checkin' => Gate::allows('checkin', License::class) ? true : false,
'clone' => Gate::allows('create', License::class) ? true : false,
'update' => Gate::allows('update', License::class) ? true : false,
'delete' => Gate::allows('delete', License::class) ? true : false,
];
+17 -7
View File
@@ -9,7 +9,7 @@ use App\Helpers\Helper;
class LocationsTransformer
{
public function transformLocations (Collection $locations, $total)
public function transformLocations(Collection $locations, $total)
{
$array = array();
foreach ($locations as $location) {
@@ -18,17 +18,20 @@ class LocationsTransformer
return (new DatatablesTransformer)->transformDatatables($array, $total);
}
public function transformLocation (Location $location = null)
public function transformLocation(Location $location = null)
{
if ($location) {
$assets_arr = [];
foreach($location->assets() as $asset) {
$assets_arr = ['id' => $asset->id];
$children_arr = [];
foreach($location->childLocations as $child) {
$children_arr[] = [
'id' => (int) $child->id,
'name' => $child->name
];
}
$array = [
'id' => e($location->id),
'id' => (int) $location->id,
'name' => e($location->name),
'address' => e($location->address),
'city' => e($location->city),
@@ -36,9 +39,16 @@ class LocationsTransformer
'assets_checkedout' => $location->assets()->count(),
'assets_default' => $location->assignedassets()->count(),
'country' => e($location->country),
'assets' => $assets_arr,
'created_at' => Helper::getFormattedDateObject($location->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($location->updated_at, 'datetime'),
'parent' => ($location->parent) ? [
'id' => (int) $location->parent->id,
'name'=> e($location->parent->name)
] : null,
'manager' => ($location->manager) ? (new UsersTransformer)->transformUser($location->manager) : null,
'children' => $children_arr,
];
$permissions_array['available_actions'] = [
@@ -23,16 +23,16 @@ class ManufacturersTransformer
if ($manufacturer) {
$array = [
'id' => e($manufacturer->id),
'id' => (int) $manufacturer->id,
'name' => e($manufacturer->name),
'url' => e($manufacturer->url),
'support_url' => e($manufacturer->support_url),
'support_phone' => e($manufacturer->support_phone),
'support_email' => e($manufacturer->support_email),
'assets_count' => e($manufacturer->assets_count),
'licenses_count' => e($manufacturer->licenses_count),
'consumables_count' => e($manufacturer->consumables_count),
'accessories_count' => e($manufacturer->accessories_count),
'assets_count' => (int) $manufacturer->assets_count,
'licenses_count' => (int) $manufacturer->licenses_count,
'consumables_count' => (int) $manufacturer->consumables_count,
'accessories_count' => (int) $manufacturer->accessories_count,
'created_at' => Helper::getFormattedDateObject($manufacturer->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($manufacturer->updated_at, 'datetime'),
];
@@ -21,7 +21,7 @@ class StatuslabelsTransformer
public function transformStatuslabel (Statuslabel $statuslabel)
{
$array = [
'id' => e($statuslabel->id),
'id' => (int) $statuslabel->id,
'name' => e($statuslabel->name),
'type' => $statuslabel->getStatuslabelType(),
'color' => ($statuslabel->color) ? e($statuslabel->color) : null,
@@ -0,0 +1,62 @@
<?php
namespace App\Http\Transformers;
use App\Models\Supplier;
use Illuminate\Database\Eloquent\Collection;
use Gate;
use App\Helpers\Helper;
class SuppliersTransformer
{
public function transformSuppliers (Collection $suppliers, $total)
{
$array = array();
foreach ($suppliers as $supplier) {
$array[] = self::transformSupplier($supplier);
}
return (new DatatablesTransformer)->transformDatatables($array, $total);
}
public function transformSupplier (Supplier $supplier = null)
{
if ($supplier) {
$array = [
'id' => (int) $supplier->id,
'name' => e($supplier->name),
'address' => ($supplier->address) ? e($supplier->address) : null,
'address2' => ($supplier->address2) ? e($supplier->address2) : null,
'city' => ($supplier->city) ? e($supplier->city) : null,
'state' => ($supplier->state) ? e($supplier->state) : null,
'country' => ($supplier->country) ? e($supplier->country) : null,
'zip' => ($supplier->zip) ? e($supplier->zip) : null,
'fax' => ($supplier->fax) ? e($supplier->fax) : null,
'phone' => ($supplier->phone) ? e($supplier->phone) : null,
'email' => ($supplier->email) ? e($supplier->email) : null,
'contact' => ($supplier->contact) ? e($supplier->contact) : null,
'assets_count' => (int) $supplier->assets_count,
'licenses_count' => (int) $supplier->licenses_count,
'image' => ($supplier->image) ? e($supplier->image) : null,
'notes' => ($supplier->notes) ? e($supplier->notes) : null,
'created_at' => Helper::getFormattedDateObject($supplier->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($supplier->updated_at, 'datetime'),
];
$permissions_array['available_actions'] = [
'update' => Gate::allows('update', Supplier::class) ? true : false,
'delete' => Gate::allows('delete', Supplier::class) ? true : false,
];
$array += $permissions_array;
return $array;
}
}
}
+42 -13
View File
@@ -22,37 +22,66 @@ class UsersTransformer
public function transformUser (User $user)
{
$array = [
'id' => e($user->id),
'id' => (int) $user->id,
'name' => e($user->first_name).' '.($user->last_name),
'firstname' => e($user->first_name),
'lastname' => e($user->last_name),
'username' => e($user->username),
'employee_num' => e($user->employee_num),
'manager' => ($user->manager) ? (new UsersTransformer)->transformUser($user->manager) : '',
'groups' => $user->groups,
'jobtitle' => e($user->jobtitle),
'manager' => ($user->manager) ? [
'id' => (int) $user->manager->id,
'name'=> e($user->manager->username)
] : null,
'jobtitle' => ($user->jobtitle) ? e($user->jobtitle) : null,
'email' => e($user->email),
'location' => (new LocationsTransformer)->transformLocation($user->userloc),
'department' => ($user->department) ? [
'id' => (int) $user->department->id,
'name'=> e($user->department->name)
] : null,
'location' => ($user->userloc) ? [
'id' => (int) $user->userloc->id,
'name'=> e($user->userloc->name)
] : null,
'permissions' => $user->decodePermissions(),
'activated' => ($user->activated =='1') ? true : false,
'two_factor_activated' => ($user->activated =='1') ? true : false,
'assets_count' => $user->assets_count,
'licenses_count' => $user->licenses_count,
'accessories_count' => $user->accessories_count,
'consumables_count' => $user->consumables_count,
'company' => ($user->company) ? ['id' => $user->company->id,'name'=> e($user->company->name)] : null,
'two_factor_activated' => ($user->two_factor_active()) ? true : false,
'assets_count' => (int) $user->assets_count,
'licenses_count' => (int) $user->licenses_count,
'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_at' => Helper::getFormattedDateObject($user->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($user->updated_at, 'datetime'),
'last_login' => Helper::getFormattedDateObject($user->last_login, 'datetime'),
];
$permissions_array['available_actions'] = [
'update' => Gate::allows('update', User::class) ? true : false,
'delete' => Gate::allows('delete', User::class) ? true : false,
'update' => (Gate::allows('update', User::class) && ($user->deleted_at=='')) ? true : false,
'delete' => (Gate::allows('delete', User::class) && ($user->deleted_at=='')) ? true : false,
'clone' => (Gate::allows('create', User::class) && ($user->deleted_at=='')) ,
'restore' => (Gate::allows('create', User::class) && ($user->deleted_at!='')) ? true : false,
];
$array += $permissions_array;
$numGroups = count($user->groups);
if($numGroups > 0)
{
$groups["total"] = $numGroups;
foreach($user->groups as $group)
{
$groups["rows"][] = [
'id' => (int) $group->id,
'name' => e($group->name)
];
}
$array["groups"] = $groups;
}
else {
$array["groups"] = null;
}
return $array;
}
+5 -17
View File
@@ -7,11 +7,9 @@ use App\Models\Accessory;
class AccessoryImporter extends ItemImporter
{
protected $accessories;
public function __construct($filename)
{
parent::__construct($filename);
$this->accessories = Accessory::all();
}
protected function handle($row)
@@ -28,36 +26,26 @@ class AccessoryImporter extends ItemImporter
*/
public function createAccessoryIfNotExists()
{
$accessoryId = $this->accessories->search(function ($key) {
return strcasecmp($key->name, $this->item['name']) == 0;
});
if ($accessoryId !== false) {
$accessory = Accessory::where('name', $this->item['name'])->first();
if ($accessory) {
if (!$this->updating) {
$this->log('A matching Accessory ' . $this->item["name"] . ' already exists. ');
return;
}
$this->log('Updating Accessory');
$accessory = $this->accessories[$accessoryId];
$accessory->update($this->sanitizeItemForUpdating($accessory));
if (!$this->testRun) {
$accessory->save();
}
$accessory->save();
return;
}
$this->log("No Matching Accessory, Creating a new one");
$accessory = new Accessory();
$accessory->fill($this->sanitizeItemForStoring($accessory));
if ($this->testRun) {
$this->log('TEST RUN - Accessory ' . $this->item["name"] . ' not created');
return;
}
if ($accessory->save()) {
$accessory->logCreate('Imported using CSV Importer');
$this->log('Accessory ' . $this->item["name"] . ' was created');
return;
}
$this->jsonError($accessory, 'Accessory');
$this->logError($accessory, 'Accessory');
}
}
+21 -24
View File
@@ -24,8 +24,10 @@ class AssetImporter extends ItemImporter
parent::handle($row);
foreach ($this->customFields as $customField) {
if ($this->item['custom_fields'][$customField->db_column_name()] = $this->array_smart_custom_field_fetch($row, $customField)) {
$this->log('Custom Field '. $customField->name.': '.$this->array_smart_custom_field_fetch($row, $customField));
$customFieldValue = $this->array_smart_custom_field_fetch($row, $customField);
if ($customFieldValue) {
$this->item['custom_fields'][$customField->db_column_name()] = $customFieldValue;
$this->log('Custom Field '. $customField->name.': '.$customFieldValue);
}
}
@@ -43,10 +45,11 @@ class AssetImporter extends ItemImporter
public function createAssetIfNotExists(array $row)
{
$editingAsset = false;
$asset = Asset::where(['asset_tag'=> $this->item['asset_tag']])->first();
$asset_tag = $this->findCsvMatch($row, "asset_tag");
$asset = Asset::where(['asset_tag'=> $asset_tag])->first();
if ($asset) {
if (!$this->updating) {
$this->log('A matching Asset ' . $this->item['asset_tag'] . ' already exists');
$this->log('A matching Asset ' . $asset_tag . ' already exists');
return;
}
@@ -56,24 +59,21 @@ class AssetImporter extends ItemImporter
$this->log("No Matching Asset, Creating a new one");
$asset = new Asset;
}
$this->item['serial'] = $this->array_smart_fetch($row, "serial number");
$this->item['image'] = $this->array_smart_fetch($row, "image");
$this->item['warranty_months'] = intval($this->array_smart_fetch($row, "warranty months"));
if ($this->item['asset_model'] = $this->createOrFetchAssetModel($row)) {
$this->item['model_id'] = $this->item['asset_model']->id;
}
if (isset($this->item["status_label"])) {
$this->item['status_id'] = $this->item["status_label"]->id;
} elseif (!$editingAsset) {
// Assume if we are editing, we already have a status and can ignore.
$this->item['image'] = $this->findCsvMatch($row, "image");
$this->item['warranty_months'] = intval($this->findCsvMatch($row, "warranty"));
$this->item['model_id'] = $this->createOrFetchAssetModel($row);
// If no status ID is found
if (!array_key_exists('status_id', $this->item) && !$editingAsset) {
$this->log("No status field found, defaulting to first status.");
$this->item['status_id'] = $this->defaultStatusLabelId;
}
$this->item['asset_tag'] = $asset_tag;
// By default we're set this to location_id in the item.
$item = $this->sanitizeItemForStoring($asset, $editingAsset);
if (isset($this->item["location"])) {
if (isset($this->item["location_id"])) {
$item['rtd_location_id'] = $this->item['location_id'];
unset($item['location_id']);
}
@@ -87,14 +87,11 @@ class AssetImporter extends ItemImporter
$asset->{$custom_field} = $val;
}
}
if (!$this->testRun) {
if ($asset->save()) {
$asset->logCreate('Imported using csv importer');
$this->log('Asset ' . $this->item["name"] . ' with serial number ' . $this->item['serial'] . ' was created');
return;
}
$this->jsonError($asset, 'Asset "' . $this->item['name'].'"');
if ($asset->save()) {
$asset->logCreate('Imported using csv importer');
$this->log('Asset ' . $this->item["name"] . ' with serial number ' . $this->item['serial'] . ' was created');
return;
}
$this->logError($asset, 'Asset "' . $this->item['name'].'"');
}
}
+4 -15
View File
@@ -7,11 +7,9 @@ use App\Models\Component;
class ComponentImporter extends ItemImporter
{
protected $components;
public function __construct($filename)
{
parent::__construct($filename);
$this->components = Component::all();
}
protected function handle($row)
@@ -31,11 +29,9 @@ class ComponentImporter extends ItemImporter
$component = null;
$editingComponent = false;
$this->log("Creating Component");
$componentId = $this->components->search(function ($key) {
return strcasecmp($key->name, $this->item['name']) == 0;
});
$component = Component::where('name', $this->item['name']);
if ($componentId !== false) {
if ($component) {
$editingComponent = true;
$this->log('A matching Component ' . $this->item["name"] . ' already exists. ');
if (!$this->updating) {
@@ -45,20 +41,13 @@ class ComponentImporter extends ItemImporter
$this->log("Updating Component");
$component = $this->components[$componentId];
$component->update($this->sanitizeItemFor($component));
if (!$this->testRun) {
$component->save();
}
$component->save();
return;
}
$this->log("No matching component, creating one");
$component = new Component;
$component->fill($$this->sanitizeItemForStoring($component));
if ($this->testRun) {
$this->log('TEST RUN - Component ' . $this->item["name"] . ' not created');
return;
}
if ($component->save()) {
$component->logCreate('Imported using CSV Importer');
$this->log("Component " . $this->item["name"] . ' was created');
@@ -75,6 +64,6 @@ class ComponentImporter extends ItemImporter
}
return;
}
$this->jsonError($component, 'Component');
$this->logError($component, 'Component');
}
}
+4 -16
View File
@@ -7,11 +7,9 @@ use App\Models\Consumable;
class ConsumableImporter extends ItemImporter
{
protected $consumables;
public function __construct($filename)
{
parent::__construct($filename);
$this->consumables = Consumable::all();
}
protected function handle($row)
@@ -28,36 +26,26 @@ class ConsumableImporter extends ItemImporter
*/
public function createConsumableIfNotExists()
{
$consumableId = $this->consumables->search(function ($key) {
return strcasecmp($key->name, $this->item['name']) == 0;
});
if ($consumableId !== false) {
$consumable = Consumable::where('name', $this->item['name'])->first();
if ($consumable) {
if (!$this->updating) {
$this->log('A matching Consumable ' . $this->item["name"] . ' already exists. ');
return;
}
$this->log('Updating Consumable');
$consumable = $this->consumables[$consumableId];
$consumable->update($this->sanitizeItemForUpdating($consumable));
if (!$this->testRun) {
$consumable->save();
}
$consumable->save();
return;
}
$this->log("No matching consumable, creating one");
$consumable = new Consumable();
$consumable->fill($this->sanitizeItemForStoring($consumable));
if ($this->testRun) {
$this->log('TEST RUN - Consumable ' . $this->item['name'] . ' not created');
return;
}
if ($consumable->save()) {
$consumable->logCreate('Imported using CSV Importer');
$this->log("Consumable " . $this->item["name"] . ' was created');
return;
}
$this->jsonError($consumable, 'Consumable');
$this->logError($consumable, 'Consumable');
return;
}
}
+134 -77
View File
@@ -1,7 +1,6 @@
<?php
namespace App\Importer;
use App\Models\CustomField;
use App\Models\Setting;
use App\Models\User;
@@ -13,16 +12,7 @@ use League\Csv\Reader;
abstract class Importer
{
/**
* @var string
*/
private $filename;
private $csv;
/**
* Should we persist to database?
* @var bool
*/
protected $testRun;
protected $csv;
/**
* Id of User performing import
* @var
@@ -33,6 +23,47 @@ abstract class Importer
* @var bool
*/
protected $updating;
/**
* Default Map of item fields->csv names
* @var array
*/
private $defaultFieldMap = [
'asset_tag' => 'asset tag',
'category' => 'category',
'company' => 'company',
'item_name' => 'item name',
'image' => 'image',
'expiration_date' => 'expiration date',
'location' => 'location',
'notes' => 'notes',
'license_email' => 'licensed to email',
'license_name' => "licensed to name",
'maintained' => 'maintained',
'manufacturer' => 'manufacturer',
'asset_model' => "model name",
'model_number' => 'model number',
'order_number' => 'order number',
'purchase_cost' => 'purchase cost',
'purchase_date' => 'purchase date',
'purchase_order' => 'purchase order',
'qty' => 'quantity',
'reassignable' => 'reassignable',
'requestable' => 'requestable',
'seats' => 'seats',
'serial_number' => 'serial number',
'status' => 'status',
'supplier' => 'supplier',
'termination_date' => 'termination date',
'warranty_months' => 'warranty',
'name' => 'name',
'email' => 'email',
'username' => 'username'
];
/**
* Map of item fields->csv names
* @var array
*/
protected $fieldMap = [];
/**
* @var callable
*/
@@ -53,13 +84,18 @@ abstract class Importer
/**
* ObjectImporter constructor.
* @param string $filename
* @param string $file
*/
public function __construct(string $filename)
public function __construct($file)
{
$this->filename = $filename;
$this->csv = Reader::createFromPath($filename);
$this->fieldMap = $this->defaultFieldMap;
// By default the importer passes a url to the file.
// However, for testing we also support passing a string directly
if (is_file($file)) {
$this->csv = Reader::createFromPath($file);
} else {
$this->csv = Reader::createFromString($file);
}
$this->csv->setNewLine('\r\n');
if (! ini_get("auto_detect_line_endings")) {
ini_set("auto_detect_line_endings", '1');
@@ -71,14 +107,25 @@ abstract class Importer
public function import()
{
$headerRow = $this->csv->fetchOne();
$results = $this->normalizeInputArray($this->csv->fetchAssoc());
$this->customFields = CustomField::All(['name']);
// Stolen From https://adamwathan.me/2016/07/14/customizing-keys-when-mapping-collections/
// This 'inverts' the fields such that we have a collection of fields indexed by name.
$cFs = CustomField::All();
$this->customFields = $cFs->reduce(function ($nameLookup, $field) {
$nameLookup[$field['name']] = $field;
return $nameLookup;
});
DB::transaction(function () use (&$results) {
Model::unguard();
$resultsCount = sizeof($results);
foreach ($results as $row) {
$this->handle($row);
call_user_func($this->progressCallback, $resultsCount);
if ($this->progressCallback) {
call_user_func($this->progressCallback, $resultsCount);
}
$this->log('------------- Action Summary ----------------');
}
@@ -87,20 +134,6 @@ abstract class Importer
abstract protected function handle($row);
/**
* @param $results
* @return array
*/
public function normalizeInputArray($results): array
{
$newArray = [];
foreach ($results as $index => $arrayToNormalize) {
$newArray[$index] = array_change_key_case($arrayToNormalize);
}
return $newArray;
}
/**
* Check to see if the given key exists in the array, and trim excess white space before returning it
*
@@ -111,17 +144,51 @@ abstract class Importer
* @param $default string
* @return string
*/
public function array_smart_fetch(array $array, $key, $default = '')
public function findCsvMatch(array $array, $key, $default = null)
{
$val = $default;
if (array_key_exists(trim($key), $array)) {
$key = $this->lookupCustomKey($key);
$this->log("Custom Key: ${key}");
if (array_key_exists($key, $array)) {
$val = e(Encoding::toUTF8(trim($array[ $key ])));
}
$key = title_case($key);
// $this->log("${key}: ${val}");
return $val;
}
/**
* Looks up A custom key in the custom field map
*
* @author Daniel Melzter
* @since 4.0
* @param $key string
* @return string|null
*/
public function lookupCustomKey($key)
{
if (array_key_exists($key, $this->fieldMap)) {
$this->log("Found a match in our custom map: {$key} is " . $this->fieldMap[$key]);
return $this->fieldMap[$key];
}
// Otherwise no custom key, return original.
return $key;
}
/**
* @param $results
* @return array
*/
public function normalizeInputArray($results)
{
$newArray = [];
foreach ($results as $index => $arrayToNormalize) {
$newArray[$index] = array_change_key_case($arrayToNormalize);
}
return $newArray;
}
/**
* Figure out the fieldname of the custom field
*
@@ -133,17 +200,21 @@ abstract class Importer
public function array_smart_custom_field_fetch(array $array, $key)
{
$index_name = strtolower($key->name);
return array_key_exists($index_name, $array) ? e(trim($array[$index_name])) : '';
return array_key_exists($index_name, $array) ? e(trim($array[$index_name])) : false;
}
protected function log($string)
{
call_user_func($this->logCallback, $string);
if ($this->logCallback) {
call_user_func($this->logCallback, $string);
}
}
protected function jsonError($item, $field)
protected function logError($item, $field)
{
call_user_func($this->errorCallback, $item, $field, $item->getErrors());
if ($this->errorCallback) {
call_user_func($this->errorCallback, $item, $field, $item->getErrors());
}
}
/**
@@ -160,9 +231,9 @@ abstract class Importer
*/
protected function createOrFetchUser($row)
{
$user_name = $this->array_smart_fetch($row, "name");
$user_email = $this->array_smart_fetch($row, "email");
$user_username = $this->array_smart_fetch($row, "username");
$user_name = $this->findCsvMatch($row, "name");
$user_email = $this->findCsvMatch($row, "email");
$user_username = $this->findCsvMatch($row, "username");
$first_name = '';
$last_name = '';
// A number was given instead of a name
@@ -171,6 +242,7 @@ abstract class Importer
$user_username = '';
// No name was given
} elseif (empty($user_name)) {
$this->log('No user data provided - skipping user creation, just adding asset');
//$user_username = '';
} else {
@@ -193,12 +265,10 @@ abstract class Importer
}
}
}
$user = new User;
if ($this->testRun) {
return $user;
}
if (!empty($user_username)) {
if ($user = User::MatchEmailOrUsername($user_username, $user_email)
->whereNotNull('username')->first()) {
$this->log('User '.$user_username.' already exists');
@@ -214,43 +284,13 @@ abstract class Importer
if ($user->save()) {
$this->log('User '.$first_name.' created');
} else {
$this->jsonError($user, 'User "' . $first_name . '"');
$this->logError($user, 'User "' . $first_name . '"');
}
}
}
return $user;
}
/**
* Sets the value of filename.
*
* @param string $filename the filename
*
* @return self
*/
public function setFilename($filename)
{
$this->filename = $filename;
return $this;
}
/**
* Sets the Should we persist to database?.
*
* @param bool $testRun the test run
*
* @return self
*/
public function setTestRun($testRun)
{
$this->testRun = $testRun;
return $this;
}
/**
* Sets the Id of User performing import.
*
@@ -279,6 +319,23 @@ abstract class Importer
return $this;
}
/**
* Defines mappings of csv fields
*
* @param bool $updating the updating
*
* @return self
*/
public function setFieldMappings($fields)
{
// Some initial sanitization.
$fields = array_map('strtolower', $fields);
$this->fieldMap = array_merge($this->defaultFieldMap, $fields);
// $this->log($this->fieldMap);
return $this;
}
/**
* Sets the callbacks for the import
*
+86 -112
View File
@@ -2,6 +2,7 @@
namespace App\Importer;
use App\Importer\UserImporter;
use App\Models\AssetModel;
use App\Models\Category;
use App\Models\Company;
@@ -9,6 +10,7 @@ use App\Models\Location;
use App\Models\Manufacturer;
use App\Models\Statuslabel;
use App\Models\Supplier;
use App\Models\User;
class ItemImporter extends Importer
{
@@ -20,59 +22,54 @@ class ItemImporter extends Importer
protected function handle($row)
{
// TODO: CHeck if this interferes with checkout to user.. it shouldn't..
$this->item["user_id"] = $this->user_id;
$item_category = $this->array_smart_fetch($row, "category");
$item_company_name = $this->array_smart_fetch($row, "company");
$item_location = $this->array_smart_fetch($row, "location");
$item_manufacturer = $this->array_smart_fetch($row, "manufacturer");
$item_status_name = $this->array_smart_fetch($row, "status");
$item_supplier = $this->array_smart_fetch($row, "supplier");
$this->item["name"] = $this->array_smart_fetch($row, "item name");
$this->item["purchase_date"] = null;
if ($this->array_smart_fetch($row, "purchase date")!='') {
$this->item["purchase_date"] = date("Y-m-d 00:00:01", strtotime($this->array_smart_fetch($row, "purchase date")));
}
$this->item["purchase_cost"] = $this->array_smart_fetch($row, "purchase cost");
$this->item["order_number"] = $this->array_smart_fetch($row, "order number");
$this->item["notes"] = $this->array_smart_fetch($row, "notes");
$this->item["qty"] = $this->array_smart_fetch($row, "quantity");
$this->item["requestable"] = $this->array_smart_fetch($row, "requestable");
$this->item["asset_tag"] = $this->array_smart_fetch($row, "asset tag");
if ($this->item["user"] = $this->createOrFetchUser($row)) {
$this->item['assigned_to'] = $this->item['user']->id;
}
if ($this->shouldUpdateField($item_location)) {
if ($this->item["location"] = $this->createOrFetchLocation($item_location)) {
$this->item["location_id"] = $this->item["location"]->id;
}
}
$item_category = $this->findCsvMatch($row, "category");
if ($this->shouldUpdateField($item_category)) {
if ($this->item["category"] = $this->createOrFetchCategory($item_category)) {
$this->item["category_id"] = $this->item["category"]->id;
}
}
if ($this->shouldUpdateField($item_manufacturer)) {
if ($this->item["manufacturer"] = $this->createOrFetchManufacturer($item_manufacturer)) {
$this->item["manufacturer_id"] = $this->item["manufacturer"]->id;
}
$this->item["category_id"] = $this->createOrFetchCategory($item_category);
}
$item_company_name = $this->findCsvMatch($row, "company");
if ($this->shouldUpdateField($item_company_name)) {
if ($this->item["company"] = $this->createOrFetchCompany($item_company_name)) {
$this->item["company_id"] = $this->item["company"]->id;
}
$this->item["company_id"] = $this->createOrFetchCompany($item_company_name);
}
$item_location = $this->findCsvMatch($row, "location");
if ($this->shouldUpdateField($item_location)) {
$this->item["location_id"] = $this->createOrFetchLocation($item_location);
}
$item_manufacturer = $this->findCsvMatch($row, "manufacturer");
if ($this->shouldUpdateField($item_manufacturer)) {
$this->item["manufacturer_id"] = $this->createOrFetchManufacturer($item_manufacturer);
}
$item_status_name = $this->findCsvMatch($row, "status");
if ($this->shouldUpdateField($item_status_name)) {
if ($this->item["status_label"] = $this->createOrFetchStatusLabel($item_status_name)) {
$this->item["status_label_id"] = $this->item["status_label"]->id;
}
$this->item["status_id"] = $this->createOrFetchStatusLabel($item_status_name);
}
$item_supplier = $this->findCsvMatch($row, "supplier");
if ($this->shouldUpdateField($item_supplier)) {
if ($this->item['supplier'] = $this->createOrFetchSupplier($item_supplier)) {
$this->item['supplier_id'] = $this->item['supplier']->id;
$this->item['supplier_id'] = $this->createOrFetchSupplier($item_supplier);
}
$this->item["name"] = $this->findCsvMatch($row, "item_name");
$this->item["notes"] = $this->findCsvMatch($row, "notes");
$this->item["order_number"] = $this->findCsvMatch($row, "order_number");
$this->item["purchase_cost"] = $this->findCsvMatch($row, "purchase_cost");
$this->item["purchase_date"] = null;
if ($this->findCsvMatch($row, "purchase_date")!='') {
$this->item["purchase_date"] = date("Y-m-d 00:00:01", strtotime($this->findCsvMatch($row, "purchase_date")));
}
$this->item["qty"] = $this->findCsvMatch($row, "quantity");
$this->item["requestable"] = $this->findCsvMatch($row, "requestable");
$this->item["user_id"] = $this->user_id;
$this->item['serial'] = $this->findCsvMatch($row, "serial_number");
// NO need to call this method if we're running the user import.
// TODO: Merge these methods.
if(get_class($this) !== UserImporter::class) {
if ($this->item["user"] = $this->createOrFetchUser($row)) {
$this->item['assigned_to'] = $this->item['user']->id;
$this->item['assigned_type'] = User::class;
}
}
}
@@ -94,7 +91,6 @@ class ItemImporter extends Importer
// Create a collection for all manipulations to come.
$item = collect($this->item);
// First Filter the item down to the model's fillable fields
$item = $item->only($model->getFillable());
// Then iterate through the item and, if we are updating, remove any blank values.
if ($updating) {
@@ -108,8 +104,8 @@ class ItemImporter extends Importer
/**
* Convenience function for updating that strips the empty values.
*
*
* @param $model SnipeModel Model that's being updated.
* @return array
*/
protected function sanitizeItemForUpdating($model)
{
@@ -142,13 +138,14 @@ class ItemImporter extends Importer
* @param array
* @param $category Category
* @param $manufacturer Manufacturer
* @return AssetModel
* @return int Id of asset model created/found
* @internal param $asset_modelno string
*/
public function createOrFetchAssetModel(array $row)
{
$asset_model_name = $this->array_smart_fetch($row, "model name");
$asset_modelNumber = $this->array_smart_fetch($row, "model number");
$asset_model_name = $this->findCsvMatch($row, "asset_model");
$asset_modelNumber = $this->findCsvMatch($row, "model_number");
// TODO: At the moment, this means we can't update the model number if the model name stays the same.
if (!$this->shouldUpdateField($asset_model_name)) {
return;
@@ -162,20 +159,18 @@ class ItemImporter extends Importer
$asset_model = AssetModel::where(['name' => $asset_model_name, 'model_number' => $asset_modelNumber])->first();
if ($asset_model) {
if (!$this->updating) {
$this->log("A matching model already exists, returning it.");
return $asset_model;
return $asset_model->id;
}
$this->log("Matching Model found, updating it.");
$item = $this->sanitizeItemForStoring($asset_model, $editingModel);
$item['name'] = $asset_model_name;
$item['model_number'] = $asset_modelNumber;
$asset_model->update($item);
if (!$this->testRun) {
$asset_model->save();
}
return $asset_model;
$asset_model->save();
$this->log("Asset Model Updated");
return $asset_model->id;
}
$this->log("No Matching Model, Creating a new one");
@@ -185,18 +180,14 @@ class ItemImporter extends Importer
$item['model_number'] = $asset_modelNumber;
$asset_model->fill($item);
if ($this->testRun) {
$this->log('TEST RUN - asset_model ' . $asset_model->name . ' not created');
return $asset_model;
}
$item = null;
if ($asset_model->save()) {
$this->log('Asset Model ' . $asset_model_name . ' with model number ' . $asset_modelNumber . ' was created');
return $asset_model;
return $asset_model->id;
}
$this->jsonError($asset_model, 'Asset Model "' . $asset_model_name . '"');
return;
$this->logError($asset_model, 'Asset Model "' . $asset_model_name . '"');
return null;
}
/**
@@ -205,7 +196,7 @@ class ItemImporter extends Importer
* @author Daniel Melzter
* @since 3.0
* @param $asset_category string
* @return Category
* @return int Id of category created/found
* @internal param string $item_type
*/
public function createOrFetchCategory($asset_category)
@@ -213,6 +204,7 @@ class ItemImporter extends Importer
// Magic to transform "AssetImporter" to "asset" or similar.
$classname = class_basename(get_class($this));
$item_type = strtolower(substr($classname, 0, strpos($classname, 'Importer')));
if (empty($asset_category)) {
$asset_category = 'Unnamed Category';
}
@@ -220,7 +212,7 @@ class ItemImporter extends Importer
if ($category) {
$this->log("A matching category: " . $asset_category . " already exists");
return $category;
return $category->id;
}
$category = new Category();
@@ -228,15 +220,13 @@ class ItemImporter extends Importer
$category->category_type = $item_type;
$category->user_id = $this->user_id;
if ($this->testRun) {
return $category;
}
if ($category->save()) {
$this->log('Category ' . $asset_category . ' was created');
return $category;
return $category->id;
}
$this->jsonError($category, 'Category "'. $asset_category. '"');
$this->logError($category, 'Category "'. $asset_category. '"');
return null;
}
/**
@@ -245,28 +235,24 @@ class ItemImporter extends Importer
* @author Daniel Melzter
* @since 3.0
* @param $asset_company_name string
* @return Company
* @return int id of company created/found
*/
public function createOrFetchCompany($asset_company_name)
{
$company = Company::where(['name' => $asset_company_name])->first();
if ($company) {
$this->log('A matching Company ' . $asset_company_name . ' already exists');
return $company;
return $company->id;
}
$company = new Company();
$company->name = $asset_company_name;
if ($this->testRun) {
return $company;
}
if ($company->save()) {
$this->log('Company ' . $asset_company_name . ' was created');
return $company;
return $company->id;
}
$this->jsonError($company, 'Company');
return;
$this->logError($company, 'Company');
return null;
}
/**
@@ -279,6 +265,7 @@ class ItemImporter extends Importer
*/
public function createOrFetchStatusLabel($asset_statuslabel_name)
{
if (empty($asset_statuslabel_name)) {
return null;
}
@@ -286,7 +273,7 @@ class ItemImporter extends Importer
if ($status) {
$this->log('A matching Status ' . $asset_statuslabel_name . ' already exists');
return $status;
return $status->id;
}
$this->log("Creating a new status");
$status = new Statuslabel();
@@ -296,17 +283,13 @@ class ItemImporter extends Importer
$status->pending = 0;
$status->archived = 0;
if ($this->testRun) {
return $status;
}
if ($status->save()) {
$this->log('Status ' . $asset_statuslabel_name . ' was created');
return $status;
return $status->id;
}
$this->jsonError($status, 'Status "'. $asset_statuslabel_name . '"');
return;
$this->logError($status, 'Status "'. $asset_statuslabel_name . '"');
return null;
}
/**
@@ -328,7 +311,7 @@ class ItemImporter extends Importer
if ($manufacturer) {
$this->log('Manufacturer ' . $item_manufacturer . ' already exists') ;
return $manufacturer;
return $manufacturer->id;
}
//Otherwise create a manufacturer.
@@ -336,15 +319,12 @@ class ItemImporter extends Importer
$manufacturer->name = $item_manufacturer;
$manufacturer->user_id = $this->user_id;
if ($this->testRun) {
return $manufacturer;
}
if ($manufacturer->save()) {
$this->log('Manufacturer ' . $manufacturer->name . ' was created');
return $manufacturer;
return $manufacturer->id;
}
$this->jsonError($manufacturer, 'Manufacturer "'. $manufacturer->name . '"');
return;
$this->logError($manufacturer, 'Manufacturer "'. $manufacturer->name . '"');
return null;
}
/**
@@ -363,9 +343,9 @@ class ItemImporter extends Importer
}
$location = Location::where(['name' => $asset_location])->first();
if ($location !== false) {
if ($location) {
$this->log('Location ' . $asset_location . ' already exists');
return $location;
return $location->id;
}
// No matching locations in the collection, create a new one.
$location = new Location();
@@ -376,15 +356,12 @@ class ItemImporter extends Importer
$location->country = '';
$location->user_id = $this->user_id;
if ($this->testRun) {
return $location;
}
if ($location->save()) {
$this->log('Location ' . $asset_location . ' was created');
return $location;
return $location->id;
}
$this->jsonError($location, 'Location');
return;
$this->logError($location, 'Location');
return null;
}
/**
@@ -405,21 +382,18 @@ class ItemImporter extends Importer
if ($supplier) {
$this->log('Supplier ' . $item_supplier . ' already exists');
return $supplier;
return $supplier->id;
}
$supplier = new Supplier();
$supplier->name = $item_supplier;
$supplier->user_id = $this->user_id;
if ($this->testRun) {
return $supplier;
}
if ($supplier->save()) {
$this->log('Supplier ' . $item_supplier . ' was created');
return $supplier;
return $supplier->id;
}
$this->jsonError($supplier, 'Supplier');
return;
$this->logError($supplier, 'Supplier');
return null;
}
}
+29 -42
View File
@@ -10,18 +10,15 @@ use App\Models\Manufacturer;
class LicenseImporter extends ItemImporter
{
protected $licenses;
public function __construct($filename)
{
parent::__construct($filename);
$this->licenses = License::all();
}
protected function handle($row)
{
// ItemImporter handles the general fetching.
parent::handle($row);
$this->createLicenseIfNotExists($row);
}
@@ -36,11 +33,8 @@ class LicenseImporter extends ItemImporter
public function createLicenseIfNotExists(array $row)
{
$editingLicense = false;
$license = new License;
$license_id = $this->licenses->search(function ($key) {
return strcasecmp($key->name, $this->item['name']) == 0;
});
if ($license_id !== false) {
$license = License::where('name', $this->item['name'])->first();
if ($license) {
if (!$this->updating) {
$this->log('A matching License ' . $this->item['name'] . ' already exists');
return;
@@ -48,54 +42,47 @@ class LicenseImporter extends ItemImporter
$this->log("Updating License");
$editingLicense = true;
$license = $this->licenses[$license_id];
} else {
$this->log("No Matching License, Creating a new one");
$license = new License;
}
$asset_tag = $this->item['asset_tag'] = $this->array_smart_fetch($row, 'asset_tag'); // used for checkout out to an asset.
$this->item['expiration_date'] = $this->array_smart_fetch($row, 'expiration date');
$this->item['license_email'] = $this->array_smart_fetch($row, "licensed to email");
$this->item['license_name'] = $this->array_smart_fetch($row, "licensed to name");
$this->item['maintained'] = $this->array_smart_fetch($row, 'maintained');
$this->item['purchase_order'] = $this->array_smart_fetch($row, 'purchase_order');
$this->item['reassignable'] = $this->array_smart_fetch($row, 'reassignable');
$this->item['serial'] = $this->array_smart_fetch($row, "serial number");
$this->item['termination_date'] = $this->array_smart_fetch($row, 'termination_date');
$this->item['seats'] = $this->array_smart_fetch($row, 'seats');
$asset_tag = $this->item['asset_tag'] = $this->findCsvMatch($row, 'asset_tag'); // used for checkout out to an asset.
$this->item['expiration_date'] = $this->findCsvMatch($row, 'expiration_date');
$this->item['license_email'] = $this->findCsvMatch($row, "license_email");
$this->item['license_name'] = $this->findCsvMatch($row, "license_name");
$this->item['maintained'] = $this->findCsvMatch($row, 'maintained');
$this->item['purchase_order'] = $this->findCsvMatch($row, 'purchase_order');
$this->item['reassignable'] = $this->findCsvMatch($row, 'reassignable');
$this->item['seats'] = $this->findCsvMatch($row, 'seats');
$this->item['termination_date'] = $this->findCsvMatch($row, 'termination_date');
if ($editingLicense) {
$license->update($this->sanitizeItemForUpdating($license));
} else {
$license->fill($this->sanitizeItemForStoring($license));
}
if (!$editingLicense) {
$this->licenses->add($license);
}
if (!$this->testRun) {
if ($license->save()) {
$license->logCreate('Imported using csv importer');
$this->log('License ' . $this->item["name"] . ' with serial number ' . $this->item['serial'] . ' was created');
if ($license->save()) {
$license->logCreate('Imported using csv importer');
$this->log('License ' . $this->item["name"] . ' with serial number ' . $this->item['serial'] . ' was created');
// Lets try to checkout seats if the fields exist and we have seats.
if ($license->seats > 0) {
$user = $this->item['user'];
$asset = Asset::where('asset_tag', $asset_tag)->first();
$targetLicense = $license->licenseSeats()->first();
if ($user) {
$targetLicense->assigned_to = $user->id;
if ($asset) {
$targetLicense->asset_id = $asset->id;
}
$targetLicense->save();
} elseif ($asset) {
// Lets try to checkout seats if the fields exist and we have seats.
if ($license->seats > 0) {
$user = $this->item['user'];
$asset = Asset::where('asset_tag', $asset_tag)->first();
$targetLicense = $license->licenseSeats()->first();
if ($user) {
$targetLicense->assigned_to = $user->id;
if ($asset) {
$targetLicense->asset_id = $asset->id;
$targetLicense->save();
}
$targetLicense->save();
} elseif ($asset) {
$targetLicense->asset_id = $asset->id;
$targetLicense->save();
}
return;
}
$this->jsonError($license, 'License "' . $this->item['name'].'"');
return;
}
$this->logError($license, 'License "' . $this->item['name'].'"');
}
}
+67
View File
@@ -0,0 +1,67 @@
<?php
namespace App\Importer;
use App\Helpers\Helper;
use App\Models\User;
class UserImporter extends ItemImporter
{
protected $users;
public function __construct($filename)
{
parent::__construct($filename);
// $this->users = User::all();
}
protected function handle($row)
{
parent::handle($row);
$this->createUserIfNotExists($row);
}
/**
* Create a user if a duplicate does not exist.
* @todo Investigate how this should interact with Importer::createOrFetchUser
*
* @author Daniel Melzter
* @since 4.0
*/
public function createUserIfNotExists(array $row)
{
// User Specific Bits
$this->item['username'] = $this->findCsvMatch($row, 'username');
$this->item['first_name'] = $this->findCsvMatch($row, 'first_name');
$this->item['last_name'] = $this->findCsvMatch($row, 'last_name');
$this->item['email'] = $this->findCsvMatch($row, 'user_email');
$this->item['phone'] = $this->findCsvMatch($row, 'phone_number');
$this->item['jobtitle'] = $this->findCsvMatch($row, 'jobtitle');
$this->item['employee_num'] = $this->findCsvMatch($row, 'employee_num');
$this->item['password'] = $this->tempPassword;
$user = User::where('username', $this->item['username'])->first();
if ($user) {
if (!$this->updating) {
$this->log('A matching User ' . $this->item["name"] . ' already exists. ');
return;
}
$this->log('Updating User');
// $user = $this->users[$userId];
$user->update($this->sanitizeItemForUpdating($user));
$user->save();
return;
}
$this->log("No matching user, creating one");
$user = new User();
$user->fill($this->sanitizeItemForStoring($user));
if ($user->save()) {
// $user->logCreate('Imported using CSV Importer');
$this->log("User " . $this->item["name"] . ' was created');
$user = null;
$this->item = null;
return;
}
$this->logError($user, 'User');
return;
}
}
+33
View File
@@ -0,0 +1,33 @@
| CSV | Item | Applicable Types |
|---------------------|------------------|-------------------------------------------|
| asset tag | asset_tag | Asset |
| category | category | All |
| company | company | All |
| item name | item_name | All |
| image | image | asset |
| expiration date | expiration_date | License |
| location | location | All |
| notes | notes | All |
| licensed to email | license_email | License |
| licensed to name | license_name | License |
| maintained | maintained | License |
| manufacturer | manufacturer | All |
| model name | asset_model | Asset |
| model number | model_number | Asset |
| order number | order_number | All ? |
| purchase cost | purchase_cost | All ? |
| purchase date | purchase_date | All ? |
| purchase order | purchase_order | License |
| quantity | qty | Accessory, Consumable, Component, License |
| reassignable | reassignable | License |
| requestable | requestable | Asset, Accessory? |
| seats | seats | License |
| serial number | serial | asset, license |
| status | status | asset ? All |
| supplier | supplier | Asset ? All |
| termination date | termination_date | License |
| warranty months | warranty_months | asset |
| User Related Fields | assigned_to | Asset |
| name | | |
| email | | |
| username | | |
+81
View File
@@ -0,0 +1,81 @@
<?php
namespace App\LegacyEncrypter;
use Illuminate\Contracts\Encryption\DecryptException;
abstract class BaseEncrypter
{
/**
* The encryption key.
*
* @var string
*/
protected $key;
/**
* Create a MAC for the given value.
*
* @param string $iv
* @param string $value
* @return string
*/
protected function hash($iv, $value)
{
return hash_hmac('sha256', $iv.$value, $this->key);
}
/**
* Get the JSON array from the given payload.
*
* @param string $payload
* @return array
*
* @throws \Illuminate\Contracts\Encryption\DecryptException
*/
protected function getJsonPayload($payload)
{
$payload = json_decode(base64_decode($payload), true);
// If the payload is not valid JSON or does not have the proper keys set we will
// assume it is invalid and bail out of the routine since we will not be able
// to decrypt the given value. We'll also check the MAC for this encryption.
if (! $payload || $this->invalidPayload($payload)) {
throw new DecryptException('The payload is invalid.');
}
if (! $this->validMac($payload)) {
throw new DecryptException('The MAC is invalid.');
}
return $payload;
}
/**
* Verify that the encryption payload is valid.
*
* @param array|mixed $data
* @return bool
*/
protected function invalidPayload($data)
{
return ! is_array($data) || ! isset($data['iv']) || ! isset($data['value']) || ! isset($data['mac']);
}
/**
* Determine if the MAC for the given payload is valid.
*
* @param array $payload
* @return bool
*
* @throws \RuntimeException
*/
protected function validMac(array $payload)
{
$bytes = random_bytes(16);
$calcMac = hash_hmac('sha256', $this->hash($payload['iv'], $payload['value']), $bytes, true);
return hash_equals(hash_hmac('sha256', $payload['mac'], $bytes, true), $calcMac);
}
}

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