Compare commits

..

431 Commits

Author SHA1 Message Date
snipe
af97d8ed24 Bumped version 2016-10-31 21:05:07 -07:00
snipe
a914dacf8e Adds drawn signature to asset acceptance (#2846)
* Adds digital signature to asset acceptance

This is still a little broken - the history is displaying “Deleted user”, since there is no item type listed. Saving the item_type as App\Models\User tries to update accepted on the users table, which obviously doesn’t exist.

* Use asset facade for folks in subdirs

* Possible fix for weird accepted/declined display

* Display signature in modal popup if sigs are required

* Wrap that display file in auth middleware, just to be sure.

It shoudl fail if you’re not authorized since you’re not logged in, but better safe than sorry

* Fixed header section of layout

* Removed extra drop from migration rollback
2016-10-31 21:00:30 -07:00
snipe
a182d8c924 Fixes #1348 - LDAP sync in artisan command
TODO:

Make the LDAP sync page work using this command to avoid code duplication
2016-10-31 20:59:46 -07:00
snipe
6400557901 Check if the edited users permissioms are superuser before edit 2016-10-31 19:37:24 -07:00
snipe
26d14b2338 Let superadmins edit their own groups 2016-10-31 19:18:06 -07:00
snipe
3dac20c20f Unset superadmin by non-superadmins on user create 2016-10-31 19:08:24 -07:00
snipe
429afc6b3f Only save user permissions if the user is a superadmin 2016-10-31 19:07:55 -07:00
snipe
8323ed27c2 Do not makes group editable if the user is not an admin
This fixes a bug where the field was (correctly) disabled if the editing user isn’t a superadmin, but because the field was disabled, it would clear the permission groups.
2016-10-31 18:57:35 -07:00
snipe
c47d391946 Feature - allow search on group names 2016-10-31 18:27:34 -07:00
snipe
25bd1acab5 Fixes permission for non-superadmin assigning user permissions 2016-10-31 18:19:55 -07:00
snipe
7c6bdcb6b2 Fix width of warning message 2016-10-31 18:15:00 -07:00
snipe
13450aa961 Include asset status type in asset detail view 2016-10-31 17:44:39 -07:00
snipe
0595867500 Fixes #2856 - add status to asset detail view
(Not sure how we missed this… oops)
2016-10-31 17:41:15 -07:00
snipe
a4ae3b0091 Show whether device is enabled and/or 2FA is active 2016-10-31 17:16:26 -07:00
snipe
cbfcf959f9 Allow certain users to override 2FA with permission 2016-10-31 16:52:25 -07:00
snipe
e065d18227 Possible fix for integer weird typing 2016-10-31 13:50:00 -07:00
snipe
adc3ebee41 Merge branch 'develop' of github.com:snipe/snipe-it into develop 2016-10-31 13:25:54 -07:00
snipe
41defb312b Moved CSRF token 2016-10-31 13:25:50 -07:00
Frank
10ea5daabd Harden PragmaRX secret to 32 bytes (#2859)
This is needed at all but that extra security is always good.
2016-10-31 11:20:31 -07:00
itsupportcmsukorg
140bac2b53 Fix missing 'filename' field in asset_log to action_log migration (#2854)
Merging this anyway, to stop the bleeding for new upgraders.
2016-10-31 11:18:48 -07:00
snipe
dce5afde78 Use config URL for links in user list 2016-10-29 07:33:33 -07:00
snipe
38b188f6ff Fixes #2448 - redirect to intended page 2016-10-29 07:32:48 -07:00
snipe
fe041b66c6 Adds two-factor to users listing 2016-10-29 07:21:34 -07:00
snipe
32c439d979 Tidy up login form 2016-10-29 06:45:24 -07:00
snipe
2fe71f3ebc Fixes #2833 - changed minimum qty to 0 2016-10-29 06:08:13 -07:00
snipe
9b714a5af5 Updated Github issue template with correct doc URL 2016-10-29 06:06:49 -07:00
snipe
408aab112b Removed unneeded else 2016-10-29 06:06:32 -07:00
snipe
2f6fcadd05 Fixes #2838 - removed duplicate requestabe field in asset models 2016-10-29 05:53:50 -07:00
snipe
cea255995c Fixes #106 - adds Google Authenticator support (#2842)
* refactor to clean up LDAP login, and make the login method easier to handle.

* Login refactor cleanup

* Google 2FA package

* Adds Google Authenticator two-factor

* Removed unused blade

* Added optin setting in profile

* Removed dumb comments

* Made lock_passwords check more consistent

* Additional two factor strings

* Lock passwords check

* Display feature disabled text if in demo mode

* Two factor admin reset options

* Translation strings
2016-10-29 05:50:55 -07:00
Daniel Meltzer
3a8edfdf58 Eager load many more things. Fixes a lot of n+1 queries in ajax/bootstrap tables requests (#2832) 2016-10-28 14:15:13 -07:00
snipe
86ef44b43d Bumped version 2016-10-27 22:17:30 -07:00
snipe
5a835a5b6e Removed old test DB schema dump 2016-10-27 21:41:27 -07:00
snipe
066d947f1a Fixes #2535 - increased varachar limit to 2048 for serial 2016-10-27 21:39:46 -07:00
snipe
a929b635ff Fixes #2809 - adds serial number to components 2016-10-27 15:33:48 -07:00
snipe
9c3c611b37 Fixes #2825 - columns misaligned when older display_asset_name field set to 1 2016-10-27 15:02:32 -07:00
snipe
3e701c6dd1 Fixes #2814 - adds job title to users listing display 2016-10-27 14:29:07 -07:00
snipe
e4140f4c48 Fixes #2817 - adds EOL to custom report 2016-10-27 14:20:55 -07:00
snipe
691f9b621e Fixes #2821 2016-10-26 11:27:37 -07:00
snipe
ccb844acd6 Fixed #2800 - use DBTablePrefix() for raw queries 2016-10-26 11:21:36 -07:00
snipe
43404e427d Bumped version 2016-10-26 10:31:13 -07:00
snipe
d7222ae1f0 Fix for defaultLoc in asset view 2016-10-26 10:12:16 -07:00
Daniel Meltzer
a418dece80 Better checking for empty values when updating. (#2811)
* Better checking for empty values when updating.  There's a lot of conditionals in here that we may want to look at cleaning up over time

* Fix typo.  No manfacturers here.

* Fix model update/import.  Also hardcode the status id of unset assets to the first existing one instead of an id that may not exist... Still not ideal, but better.

* Let requests to .env through the middleware.  We check to see if this is readable during setup as a warning, and as it stands it triggers an infinite loop trying to hit the file.
2016-10-25 19:51:13 -07:00
snipe
f30631efb6 Fixed parens on target 2016-10-25 12:53:07 -07:00
snipe
f156ec58b6 Bumped version 2016-10-25 12:38:18 -07:00
snipe
f9a06a183e Updated language strings 2016-10-25 12:30:52 -07:00
snipe
da0b6d4d90 Merge branch 'hotfixes/fix_typo_in_permissions_for_accessories_create' into develop 2016-10-25 11:40:34 -07:00
snipe
40befa7b37 Fixes #2792 - corrected typo in permissions array for creating accessories 2016-10-25 11:38:24 -07:00
snipe
66585bcc40 Merge branch 'hotfixes/eagerload_license_checkout' into develop 2016-10-25 11:12:32 -07:00
snipe
d57135c81b Removed unused helper methods, added docblocks 2016-10-25 11:11:47 -07:00
snipe
f976f440ef Fixes #2808 - eager loading user objects for licenses 2016-10-25 10:52:37 -07:00
snipe
0728a991a8 Merge branch 'hotfixes/datepicker_for_date_custom_field' into develop
# Conflicts:
#	resources/views/models/custom_fields_form.blade.php
2016-10-25 05:18:55 -07:00
snipe
33a0c2087a Use datepicker if custom field format is a date 2016-10-25 05:16:41 -07:00
snipe
59ce46dce7 Merge branch 'hotfixes/use_modelno_if_no_name_in_import' into develop 2016-10-25 03:53:45 -07:00
snipe
2dbd1089f5 Use model number if model name is blank 2016-10-25 03:53:19 -07:00
snipe
85f3cc1762 Merge branch 'hotfixes/add_username_to_csv_export' into develop 2016-10-25 02:51:27 -07:00
snipe
1793461642 Added username, fixed duplicate company name 2016-10-25 02:50:23 -07:00
snipe
d24c4b1152 Merge branch 'hotfixes/export_all_users' into develop 2016-10-25 02:42:20 -07:00
snipe
30f0f6f527 Export users to CSV
Bypasses the weird limit bug in the javascript
2016-10-25 02:41:34 -07:00
snipe
b839741069 Merge branch 'hotfixes/order_number_numeric' into develop 2016-10-19 15:03:05 -07:00
snipe
d7434797ec Change order number to string in components table 2016-10-19 14:59:28 -07:00
Daniel Meltzer
85af8e46e3 Set a user_id of -1 if there isn't a logged in user. This fixes the CLI importer, and opens the door in the future for some sort of virtual importer user... which may fix other issues the importer currently has (#2775) 2016-10-17 11:07:08 -07:00
snipe
0a0006c68c Fixes #2774 - change order_number to string in components and consumables 2016-10-14 13:12:17 -07:00
Daniel Meltzer
e85241af6a Log checkouts (#2772)
* Ensure the log has a target before trying to fetch the associated company

* Log creation of items, both in importer and manually
2016-10-12 18:45:32 -07:00
snipe
219ef23126 Fixes #2713 - error displayed with license checked out to asset 2016-10-12 14:32:21 -07:00
snipe
31898d0f85 Fixes #2751 - asset tag added to asset maintenance report 2016-10-12 14:18:51 -07:00
snipe
1e82058f4d Fixes #2763 - added missing translations methods for dashboard 2016-10-12 13:01:29 -07:00
snipe
b3329135df Merge branch 'develop' of github.com:snipe/snipe-it into develop 2016-10-12 12:50:35 -07:00
snipe
2350c1c15c Fixes #2352 2016-10-12 12:50:30 -07:00
snipe
8f4e016c01 Fixes #2768 and #2753 2016-10-12 12:48:37 -07:00
Daniel Meltzer
8e60767c00 Guard against null values in the reports generator. May fix #2758 (#2762) 2016-10-12 12:06:38 -07:00
Daniel Meltzer
2e0a7abbe9 Rework permissions view (#2756)
* Early layout work on a cleaner permissions interface

* Cleanup layout.  Make new permissions view work.  Still needs some css and javascript improvements.  Also need to do the same thing to the group view.

* Improve styling, add javascript to toggle an entire group of permissions if choosing the permission on the header row.  Would be nice to add collapsing of sections in the future.

* Toggle viewing sections.

* Special case places where we only have one item in a group to only display the item once.

* Filter getCreate the same way.
2016-10-12 12:06:28 -07:00
Matthias Frei
4b6ba6cb30 BugFix: Asset name was not included in custom report (#2733)
* BugFix: Asset name was not included in custom report

* BugFix: Custom Asset Report did not escape commas in custom fields. So the csv file is inconsistent, if a custom field containes a comma.  Added an escape function which escapes the commas with a backslash.
A csvreader can be configured to handle the escape character.
2016-10-12 12:05:49 -07:00
snipe
fe5e813970 Updated translations 2016-10-04 12:23:02 -07:00
snipe
d6f7e03431 Bumped version for pre-release 2016-10-04 11:58:19 -07:00
snipe
87f50dfd10 Merge branch 'develop' of github.com:snipe/snipe-it into develop 2016-09-29 22:37:59 -07:00
snipe
85ddb9cfff Bumped version 2016-09-29 22:37:54 -07:00
Michael T
c6338d6a8b Apologies. Still learning Git, and CentOS isn't a big strength for me. (#2701)
This should properly include #2674
Cleaned up the script itself, added progress bars so end users don't think the script is stuck
2016-09-29 22:37:05 -07:00
Daniel Meltzer
b92d26f3c4 When checking out a consumable, don't say asset (#2718) 2016-09-29 22:20:58 -07:00
Daniel Meltzer
2a95a95e00 Company to logs (#2717)
* Fix the actionlog/companyables problem by adding a company_id to all actionlogs and scoping directly on that.  Works around bugs in laravel where trying to hunt down the polymorphic relationship would lead to an infinite loop

* Scope companyables in getactivityreport.  Also eager load.

* Improve reportscontroller, work on seeder to test this.

* Only show company users in checkout dialogs

* If no admin associated with log, it might be a request.  Leave blank instead of saying deleted admin

* When injecting company_id, use target instead of user if user is a superadmin

* Build up the seeder to generate users, companies, and logs.

* Eager load the log, don't scope the users log because the log should already include things only related to the user.
2016-09-29 22:20:49 -07:00
snipe
b41883c125 Use user object to prevent errors on deleted users 2016-09-29 11:37:38 -07:00
snipe
0a218a37d0 Check that the user exists before trying to get location id 2016-09-29 10:32:09 -07:00
Brady Wetherington
7ca7877740 Fix mismerged code. (#2705) 2016-09-28 22:57:19 -07:00
snipe
1394424760 Merge branch 'hotfixes/customfields_in_asset_report' into develop
# Conflicts:
#	resources/views/models/custom_fields_form.blade.php
2016-09-28 19:28:55 -07:00
snipe
fc07753a5c Use $customfields in closure 2016-09-28 19:18:01 -07:00
snipe
7bbe85801e Fixed typo :( 2016-09-28 15:45:05 -07:00
snipe
8774927b91 PHPStorm lag = fail 2016-09-28 15:40:51 -07:00
snipe
8cb4954f8a Apply encrypted fields patch from develop 2016-09-28 14:58:01 -07:00
snipe
48b52a0ccc Merge branch 'hotfixes/p-typo' into develop 2016-09-28 08:59:07 -07:00
snipe
9ecb0e6ca1 Fixed errant typo 2016-09-28 08:58:16 -07:00
snipe
9091385182 Merge branch 'hotfixes/purchase_cost' into develop
# Conflicts:
#	app/Http/Controllers/ReportsController.php
#	config/version.php
2016-09-27 19:13:21 -07:00
snipe
b90c0de822 Fix companyable reult in maintenances 2016-09-27 19:07:45 -07:00
snipe
ee2522571c Fixes #2673 2016-09-27 19:07:30 -07:00
snipe
d3a13bcd45 Functional config for laravel 5 2016-09-27 18:47:00 -07:00
snipe
67f199b09d Added customfields to asset CSV export 2016-09-27 15:09:47 -07:00
snipe
f1c458185d Client-side pagination on asset report for faster loading 2016-09-27 14:56:05 -07:00
snipe
ed22ec4b36 Bumped hash 2016-09-27 08:42:55 -07:00
snipe
fa72e64b98 Add checkout date to asset report 2016-09-27 08:42:48 -07:00
snipe
2a8ab06ca3 Remove escaping for CSV to prevent weird encoding 2016-09-27 07:25:28 -07:00
snipe
61d07bdc7c Sigh. 2016-09-27 07:24:26 -07:00
snipe
3061ce2983 Missed delimiter for CSV 2016-09-27 07:23:30 -07:00
snipe
e9f3d622f5 Add company name to custom asset report 2016-09-27 07:19:52 -07:00
snipe
1e3244b2b3 Merge branch 'hotfixes/eol' into develop
# Conflicts:
#	app/Http/Controllers/AssetModelsController.php
2016-09-27 07:04:45 -07:00
snipe
a92bfe8ade Default EOL to null, not 0, if no value entered 2016-09-27 06:53:59 -07:00
snipe
c42dfadd17 Merge branch 'hotfixes/purchase_order' into develop
# Conflicts:
#	app/Http/Controllers/LicensesController.php
2016-09-27 01:31:02 -07:00
snipe
0a391de09f Fixes #2682 - search on purchase_order 2016-09-27 01:29:31 -07:00
snipe
b6cc7e7c14 Fixes bug where 12-hour fprmat for hours was used 2016-09-26 22:35:51 -07:00
snipe
819ca2921b Fixes bug where 12-hour format was used for hours 2016-09-26 22:34:09 -07:00
Joris van Eijden
7d272e3c96 Fix pre-flight port number check. (#2681) 2016-09-26 18:23:56 -07:00
Andrés Núñez
40f00665b3 Translate emails (#2652)
* commit temporal

* final translation commit -- added email translations

* final translation commit -- removed file for spanish translations

* final translation commit -- removed file for spanish translations

* added missing translations

* method overrided and config files back to default

* config files back to default

* config files back to default
2016-09-26 14:13:07 -07:00
tiagom62
03ee6b8f91 SELinux and iptables update for installer (#2674)
* detect SELinux

detect SELinux is enforcing and set required security policies for
CentOS 7

* Centos 6 iptables

allow http/https if iptables is running
2016-09-26 14:11:43 -07:00
snipe
937192f7ce Ugh… git… why? 2016-09-23 14:13:41 -07:00
snipe
ce1f62b9be Merge branch 'hotfixes/2672' into develop
# Conflicts:
#	app/Http/Controllers/ReportsController.php
2016-09-23 14:12:52 -07:00
snipe
3208522dd1 Fixes #2672 - model_no field updated to be string 2016-09-23 14:10:08 -07:00
snipe
c3cd329604 Merge branch 'develop' of github.com:snipe/snipe-it into develop 2016-09-23 13:14:18 -07:00
snipe
2ba4986396 Updated history importer message 2016-09-23 13:14:11 -07:00
snipe
8ba19632cf Removed new badge 2016-09-23 13:13:42 -07:00
Michael T
caf6a10227 grr.. Fixed git commit message stuck in file. (#2659) 2016-09-21 15:27:09 -07:00
Eammon Hanlon
580091269d mkdir not recursive (#2460)
* Fix path to snipeit-ssl.crt (#2428)

* Modified 'recursive' part of the tuple to true
2016-09-21 12:05:06 -07:00
Michael T
bcc6ca5180 Deb/Ubu pro bar & Ubu 16 php-xml pkg (#2644) 2016-09-20 13:26:53 -07:00
snipe
7fdd4fbe98 Updates to the history importer to make it a little less brittle and provide better feedback 2016-09-20 09:22:49 -07:00
snipe
aecef2618f Add reply-to for mail 2016-09-20 07:20:40 -07:00
snipe
bd5e6d8551 Add reply-to config setting 2016-09-20 07:20:10 -07:00
snipe
1e4e9dd3d7 Updated language files 2016-09-20 05:08:04 -07:00
snipe
2ab91fed01 Fixes #2607 - non-encrypted now visible to non-admins with asset access 2016-09-20 03:48:38 -07:00
snipe
5b0220ac1e Fixed typo 2016-09-20 03:01:04 -07:00
snipe
aa92b93bd1 Fixes #2622 - add depreciation to license report 2016-09-20 02:58:08 -07:00
snipe
998624ad68 Bumped version for v3.5-beta 2016-09-20 00:50:35 -07:00
snipe
d3d36315d3 Hotfixes adding company name to custom report 2016-09-20 00:49:08 -07:00
snipe
6dc143d95d Use Ajax activity report for dashboard to prevent data duplication 2016-09-20 00:46:46 -07:00
snipe
d8753a7d86 Use Ajax for activity report 2016-09-20 00:46:24 -07:00
snipe
90af734f6b Fix migration from integer to string to handle polymorphic migration 2016-09-20 00:46:14 -07:00
snipe
3aa7c60765 Costometic cleanup 2016-09-20 00:45:25 -07:00
snipe
0962d770cf Ajax activity report 2016-09-20 00:45:16 -07:00
snipe
5d8c06bc30 Eager loading for custom report 2016-09-19 23:52:20 -07:00
snipe
2597a7b896 Added Ajax reporting view 2016-09-19 23:52:01 -07:00
snipe
3741a93884 Added docblocks and cleaned up spacing 2016-09-19 23:51:45 -07:00
snipe
71be73781b Add company name option to reports 2016-09-19 22:27:34 -07:00
Daniel Meltzer
7aea9341f8 Have the installer install php-xml in ubuntu 16.04, it's where the utf8_decode function is located (#2638) 2016-09-19 17:28:07 -07:00
tiagom62
e5098c3ba1 missing semicolon (#2629)
Rookie mistake. Fixes missing semicolon in previous pr #2624.
2016-09-17 11:39:24 -07:00
tiagom62
46507c929a Sort backups newest to oldest (#2624)
Viewing the backup list produces a seemingly random list.

This PR sorts the files newest to oldest.
2016-09-17 00:00:39 -07:00
tiagom62
8233d520c6 Missing file formats (#2621)
Missing allowed file formats zip and rar.

Added rtf format pending PR 2614.
2016-09-16 16:18:33 -07:00
tiagom62
06f174adf9 Allow uploading rtf files (#2620)
Microsoft Open License Order Confirmation's are sent in RTF format. 

This change allows us to upload the RTF files under View License -> File Uploads.
2016-09-16 16:18:24 -07:00
tiagom62
08f320b76a DB_DUMP_PATH not set when using install.sh (#2623)
Backup errors out when DB_DUMP_PATH is not set. According to https://snipe-it.readme.io/docs/configuration#required-database-settings this is usually '/usr/bin'
2016-09-16 16:17:04 -07:00
snipe
04898c49b2 Fixed wrong translation from PR 2016-09-15 20:03:47 -07:00
Karol
eeff305b02 Update dashboard.blade.php (#2593) 2016-09-15 19:59:01 -07:00
Daniel Meltzer
2d8269ddcd Checkout Improvements, and initial support for requesting an asset model (#2573)
* Create a new action_log table to replace asset_log.  Use Polymorphism to generalize class and targets.  Port everything I can find to use it.  Add a migration to port the asset_logs table to action_logs.

* Initial work on requestable asset models

* Backend work for polymorphic requests table to store checkout requests.

* Add missing files

* Add a record to the db when requesting items.  Build up a testing route for interfacing with this.

* Users can now toggle requests of items on the request page.  Reformat page to use the same tab layout we use elsewhere

* Polymorphic request function.  Implement requesting of asset models.  Need to port mail/slack to notifications still.

* Implement requesting of asset models.  Build up emails and notifications to support it.  Allow specifying a quantity of model to request.

* Add view to show currently requested assets.  Needs some work and cleanup, but it isn't accessible from anywhere yet.
2016-09-15 19:58:27 -07:00
snipe
b0a8a0427d Merge branch 'hotfix/license-clone' into develop
# Conflicts:
#	app/Http/Controllers/ReportsController.php
2016-09-14 19:08:06 -07:00
snipe
f384593e19 Fix license cloning 2016-09-14 19:04:52 -07:00
snipe
5846f23d8b Fix stupid migration? Maybe? Might be more trouble later 2016-09-14 18:59:14 -07:00
snipe
91a035ec5b Text BOM text BOM, you’re my Text BOM…. 2016-09-14 18:58:52 -07:00
snipe
d357326dc1 Use PHP streaming to generate asset report to prevent timeouts 2016-09-12 14:10:04 -07:00
snipe
5e2dbaffc4 Use streaming to handle large exports 2016-09-12 14:06:55 -07:00
snipe
391c9a77ef Misc debug template for use with debugging CSV exports, etc 2016-09-12 14:05:31 -07:00
snipe
7bde0f4f92 Fixes #2586 2016-09-08 20:01:46 -07:00
snipe
aa0ccf11fa Only load the remote gravatar image if the server can talk to the outside world 2016-09-07 01:41:23 -07:00
snipe
a8f79369ee Added components checkout gate 2016-09-07 01:15:14 -07:00
snipe
0a506120b7 Hotfix for dumb enum issue 2016-09-06 20:01:10 -07:00
snipe
0e28f36678 Fixes for weird stupid enum issue 2016-09-06 20:00:37 -07:00
Daniel Meltzer
e86adccf19 Actionlog Class: Improvements and polymorphism (#2561)
* Save progress

* Create a new action_log table to replace asset_log.  Use Polymorphism to generalize class and targets.  Port everything I can find to use it.  Add a migration to port the asset_logs table to action_logs.

* Allow accepted_id to be nullable.

* Comment out the thread_id migration, because it b0rks on a new database with the move.  I'm unsure if the thread_id does anything...It doesn't seem to be used

* Clean up all old methods from Actionlog model.  Port everything to use new cleaner interface.

* Port the actionlog factory to fix travis.

* Adjust code to work on php5.  Also fix lurking adminlog call.

* Remove weird code

* Port the pave command.  Also fix dangling adminlog
2016-09-06 19:39:42 -07:00
snipe
e7fba08f92 Merge remote-tracking branch 'origin/develop' 2016-09-06 10:38:31 -07:00
snipe
35f3f1432f Bumped version 2016-09-06 10:38:07 -07:00
snipe
934b39268d Merge remote-tracking branch 'origin/develop' 2016-09-06 10:35:33 -07:00
snipe
67315d81d6 Fixes #2134 - hide archived assets from list all 2016-09-01 13:28:15 -07:00
snipe
eee64d5509 Set the public path for users who can’t use public as a directory (shared hosting) 2016-09-01 12:53:38 -07:00
snipe
b450ef3534 Cast group permissions as array for older, wonky installs 2016-08-30 13:25:14 -07:00
snipe
d4dc1830ec Fixes #2527 - honor the setting for whether Snpie-IT can access the outside world 2016-08-30 12:58:08 -07:00
snipe
04e9ca0942 Fixes #2399 2016-08-30 12:34:23 -07:00
snipe
06021d79c1 Fixed typo 2016-08-30 12:25:46 -07:00
snipe
7ecb8d7bc1 Patches PR#2526 to develop 2016-08-30 12:13:29 -07:00
Ryan Stafford
efe95d9ad0 Syntax error on VOLUME instruction (#2526)
Added quotes to volume path.
2016-08-30 12:11:42 -07:00
snipe
6f89699f1a Make purchase cost default to null
I don’t know why I need to do this?
2016-08-30 08:52:33 -07:00
snipe
2c18bc24a7 Check if username is userprincipalname
If it is, skip building the UPN for AD
2016-08-30 08:34:17 -07:00
snipe
f81b21208b Bumped version for v3.4.0-beta 2016-08-30 07:39:55 -07:00
snipe
ba70e5b053 A little demo-proofing of the maintenances page 2016-08-30 07:34:33 -07:00
snipe
5090468357 Fixes #2510 and #2488 - CSS class added to images in views 2016-08-30 07:20:07 -07:00
snipe
213cda8cf4 Fixes #2525 2016-08-30 07:03:22 -07:00
snipe
421cbf11fc Patches PR#2500 for dev because @dmeltzer forgot that we commit to the develop branch :P 2016-08-30 06:54:04 -07:00
snipe
8816c481af Added HTML for generating passwords in asset user creation modal 2016-08-30 06:48:23 -07:00
snipe
3ed0cf2be8 Moved import errors up higher on the screen, fixed some weird formatting bugaboos 2016-08-30 06:48:00 -07:00
snipe
cd28b012b3 Remove last name requirement in save user request 2016-08-30 06:47:38 -07:00
snipe
25902db659 Generate password from modal 2016-08-30 06:47:18 -07:00
snipe
35a67ab18a Fixes #2516 - listbox error on new asset 2016-08-29 23:49:23 -07:00
snipe
2cfb015b1a Removed extra debugging info 2016-08-29 23:13:30 -07:00
snipe
e4dcd47d6c Fix UTF-8 issues in imports 2016-08-29 22:57:48 -07:00
snipe
64cd4fb1c9 Allow X-Frame-Options to be disabled via env if necessary 2016-08-29 22:57:29 -07:00
Daniel Meltzer
276e0a7114 Importer: Implement item update and interface improvments (#2507)
* Add support for updating assets to the importer.

If an asset with a matching asset tag is found, and the --update flag is
passed to the importer, we edit the matching asset with any
asset-specific values, and persist to the database.  Any missing/blank
values are skipped.

TODO: Add to web interface, add support in consumables/accessories

* Allow deleting of files on the import page.

* Extend web interface to allow updating of imported items.

This adds a modal dialog to the import process.  Currently the dialog
allows the choice of update vs ignore, and choosing the item type to
import (Accessory, Asset, Consumable).

Also use Helper::ParseFloat() for purchase_cost processing.  It exists,
and fixes issues on my end at least.

* Implement editing of consumables and accessories.

* Rename getProcessImportFile to postProcessImportFile to reflect how it's now used

* Fix copy-pasta error.
2016-08-29 15:49:32 -07:00
Daniel Meltzer
9bf3403f31 Fix #2499 (#2500)
Missed this instance when renaming the method. Sorry!
2016-08-26 06:01:58 -07:00
snipe
0d088f3031 Fixes #2491 - show asset tag on dashboard 2016-08-25 21:28:46 -07:00
snipe
a92ed97b4e Definitely not beta ;) 2016-08-25 21:06:43 -07:00
snipe
fcdea4825e Bumped version 2016-08-25 21:04:43 -07:00
snipe
35439f9976 Additional strings 2016-08-25 21:04:36 -07:00
snipe
d473432436 Show encryption in fieldset list 2016-08-25 21:04:25 -07:00
snipe
4dff58ec26 Fix array generation for select 2016-08-25 21:04:10 -07:00
snipe
537ad28a67 Don’t make required encrypted custom fields required if user is not an admin 2016-08-25 21:03:52 -07:00
snipe
96eb832fd3 Only decrypt if the user is an admin 2016-08-25 21:03:24 -07:00
snipe
130c798c90 Only accept a new value for encrypted fields if the user is an admin 2016-08-25 20:59:54 -07:00
snipe
e1229bfb0f Graceful decryption method 2016-08-25 20:58:56 -07:00
snipe
f185c2e0de Hide radio and checkboxes for now 2016-08-25 19:48:11 -07:00
snipe
122f0b9cba Custom fields form in asset edit view 2016-08-25 18:35:28 -07:00
snipe
c49f10c9bb Removed line break 2016-08-25 18:35:16 -07:00
snipe
97a938f119 Method helper to translate piped field_values into a useable array 2016-08-25 18:35:01 -07:00
snipe
308fcf96de Updated language strings 2016-08-25 17:43:07 -07:00
snipe
f1fab8b164 Added Indonesian to dropdown locale list 2016-08-25 17:22:08 -07:00
snipe
0e8502a323 Removed newline 2016-08-25 17:12:50 -07:00
snipe
3171d9230b Better language 2016-08-25 17:12:34 -07:00
snipe
11b9df4b48 Use updated L5 request method 2016-08-25 17:11:52 -07:00
snipe
0c2524954f Removed unusued status_id variable 2016-08-25 17:10:09 -07:00
snipe
b76ad5ea88 Reverted name of form field 2016-08-25 17:08:39 -07:00
snipe
43fbd54a12 Store new fields in the database 2016-08-25 17:08:08 -07:00
snipe
406d270c01 Use L5 Request method for input 2016-08-25 17:07:58 -07:00
snipe
98eb26a2bd Merge branch 'features/cusom_field_types' into develop 2016-08-25 16:36:21 -07:00
snipe
61aa9beddb Added new fields to custom fields views 2016-08-25 16:36:00 -07:00
snipe
e89fd9b3a2 Additional strings 2016-08-25 16:35:45 -07:00
snipe
d72443c335 Use trans() for custom format text 2016-08-25 16:35:31 -07:00
snipe
f38593b530 Merge remote-tracking branch 'origin/develop' 2016-08-23 19:01:53 -07:00
snipe
4cf2d16c7a Temp fix for number import on cost 2016-08-23 19:01:40 -07:00
snipe
f38912a5cf Custom fields additions 2016-08-23 18:52:54 -07:00
snipe
ad22293f4b Added show in nav for status label views and controller 2016-08-23 18:52:42 -07:00
snipe
fb402e138d Smaller dashboard number 2016-08-23 18:52:12 -07:00
snipe
90d2d0c7e1 Fixes #2469 - corrected config app.url 2016-08-23 16:04:22 -07:00
snipe
9d730af50f Added single quotes to env for mail sender 2016-08-23 16:03:57 -07:00
snipe
9407b4e28c Removed console warning 2016-08-23 15:53:18 -07:00
snipe
ec19924bea Custom field types 2016-08-23 15:52:34 -07:00
snipe
7b8403cdb9 Pass status ID to ajax 2016-08-23 15:52:10 -07:00
snipe
85f3e7e3d4 Added filter by status type 2016-08-23 15:51:59 -07:00
snipe
11dc20de61 Show in nav language option 2016-08-23 15:51:45 -07:00
snipe
14fa7ed965 Fixed indenting 2016-08-23 15:51:14 -07:00
snipe
5cf1c8dfa3 Added DB DUMP PATH to docker.env 2016-08-23 15:51:05 -07:00
snipe
f04cfb3e7f Allow admins to show status labels in nav 2016-08-23 15:50:52 -07:00
snipe
d970daa666 Add new fields to custom fields table 2016-08-23 15:50:43 -07:00
snipe
0b0c81a110 Merge remote-tracking branch 'origin/develop' 2016-08-23 11:38:03 -07:00
snipe
b1324c2e64 Removed beta from version 2016-08-23 11:37:49 -07:00
snipe
3c28be33c5 Bumped version 2016-08-23 11:37:00 -07:00
snipe
e52a0f65bb Update asset report to show deployed if asset is checked out 2016-08-23 11:36:34 -07:00
snipe
b726d131a4 More helpful message for LDAP TLS issue 2016-08-23 11:32:11 -07:00
snipe
014167699d Fixes #2441 - use showAssetName to avoid blank entries in link name which makes Slack do weird things 2016-08-18 13:10:31 -07:00
snipe
d9f2e7bf58 If custom field is type URL, display it as a link 2016-08-18 12:44:55 -07:00
snipe
4c8c58d453 Clean up divs for gates in list view 2016-08-18 12:31:45 -07:00
snipe
923352537c Moved column for in/out 2016-08-18 07:06:55 -07:00
snipe
be8049b41a Include asset maintenances in purge 2016-08-18 07:06:15 -07:00
snipe
4419dc7434 Merge branch 'fix-double-format' of https://github.com/dmeltzer/snipe-it into dmeltzer-fix-double-format
# Conflicts:
#	app/Http/Controllers/ConsumablesController.php
#	app/Http/Controllers/LicensesController.php
#	resources/views/hardware/view.blade.php
2016-08-16 18:53:45 -07:00
Daniel Meltzer
ac63642224 Add manufacturer to licenses (#2436)
* Add manufacturer to licenses.  Shows in table and edit.  Need to improve manufacturer view to show lists beyond assets still.

* Remove extra closing tags, formatting

* Work on making the manufacturer view show more options. Need to figure out how to change the table dynamically.

* Cleanup formatting and fix a few weirdities in hardware/view.blade.php

* Standardize on two-space tabs in this file, as it seems the most
* common.

* Fix a few places where we call number_format without guaranteeing the
* item is a number and not a string.

* Show a "No Results" message on components page if there are no
* components.

* Show table of licenses on manufacturer view page.

This reworks the ManufacturersController::getDataView method to delegate
the view to a sub method (currently assets or licenses, but plan to
extend to consumables/accessories/components as well).  We then put tabs
at the top of the view to show multiple tables.  This just duplicates
the table layout from licenses/index.blade, but I wonder if theres a way
to centralize that code, maybe through partials, over time..

The only known missing part of manufacturers for licenses would be adding it
to the importer, but the license importer should probably migrate to
object importer before doing too much more...

* Add manufacturer to accessory.

* Add consumables to the manufacturer view page.
2016-08-16 18:49:54 -07:00
Daniel Meltzer
5959f83de3 Rename parseCurrencyString to formatCurrencyOutput to clarify what it does better. 2016-08-16 20:47:53 -05:00
Daniel Meltzer
0c912bcf49 Fix more number_format madness.
This does two main things:
1) The importer now imports as numbers, not parsed strings.  This allows
is to format values on output instead of input, which is what was
happening in most places.

2) Add a Helper::parseCurrencyString method and port everything to use
this.  This checks to see if the value is numeric or empty, and returns
the appropriate value in all cases.  Should fix all known occurances of
number_format expections.
2016-08-16 20:41:28 -05:00
snipe
16014945b6 Merge remote-tracking branch 'origin/develop' 2016-08-16 18:23:36 -07:00
snipe
44821b9667 Fixes #2404 Only update name of asset if it isn't null. 2016-08-16 18:23:20 -07:00
snipe
c5d7a1fdd6 Merge remote-tracking branch 'origin/develop' 2016-08-16 18:21:05 -07:00
snipe
29c4189419 Bumped version 2016-08-16 18:20:42 -07:00
Daniel Meltzer
7ef4f23d0f Validate that purchase_cost is a numeric value. (#2452) 2016-08-16 18:18:50 -07:00
timwsuqld
8232cefbba Fix path to snipeit-ssl.crt (#2428) 2016-08-16 13:03:55 -07:00
Daniel Meltzer
a852c624d3 Fix 2347 (#2394)
* Prevent multiple checkouts of the same asset.

This adds a new method to the Asset model, availableForCheckout.
Port getDataTable to use availableForCheckout instead of doing the
check manually.

Fixes Issue #2347

* Use availableForCheckout in categories controller.  Also gate the checkin/checkout actions here.

* Use gate and availableForCheckout in manufactuers as well.
2016-08-16 13:02:42 -07:00
snipe
7edf1db101 Small tweaks to history 2016-08-12 19:03:32 -07:00
snipe
5e9740e0b4 Merge branch 'develop' of github.com:snipe/snipe-it into develop 2016-08-12 17:10:10 -07:00
snipe
41a20d8f66 Tidied up some debugging code, better explanation 2016-08-12 17:10:03 -07:00
snipe
7a0843e954 Import history language file 2016-08-12 16:02:51 -07:00
snipe
4a9f3fd6ff Generate email method 2016-08-12 16:02:39 -07:00
snipe
9ae1841fc4 Make additional fields fillable 2016-08-12 16:02:18 -07:00
snipe
ba5a2edd54 CSV history routes 2016-08-12 16:02:09 -07:00
snipe
c73cbccffc Method to import CSV history 2016-08-12 16:01:59 -07:00
snipe
24d2726c86 Added helper for imports 2016-08-12 16:01:45 -07:00
snipe
06fcf3e07d Import history blade 2016-08-12 16:01:34 -07:00
Daniel Meltzer
cc15a4f018 Use showAssetName instead of asset->name to include the asset tag (#2437) 2016-08-11 23:56:40 -07:00
snipe
18e576e5fd Merge branch 'develop' of github.com:snipe/snipe-it into develop 2016-08-11 22:03:25 -07:00
snipe
4c787891e4 Use custom maintenance middleware 2016-08-11 19:22:26 -07:00
Daniel Meltzer
dbd96a4c10 Don't try to format a formatted number string. (#2396)
The importer already formatted/parsed numbers on input into the db
(maybe it shouldn't have?) so running number_format on that string
throws an exception.  Check to make sure the value is numeric before
formatting it.
2016-08-11 19:13:49 -07:00
snipe
d314f85b93 Merge branch 'develop' of github.com:snipe/snipe-it into develop 2016-08-11 15:58:22 -07:00
snipe
3a81b7e612 Eager load asset query on maintenances to prevent n+1 queries 2016-08-11 15:56:21 -07:00
snipe
7992258b46 Updated UI with new required indicator 2016-08-11 15:44:01 -07:00
snipe
869da1da78 Add maintenance notes to maintenances tab in hardware view 2016-08-11 15:40:41 -07:00
Michael T
a6a6aa78b0 Fixing the script freezing prior to mysql secure install (#2434) 2016-08-11 15:17:55 -07:00
snipe
4ffea7ceaa Fixes #2406 - added missing gate for assets.edit 2016-08-09 16:38:43 -07:00
snipe
1d3255a00b Allow admin to turn LDAP password sync off.
This is added to handle customers/users with a security policy that prohibits third-parties or external databases from storing LDAP passwords.
2016-08-04 14:29:28 -07:00
snipe
29eadb10ae Fixes #2387 2016-08-02 17:03:15 -07:00
snipe
1ca5f8bee5 Removed asterisks, use orange bar for req fields in locations 2016-08-02 16:40:38 -07:00
snipe
8dbc098836 Bumped hash for 3.2.0 2016-08-02 15:25:23 -07:00
snipe
45ea44e172 Bumped hash 2016-08-02 15:16:16 -07:00
snipe
fff2bce9e4 Added missing username in header row 2016-08-02 15:16:01 -07:00
snipe
75e0c5565c Add username and custom fields option to custom report 2016-08-02 15:04:10 -07:00
snipe
098e7e4feb Hide email address if there is no value 2016-08-02 15:03:45 -07:00
snipe
e4355292e4 Bumped hash version 2016-08-02 13:30:00 -07:00
snipe
ca8ca89955 Added custom color to status labels, only show status labels if there are results 2016-08-02 13:25:50 -07:00
snipe
30c45442f9 Merge remote-tracking branch 'origin/develop' 2016-08-02 12:40:06 -07:00
snipe
03c2c267bc Added favicon explicit link 2016-08-02 12:39:49 -07:00
snipe
a76fe98b2d Only show a logo if a logo is uploaded 2016-08-02 12:34:08 -07:00
snipe
9e43a44d20 Better styling for forgotten password screens 2016-08-02 12:30:22 -07:00
snipe
6fe639f490 Skip email if no email domain is given 2016-08-02 12:30:02 -07:00
snipe
a5467ba25d Slug the username to handle spaces, etc. 2016-08-02 11:12:28 -07:00
snipe
1c09479d5f Merge remote-tracking branch 'origin/develop' 2016-08-02 10:34:43 -07:00
snipe
682c75e990 Bumped version 2016-08-02 10:34:30 -07:00
snipe
1612562f41 Create log record and send EULA when creating a new asset that’s checked out 2016-08-02 10:33:44 -07:00
snipe
1b7f28598d Merge remote-tracking branch 'origin/develop' 2016-08-02 09:54:47 -07:00
snipe
17d5e40e02 Fixes #2383 2016-08-02 09:54:31 -07:00
snipe
099a85e26d Merge remote-tracking branch 'origin/develop' 2016-08-02 05:06:29 -07:00
snipe
0e5209e80f Few more dashboard fixes 2016-08-02 05:06:17 -07:00
snipe
95328f0a6a Merge remote-tracking branch 'origin/develop' 2016-08-02 04:46:25 -07:00
snipe
cbc42f3e59 Fix for deleted users display 2016-08-02 04:45:48 -07:00
snipe
846356974d Merge remote-tracking branch 'origin/develop' 2016-08-02 04:26:19 -07:00
snipe
ef6fb69cee Fix translation 2016-08-02 04:26:07 -07:00
snipe
fb1eab0978 Merge remote-tracking branch 'origin/develop' 2016-08-02 04:24:09 -07:00
snipe
39929c7d89 Better handling for deleted users 2016-08-02 04:23:13 -07:00
snipe
d6ba0b67f0 Merge remote-tracking branch 'origin/develop' 2016-08-02 03:50:20 -07:00
snipe
66ad0f1d4c Better fix for location LDAP sync 2016-08-02 03:50:08 -07:00
snipe
bfac25d445 Merge remote-tracking branch 'origin/develop' 2016-08-02 03:45:17 -07:00
snipe
3b247ba31f Ignore location field if no value is passed 2016-08-02 03:45:03 -07:00
snipe
bc3482b281 Merge remote-tracking branch 'origin/develop' 2016-08-02 03:26:53 -07:00
snipe
23e23bab90 Remove display of port number since it’s ignored anyway 2016-08-02 03:26:38 -07:00
snipe
848e3837aa Merge remote-tracking branch 'origin/develop' 2016-08-02 02:36:40 -07:00
Brady Wetherington
1747be4b29 Enable .env file to point to location of CA Cert (#2382) 2016-08-02 02:36:00 -07:00
snipe
565ea95803 Merge remote-tracking branch 'origin/develop' 2016-08-02 02:33:04 -07:00
snipe
e7e8c487c9 Bumped version 2016-08-02 02:32:52 -07:00
snipe
5a242433fb Merge remote-tracking branch 'origin/develop' 2016-08-02 02:12:33 -07:00
snipe
6204969639 Fixed requestable link 2016-08-02 02:12:18 -07:00
snipe
cde5efd698 Merge remote-tracking branch 'origin/develop' 2016-08-02 01:36:32 -07:00
snipe
283bb4ae4b Fixes #2381 2016-08-02 01:36:14 -07:00
snipe
3d1d248bb5 Merge remote-tracking branch 'origin/develop' 2016-08-02 01:26:51 -07:00
snipe
9c31c0edce Ignore uploaded barcodes 2016-08-02 01:26:44 -07:00
snipe
39450c1fe9 Eager load throttle query 2016-08-02 01:23:53 -07:00
snipe
64ffd261fc Bumped version 2016-08-02 01:14:11 -07:00
snipe
de17da099f Fixed tests 2016-08-02 01:12:58 -07:00
snipe
886a31190c Fixed route 2016-08-02 01:08:37 -07:00
snipe
8246a319a2 Fixes #2363 and #1097 2016-08-02 00:54:38 -07:00
snipe
27adeb427e Generate barcodes locally and try to serve them if they exist 2016-08-01 22:56:28 -07:00
snipe
bfc18c758a Removed console message from JS 2016-08-01 21:43:56 -07:00
snipe
735595be07 Typeahead library
(not implemented yet)
2016-08-01 21:43:01 -07:00
snipe
27dee1b793 Removed comment 2016-08-01 20:15:25 -07:00
snipe
cdeccb399f Hide extra options if superadmin is checked 2016-08-01 20:11:54 -07:00
snipe
2f679ccc29 Merge remote-tracking branch 'origin/develop' 2016-08-01 18:44:32 -07:00
snipe
eac6abe60a Fixes #2378 - disallow admins to create/edit superadmins
Also disables admins from being able to edit groups, since that can grant superadmin access.
2016-08-01 18:43:11 -07:00
Daniel Meltzer
c9d3cd724b Fix installer again (#2370)
I hate bash... anyone else want to maintain this? :)
2016-08-01 11:08:46 -07:00
snipe
1fa2fe3c24 Merge remote-tracking branch 'origin/develop' 2016-08-01 10:32:04 -07:00
snipe
b6986ad808 Bumped version 2016-08-01 10:31:46 -07:00
snipe
715c9aa780 Merge remote-tracking branch 'origin/develop' 2016-08-01 10:18:01 -07:00
snipe
139325d8ba Small tweaks for bad data 2016-08-01 10:17:46 -07:00
snipe
d65a9091c8 Merge remote-tracking branch 'origin/develop' 2016-07-30 17:27:29 -07:00
snipe
1f30bdee99 Fixes #2361 2016-07-30 17:27:08 -07:00
snipe
4e4f338680 Merge remote-tracking branch 'origin/develop' 2016-07-29 14:32:49 -07:00
snipe
0f72989953 Updated language strings 2016-07-29 14:32:31 -07:00
snipe
93e038006c Merge remote-tracking branch 'origin/develop' 2016-07-29 14:18:21 -07:00
snipe
b63a3abf70 Bumped hash 2016-07-29 14:18:05 -07:00
snipe
46eca54b44 Moved bulk checkout into assets nav 2016-07-29 14:17:59 -07:00
zjean
fcb1d6ac15 Fixed feedback on #2349 (#2359) 2016-07-29 13:59:50 -07:00
snipe
3f54c034dd Merge remote-tracking branch 'origin/develop' 2016-07-29 12:15:45 -07:00
snipe
a53346be1f Merge branch 'develop' of github.com:snipe/snipe-it into develop 2016-07-29 12:15:14 -07:00
snipe
fd94c76874 Fixes asset created_at 2016-07-29 12:15:09 -07:00
zjean
108a3c9dad Updated view for #2324 (#2357) 2016-07-29 11:55:16 -07:00
snipe
85232c47da Merge branch 'develop' of github.com:snipe/snipe-it into develop 2016-07-28 21:31:58 -07:00
snipe
47f6635992 A few more permissions tweaks 2016-07-28 21:31:53 -07:00
Daniel Meltzer
eef8d1609e Small fixes (#2350)
* components.view should point to view, not create

* Fix comment

* Rename variable to accurately reflect its responsibility

* Fix line breaks in serial key, remove places where adding line breaks makes no sense.  Fixes #2344
2016-07-28 20:59:42 -07:00
snipe
8a9307f357 Wordwrap license key 2016-07-28 18:56:02 -07:00
snipe
0a73297f24 Merge remote-tracking branch 'origin/develop' 2016-07-28 12:51:01 -07:00
snipe
1f0737cfb7 Allow super admins to override company 2016-07-28 12:40:19 -07:00
snipe
fae9755ffb Merge remote-tracking branch 'origin/develop' 2016-07-28 09:16:46 -07:00
snipe
c07ad03e74 Removed unique from form request 2016-07-28 09:16:30 -07:00
snipe
011cb1120d Merge remote-tracking branch 'origin/develop' 2016-07-28 08:51:15 -07:00
snipe
68b7b8f932 Fixes Carbon date 2016-07-28 08:51:01 -07:00
snipe
f78a577210 Merge remote-tracking branch 'origin/develop' 2016-07-28 08:41:47 -07:00
snipe
c0f4e621ea Bumped version 2016-07-28 08:41:33 -07:00
snipe
c78dbfc21f Merge remote-tracking branch 'origin/develop' 2016-07-28 08:39:59 -07:00
snipe
f31637adb4 Fixes #2346 2016-07-28 08:39:28 -07:00
snipe
3e5d2b5385 Ability to remove field from fieldset 2016-07-28 08:10:15 -07:00
snipe
fbd0059bbb Fixes #2317 2016-07-28 08:07:14 -07:00
snipe
f53c5706f6 Fixes #2341 2016-07-28 07:36:58 -07:00
snipe
214a7d548d Bumped version 2016-07-28 06:44:59 -07:00
snipe
0ee5dea1a1 Fixes #2344 2016-07-28 06:43:31 -07:00
snipe
29c60ee6b5 Merge remote-tracking branch 'origin/develop' 2016-07-28 05:50:22 -07:00
snipe
075f8fd021 Fixed typo 2016-07-28 05:49:55 -07:00
snipe
14b0a6315f Pass users path to get_src 2016-07-28 05:49:41 -07:00
snipe
b99d300ab2 Merge remote-tracking branch 'origin/develop' 2016-07-27 21:47:25 -07:00
snipe
9dda0d02ea Change default zerofill to 5 2016-07-27 21:47:03 -07:00
snipe
8e6c157e7e Merge remote-tracking branch 'origin/develop' 2016-07-27 21:33:00 -07:00
snipe
9fbe6c68ac Fixes #2304 2016-07-27 21:30:38 -07:00
snipe
eb508901c5 Zerofilling for auto-increment 2016-07-27 21:28:00 -07:00
snipe
07b70a8cd0 Merge remote-tracking branch 'origin/develop' 2016-07-27 20:30:25 -07:00
snipe
e9eb5ad372 Bumped version 2016-07-27 20:30:11 -07:00
snipe
3fd5fb836f Restore linebreaks in notes 2016-07-27 20:24:09 -07:00
snipe
3514ae2c0d Merge branch 'develop' of github.com:snipe/snipe-it into develop 2016-07-27 20:16:54 -07:00
snipe
1493251794 Gitignore cleanup 2016-07-27 20:16:46 -07:00
Daniel Meltzer
b4e54225a2 Fix exports (#2338)
* Update tableexport.js to the new version.

* Give the export file in each table a useful name.

The name takes the form of tabletype-export-YYYY-MM-DD.extension.
2016-07-27 19:45:45 -07:00
Daniel Meltzer
4c9e75cec9 Install php-zip so backups work. Not needed in 14.04 because it looks like this is part of the php7 split. (#2340)
Issue #2269
2016-07-27 19:44:46 -07:00
Daniel Meltzer
a401986ef5 Only set the category_type in postEdit if the category is empty. (#2337)
Fixes #2333
2016-07-27 16:13:54 -07:00
snipe
288584cb60 Merge branch 'master' of github.com:snipe/snipe-it 2016-07-26 16:33:32 -07:00
Daniel Meltzer
399e70763b Scope requestable assets to company as well. Updates to #2206. (#2326) 2016-07-26 16:22:56 -07:00
Brady Wetherington
f145d6cc8c Change README to point to new documentation site 2016-07-26 13:56:40 -07:00
Daniel Meltzer
9e4ac018ea Don't allow users without a company to change the company of items if full company support is enabled. (#2321) 2016-07-26 13:31:36 -07:00
Daniel Meltzer
0bf5c6978e Make sure the assigned user is actually shown in the dropdown list. Not sure why this wasn't throwing an error for me, but this makes it actually behave. (#2322) 2016-07-26 13:06:38 -07:00
snipe
9a9b214c1d Fixes #2319 2016-07-26 06:07:47 -07:00
snipe
b76dc25ac0 Duh, we don’t soft-delete companies 2016-07-26 02:11:41 -07:00
snipe
b30369f7ce Added table name for trait 2016-07-26 02:04:31 -07:00
snipe
16fe53928c Updated undeleted validation 2016-07-26 01:49:21 -07:00
snipe
2e665e128f Putting uniqueUndeleted into a trait for use across models 2016-07-26 01:39:30 -07:00
snipe
60560e4994 Remove unused Log statement 2016-07-26 00:50:16 -07:00
snipe
a44b90dfc9 Custom validator for multiple deleted items with the same unique field 2016-07-26 00:44:26 -07:00
snipe
987b969e88 Move bcrypt out of loop for object importer 2016-07-25 22:31:33 -07:00
snipe
ad531d6d59 Merge branch 'develop' of github.com:snipe/snipe-it into develop 2016-07-25 22:10:38 -07:00
snipe
261d2f133b Only bcrypt temp passwords once for performance 2016-07-25 22:10:33 -07:00
Daniel Meltzer
e0938cf82d Scope to company when viewing assets (#2315)
* If a user doesn't belong to a company, when scoping to a company we should only show items that don't belong to a company.

* Scope tables/items to the company they belong to when fetching items for the index.

* Fix asset count to also scope to company.  This fixes dashboard view

* Exempt super users from the child company check to be consistent.  Fixes license count on dashboard now that we scope everything
2016-07-25 19:46:29 -07:00
snipe
eec22c5aeb Removed port stuff, since LDAP ignores it anyway :-/ 2016-07-22 16:21:16 -07:00
snipe
b03330aae0 Added TLS option in settings for LDAP 2016-07-22 16:00:37 -07:00
snipe
7f5ea72dc7 Bumped version 2016-07-22 15:11:03 -07:00
snipe
ba25972b49 Add LDAP port number option 2016-07-22 15:09:49 -07:00
snipe
cc6b2a0081 FIxes #2280
This shouldn’t ever happen though. Bad data somwhere, I’m guessing.
2016-07-22 07:48:46 -07:00
snipe
a590cc3dd2 One more fix for MAC address weirdness 2016-07-22 05:56:00 -07:00
snipe
d4138f4364 Fixes #2299 2016-07-22 03:10:25 -07:00
snipe
128290bd82 Cleanup checkin blade 2016-07-22 02:34:25 -07:00
snipe
114540d836 Cleanup checkout form 2016-07-22 02:20:05 -07:00
snipe
0b57f74e36 Check for model name (this should never be blank, but…) 2016-07-22 02:14:12 -07:00
snipe
03d7d01e12 Fixes #2300 2016-07-22 02:12:04 -07:00
snipe
a1640d7fe3 Form cleanup 2016-07-22 02:11:57 -07:00
snipe
1f85f4b337 Clearer demo mode text 2016-07-22 02:11:46 -07:00
snipe
b2d958724b Removed commented code 2016-07-22 02:11:37 -07:00
snipe
297820d347 Newer required style 2016-07-22 01:33:55 -07:00
snipe
094c5ac8df Fixes #2292 2016-07-22 01:16:18 -07:00
snipe
78fda31379 Helper method to introspect into the model level validation to see if the field is required
(This does not yet handle form request validation)
2016-07-22 00:29:23 -07:00
snipe
3a04686ade Nicer demo mode message 2016-07-22 00:28:22 -07:00
snipe
ca5d3e3006 Nicer license form display 2016-07-22 00:25:41 -07:00
snipe
d427dcc8e2 updated version 2016-07-22 00:24:42 -07:00
snipe
f0c00897ca Required class 2016-07-22 00:21:56 -07:00
snipe
e256bdc9f7 Clearer version in footer 2016-07-21 21:39:23 -07:00
snipe
2e6e0e8911 Fixed versioning path 2016-07-21 21:30:49 -07:00
snipe
b0dc5b4183 Fixes #2290 2016-07-21 21:28:17 -07:00
snipe
9385c3e9cf Remove last name requirement from Form Request 2016-07-21 19:46:46 -07:00
snipe
61108102d7 No longer require last name
I may regret this…
2016-07-21 19:44:07 -07:00
snipe
8ba9399de7 Merge branch 'master' into develop 2016-07-21 19:42:11 -07:00
snipe
f6a4d4aaab Better display for some features disabled for demo mode 2016-07-21 19:40:23 -07:00
Daniel Meltzer
df664bdc9d Fix categories acceptance test as it stands. We need to choose a category type to pass validation, and we need to see the elemnt alert-danger, not the text, to make the test fail when it should. (#2289) 2016-07-20 21:36:43 -07:00
Daniel Meltzer
c2f6e0cfd8 Don't escape html in default eula. Fixes #2277 (#2279) 2016-07-20 19:39:48 -07:00
Daniel Meltzer
ba6f26cef9 If a category has items in it, disable changing the category type (#2288) 2016-07-20 19:27:33 -07:00
Daniel Meltzer
68b0bbbec9 Fix tests (#2273)
* Update installer script for v3 now that things have moved around.

* Make Statuslabel attributes fillable and add them to the generated array.  Fixes status label tests.
2016-07-19 15:50:21 -07:00
snipe
52425f62c5 Set default values for status labels in import 2016-07-19 15:49:04 -07:00
Daniel Meltzer
54a0d0de0e Fetch the installer from master instead of v3 branch. (#2266) 2016-07-19 09:41:00 -07:00
Daniel Meltzer
099f5d4cfd Update installer script for v3 now that things have moved around. (#2263) 2016-07-19 08:41:56 -07:00
881 changed files with 20114 additions and 8178 deletions

View File

@@ -30,7 +30,9 @@ MAIL_USERNAME=YOURUSERNAME
MAIL_PASSWORD=YOURPASSWORD
MAIL_ENCRYPTION=null
MAIL_FROM_ADDR=you@example.com
MAIL_FROM_NAME=Snipe-IT
MAIL_FROM_NAME='Snipe-IT'
MAIL_REPLYTO_ADDR=you@example.com
MAIL_REPLYTO_NAME='Snipe-IT'
# --------------------------------------------
@@ -74,4 +76,5 @@ AWS_BUCKET=null
APP_LOG=single
APP_LOCKED=false
FILESYSTEM_DISK=local
APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1
APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1
ALLOW_IFRAMING=false

View File

@@ -13,7 +13,7 @@
#### Please confirm you have done the following before posting your bug report:
- [ ] I have enabled debug mode
- [ ] I have read [checked the Common Issues page](http://docs.snipeitapp.com/common-issues.html)
- [ ] I have read [checked the Common Issues page](https://snipe-it.readme.io/docs/common-issues)
-----
#### Please provide answers to these questions before posting your bug report:
@@ -21,7 +21,7 @@
- Version of Snipe-IT you're running
- What OS and web server you're running Snipe-IT on
- What method you used to install Snipe-IT (install.sh, manual installation, docker, etc)
- If you're getting an error in your browser, include that error
- WITH DEBUG TURNED ON, if you're getting an error in your browser, include that error
- What specific Snipe-IT page you're on, and what specific element you're interacting with to trigger the error
- If a stacktrace is provided in the error, include that too.
- Any errors that appear in your browser's error console.

68
.gitignore vendored
View File

@@ -1,49 +1,39 @@
/vendor
/node_modules
Homestead.yaml
Homestead.json
.env
tests/_output/*
.couscous
.DS_Store
public/uploads/models/*
public/uploads/avatars/*
public/uploads/suppliers/*
public/uploads/assets/*
public/uploads/users/*
public/uploads/*.gif
public/uploads/*.jpg
public/uploads/*.png
public/uploads/*.tif
public/uploads/*.svg
storage/app/private_uploads/users/*
phpDocumentor.phar
output
tests/_support/_generated/*
.env
.idea
/bin/
/bootstrap/compiled.php
composer.phar
app/config/database.php
app/config/mail.php
/node_modules
/vendor
app/database/*.sqlite
app/storage/meta/services.json
app/config/*/mail.php
app/config/*/session.php
app/config/*/database.php
app/config/*/app.php
app/config/*/ldap.php
public/packages/*
storage/logs/*
storage/debugbar/
/bin/
.idea
composer.phar
crowdin.yaml
Homestead.json
Homestead.yaml
output
phpDocumentor.phar
public/uploads/*.gif
public/uploads/barcodes/*.png
public/uploads/*.jpg
public/uploads/*.png
public/uploads/*.svg
public/uploads/*.tif
public/uploads/assets/*
public/uploads/avatars/*
public/uploads/logo.gif
public/uploads/logo.svg
public/uploads/logo.png
.couscous
public/uploads/logo.svg
public/uploads/models/*
public/uploads/suppliers/*
public/uploads/users/*
storage/app/private_uploads/users/*
storage/debugbar/
storage/dumps/*
tests/_data/scenarios
storage/laravel-backups
storage/logs/*
storage/private_uploads/users/*
tests/_data/scenarios
tests/_output/*
tests/_support/_generated/*

View File

@@ -80,7 +80,7 @@ RUN cd /var/www/html;composer install
############### DATA VOLUME #################
VOLUME [/var/lib/snipeit]
VOLUME ["/var/lib/snipeit"]
##### START SERVER

View File

@@ -0,0 +1,164 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\Setting;
use App\Models\Ldap;
use App\Models\User;
use App\Models\Location;
use Log;
class LdapSync extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'snipeit:ldap-sync {--location=} {--location_id=} {--summary}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command line LDAP sync';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
ini_set('max_execution_time', 600); //600 seconds = 10 minutes
ini_set('memory_limit', '500M');
$ldap_result_username = Setting::getSettings()->ldap_username_field;
$ldap_result_last_name = Setting::getSettings()->ldap_lname_field;
$ldap_result_first_name = Setting::getSettings()->ldap_fname_field;
$ldap_result_active_flag = Setting::getSettings()->ldap_active_flag_field;
$ldap_result_emp_num = Setting::getSettings()->ldap_emp_num;
$ldap_result_email = Setting::getSettings()->ldap_email;
try {
$ldapconn = Ldap::connectToLdap();
} catch (\Exception $e) {
LOG::error($e);
}
try {
Ldap::bindAdminToLdap($ldapconn);
} catch (\Exception $e) {
LOG::error($e);
}
$summary = array();
$results = Ldap::findLdapUsers();
if ($this->option('location')!='') {
$location = Location::where('name','=',$this->option('location'))->first();
LOG::debug('Location name '.$this->option('location').' passed');
LOG::debug('Importing to '.$location->name.' ('.$location->id.')');
} elseif ($this->option('location_id')!='') {
$location = Location::where('id','=',$this->option('location_id'))->first();
LOG::debug('Location ID '.$this->option('location_id').' passed');
LOG::debug('Importing to '.$location->name.' ('.$location->id.')');
} else {
$location = new Location;
}
if (!isset($location)) {
LOG::debug('That location is invalid, so no location will be assigned.');
}
$tmp_pass = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 20);
$pass = bcrypt($tmp_pass);
for ($i = 0; $i < $results["count"]; $i++) {
if (empty($ldap_result_active_flag) || $results[$i][$ldap_result_active_flag][0] == "TRUE") {
$item = array();
$item["username"] = isset($results[$i][$ldap_result_username][0]) ? $results[$i][$ldap_result_username][0] : "";
$item["employee_number"] = isset($results[$i][$ldap_result_emp_num][0]) ? $results[$i][$ldap_result_emp_num][0] : "";
$item["lastname"] = isset($results[$i][$ldap_result_last_name][0]) ? $results[$i][$ldap_result_last_name][0] : "";
$item["firstname"] = isset($results[$i][$ldap_result_first_name][0]) ? $results[$i][$ldap_result_first_name][0] : "";
$item["email"] = isset($results[$i][$ldap_result_email][0]) ? $results[$i][$ldap_result_email][0] : "" ;
// User exists
$item["createorupdate"] = 'updated';
if (!$user = User::where('username', $item["username"])->first()) {
$user = new User;
$user->password = $pass;
$item["createorupdate"] = 'created';
}
// 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->employee_num = e($item["employee_number"]);
$user->activated = 1;
if ($location) {
$user->location_id = e($location->id);
}
$user->notes = 'Imported from LDAP';
$user->ldap_import = 1;
$errors = '';
if ($user->save()) {
$item["note"] = $item["createorupdate"];
$item["status"]='success';
} else {
foreach ($user->getErrors()->getMessages() as $key => $err) {
$errors .= $err[0];
}
$item["note"] = $errors;
$item["status"]='error';
}
array_push($summary, $item);
}
}
if ($this->option('summary')) {
for ($x = 0; $x < count($summary); $x++) {
if ($summary[$x]['status']=='error') {
$this->error('ERROR: '.$summary[$x]['firstname'].' '.$summary[$x]['lastname'].' (username: '.$summary[$x]['username'].' was not imported: '.$summary[$x]['note'] );
} else {
$this->info('User '.$summary[$x]['firstname'].' '.$summary[$x]['lastname'].' (username: '.$summary[$x]['username'].' was '.strtoupper($summary[$x]['createorupdate']).'.');
}
}
} else {
return $summary;
}
}
}

View File

@@ -1,25 +1,27 @@
<?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\Helpers\Helper;
use App\Models\Accessory;
use App\Models\Asset;
use App\Models\AssetModel;
use App\Models\Category;
use App\Models\Company;
use App\Models\Consumable;
use App\Models\CustomField;
use App\Models\Location;
use App\Models\Manufacturer;
use App\Models\Setting;
use App\Models\Statuslabel;
use App\Models\Supplier;
use App\Models\User;
use App\Models\CustomField;
use DB;
use App\Models\Setting;
use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Model;
use League\Csv\Reader;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use ForceUTF8\Encoding;
ini_set('max_execution_time', 600); //600 seconds = 10 minutes
ini_set('memory_limit', '500M');
@@ -63,7 +65,10 @@ class ObjectImportCommand extends Command
{
$filename = $this->argument('filename');
$tmp_password = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 20);
$password = bcrypt($tmp_password);
$this->updating = $this->option('update');
if (!$this->option('web-importer')) {
$logFile = $this->option('logfile');
\Log::useFiles($logFile);
@@ -99,9 +104,17 @@ class ObjectImportCommand extends Command
$this->companies = Company::All(['name', 'id']);
$this->status_labels = Statuslabel::All(['name', 'id']);
$this->suppliers = Supplier::All(['name', 'id']);
$this->assets = Asset::all(['asset_tag']);
$this->accessories = Accessory::All(['name']);
$this->consumables = Consumable::All(['name']);
switch (strtolower($this->option('item-type'))) {
case "asset":
$this->assets = Asset::all();
break;
case "accessory":
$this->accessories = Accessory::All();
break;
case "consumable":
$this->consumables = Consumable::All();
break;
}
$this->customfields = CustomField::All(['name']);
$bar = null;
@@ -109,7 +122,7 @@ class ObjectImportCommand extends Command
$bar = $this->output->createProgressBar(count($newarray));
}
// Loop through the records
DB::transaction(function () use (&$newarray, $bar) {
DB::transaction(function () use (&$newarray, $bar, $password) {
Model::unguard();
$item_type = strtolower($this->option('item-type'));
@@ -125,7 +138,7 @@ class ObjectImportCommand extends Command
$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["item_name"] = $this->array_smart_fetch($row, "item name");
@@ -149,19 +162,31 @@ class ObjectImportCommand extends Command
}
$this->log('Category: ' . $item_category);
$this->log('Location: ' . $item_location);
$this->log('Manufacturer: ' . $item_manufacturer);
$this->log('Purchase Date: ' . $item["purchase_date"]);
$this->log('Purchase Cost: ' . $item["purchase_cost"]);
$this->log('Company Name: ' . $item_company_name);
$this->log('Status: ' . $item_status_name);
$item["user"] = $this->createOrFetchUser($row);
$item["location"] = $this->createOrFetchLocation($item_location);
$item["category"] = $this->createOrFetchCategory($item_category, $item_type);
$item["manufacturer"] = $this->createOrFetchManufacturer($row);
$item["company"] = $this->createOrFetchCompany($item_company_name);
$item["user"] = $this->createOrFetchUser($row, $password);
$item["status_label"] = $this->createOrFetchStatusLabel($item_status_name);
if (!($this->updating && empty($item_location))) {
$item["location"] = $this->createOrFetchLocation($item_location);
}
if (!($this->updating && empty($item_category))) {
$item["category"] = $this->createOrFetchCategory($item_category, $item_type);
}
if (!($this->updating && empty($item_manufacturer))) {
$item["manufacturer"] = $this->createOrFetchManufacturer($item_manufacturer);
}
if (!($this->updating && empty($item_company_name))) {
$item["company"] = $this->createOrFetchCompany($item_company_name);
}
if (!($this->updating && empty($item_status_name))) {
$item["status_label"] = $this->createOrFetchStatusLabel($item_status_name);
}
switch ($item_type) {
case "asset":
@@ -222,7 +247,7 @@ class ObjectImportCommand extends Command
}
// Tracks the current item for error messages
private $current_assetId;
private $updating;
// An array of errors encountered while parsing
private $errors;
@@ -271,7 +296,7 @@ class ObjectImportCommand extends Command
*/
public function array_smart_fetch(array $array, $key, $default = '')
{
return array_key_exists($key, $array) ? e(trim($array[ $key ])) : $default;
return array_key_exists(trim($key), $array) ? e(Encoding::fixUTF8(trim($array[ $key ]))) : $default;
}
@@ -308,8 +333,10 @@ class ObjectImportCommand extends Command
$asset_model_name = $this->array_smart_fetch($row, "model name");
$asset_modelno = $this->array_smart_fetch($row, "model number");
if (empty($asset_model_name)) {
$asset_model_name='Unknown';
if ((empty($asset_model_name)) && (!empty($asset_modelno))) {
$asset_model_name = $asset_modelno;
} elseif ((empty($asset_model_name)) && (empty($asset_modelno))) {
$asset_model_name ='Unknown';
}
if (empty($asset_modelno)) {
$asset_modelno='';
@@ -317,31 +344,44 @@ class ObjectImportCommand extends Command
$this->log('Model Name: ' . $asset_model_name);
$this->log('Model No: ' . $asset_modelno);
$asset_model = null;
$editingModel = false;
foreach ($this->asset_models as $tempmodel) {
if ((strcasecmp($tempmodel->name, $asset_model_name) == 0)
&& $tempmodel->modelno == $asset_modelno
&& $tempmodel->category_id == $category->id
&& $tempmodel->manufacturer_id == $manufacturer->id ) {
$this->log('A matching model ' . $asset_model_name . ' with model number ' . $asset_modelno . ' already exists');
return $tempmodel;
if (strcasecmp($tempmodel->name, $asset_model_name) == 0
&& $tempmodel->modelno == $asset_modelno) {
$this->log('A matching model ' . $asset_model_name . ' already exists');
if (!$this->option('update')) {
return $tempmodel;
}
$this->log('Updating matching model with new values');
$editingModel = true;
$asset_model = $tempmodel;
}
}
$asset_model = new AssetModel();
$asset_model->name = $asset_model_name;
$asset_model->manufacturer_id = $manufacturer->id;
$asset_model->modelno = $asset_modelno;
$asset_model->category_id = $category->id;
if (is_null($asset_model)) {
$this->log("No Matching Model, Creating a new one");
$asset_model = new AssetModel();
}
if (($editingModel && (!$asset_model_name === "Unknown")) || (!$editingModel)) {
$asset_model->name = $asset_model_name;
}
isset($manufacturer) && $manufacturer->exists && $asset_model->manufacturer_id = $manufacturer->id;
isset($asset_modelno) && $asset_model->modelno = $asset_modelno;
if (isset($category) && $category->exists) {
$asset_model->category_id = $category->id;
}
$asset_model->user_id = $this->option('user_id');
if (!$editingModel) {
$this->asset_models->add($asset_model);
}
if (!$this->option('testrun')) {
if ($asset_model->save()) {
$this->asset_models->add($asset_model);
$this->log('Asset Model ' . $asset_model_name . ' with model number ' . $asset_modelno . ' was created');
return $asset_model;
} else {
$this->jsonError('Asset Model "' . $asset_model_name . '"', $asset_model->getErrors());
$this->log('Asset Model "' . $asset_model_name . '"', $asset_model->getErrors());
return $asset_model;
}
} else {
@@ -456,6 +496,10 @@ class ObjectImportCommand extends Command
$status = new Statuslabel();
$status->name = $asset_statuslabel_name;
$status->deployable = 1;
$status->pending = 0;
$status->archived = 0;
if (!$this->option('testrun')) {
if ($status->save()) {
@@ -479,23 +523,20 @@ class ObjectImportCommand extends Command
*
* @author Daniel Melzter
* @since 3.0
* @param $row array
* @param $item_manufacturer string
* @return Manufacturer
* @internal param $asset_mfgr string
*/
public function createOrFetchManufacturer(array $row)
public function createOrFetchManufacturer($item_manufacturer)
{
$asset_mfgr = $this->array_smart_fetch($row, "manufacturer");
if (empty($asset_mfgr)) {
$asset_mfgr='Unknown';
if (empty($item_manufacturer)) {
$item_manufacturer='Unknown';
}
$this->log('Manufacturer ID: ' . $asset_mfgr);
foreach ($this->manufacturers as $tempmanufacturer) {
if (strcasecmp($tempmanufacturer->name, $asset_mfgr) == 0) {
$this->log('Manufacturer ' . $asset_mfgr . ' already exists') ;
if (strcasecmp($tempmanufacturer->name, $item_manufacturer) == 0) {
$this->log('Manufacturer ' . $item_manufacturer . ' already exists') ;
return $tempmanufacturer;
}
}
@@ -503,7 +544,7 @@ class ObjectImportCommand extends Command
//Otherwise create a manufacturer.
$manufacturer = new Manufacturer();
$manufacturer->name = $asset_mfgr;
$manufacturer->name = $item_manufacturer;
$manufacturer->user_id = $this->option('user_id');
if (!$this->option('testrun')) {
@@ -583,27 +624,26 @@ class ObjectImportCommand extends Command
* @param $row array
* @return Supplier
*/
public function createOrFetchSupplier(array $row)
public function createOrFetchSupplier($item_supplier)
{
$supplier_name = $this->array_smart_fetch($row, "supplier");
if (empty($supplier_name)) {
$supplier_name='Unknown';
if (empty($item_supplier)) {
$item_supplier='Unknown';
}
foreach ($this->suppliers as $tempsupplier) {
if (strcasecmp($tempsupplier->name, $supplier_name) == 0) {
$this->log('A matching Company ' . $supplier_name . ' already exists');
if (strcasecmp($tempsupplier->name, $item_supplier) == 0) {
$this->log('A matching Supplier ' . $item_supplier . ' already exists');
return $tempsupplier;
}
}
$supplier = new Supplier();
$supplier->name = $supplier_name;
$supplier->name = $item_supplier;
$supplier->user_id = $this->option('user_id');
if (!$this->option('testrun')) {
if ($supplier->save()) {
$this->suppliers->add($supplier);
$this->log('Supplier ' . $supplier_name . ' was created');
$this->log('Supplier ' . $item_supplier . ' was created');
return $supplier;
} else {
$this->log('Supplier', $supplier->getErrors());
@@ -627,7 +667,7 @@ class ObjectImportCommand extends Command
* @internal param string $first_name
* @internal param string $last_name
*/
public function createOrFetchUser($row)
public function createOrFetchUser($row, $password = null)
{
$user_name = $this->array_smart_fetch($row, "name");
$user_email = $this->array_smart_fetch($row, "email");
@@ -652,7 +692,12 @@ class ObjectImportCommand extends Command
$last_name = $user_email_array['last_name'];
if ($user_email=='') {
$user_email = $user_email_array['username'].'@'.Setting::getSettings()->email_domain;
if (Setting::getSettings()->email_domain) {
$user_email = str_slug($user_email_array['username']).'@'.Setting::getSettings()->email_domain;
} else {
$user_email = '';
}
}
if ($user_username=='') {
@@ -685,14 +730,13 @@ class ObjectImportCommand extends Command
$this->log('User '.$user_username.' already exists');
} elseif (( $first_name != '') && ($last_name != '') && ($user_username != '')) {
$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->password = bcrypt($password);
$user->activated = 1;
$user->password = $password;
if ($user->save()) {
$this->log('User '.$first_name.' created');
} else {
@@ -720,6 +764,24 @@ class ObjectImportCommand extends Command
*/
public function createAssetIfNotExists(array $row, array $item)
{
$asset = null;
$editingAsset = false;
foreach ($this->assets as $tempasset) {
if (strcasecmp($tempasset->asset_tag, $item['asset_tag']) == 0) {
$this->log('A matching Asset ' . $item['asset_tag'] . ' already exists');
if (!$this->option('update')) {
$this->log("Skipping item.");
return;
}
$this->log('Updating matching asset with new values');
$editingAsset = true;
$asset = $tempasset;
}
}
if (is_null($asset)) {
$this->log("No Matching Asset, Creating a new one");
$asset = new Asset;
}
$asset_serial = $this->array_smart_fetch($row, "serial number");
$asset_image = $this->array_smart_fetch($row, "image");
$asset_warranty_months = intval($this->array_smart_fetch($row, "warranty months"));
@@ -727,36 +789,42 @@ class ObjectImportCommand extends Command
$asset_warranty_months = null;
}
// Check for the asset model match and create it if it doesn't exist
$asset_model = $this->createOrFetchAssetModel($row, $item["category"], $item["manufacturer"]);
$supplier = $this->createOrFetchSupplier($row);
if (!($editingAsset && empty($this->array_smart_fetch($row, 'model name')))) {
// Ignore the asset_model
isset($item["category"]) || $item["category"] = new Category();
isset($item["manufacturer"]) || $item["manufacturer"] = new Manufacturer();
$asset_model = $this->createOrFetchAssetModel($row, $item["category"], $item["manufacturer"]);
}
$item_supplier = $this->array_smart_fetch($row, "supplier");
// If we're editing, only update if value isn't empty
if (!($editingAsset && empty($item_supplier))) {
$supplier = $this->createOrFetchSupplier($item_supplier);
}
$this->log('Serial No: '.$asset_serial);
$this->log('Asset Tag: '.$item['asset_tag']);
$this->log('Notes: '.$item["notes"]);
$this->log('Warranty Months: ' . $asset_warranty_months);
foreach ($this->assets as $tempasset) {
if (strcasecmp($tempasset->asset_tag, $item['asset_tag']) == 0) {
$this->log('A matching Asset ' . $item['asset_tag'] . ' already exists');
return;
}
}
if ($item["status_label"]) {
if (isset($item["status_label"])) {
$status_id = $item["status_label"]->id;
} else {
} else if (!$editingAsset) {
// Assume if we are editing, we already have a status and can ignore.
// FIXME: We're already grabbing the list of statuses, we should probably not hardcode here
$this->log("No status field found, defaulting to id 1.");
$status_id = 1;
$status_id = $this->status_labels->first()->id;
}
$asset = new Asset();
$asset->name = $item["item_name"];
if ($item["purchase_date"] != '') {
if (!$editingAsset) {
$asset->asset_tag = $item['asset_tag']; // This doesn't need to be guarded for empty because it's the key we use to identify the asset.
}
if (!empty($item['item_name'])) {
$asset->name = $item["item_name"];
}
if (!empty($item["purchase_date"])) {
$asset->purchase_date = $item["purchase_date"];
} else {
$asset->purchase_date = null;
}
if (array_key_exists('custom_fields', $item)) {
@@ -768,40 +836,57 @@ class ObjectImportCommand extends Command
if (!empty($item["purchase_cost"])) {
//TODO How to generalize this for not USD?
$purchase_cost = substr($item["purchase_cost"], 0, 1) === '$' ? substr($item["purchase_cost"], 1) : $item["purchase_cost"];
$asset->purchase_cost = number_format($purchase_cost, 2);
// $asset->purchase_cost = number_format($purchase_cost, 2, '.', '');
$asset->purchase_cost = Helper::ParseFloat($purchase_cost);
$this->log("Asset cost parsed: " . $asset->purchase_cost);
} else {
$asset->purchase_cost = 0.00;
}
$asset->serial = $asset_serial;
$asset->asset_tag = $item['asset_tag'];
$asset->warranty_months = $asset_warranty_months;
if (!empty($asset_serial)) {
$asset->serial = $asset_serial;
}
if (!empty($asset_warranty_months)) {
$asset->warranty_months = $asset_warranty_months;
}
if ($asset_model) {
if (isset($asset_model)) {
$asset->model_id = $asset_model->id;
}
if ($item["user"]) {
$asset->assigned_to = $item["user"]->id;
}
if ($item["location"]) {
if (isset($item["location"])) {
$asset->rtd_location_id = $item["location"]->id;
}
$asset->user_id = $this->option('user_id');
$this->log("status_id: " . $status_id);
$asset->status_id = $status_id;
if ($item["company"]) {
if (isset($status_id)) {
$asset->status_id = $status_id;
}
if (isset($item["company"])) {
$asset->company_id = $item["company"]->id;
}
$asset->order_number = $item["order_number"];
if ($supplier) {
if ($item["order_number"]) {
$asset->order_number = $item["order_number"];
}
if (isset($supplier)) {
$asset->supplier_id = $supplier->id;
}
$asset->notes = $item["notes"];
$asset->image = $asset_image;
$this->assets->add($asset);
if ($item["notes"]) {
$asset->notes = $item["notes"];
}
if (!empty($asset_image)) {
$asset->image = $asset_image;
}
if (!$editingAsset) {
$this->assets->add($asset);
}
if (!$this->option('testrun')) {
if ($asset->save()) {
$asset->logCreate('Imported using csv importer');
$this->log('Asset ' . $item["item_name"] . ' with serial number ' . $asset_serial . ' was created');
} else {
$this->jsonError('Asset', $asset->getErrors());
@@ -823,17 +908,29 @@ class ObjectImportCommand extends Command
*/
public function createAccessoryIfNotExists(array $item)
{
$accessory = null;
$editingAccessory = false;
$this->log("Creating Accessory");
foreach ($this->accessories as $tempaccessory) {
if (strcasecmp($tempaccessory->name, $item["item_name"]) == 0) {
$this->log('A matching Accessory ' . $item["item_name"] . ' already exists. ');
// FUTURE: Adjust quantity on import maybe?
return;
if (!$this->option('update')) {
$this->log("Skipping accessory.");
return;
}
$this->log('Updating matching accessory with new values');
$editingAccessory = true;
$accessory = $tempaccessory;
}
}
if (is_null($accessory)) {
$this->log("No Matching Accessory, Creating a new one");
$accessory = new Accessory();
}
$accessory = new Accessory();
$accessory->name = $item["item_name"];
if (!$editingAccessory) {
$accessory->name = $item["item_name"];
}
if (!empty($item["purchase_date"])) {
$accessory->purchase_date = $item["purchase_date"];
@@ -841,35 +938,41 @@ class ObjectImportCommand extends Command
$accessory->purchase_date = null;
}
if (!empty($item["purchase_cost"])) {
$accessory->purchase_cost = number_format(e($item["purchase_cost"]), 2);
} else {
$accessory->purchase_cost = 0.00;
$accessory->purchase_cost = Helper::ParseFloat($item["purchase_cost"]);
}
if ($item["location"]) {
if (isset($item["location"])) {
$accessory->location_id = $item["location"]->id;
}
$accessory->user_id = $this->option('user_id');
if ($item["company"]) {
if (isset($item["company"])) {
$accessory->company_id = $item["company"]->id;
}
$accessory->order_number = $item["order_number"];
if ($item["category"]) {
if (!empty($item["order_number"])) {
$accessory->order_number = $item["order_number"];
}
if (isset($item["category"])) {
$accessory->category_id = $item["category"]->id;
}
//TODO: Implement
// $accessory->notes = e($item_notes);
$accessory->requestable = filter_var($item["requestable"], FILTER_VALIDATE_BOOLEAN);
if (!empty($item["requestable"])) {
$accessory->requestable = filter_var($item["requestable"], FILTER_VALIDATE_BOOLEAN);
}
//Must have at least zero of the item if we import it.
if ($item["quantity"] > -1) {
$accessory->qty = $item["quantity"];
} else {
$accessory->qty = 1;
if (!empty($item["quantity"])) {
if ($item["quantity"] > -1) {
$accessory->qty = $item["quantity"];
} else {
$accessory->qty = 1;
}
}
if (!$this->option('testrun')) {
if ($accessory->save()) {
$accessory->logCreate('Imported using CSV Importer');
$this->log('Accessory ' . $item["item_name"] . ' was created');
// $this->comment('Accessory ' . $item["item_name"] . ' was created');
@@ -892,18 +995,29 @@ class ObjectImportCommand extends Command
*/
public function createConsumableIfNotExists(array $item)
{
$consumable = null;
$editingConsumable = false;
$this->log("Creating Consumable");
foreach ($this->consumables as $tempconsumable) {
if (strcasecmp($tempconsumable->name, $item["item_name"]) == 0) {
$this->log("A matching consumable " . $item["item_name"] . " already exists");
//TODO: Adjust quantity if different maybe?
return;
if (!$this->option('update')) {
$this->log("Skipping consumable.");
return;
}
$this->log('Updating matching consumable with new values');
$editingConsumable = true;
$consumable = $tempconsumable;
}
}
$consumable = new Consumable();
$consumable->name = $item["item_name"];
if (is_null($consumable)) {
$this->log("No matching consumable, creating one");
$consumable = new Consumable();
}
if (!$editingConsumable) {
$consumable->name = $item["item_name"];
}
if (!empty($item["purchase_date"])) {
$consumable->purchase_date = $item["purchase_date"];
} else {
@@ -911,27 +1025,39 @@ class ObjectImportCommand extends Command
}
if (!empty($item["purchase_cost"])) {
$consumable->purchase_cost = number_format(e($item["purchase_cost"]), 2);
} else {
$consumable->purchase_cost = 0.00;
$consumable->purchase_cost = Helper::ParseFloat($item["purchase_cost"]);
}
if (isset($item["location"])) {
$consumable->location_id = $item["location"]->id;
}
$consumable->location_id = $item["location"]->id;
$consumable->user_id = $this->option('user_id');
$consumable->company_id = $item["company"]->id;
$consumable->order_number = $item["order_number"];
$consumable->category_id = $item["category"]->id;
if (isset($item["company"])) {
$consumable->company_id = $item["company"]->id;
}
if (!empty($item["order_number"])) {
$consumable->order_number = $item["order_number"];
}
if (isset($item["category"])) {
$consumable->category_id = $item["category"]->id;
}
// TODO:Implement
//$consumable->notes= e($item_notes);
$consumable->requestable = filter_var($item["requestable"], FILTER_VALIDATE_BOOLEAN);
if (!empty($item["requestable"])) {
$consumable->requestable = filter_var($item["requestable"], FILTER_VALIDATE_BOOLEAN);
}
if ($item["quantity"] > -1) {
$consumable->qty = $item["quantity"];
} else {
$consumable->qty = 1;
if (!empty($item["quantity"])) {
if ($item["quantity"] > -1) {
$consumable->qty = $item["quantity"];
} else {
$consumable->qty = 1;
}
}
if (!$this->option("testrun")) {
// dd($consumable);
if ($consumable->save()) {
$consumable->logCreate('Imported using CSV Importer');
$this->log("Consumable " . $item["item_name"] . ' was created');
// $this->comment("Consumable " . $item["item_name"] . ' was created');
@@ -973,8 +1099,9 @@ class ObjectImportCommand extends Command
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('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('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'),
);
}

View File

@@ -77,6 +77,8 @@ class PaveIt extends Command
DB::statement('delete from asset_logs');
DB::statement('delete from asset_maintenances');
DB::statement('delete from asset_uploads');
DB::statement('delete from action_logs');
DB::statement('delete from checkout_requests');
DB::statement('delete from consumables_users');
DB::statement('delete from custom_field_custom_fieldset');
DB::statement('delete from custom_fields');
@@ -92,10 +94,12 @@ class PaveIt extends Command
\DB::statement('drop table IF EXISTS accessories_users');
\DB::statement('drop table IF EXISTS accessories');
\DB::statement('drop table IF EXISTS asset_logs');
\DB::statement('drop table IF EXISTS action_logs');
\DB::statement('drop table IF EXISTS asset_maintenances');
\DB::statement('drop table IF EXISTS asset_uploads');
\DB::statement('drop table IF EXISTS assets');
\DB::statement('drop table IF EXISTS categories');
\DB::statement('drop table IF EXISTS checkout_requests');
\DB::statement('drop table IF EXISTS companies');
\DB::statement('drop table IF EXISTS consumables_users');
\DB::statement('drop table IF EXISTS consumables');

View File

@@ -62,15 +62,19 @@ class Purge extends Command
$assetcount = $assets->count();
$this->info($assets->count().' assets purged.');
$asset_assoc = 0;
$asset_maintenances = 0;
foreach ($assets as $asset) {
$this->info('- Asset "'.$asset->showAssetName().'" deleted.');
$asset_assoc += $asset->assetlog()->count();
$asset->assetlog()->forceDelete();
$asset_maintenances += $asset->assetmaintenances()->count();
$asset->assetmaintenances()->forceDelete();
$asset->forceDelete();
}
$this->info($asset_assoc.' corresponding log records purged.');
$this->info($asset_maintenances.' corresponding maintenance records purged.');
$locations = Location::whereNotNull('deleted_at')->withTrashed()->get();
$this->info($locations->count().' locations purged.');

View File

@@ -66,7 +66,7 @@ class SendExpirationAlerts extends Command
$asset_data['email_content'] .= '<td><a href="'.config('app.url').'/hardware/'.e($asset->id).'/view">';
$asset_data['email_content'] .= $asset->showAssetName().'</a></td><td>'.e($asset->asset_tag).'</td>';
$asset_data['email_content'] .= '<td>'.e($asset->warrantee_expires()).'</td>';
$asset_data['email_content'] .= '<td>'.$difference.' days</td>';
$asset_data['email_content'] .= '<td>'.$difference.' '.trans('mail.days').'</td>';
$asset_data['email_content'] .= '<td>'.($asset->supplier ? e($asset->supplier->name) : '').'</td>';
$asset_data['email_content'] .= '<td>'.($asset->assigneduser ? e($asset->assigneduser->fullName()) : '').'</td>';
$asset_data['email_content'] .= '</tr>';
@@ -100,17 +100,21 @@ class SendExpirationAlerts extends Command
if (count($expiring_assets) > 0) {
$this->info('Report sent to '.Setting::getSettings()->alert_email);
\Mail::send('emails.expiring-assets-report', $asset_data, function ($m) {
$m->to(explode(',', Setting::getSettings()->alert_email), Setting::getSettings()->site_name);
$m->subject('Expiring Assets Report');
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.Expiring_Assets_Report'));
});
}
if (count($expiring_licenses) > 0) {
$this->info('Report sent to '.Setting::getSettings()->alert_email);
\Mail::send('emails.expiring-licenses-report', $license_data, function ($m) {
$m->to(explode(',', Setting::getSettings()->alert_email), Setting::getSettings()->site_name);
$m->subject('Expiring Licenses Report');
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.Expiring_Licenses_Report'));
});
}

View File

@@ -50,7 +50,8 @@ class SendInventoryAlerts extends Command
if (count($data['data']) > 0) {
\Mail::send('emails.low-inventory', $data, function ($m) {
$m->to(explode(',', Setting::getSettings()->alert_email), Setting::getSettings()->site_name);
$m->subject('Low Inventory Report');
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.Low_Inventory_Report'));
});
}

View File

@@ -42,7 +42,7 @@ class Versioning extends Command
{
// Path to the file containing your version
// This will be overwritten everything you commit a message
$versionFile = app_path().'/config/version.php';
$versionFile = 'config/version.php';
// The git's output
// get the argument passed in the git command
@@ -50,7 +50,7 @@ class Versioning extends Command
// discard the commit hash
$version = explode('-', $hash_version);
$realVersion = $version[0] . '-' . $version[1];
$realVersion = $version[0];
// save the version array to a variable
$array = var_export(array('app_version' => $realVersion,'hash_version' => $hash_version), true);

View File

@@ -23,6 +23,7 @@ class Kernel extends ConsoleKernel
Commands\SystemBackup::class,
Commands\DisableLDAP::class,
Commands\Purge::class,
Commands\LdapSync::class,
];
/**

View File

@@ -17,16 +17,20 @@ use App\Models\Component;
use App\Models\Accessory;
use App\Models\Consumable;
use App\Models\Asset;
use Crypt;
use Illuminate\Contracts\Encryption\DecryptException;
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
class Helper
{
/**
* Simple helper to invoke the markdown parser
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @return String
*/
public static function parseEscapedMarkedown($str) {
$Parsedown = new \Parsedown();
@@ -36,20 +40,33 @@ class Helper
}
// This doesn't do anything yet
public static function parseEmailList($emails)
/**
* The importer has formatted number strings since v3,
* so the value might be a string, or an integer.
* If it's a number, format it as a string.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @return String
*/
public static function formatCurrencyOutput($cost)
{
$emails_array = explode(',', $emails);
return array_walk($emails_array, 'trim_value');
if (is_numeric($cost)) {
return number_format($cost, 2, '.', '');
}
// It's already been parsed.
return $cost;
}
// This doesn't do anything yet
public static function trim_value(&$value)
{
return trim($value);
}
// Static colors for pie charts
/**
* Static colors for pie charts.
* This is inelegant, and could be refactored later.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.3]
* @return Array
*/
public static function chartColors()
{
$colors = [
@@ -67,8 +84,15 @@ class Helper
return $colors;
}
// Static background (highlight) colors for pie charts
// This is not currently used, but might be in the near future.
/**
* Static background (highlight) colors for pie charts
* This is inelegant, and could be refactored later.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.2]
* @return Array
*/
public static function chartBackgroundColors()
{
$colors = [
@@ -87,10 +111,15 @@ class Helper
}
/**
* Format currency using comma for thousands until local info is property used.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.7]
* @return String
*/
public static function ParseFloat($floatString)
{
// use comma for thousands until local info is property used
$LocaleInfo = localeconv();
$floatString = str_replace(",", "", $floatString);
$floatString = str_replace($LocaleInfo["decimal_point"], ".", $floatString);
@@ -98,6 +127,13 @@ class Helper
}
/**
* Get the list of models in an array to make a dropdown menu
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.5]
* @return Array
*/
public static function modelList()
{
$models = AssetModel::with('manufacturer')->get();
@@ -108,6 +144,13 @@ class Helper
return $model_array;
}
/**
* Get the list of companies in an array to make a dropdown menu
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.5]
* @return Array
*/
public static function companyList()
{
$company_list = array('0' => trans('general.select_company')) + DB::table('companies')
@@ -117,6 +160,13 @@ class Helper
}
/**
* 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 categoryList($category_type = null)
{
$categories = Category::orderBy('name', 'asc')
@@ -128,6 +178,13 @@ class Helper
return $category_list;
}
/**
* Get the list of suppliers in an array to make a dropdown menu
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.5]
* @return Array
*/
public static function suppliersList()
{
$supplier_list = array('' => trans('general.select_supplier')) + Supplier::orderBy('name', 'asc')
@@ -136,6 +193,14 @@ class Helper
return $supplier_list;
}
/**
* Get the list of status labels in an array to make a dropdown menu
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.5]
* @return Array
*/
public static function statusLabelList()
{
$statuslabel_list = array('' => trans('general.select_statuslabel')) + Statuslabel::orderBy('name', 'asc')
@@ -143,6 +208,14 @@ class Helper
return $statuslabel_list;
}
/**
* Get the list of locations in an array to make a dropdown menu
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.5]
* @return Array
*/
public static function locationsList()
{
$location_list = array('' => trans('general.select_location')) + Location::orderBy('name', 'asc')
@@ -150,6 +223,14 @@ class Helper
return $location_list;
}
/**
* Get the list of manufacturers in an array to make a dropdown menu
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.5]
* @return Array
*/
public static function manufacturerList()
{
$manufacturer_list = array('' => trans('general.select_manufacturer')) +
@@ -158,12 +239,26 @@ class Helper
return $manufacturer_list;
}
/**
* Get the list of status label types in an array to make a dropdown menu
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.5]
* @return Array
*/
public static function statusTypeList()
{
$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 $statuslabel_types;
}
/**
* Get the list of managers in an array to make a dropdown menu
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.5]
* @return Array
*/
public static function managerList()
{
$manager_list = array('' => trans('general.select_user')) +
@@ -175,6 +270,13 @@ class Helper
return $manager_list;
}
/**
* Get the list of depreciations in an array to make a dropdown menu
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.5]
* @return Array
*/
public static function depreciationList()
{
$depreciation_list = ['' => 'Do Not Depreciate'] + Depreciation::orderBy('name', 'asc')
@@ -182,16 +284,30 @@ class Helper
return $depreciation_list;
}
/**
* Get the list of category types in an array to make a dropdown menu
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.5]
* @return Array
*/
public static function categoryTypeList()
{
$category_types = array('' => '','accessory' => 'Accessory', 'asset' => 'Asset', 'consumable' => 'Consumable','component' => 'Component');
return $category_types;
}
/**
* Get the list of users in an array to make a dropdown menu
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.5]
* @return Array
*/
public static function usersList()
{
$users_list = array( '' => trans('general.select_user')) +
User::where('deleted_at', '=', null)
Company::scopeCompanyables(User::where('deleted_at', '=', null))
->where('show_in_list','=',1)
->orderBy('last_name', 'asc')
->orderBy('first_name', 'asc')->get()
@@ -200,6 +316,13 @@ class Helper
return $users_list;
}
/**
* Get the list of assets in an array to make a dropdown menu
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.5]
* @return Array
*/
public static function assetsList()
{
$assets_list = array('' => trans('general.select_asset')) + Asset::orderBy('name', 'asc')
@@ -208,27 +331,54 @@ class Helper
return $assets_list;
}
/**
* Get the detailed list of assets in an array to make a dropdown menu
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.5]
* @return Array
*/
public static function detailedAssetList()
{
$assets = array('' => trans('general.select_asset')) + Company::scopeCompanyables(Asset::all(), 'assets.company_id')->lists('detailed_name', 'id')->toArray();
$assets = array('' => trans('general.select_asset')) + Company::scopeCompanyables(Asset::with('assignedUser', 'model'), 'assets.company_id')->get()->lists('detailed_name', 'id')->toArray();
return $assets;
}
/**
* Get the list of custom fields in an array to make a dropdown menu
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.5]
* @return Array
*/
public static function customFieldsetList()
{
$customfields = array('' => trans('admin/models/general.no_custom_field')) + CustomFieldset::pluck('name', 'id')->toArray();
return $customfields;
}
/**
* Get the list of custom field formats in an array to make a dropdown menu
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.4]
* @return Array
*/
public static function predefined_formats()
{
$keys=array_keys(CustomField::$PredefinedFormats);
$stuff=array_combine($keys, $keys);
return $stuff+["" => "Custom Format..."];
return $stuff+["" => trans('admin/custom_fields/general.custom_format')];
}
/**
* Get the list of barcode dimensions
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.3]
* @return Array
*/
public static function barcodeDimensions($barcode_type = 'QRCODE')
{
if ($barcode_type == 'C128') {
@@ -244,6 +394,13 @@ class Helper
return $size;
}
/**
* Generates a random string
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return Array
*/
public static function generateRandomString($length = 10)
{
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
@@ -255,10 +412,15 @@ class Helper
return $randomString;
}
/**
* This nasty little method gets the low inventory info for the
* alert dropdown
**/
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return Array
*/
public static function checkLowInventory()
{
$consumables = Consumable::with('users')->whereNotNull('min_amt')->get();
@@ -339,9 +501,16 @@ class Helper
}
/**
* Check if the file is an image, so we can show a preview
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @param File $file
* @return String | Boolean
*/
public static function checkUploadIsImage($file)
{
// Check if the file is an image, so we can show a preview
$finfo = @finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension
$filetype = @finfo_file($finfo, $file);
finfo_close($finfo);
@@ -403,4 +572,117 @@ class Helper
return $permissions_arr;
}
/**
* Introspects into the model validation to see if the field passed is required.
* This is used by the blades to add a required class onto the HTML element.
* This isn't critical, but is helpful to keep form fields in sync with the actual
* model level validation.
*
* This does not currently handle form request validation requiredness :(
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return boolean
*/
public static function checkIfRequired($class, $field) {
$rules = $class::rules();
foreach ($rules as $rule_name => $rule) {
if ($rule_name == $field) {
if (strpos($rule, 'required') === false) {
return false;
} else {
return true;
}
}
}
}
/**
* Check to see if the given key exists in the array, and trim excess white space before returning it
*
* @author Daniel Melzter
* @since 3.0
* @param $array array
* @param $key string
* @param $default string
* @return string
*/
public static function array_smart_fetch(array $array, $key, $default = '')
{
array_change_key_case($array, CASE_LOWER);
return array_key_exists(strtolower($key), array_change_key_case($array)) ? e(trim($array[ $key ])) : $default;
}
/**
* Check to see if the given key exists in the array, and trim excess white space before returning it
*
* @author A. Gianotto
* @since 3.2
* @param $array array
* @return string
*/
public static function getLastDateFromHistoryArray(array $array)
{
foreach ($array as $key => $value) {
// echo '<pre>';
// echo 'last:'.$key;
// print_r($array);
// echo '</pre>';
}
}
/**
* Gracefully handle decrypting the legacy data (encrypted via mcrypt) and use the new
* decryption method instead.
*
* This is not currently used, but will be.
*
* @author A. Gianotto
* @since 3.6
* @param CustomField $field
* @param String $string
* @return string
*/
public static function gracefulDecrypt(CustomField $field, $string) {
if ($field->isFieldDecryptable($string)) {
try {
Crypt::decrypt($string);
return Crypt::decrypt($string);
} catch (DecryptException $e) {
return 'Error Decrypting: '.$e->getMessage();
}
}
return $string;
}
/**
* Strip HTML out of returned JSON. This is pretty gross, and I'd like to find a better way
* to handle this, but the REST API will solve some of these problems anyway.
*
* This is not currently used, but will be.
*
* @author A. Gianotto
* @since 3.4
* @param $array array
* @return Array
*/
public static function stripTagsFromJSON(Array $array) {
foreach ($array as $key => $value) {
$clean_value = strip_tags($value);
$clean_array[$key] = $clean_value;
}
return $clean_array;
}
}

View File

@@ -19,6 +19,7 @@ use Str;
use View;
use Auth;
use Request;
use Gate;
/** This controller handles all actions related to Accessories for
* the Snipe-IT Asset Management application.
@@ -52,14 +53,12 @@ class AccessoriesController extends Controller
public function getCreate(Request $request)
{
// Show the page
$category_list = Helper::categoryList('accessory');
$company_list = Helper::companyList();
$location_list = Helper::locationsList();
return View::make('accessories/edit')
->with('accessory', new Accessory)
->with('category_list', $category_list)
->with('company_list', $company_list)
->with('location_list', $location_list);
->with('category_list', Helper::categoryList('accessory'))
->with('company_list', Helper::companyList())
->with('location_list', Helper::locationsList())
->with('manufacturer_list', Helper::manufacturerList());
}
@@ -76,12 +75,13 @@ class AccessoriesController extends Controller
$accessory = new Accessory();
// Update the accessory data
$accessory->name = e(Input::get('name'));
$accessory->category_id = e(Input::get('category_id'));
$accessory->location_id = e(Input::get('location_id'));
$accessory->min_amt = e(Input::get('min_amt'));
$accessory->name = e(Input::get('name'));
$accessory->category_id = e(Input::get('category_id'));
$accessory->location_id = e(Input::get('location_id'));
$accessory->min_amt = e(Input::get('min_amt'));
$accessory->company_id = Company::getIdForCurrentUser(Input::get('company_id'));
$accessory->order_number = e(Input::get('order_number'));
$accessory->manufacturer_id = e(Input::get('manufacturer_id'));
if (e(Input::get('purchase_date')) == '') {
$accessory->purchase_date = null;
@@ -92,14 +92,15 @@ class AccessoriesController extends Controller
if (e(Input::get('purchase_cost')) == '0.00') {
$accessory->purchase_cost = null;
} else {
$accessory->purchase_cost = e(Input::get('purchase_cost'));
$accessory->purchase_cost = Helper::ParseFloat(e(Input::get('purchase_cost')));
}
$accessory->qty = e(Input::get('qty'));
$accessory->user_id = Auth::user()->id;
$accessory->qty = e(Input::get('qty'));
$accessory->user_id = Auth::user()->id;
// Was the accessory created?
if ($accessory->save()) {
$accessory->logCreate();
// Redirect to the new accessory page
return redirect()->to("admin/accessories")->with('success', trans('admin/accessories/message.create.success'));
}
@@ -125,14 +126,11 @@ class AccessoriesController extends Controller
return redirect()->to('admin/accessories')->with('error', trans('general.insufficient_permissions'));
}
$category_list = Helper::categoryList('accessory');
$company_list = Helper::companyList();
$location_list = Helper::locationsList();
return View::make('accessories/edit', compact('accessory'))
->with('category_list', $category_list)
->with('company_list', $company_list)
->with('location_list', $location_list);
->with('category_list', Helper::categoryList('accessory'))
->with('company_list', Helper::companyList())
->with('location_list', Helper::locationsList())
->with('manufacturer_list', Helper::manufacturerList());
}
@@ -145,9 +143,9 @@ class AccessoriesController extends Controller
*/
public function postEdit(Request $request, $accessoryId = null)
{
// Check if the blog post exists
// Check if the accessory exists
if (is_null($accessory = Accessory::find($accessoryId))) {
// Redirect to the blogs management page
// Redirect to the accessory index page
return redirect()->to('admin/accessories')->with('error', trans('admin/accessories/message.does_not_exist'));
} elseif (!Company::isCurrentUserHasAccess($accessory)) {
return redirect()->to('admin/accessories')->with('error', trans('general.insufficient_permissions'));
@@ -159,11 +157,12 @@ class AccessoriesController extends Controller
if (e(Input::get('location_id')) == '') {
$accessory->location_id = null;
} else {
$accessory->location_id = e(Input::get('location_id'));
$accessory->location_id = e(Input::get('location_id'));
}
$accessory->min_amt = e(Input::get('min_amt'));
$accessory->min_amt = e(Input::get('min_amt'));
$accessory->category_id = e(Input::get('category_id'));
$accessory->company_id = Company::getIdForCurrentUser(Input::get('company_id'));
$accessory->manufacturer_id = e(Input::get('manufacturer_id'));
$accessory->order_number = e(Input::get('order_number'));
if (e(Input::get('purchase_date')) == '') {
@@ -180,9 +179,9 @@ class AccessoriesController extends Controller
$accessory->qty = e(Input::get('qty'));
// Was the accessory created?
// Was the accessory updated?
if ($accessory->save()) {
// Redirect to the new accessory page
// Redirect to the updated accessory page
return redirect()->to("admin/accessories")->with('success', trans('admin/accessories/message.update.success'));
}
@@ -311,14 +310,7 @@ class AccessoriesController extends Controller
'user_id' => Auth::user()->id,
'assigned_to' => e(Input::get('assigned_to'))));
$logaction = new Actionlog();
$logaction->accessory_id = $accessory->id;
$logaction->asset_id = 0;
$logaction->checkedout_to = $accessory->assigned_to;
$logaction->asset_type = 'accessory';
$logaction->location_id = $user->location_id;
$logaction->user_id = Auth::user()->id;
$logaction->note = e(Input::get('note'));
$logaction = $accessory->logCheckout(e(Input::get('note')));
@@ -342,11 +334,11 @@ class AccessoriesController extends Controller
'fields' => [
[
'title' => 'Checked Out:',
'value' => strtoupper($logaction->asset_type).' <'.config('app.url').'/admin/accessories/'.$accessory->id.'/view'.'|'.$accessory->name.'> checked out to <'.config('app.url').'/admin/users/'.$user->id.'/view|'.$user->fullName().'> by <'.config('app.url').'/admin/users/'.$admin_user->id.'/view'.'|'.$admin_user->fullName().'>.'
'value' => 'Accessory <'.config('app.url').'/admin/accessories/'.$accessory->id.'/view'.'|'.$accessory->name.'> checked out to <'.config('app.url').'/admin/users/'.$user->id.'/view|'.$user->fullName().'> by <'.config('app.url').'/admin/users/'.$admin_user->id.'/view'.'|'.$admin_user->fullName().'>.'
],
[
'title' => 'Note:',
'value' => e($logaction->note)
'value' => e(Input::get('note'))
],
]
])->send('Accessory Checked Out');
@@ -357,9 +349,6 @@ class AccessoriesController extends Controller
}
$log = $logaction->logaction('checkout');
$accessory_user = DB::table('accessories_users')->where('assigned_to', '=', $accessory->assigned_to)->where('accessory_id', '=', $accessory->id)->first();
$data['log_id'] = $logaction->id;
@@ -377,7 +366,8 @@ class AccessoriesController extends Controller
Mail::send('emails.accept-accessory', $data, function ($m) use ($user) {
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
$m->subject('Confirm accessory delivery');
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.Confirm_accessory_delivery'));
});
}
@@ -437,8 +427,7 @@ class AccessoriesController extends Controller
return redirect()->to('admin/accessories')->with('error', trans('general.insufficient_permissions'));
}
$logaction = new Actionlog();
$logaction->checkedout_to = e($accessory_user->assigned_to);
$logaction = $accessory->logCheckin(e(Input::get('note')));
$return_to = e($accessory_user->assigned_to);
$admin_user = Auth::user();
@@ -446,12 +435,6 @@ class AccessoriesController extends Controller
// Was the accessory updated?
if (DB::table('accessories_users')->where('id', '=', $accessory_user->id)->delete()) {
$logaction->accessory_id = e($accessory->id);
$logaction->location_id = null;
$logaction->asset_type = 'accessory';
$logaction->user_id = e($admin_user->id);
$logaction->note = e(Input::get('note'));
$settings = Setting::getSettings();
if ($settings->slack_endpoint) {
@@ -471,7 +454,7 @@ class AccessoriesController extends Controller
'fields' => [
[
'title' => 'Checked In:',
'value' => strtoupper($logaction->asset_type).' <'.config('app.url').'/admin/accessories/'.e($accessory->id).'/view'.'|'.e($accessory->name).'> checked in by <'.config('app.url').'/admin/users/'.e($admin_user->id).'/view'.'|'.e($admin_user->fullName()).'>.'
'value' => class_basename(strtoupper($logaction->item_type)).' <'.config('app.url').'/admin/accessories/'.e($accessory->id).'/view'.'|'.e($accessory->name).'> checked in by <'.config('app.url').'/admin/users/'.e($admin_user->id).'/view'.'|'.e($admin_user->fullName()).'>.'
],
[
'title' => 'Note:',
@@ -487,9 +470,6 @@ class AccessoriesController extends Controller
}
$log = $logaction->logaction('checkin from');
if (!is_null($accessory_user->assigned_to)) {
$user = User::find($accessory_user->assigned_to);
}
@@ -505,7 +485,8 @@ class AccessoriesController extends Controller
Mail::send('emails.checkin-asset', $data, function ($m) use ($user) {
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
$m->subject('Confirm Accessory Checkin');
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.Confirm_Accessory_Checkin'));
});
}
@@ -549,9 +530,11 @@ class AccessoriesController extends Controller
**/
public function getDatatable(Request $request)
{
$accessories = Accessory::select('accessories.*')->with('category', 'company')
->whereNull('accessories.deleted_at');
$accessories = Company::scopeCompanyables(
Accessory::select('accessories.*')
->whereNull('accessories.deleted_at')
->with('category', 'company', 'manufacturer', 'users', 'location')
);
if (Input::has('search')) {
$accessories = $accessories->TextSearch(e(Input::get('search')));
}
@@ -591,7 +574,21 @@ class AccessoriesController extends Controller
$rows = array();
foreach ($accessories as $accessory) {
$actions = '<nobr><a href="'.route('checkout/accessory', $accessory->id).'" style="margin-right:5px;" class="btn btn-info btn-sm" '.(($accessory->numRemaining() > 0 ) ? '' : ' disabled').'>'.trans('general.checkout').'</a><a href="'.route('update/accessory', $accessory->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/accessory', $accessory->id).'" data-content="'.trans('admin/accessories/message.delete.confirm').'" data-title="'.trans('general.delete').' '.htmlspecialchars($accessory->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a></nobr>';
$actions = '<nobr>';
if (Gate::allows('accessories.checkout')) {
$actions .= '<a href="' . route('checkout/accessory',
$accessory->id) . '" style="margin-right:5px;" class="btn btn-info btn-sm" ' . (($accessory->numRemaining() > 0) ? '' : ' disabled') . '>' . trans('general.checkout') . '</a>';
}
if (Gate::allows('accessories.edit')) {
$actions .= '<a href="' . route('update/accessory',
$accessory->id) . '" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a>';
}
if (Gate::allows('accessories.delete')) {
$actions .= '<a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="' . route('delete/accessory',
$accessory->id) . '" data-content="' . trans('admin/accessories/message.delete.confirm') . '" data-title="' . trans('general.delete') . ' ' . htmlspecialchars($accessory->name) . '?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>';
}
$actions .= '</nobr>';
$company = $accessory->company;
$rows[] = array(
@@ -602,10 +599,12 @@ class AccessoriesController extends Controller
'min_amt' => e($accessory->min_amt),
'location' => ($accessory->location) ? e($accessory->location->name): '',
'purchase_date' => e($accessory->purchase_date),
'purchase_cost' => number_format($accessory->purchase_cost, 2),
'purchase_cost' => Helper::formatCurrencyOutput($accessory->purchase_cost),
'numRemaining' => $accessory->numRemaining(),
'actions' => $actions,
'companyName' => is_null($company) ? '' : e($company->name)
'companyName' => is_null($company) ? '' : e($company->name),
'manufacturer' => $accessory->manufacturer ? (string) link_to('/admin/settings/manufacturers/'.$accessory->manufacturer_id.'/view', $accessory->manufacturer->name) : ''
);
}
@@ -654,10 +653,20 @@ class AccessoriesController extends Controller
$rows = array();
foreach ($accessory_users as $user) {
$actions = '<a href="'.route('checkin/accessory', $user->pivot->id).'" class="btn btn-info btn-sm">Checkin</a>';
$actions = '';
if (Gate::allows('accessories.checkin')) {
$actions .= '<a href="' . route('checkin/accessory',
$user->pivot->id) . '" class="btn btn-info btn-sm">Checkin</a>';
}
if (Gate::allows('users.view')) {
$name = (string) link_to('/admin/users/'.$user->id.'/view', e($user->fullName()));
} else {
$name = e($user->fullName());
}
$rows[] = array(
'name' =>(string) link_to('/admin/users/'.$user->id.'/view', e($user->fullName())),
'name' => $name,
'actions' => $actions
);
}

View File

@@ -0,0 +1,18 @@
<?php
namespace App\Http\Controllers;
use App\Helpers\Helper;
use Response;
class ActionlogController extends Controller
{
public function displaySig($filename)
{
$file = config('app.private_uploads') . '/signatures/' . $filename;
$filetype = Helper::checkUploadIsImage($file);
$contents = file_get_contents($file);
return Response::make($contents)->header('Content-Type', $filetype);
}
}

View File

@@ -122,20 +122,18 @@ class AssetMaintenancesController extends Controller
$actions = '<nobr><a href="'.route('update/asset_maintenance', $maintenance->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/asset_maintenance', $maintenance->id).'" data-content="'.trans('admin/asset_maintenances/message.delete.confirm').'" data-title="'.trans('general.delete').' '.htmlspecialchars($maintenance->title).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a></nobr>';
if (($maintenance->cost) && ($maintenance->asset->assetloc) && ($maintenance->asset->assetloc->currency!='')) {
if (($maintenance->cost) && (isset($maintenance->asset)) && ($maintenance->asset->assetloc) && ($maintenance->asset->assetloc->currency!='')) {
$maintenance_cost = $maintenance->asset->assetloc->currency.$maintenance->cost;
} else {
$maintenance_cost = $settings->default_currency.$maintenance->cost;
}
$company = $maintenance->asset->company;
$rows[] = array(
'id' => $maintenance->id,
'asset_name' => (string)link_to('/hardware/'.$maintenance->asset->id.'/view', $maintenance->asset->showAssetName()) ,
'asset_name' => ($maintenance->asset) ? (string)link_to('/hardware/'.$maintenance->asset->id.'/view', $maintenance->asset->showAssetName()) : 'Deleted Asset' ,
'title' => $maintenance->title,
'notes' => $maintenance->notes,
'supplier' => $maintenance->supplier->name,
'supplier' => ($maintenance->supplier) ? (string)link_to('/admin/settings/suppliers/'.$maintenance->supplier->id.'/view', $maintenance->supplier->name) : 'Deleted Supplier',
'cost' => $maintenance_cost,
'asset_maintenance_type' => e($maintenance->asset_maintenance_type),
'start_date' => $maintenance->start_date,
@@ -143,7 +141,7 @@ class AssetMaintenancesController extends Controller
'completion_date' => $maintenance->completion_date,
'user_id' => ($maintenance->admin) ? (string)link_to('/admin/users/'.$maintenance->admin->id.'/view', $maintenance->admin->fullName()) : '',
'actions' => $actions,
'companyName' => is_null($company) ? '' : $company->name
'companyName' => ($maintenance->asset->company) ? $maintenance->asset->company->name : ''
);
}
@@ -217,7 +215,7 @@ class AssetMaintenancesController extends Controller
if (e(Input::get('cost')) == '') {
$assetMaintenance->cost = '';
} else {
$assetMaintenance->cost = e(Input::get('cost'));
$assetMaintenance->cost = Helper::ParseFloat(e(Input::get('cost')));
}
if (e(Input::get('notes')) == '') {
@@ -309,7 +307,7 @@ class AssetMaintenancesController extends Controller
'' => 'Select an improvement type',
] + AssetMaintenance::getImprovementOptions();
$assets = Company::scopeCompanyables(Asset::all(), 'assets.company_id')->lists('detailed_name', 'id');
$assets = Company::scopeCompanyables(Asset::with('model','assignedUser')->get(), 'assets.company_id')->lists('detailed_name', 'id');
// Get Supplier List
$supplier_list = Helper::suppliersList();
@@ -365,7 +363,7 @@ class AssetMaintenancesController extends Controller
if (e(Input::get('cost')) == '') {
$assetMaintenance->cost = '';
} else {
$assetMaintenance->cost = e(Input::get('cost'));
$assetMaintenance->cost = Helper::ParseFloat(e(Input::get('cost')));
}
if (e(Input::get('notes')) == '') {

View File

@@ -92,19 +92,19 @@ class AssetModelsController extends Controller
$model->eol = e(Input::get('eol'));
}
// Save the model data
$model->name = e(Input::get('name'));
$model->modelno = e(Input::get('modelno'));
$model->manufacturer_id = e(Input::get('manufacturer_id'));
$model->category_id = e(Input::get('category_id'));
$model->note = e(Input::get('note'));
$model->user_id = Auth::user()->id;
// Save the model data
$model->name = e(Input::get('name'));
$model->modelno = e(Input::get('modelno'));
$model->manufacturer_id = e(Input::get('manufacturer_id'));
$model->category_id = e(Input::get('category_id'));
$model->note = e(Input::get('note'));
$model->user_id = Auth::user()->id;
$model->requestable = Input::has('requestable');
if (Input::get('custom_fieldset')!='') {
$model->fieldset_id = e(Input::get('custom_fieldset'));
}
//$model->show_mac_address = e(Input::get('show_mac_address', '0'));
if (Input::file('image')) {
$image = Input::file('image');
@@ -141,7 +141,7 @@ class AssetModelsController extends Controller
$model = new AssetModel;
$settings=Input::all();
$settings['eol']=0;
$settings['eol']= null;
$model->name=e(Input::get('name'));
$model->manufacturer_id = e(Input::get('manufacturer_id'));
@@ -149,7 +149,7 @@ class AssetModelsController extends Controller
$model->modelno = e(Input::get('modelno'));
$model->user_id = Auth::user()->id;
$model->note = e(Input::get('note'));
$model->eol=0;
$model->eol= null;
if (Input::get('fieldset_id')=='') {
$model->fieldset_id = null;
@@ -217,7 +217,7 @@ class AssetModelsController extends Controller
}
if (e(Input::get('eol')) == '') {
$model->eol = 0;
$model->eol = null;
} else {
$model->eol = e(Input::get('eol'));
}
@@ -227,7 +227,10 @@ class AssetModelsController extends Controller
$model->modelno = e(Input::get('modelno'));
$model->manufacturer_id = e(Input::get('manufacturer_id'));
$model->category_id = e(Input::get('category_id'));
$model->note = e(Input::get('note'));
$model->note = e(Input::get('note'));
$model->requestable = Input::has('requestable');
if (Input::get('custom_fieldset')=='') {
$model->fieldset_id = null;
} else {
@@ -413,7 +416,7 @@ class AssetModelsController extends Controller
public function getDatatable($status = null)
{
$models = AssetModel::with('category', 'assets', 'depreciation');
$models = AssetModel::with('category', 'assets', 'depreciation', 'manufacturer');
switch ($status) {
case 'Deleted':
@@ -488,7 +491,7 @@ class AssetModelsController extends Controller
*/
public function getDataView($modelID)
{
$assets = Asset::where('model_id', '=', $modelID)->with('company');
$assets = Asset::where('model_id', '=', $modelID)->with('company', 'assetstatus');
if (Input::has('search')) {
$assets = $assets->TextSearch(e(Input::get('search')));

View File

@@ -23,6 +23,7 @@ use Validator;
use Artisan;
use Auth;
use Config;
use League\Csv\Reader;
use DB;
use Image;
use Input;
@@ -39,6 +40,8 @@ use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\HttpFoundation\JsonResponse;
use TCPDF;
use View;
use Carbon\Carbon;
use Gate;
/**
* This class controls all actions related to assets for
@@ -175,7 +178,7 @@ class AssetsController extends Controller
if (e(Input::get('purchase_cost')) == '') {
$asset->purchase_cost = null;
} else {
$asset->purchase_cost = (e(Input::get('purchase_cost')));
$asset->purchase_cost = Helper::ParseFloat(e(Input::get('purchase_cost')));
}
if (e(Input::get('purchase_date')) == '') {
@@ -228,7 +231,7 @@ class AssetsController extends Controller
$directory= public_path('uploads/assets/');
// Check if the uploads directory exists. If not, try to create it.
if (!file_exists($directory)) {
mkdir($directory, 0755);
mkdir($directory, 0755, true);
}
$path = public_path('uploads/assets/'.$file_name);
try {
@@ -237,7 +240,7 @@ class AssetsController extends Controller
$constraint->upsize();
})->save($path);
$asset->image = $file_name;
} catch(\Exception $e) {
} catch (\Exception $e) {
\Input::flash();
$messageBag = new \Illuminate\Support\MessageBag();
$messageBag->add('image', $e->getMessage());
@@ -261,15 +264,10 @@ class AssetsController extends Controller
// Was the asset created?
if ($asset->save()) {
$asset->logCreate();
if (Input::get('assigned_to')!='') {
$logaction = new Actionlog();
$logaction->asset_id = $asset->id;
$logaction->checkedout_to = $asset->assigned_to;
$logaction->asset_type = 'hardware';
$logaction->user_id = Auth::user()->id;
$logaction->note = e(Input::get('note'));
$log = $logaction->logaction('checkout');
$user = User::find(e(Input::get('assigned_to')));
$asset->checkOutToUser($user, Auth::user(), date('Y-m-d H:i:s'), '', 'Checked out on asset creation', e(Input::get('name')));
}
// Redirect to the asset listing page
\Session::flash('success', trans('admin/hardware/message.create.success'));
@@ -290,7 +288,7 @@ class AssetsController extends Controller
*/
public function getEdit($assetId = null)
{
// Check if the asset exists
if (!$asset = Asset::find($assetId)) {
// Redirect to the asset management page
@@ -356,7 +354,7 @@ class AssetsController extends Controller
}
if ($request->has('purchase_cost')) {
$asset->purchase_cost = e($request->input('purchase_cost'));
$asset->purchase_cost = Helper::ParseFloat(e($request->input('purchase_cost')));
} else {
$asset->purchase_cost = null;
}
@@ -409,7 +407,7 @@ class AssetsController extends Controller
$directory= public_path('uploads/assets/');
// Check if the uploads directory exists. If not, try to create it.
if (!file_exists($directory)) {
mkdir($directory, 0755);
mkdir($directory, 0755, true);
}
$file_name = str_random(25).".".$extension;
@@ -420,7 +418,7 @@ class AssetsController extends Controller
$constraint->upsize();
})->save($path);
$asset->image = $file_name;
} catch(\Exception $e) {
} catch (\Exception $e) {
\Input::flash();
$messageBag = new \Illuminate\Support\MessageBag();
$messageBag->add('image', $e->getMessage());
@@ -438,14 +436,22 @@ class AssetsController extends Controller
$model = AssetModel::find($request->get('model_id'));
if ($model->fieldset) {
foreach ($model->fieldset->fields as $field) {
$asset->{\App\Models\CustomField::name_to_db_name($field->name)} = e($request->input(\App\Models\CustomField::name_to_db_name($field->name)));
// LOG::debug($field->name);
// LOG::debug(\App\Models\CustomField::name_to_db_name($field->name));
// LOG::debug($field->db_column_name());
if ($field->field_encrypted=='1') {
if (Gate::allows('admin')) {
$asset->{\App\Models\CustomField::name_to_db_name($field->name)} = \Crypt::encrypt(e($request->input(\App\Models\CustomField::name_to_db_name($field->name))));
}
} else {
$asset->{\App\Models\CustomField::name_to_db_name($field->name)} = e($request->input(\App\Models\CustomField::name_to_db_name($field->name)));
}
}
}
if ($asset->save()) {
// Redirect to the new asset page
\Session::flash('success', trans('admin/hardware/message.update.success'));
@@ -532,6 +538,8 @@ class AssetsController extends Controller
return redirect()->to('hardware')->with('error', trans('admin/hardware/message.does_not_exist'));
} elseif (!Company::isCurrentUserHasAccess($asset)) {
return redirect()->to('hardware')->with('error', trans('general.insufficient_permissions'));
} elseif (!$asset->availableForCheckout()) {
return redirect()->to('hardware')->with('error', trans('admin/hardware/message.checkout.not_available'));
}
$user = User::find(e(Input::get('assigned_to')));
@@ -624,8 +632,13 @@ class AssetsController extends Controller
// Was the asset updated?
if ($asset->save()) {
$checkout_at = e(Input::get('checkin_at'));
$logaction = $asset->createLogRecord('checkin', $asset, $admin, $user, null, e(Input::get('note')), $checkout_at);
if ($request->input('checkin_at') == Carbon::now()->format('Y-m-d')) {
$checkin_at = Carbon::now();
} else {
$checkin_at = $request->input('checkin_at').' 00:00:00';
}
//$checkin_at = e(Input::get('checkin_at'));
$logaction = $asset->createLogRecord('checkin', $asset, $admin, $user, null, e(Input::get('note')), $checkin_at);
$settings = Setting::getSettings();
@@ -646,7 +659,7 @@ class AssetsController extends Controller
'fields' => [
[
'title' => 'Checked In:',
'value' => strtoupper($logaction->asset_type).' asset <'.config('app.url').'/hardware/'.$asset->id.'/view'.'|'.e($asset->showAssetName()).'> checked in by <'.config('app.url').'/admin/users/'.Auth::user()->id.'/view'.'|'.e(Auth::user()->fullName()).'>.'
'value' => class_basename(strtoupper($logaction->item_type)).' asset <'.config('app.url').'/hardware/'.$asset->id.'/view'.'|'.e($asset->showAssetName()).'> checked in by <'.config('app.url').'/admin/users/'.Auth::user()->id.'/view'.'|'.e(Auth::user()->fullName()).'>.'
],
[
'title' => 'Note:',
@@ -673,7 +686,8 @@ class AssetsController extends Controller
if ((($asset->checkin_email()=='1')) && ($user) && (!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->subject('Confirm Asset Checkin');
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.Confirm_Asset_Checkin'));
});
}
@@ -755,14 +769,20 @@ 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';
if (isset($asset->id,$asset->asset_tag)) {
$barcode = new \Com\Tecnick\Barcode\Barcode();
$barcode_obj = $barcode->getBarcodeObj($settings->barcode_type, route('view/hardware', $asset->id), $size['height'], $size['width'], 'black', array(-2, -2, -2, -2));
return response($barcode_obj->getPngData())->header('Content-type', 'image/png');
if (file_exists($qr_file)) {
$header = ['Content-type' => 'image/png'];
return response()->file($qr_file, $header);
} else {
$barcode = new \Com\Tecnick\Barcode\Barcode();
$barcode_obj = $barcode->getBarcodeObj($settings->barcode_type, route('view/hardware', $asset->id), $size['height'], $size['width'], 'black', array(-2, -2, -2, -2));
file_put_contents($qr_file, $barcode_obj->getPngData());
return response($barcode_obj->getPngData())->header('Content-type', 'image/png');
}
}
}
@@ -782,12 +802,20 @@ class AssetsController extends Controller
$settings = Setting::getSettings();
$asset = Asset::find($assetId);
$barcode_file = public_path().'/uploads/barcodes/'.str_slug($settings->alt_barcode).'-'.str_slug($asset->asset_tag).'.png';
if (isset($asset->id,$asset->asset_tag)) {
$barcode = new \Com\Tecnick\Barcode\Barcode();
$barcode_obj = $barcode->getBarcodeObj($settings->alt_barcode, $asset->asset_tag, 250, 20);
return response($barcode_obj->getPngData())->header('Content-type', 'image/png');
if (file_exists($barcode_file)) {
$header = ['Content-type' => 'image/png'];
return response()->file($barcode_file, $header);
} else {
$barcode = new \Com\Tecnick\Barcode\Barcode();
$barcode_obj = $barcode->getBarcodeObj($settings->alt_barcode, $asset->asset_tag, 250, 20);
file_put_contents($barcode_file, $barcode_obj->getPngData());
return response($barcode_obj->getPngData())->header('Content-type', 'image/png');
}
}
}
@@ -812,7 +840,7 @@ class AssetsController extends Controller
// Check if the uploads directory exists. If not, try to create it.
if (!file_exists($path)) {
mkdir($path, 0755);
mkdir($path, 0755, true);
}
if ($handle = opendir($path)) {
@@ -873,11 +901,11 @@ class AssetsController extends Controller
try {
$file->move($path, $date.'-'.$fixed_filename);
} catch (\Symfony\Component\HttpFoundation\File\Exception\FileException $exception) {
$results['error']=trans('admin/hardware/message.upload.error');
if( config('app.debug')) {
$results['error'].= ' ' . $exception->getMessage();
}
return $results;
$results['error']=trans('admin/hardware/message.upload.error');
if (config('app.debug')) {
$results['error'].= ' ' . $exception->getMessage();
}
return $results;
}
$name = date('Y-m-d-his').'-'.$fixed_filename;
$filesize = Setting::fileSizeConvert(filesize($path.'/'.$name));
@@ -900,6 +928,18 @@ class AssetsController extends Controller
}
public function getDeleteImportFile($filename)
{
if (!Company::isCurrentUserAuthorized()) {
return redirect()->to('hardware')->with('error', trans('general.insufficient_permissions'));
}
if (unlink(config('app.private_uploads').'/imports/assets/'.$filename)) {
return redirect()->back()->with('success', trans('admin/hardware/message.import.file_delete_success'));
}
return redirect()->back()->with('error', trans('admin/hardware/message.import.file_delete_error'));
}
/**
* Process the uploaded file
@@ -909,28 +949,47 @@ class AssetsController extends Controller
* @since [v2.0]
* @return Redirect
*/
public function getProcessImportFile($filename)
public function postProcessImportFile()
{
// php artisan asset-import:csv path/to/your/file.csv --domain=yourdomain.com --email_format=firstname.lastname
$filename = Input::get('filename');
$itemType = Input::get('import-type');
$updateItems = Input::get('import-update');
if (!Company::isCurrentUserAuthorized()) {
return redirect()->to('hardware')->with('error', trans('general.insufficient_permissions'));
}
$return = Artisan::call(
'snipeit:import',
['filename'=> config('app.private_uploads').'/imports/assets/'.$filename,
$importOptions = ['filename'=> config('app.private_uploads').'/imports/assets/'.$filename,
'--email_format'=>'firstname.lastname',
'--username_format'=>'firstname.lastname',
'--web-importer' => true,
'--user_id' => Auth::user()->id
]
);
'--user_id' => Auth::user()->id,
'--item-type' => $itemType,
];
if ($updateItems) {
$importOptions['--update'] = true;
}
$return = Artisan::call('snipeit:import', $importOptions);
$display_output = Artisan::output();
$file = config('app.private_uploads').'/imports/assets/'.str_replace('.csv', '', $filename).'-output-'.date("Y-m-d-his").'.txt';
file_put_contents($file, $display_output);
// We use hardware instead of asset in the url
$redirectTo = "hardware";
switch($itemType) {
case "asset":
$redirectTo = "hardware";
break;
case "accessory":
$redirectTo = "accessories";
break;
case "consumable":
$redirectTo = "consumables";
break;
}
if ($return === 0) { //Success
return redirect()->to('hardware')->with('success', trans('admin/hardware/message.import.success'));
return redirect()->to(route($redirectTo))->with('success', trans('admin/hardware/message.import.success'));
} elseif ($return === 1) { // Failure
return redirect()->back()->with('import_errors', json_decode($display_output))->with('error', trans('admin/hardware/message.import.error'));
}
@@ -988,6 +1047,178 @@ class AssetsController extends Controller
}
/**
* Return history import view
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
public function getImportHistory()
{
return View::make('hardware/history');
}
/**
* Import history
*
* This needs a LOT of love. It's done very inelegantly right now, and there are
* a ton of optimizations that could (and should) be done.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.3]
* @return View
*/
public function postImportHistory(Request $request)
{
if (!ini_get("auto_detect_line_endings")) {
ini_set("auto_detect_line_endings", '1');
}
$assets = Asset::all(['asset_tag']);
$csv = Reader::createFromPath(Input::file('user_import_csv'));
$csv->setNewline("\r\n");
//get the first row, usually the CSV header
//$headers = $csv->fetchOne();
$results = $csv->fetchAssoc();
$item = array();
$status = array();
$status['error'] = array();
$status['success'] = array();
foreach($results as $row) {
if (is_array($row)) {
$row = array_change_key_case($row, CASE_LOWER);
$asset_tag = Helper::array_smart_fetch($row, "asset tag");
if (!array_key_exists($asset_tag, $item)) {
$item[$asset_tag] = array();
}
$batch_counter = count($item[$asset_tag]);
$item[$asset_tag][$batch_counter]['checkout_date'] = Carbon::parse(Helper::array_smart_fetch($row, "date"))->format('Y-m-d H:i:s');
$item[$asset_tag][$batch_counter]['asset_tag'] = Helper::array_smart_fetch($row, "asset tag");
$item[$asset_tag][$batch_counter]['name'] = Helper::array_smart_fetch($row, "name");
$item[$asset_tag][$batch_counter]['email'] = Helper::array_smart_fetch($row, "email");
if ($asset = Asset::where('asset_tag','=',$asset_tag)->first()) {
$item[$asset_tag][$batch_counter]['asset_id'] = $asset->id;
$base_username = User::generateFormattedNameFromFullName(Setting::getSettings()->username_format,$item[$asset_tag][$batch_counter]['name']);
$user = User::where('username','=',$base_username['username']);
$user_query = ' on username '.$base_username['username'];
if ($request->input('match_firstnamelastname')=='1') {
$firstnamedotlastname = User::generateFormattedNameFromFullName('firstname.lastname',$item[$asset_tag][$batch_counter]['name']);
$item[$asset_tag][$batch_counter]['username'][] = $firstnamedotlastname['username'];
$user->orWhere('username','=',$firstnamedotlastname['username']);
$user_query .= ', or on username '.$firstnamedotlastname['username'];
}
if ($request->input('match_flastname')=='1') {
$flastname = User::generateFormattedNameFromFullName('filastname',$item[$asset_tag][$batch_counter]['name']);
$item[$asset_tag][$batch_counter]['username'][] = $flastname['username'];
$user->orWhere('username','=',$flastname['username']);
$user_query .= ', or on username '.$flastname['username'];
}
if ($request->input('match_firstname')=='1') {
$firstname = User::generateFormattedNameFromFullName('firstname',$item[$asset_tag][$batch_counter]['name']);
$item[$asset_tag][$batch_counter]['username'][] = $firstname['username'];
$user->orWhere('username','=',$firstname['username']);
$user_query .= ', or on username '.$firstname['username'];
}
if ($request->input('match_email')=='1') {
if ($item[$asset_tag][$batch_counter]['email']=='') {
$item[$asset_tag][$batch_counter]['username'][] = $user_email = User::generateEmailFromFullName($item[$asset_tag][$batch_counter]['name']);
$user->orWhere('username','=',$user_email);
$user_query .= ', or on username '.$user_email;
}
}
// A matching user was found
if ($user = $user->first()) {
$item[$asset_tag][$batch_counter]['checkedout_to'] = $user->id;
$item[$asset_tag][$batch_counter]['user_id'] = $user->id;
Actionlog::firstOrCreate(array(
'item_id' => $asset->id,
'item_type' => Asset::class,
'user_id' => Auth::user()->id,
'note' => 'Checkout imported by '.Auth::user()->fullName().' from history importer',
'target_id' => $item[$asset_tag][$batch_counter]['user_id'],
'target_type' => User::class,
'created_at' => $item[$asset_tag][$batch_counter]['checkout_date'],
'action_type' => 'checkout',
)
);
$asset->assigned_to = $user->id;
if ($asset->save()) {
$status['success'][]['asset'][$asset_tag]['msg'] = 'Asset successfully matched for '.Helper::array_smart_fetch($row, "name").$user_query.' on '.$item[$asset_tag][$batch_counter]['checkout_date'];
} else {
$status['error'][]['asset'][$asset_tag]['msg'] = 'Asset and user was matched but could not be saved.';
}
} else {
$item[$asset_tag][$batch_counter]['checkedout_to'] = null;
$status['error'][]['user'][Helper::array_smart_fetch($row, "name")]['msg'] = 'User does not exist so no checkin log was created.';
}
} else {
$item[$asset_tag][$batch_counter]['asset_id'] = null;
$status['error'][]['asset'][$asset_tag]['msg'] = 'Asset does not exist so no match was attempted.';
}
}
}
// Loop through and backfill the checkins
foreach ($item as $key => $asset_batch) {
$total_in_batch = count($asset_batch);
for($x = 0; $x < $total_in_batch; $x++) {
$next = $x + 1;
// Only do this if a matching user was found
if ((array_key_exists('checkedout_to',$asset_batch[$x])) && ($asset_batch[$x]['checkedout_to']!='')) {
if (($total_in_batch > 1) && ($x < $total_in_batch) && (array_key_exists($next,$asset_batch))) {
$checkin_date = Carbon::parse($asset_batch[$next]['checkout_date'])->subDay(1)->format('Y-m-d H:i:s');
$asset_batch[$x]['real_checkin'] = $checkin_date;
Actionlog::firstOrCreate(array(
'item_id' => $asset_batch[$x]['asset_id'],
'item_type' => Asset::class,
'user_id' => Auth::user()->id,
'note' => 'Checkin imported by ' . Auth::user()->fullName() . ' from history importer',
'target_id' => null,
'created_at' => $checkin_date,
'action_type' => 'checkin'
)
);
}
}
}
}
return View::make('hardware/history')->with('status',$status);
}
/**
* Retore a deleted asset.
*
@@ -1049,15 +1280,8 @@ class AssetsController extends Controller
$upload_success = $file->move($destinationPath, $filename);
//Log the deletion of seats to the log
$logaction = new Actionlog();
$logaction->asset_id = $asset->id;
$logaction->asset_type = 'hardware';
$logaction->user_id = Auth::user()->id;
$logaction->note = e(Input::get('notes'));
$logaction->checkedout_to = null;
$logaction->created_at = date("Y-m-d H:i:s");
$logaction->filename = $filename;
$log = $logaction->logaction('uploaded');
$asset->logUpload($filename, e(Input::get('notes')));
}
} else {
return redirect()->back()->with('error', trans('admin/hardware/message.upload.nofiles'));
@@ -1200,7 +1424,7 @@ class AssetsController extends Controller
return View::make('hardware/labels')->with('assets', $assets)->with('settings', $settings)->with('count', $count)->with('settings', $settings);
} elseif (Input::get('bulk_actions')=='delete') {
@@ -1268,7 +1492,7 @@ class AssetsController extends Controller
}
if (Input::has('purchase_cost')) {
$update_array['purchase_cost'] = e(Input::get('purchase_cost'));
$update_array['purchase_cost'] = Helper::ParseFloat(e(Input::get('purchase_cost')));
}
if (Input::has('supplier_id')) {
@@ -1314,8 +1538,8 @@ class AssetsController extends Controller
->update($update_array)) {
$logaction = new Actionlog();
$logaction->asset_id = $key;
$logaction->asset_type = 'hardware';
$logaction->item_type = Asset::class;
$logaction->item_id = $key;
$logaction->created_at = date("Y-m-d H:i:s");
if (Input::has('rtd_location_id')) {
@@ -1364,7 +1588,7 @@ class AssetsController extends Controller
foreach ($assets as $asset) {
//echo '<li>'.$asset;
$update_array['deleted_at'] = date('Y-m-d h:i:s');
$update_array['deleted_at'] = date('Y-m-d H:i:s');
$update_array['assigned_to'] = null;
if (DB::table('assets')
@@ -1372,8 +1596,8 @@ class AssetsController extends Controller
->update($update_array)) {
$logaction = new Actionlog();
$logaction->asset_id = $asset->id;
$logaction->asset_type = 'hardware';
$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');
@@ -1404,31 +1628,31 @@ class AssetsController extends Controller
* @since [v2.0]
* @return String JSON
*/
public function getDatatable($status = null)
public function getDatatable(Request $request, $status = null)
{
$assets = Asset::select('assets.*')->with('model', 'assigneduser', 'assigneduser.userloc', 'assetstatus', 'defaultLoc', 'assetlog', 'model', 'model.category', 'model.manufacturer', 'model.fieldset', 'assetstatus', 'assetloc', 'company')
$assets = Company::scopeCompanyables(Asset::select('assets.*'))->with('model', 'assigneduser', 'assigneduser.userloc', 'assetstatus', 'defaultLoc', 'assetlog', 'model', 'model.category', 'model.manufacturer', 'model.fieldset', 'assetstatus', 'assetloc', 'company')
->Hardware();
if (Input::has('search')) {
$assets = $assets->TextSearch(e(Input::get('search')));
if ($request->has('search')) {
$assets = $assets->TextSearch(e($request->get('search')));
}
if (Input::has('offset')) {
$offset = e(Input::get('offset'));
if ($request->has('offset')) {
$offset = e($request->get('offset'));
} else {
$offset = 0;
}
if (Input::has('limit')) {
$limit = e(Input::get('limit'));
if ($request->has('limit')) {
$limit = e($request->get('limit'));
} else {
$limit = 50;
}
if (Input::has('order_number')) {
$assets->where('order_number', '=', e(Input::get('order_number')));
if ($request->has('order_number')) {
$assets->where('order_number', '=', e($request->get('order_number')));
}
switch ($status) {
@@ -1453,9 +1677,14 @@ class AssetsController extends Controller
case 'Deployed':
$assets->Deployed();
break;
}
if ($request->has('status_id')) {
$assets->where('status_id','=', e($request->get('status_id')));
}
$allowed_columns = [
'id',
'name',
@@ -1485,8 +1714,8 @@ class AssetsController extends Controller
$allowed_columns[]=$field->db_column_name();
}
$order = Input::get('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'asset_tag';
$order = $request->get('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->get('sort'), $allowed_columns) ? $request->get('sort') : 'asset_tag';
switch ($sort) {
case 'model':
@@ -1525,23 +1754,42 @@ class AssetsController extends Controller
$rows = array();
foreach ($assets as $asset) {
$inout = '';
$actions = '';
$actions = '<div style="white-space: nowrap;">';
if ($asset->deleted_at=='') {
$actions = '<div style=" white-space: nowrap;"><a href="'.route('clone/hardware', $asset->id).'" class="btn btn-info btn-sm" title="Clone asset" data-toggle="tooltip"><i class="fa fa-clone"></i></a> <a href="'.route('update/hardware', $asset->id).'" class="btn btn-warning btn-sm" title="Edit asset" data-toggle="tooltip"><i class="fa fa-pencil icon-white"></i></a> <a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/hardware', $asset->id).'" data-content="'.trans('admin/hardware/message.delete.confirm').'" data-title="'.trans('general.delete').' '.htmlspecialchars($asset->asset_tag).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a></div>';
if (Gate::allows('assets.create')) {
$actions .= '<a href="' . route('clone/hardware',
$asset->id) . '" class="btn btn-info btn-sm" title="Clone asset" data-toggle="tooltip"><i class="fa fa-clone"></i></a> ';
}
if (Gate::allows('assets.edit')) {
$actions .= '<a href="' . route('update/hardware',
$asset->id) . '" class="btn btn-warning btn-sm" title="Edit asset" data-toggle="tooltip"><i class="fa fa-pencil icon-white"></i></a> ';
}
if (Gate::allows('assets.delete')) {
$actions .= '<a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="' . route('delete/hardware',
$asset->id) . '" data-content="' . trans('admin/hardware/message.delete.confirm') . '" data-title="' . trans('general.delete') . ' ' . htmlspecialchars($asset->asset_tag) . '?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>';
}
} elseif ($asset->model->deleted_at=='') {
$actions = '<a href="'.route('restore/hardware', $asset->id).'" title="Restore asset" data-toggle="tooltip" class="btn btn-warning btn-sm"><i class="fa fa-recycle icon-white"></i></a>';
$actions .= '<a href="'.route('restore/hardware', $asset->id).'" title="Restore asset" data-toggle="tooltip" class="btn btn-warning btn-sm"><i class="fa fa-recycle icon-white"></i></a>';
}
if ($asset->assetstatus) {
if (($asset->assetstatus->deployable != 0) && ($asset->deleted_at=='')) {
if (($asset->assigned_to !='') && ($asset->assigned_to > 0)) {
$inout = '<a href="'.route('checkin/hardware', $asset->id).'" class="btn btn-primary btn-sm" title="Checkin this asset" data-toggle="tooltip">'.trans('general.checkin').'</a>';
} else {
$inout = '<a href="'.route('checkout/hardware', $asset->id).'" class="btn btn-info btn-sm" title="Checkout this asset to a user" data-toggle="tooltip">'.trans('general.checkout').'</a>';
}
$actions .= '</div>';
if (($asset->availableForCheckout()))
{
if (Gate::allows('assets.checkout')) {
$inout = '<a href="' . route('checkout/hardware',
$asset->id) . '" class="btn btn-info btn-sm" title="Checkout this asset to a user" data-toggle="tooltip">' . trans('general.checkout') . '</a>';
}
} else {
if (Gate::allows('assets.checkin')) {
$inout = '<a href="' . route('checkin/hardware',
$asset->id) . '" class="btn btn-primary btn-sm" title="Checkin this asset" data-toggle="tooltip">' . trans('general.checkin') . '</a>';
}
}
$purchase_cost = Helper::formatCurrencyOutput($asset->purchase_cost);
$row = array(
'checkbox' =>'<div class="text-center"><input type="checkbox" name="edit_asset['.$asset->id.']" class="one_required"></div>',
'id' => $asset->id,
@@ -1553,11 +1801,11 @@ class AssetsController extends Controller
'model_number' => ($asset->model && $asset->model->modelno) ? (string)$asset->model->modelno : '',
'status_label' => ($asset->assigneduser) ? 'Deployed' : ((e($asset->assetstatus)) ? e($asset->assetstatus->name) : ''),
'assigned_to' => ($asset->assigneduser) ? (string)link_to(config('app.url').'/admin/users/'.$asset->assigned_to.'/view', e($asset->assigneduser->fullName())) : '',
'location' => (($asset->assigneduser) && ($asset->assigneduser->userloc!='')) ? (string)link_to('admin/settings/locations/'.$asset->assigneduser->userloc->id.'/view', e($asset->assigneduser->userloc->name)) : (($asset->defaultLoc!='') ? (string)link_to('admin/settings/locations/'.$asset->defaultLoc->id.'/edit', e($asset->defaultLoc->name)) : ''),
'location' => (($asset->assigneduser) && ($asset->assigneduser->userloc!='')) ? (string)link_to('admin/settings/locations/'.$asset->assigneduser->userloc->id.'/view', e($asset->assigneduser->userloc->name)) : (($asset->defaultLoc!='') ? (string)link_to('admin/settings/locations/'.$asset->defaultLoc->id.'/view', e($asset->defaultLoc->name)) : ''),
'category' => (($asset->model) && ($asset->model->category)) ?(string)link_to('/admin/settings/categories/'.$asset->model->category->id.'/view', e($asset->model->category->name)) : '',
'manufacturer' => (($asset->model) && ($asset->model->manufacturer)) ? (string)link_to('/admin/settings/manufacturers/'.$asset->model->manufacturer->id.'/view', e($asset->model->manufacturer->name)) : '',
'eol' => ($asset->eol_date()) ? $asset->eol_date() : '',
'purchase_cost' => ($asset->purchase_cost) ? number_format($asset->purchase_cost, 2) : '',
'purchase_cost' => $purchase_cost,
'purchase_date' => ($asset->purchase_date) ? $asset->purchase_date : '',
'notes' => e($asset->notes),
'order_number' => ($asset->order_number!='') ? '<a href="'.config('app.url').'/hardware?order_number='.e($asset->order_number).'">'.e($asset->order_number).'</a>' : '',
@@ -1569,13 +1817,104 @@ class AssetsController extends Controller
'companyName' => is_null($asset->company) ? '' : e($asset->company->name)
);
foreach ($all_custom_fields as $field) {
$row[$field->db_column_name()]=$asset->{$field->db_column_name()};
$column_name = $field->db_column_name();
if ($field->isFieldDecryptable($asset->{$column_name})) {
if (Gate::allows('admin')) {
if (($field->format=='URL') && ($asset->{$column_name}!='')) {
$row[$column_name] = '<a href="'.Helper::gracefulDecrypt($field, $asset->{$column_name}).'" target="_blank">'.Helper::gracefulDecrypt($field, $asset->{$column_name}).'</a>';
} else {
$row[$column_name] = Helper::gracefulDecrypt($field, $asset->{$column_name});
}
} else {
$row[$field->db_column_name()] = strtoupper(trans('admin/custom_fields/general.encrypted'));
}
} else {
if (($field->format=='URL') && ($asset->{$field->db_column_name()}!='')) {
$row[$field->db_column_name()] = '<a href="'.$asset->{$field->db_column_name()}.'" target="_blank">'.$asset->{$field->db_column_name()}.'</a>';
} else {
$row[$field->db_column_name()] = e($asset->{$field->db_column_name()});
}
}
}
$rows[]=$row;
if (($request->has('report')) && ($request->get('report')=='true')) {
$rows[]= Helper::stripTagsFromJSON($row);
} else {
$rows[]= $row;
}
}
$data = array('total'=>$assetCount, 'rows'=>$rows);
return $data;
}
public function getBulkCheckout()
{
// Get the dropdown of users and then pass it to the checkout view
$users_list = Helper::usersList();
// Filter out assets that are not deployable.
$assets = Asset::RTD()->get();
$assets_list = Company::scopeCompanyables($assets, 'assets.company_id')->lists('detailed_name', 'id')->toArray();
return View::make('hardware/bulk-checkout')->with('users_list', $users_list)->with('assets_list', $assets_list);
}
public function postBulkCheckout(Request $request)
{
$this->validate($request, [
"assigned_to" => 'required'
]);
$user = User::find(e(Input::get('assigned_to')));
$admin = Auth::user();
$asset_ids = array_filter(Input::get('selected_assets'));
if ((Input::has('checkout_at')) && (Input::get('checkout_at')!= date("Y-m-d"))) {
$checkout_at = e(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'));
} else {
$expected_checkin = '';
}
$has_errors = false;
$errors = [];
DB::transaction(function() use ($user, $admin, $checkout_at, $expected_checkin, $errors, $asset_ids)
{
foreach($asset_ids as $asset_id)
{
$asset = Asset::find($asset_id);
$error = $asset->checkOutToUser($user, $admin, $checkout_at, $expected_checkin, e(Input::get('note')), null);
if($error)
{
$has_errors = true;
array_merge_recursive($errors, $asset->getErrors()->toArray());
}
}
});
if (!$errors) {
// Redirect to the new asset page
return redirect()->to("hardware")->with('success', trans('admin/hardware/message.checkout.success'));
}
// Redirect to the asset management page with error
return redirect()->to("hardware/bulk-checkout")->with('error', trans('admin/hardware/message.checkout.error'))->withErrors($errors);
}
}

View File

@@ -15,6 +15,7 @@ use Input;
use Redirect;
use Log;
use View;
use PragmaRX\Google2FA\Google2FA;
@@ -48,7 +49,7 @@ class AuthController extends Controller
*/
public function __construct()
{
$this->middleware('guest', ['except' => 'logout']);
$this->middleware('guest', ['except' => ['logout','postTwoFactorAuth','getTwoFactorAuth','getTwoFactorEnroll']]);
}
@@ -63,6 +64,51 @@ class AuthController extends Controller
return View::make('auth.login');
}
private function login_via_ldap(Request $request)
{
LOG::debug("Binding user to LDAP.");
$ldap_user = Ldap::findAndBindUserLdap($request->input('username'), $request->input('password'));
if(!$ldap_user) {
LOG::debug("LDAP user ".$request->input('username')." not found in LDAP or could not bind");
throw new \Exception("Could not find user in LDAP directory");
} else {
LOG::debug("LDAP user ".$request->input('username')." successfully bound to LDAP");
}
// Check if the user exists in the database
$user = User::where('username', '=', Input::get('username'))->whereNull('deleted_at')->first();
LOG::debug("Local auth lookup complete");
// The user does not exist in the database. Try to get them from LDAP.
// If user does not exist and authenticates successfully with LDAP we
// will create it on the fly and sign in with default permissions
if (!$user) {
LOG::debug("Local user ".Input::get('username')." does not exist");
LOG::debug("Creating local user ".Input::get('username'));
if ($user = Ldap::createUserFromLdap($ldap_user)) { //this handles passwords on its own
LOG::debug("Local user created.");
} else {
LOG::debug("Could not create local user.");
throw new \Exception("Could not create local user");
}
// If the user exists and they were imported from LDAP already
} else {
LOG::debug("Local user ".$request->input('username')." exists in database. Updating existing user against LDAP.");
$ldap_attr = Ldap::parseAndMapLdapAttributes($ldap_user);
if (Setting::getSettings()->ldap_pw_sync=='1') {
$user->password = bcrypt($request->input('password'));
}
$user->email = $ldap_attr['email'];
$user->first_name = $ldap_attr['firstname'];
$user->last_name = $ldap_attr['lastname'];
$user->save();
} // End if(!user)
return $user;
}
/**
@@ -77,81 +123,28 @@ class AuthController extends Controller
if ($validator->fails()) {
return redirect()->back()->withInput()->withErrors($validator);
}
$user = null;
// Should we even check for LDAP users?
if (Setting::getSettings()->ldap_enabled=='1') {
LOG::debug("LDAP is enabled.");
// Check if the user exists in the database
$user = User::where('username', '=', Input::get('username'))->whereNull('deleted_at')->first();
LOG::debug("Local auth lookup complete");
try {
Ldap::findAndBindUserLdap($request->input('username'), $request->input('password'));
LOG::debug("Binding user to LDAP.");
$user = $this->login_via_ldap($request);
Auth::login($user, true);
} catch (\Exception $e) {
LOG::debug("User ".Input::get('username').' did not authenticate successfully against LDAP.');
//$ldap_error = $e->getMessage();
// return redirect()->back()->withInput()->with('error',$e->getMessage());
if(Setting::getSettings()->ldap_pw_sync!='1') {
return redirect()->back()->withInput()->with('error',$e->getMessage());
}
}
// The user does not exist in the database. Try to get them from LDAP.
// If user does not exist and authenticates sucessfully with LDAP we
// will create it on the fly and sign in with default permissions
if (!$user) {
LOG::debug("Local user ".Input::get('username')." does not exist");
try {
if ($userattr = Ldap::findAndBindUserLdap($request->input('username'), $request->input('password'))) {
LOG::debug("Creating local user ".Input::get('username'));
if ($newuser = Ldap::createUserFromLdap($userattr)) {
LOG::debug("Local user created..");
} else {
LOG::debug("Could not create local user.");
}
} else {
LOG::debug("User did not authenticate correctly against LDAP. No local user was created.");
}
} catch (\Exception $e) {
return redirect()->back()->withInput()->with('error',$e->getMessage());
}
// If the user exists and they were imported from LDAP already
} else {
LOG::debug("Local user ".Input::get('username')." exists in database. Authenticating existing user against LDAP.");
if ($ldap_user = Ldap::findAndBindUserLdap($request->input('username'), $request->input('password'))) {
$ldap_attr = Ldap::parseAndMapLdapAttributes($ldap_user);
LOG::debug("Valid LDAP login. Updating the local data.");
$user->password = bcrypt($request->input('password'));
$user->email = $ldap_attr['email'];
$user->first_name = $ldap_attr['firstname'];
$user->last_name = $ldap_attr['lastname'];
$user->save();
} else {
LOG::debug("User ".Input::get('username')." did not authenticate correctly against LDAP. Local user was not updated.");
}// End LDAP auth
} // End if(!user)
// NO LDAP enabled - just try to login the user normally
}
LOG::debug("Authenticating user against database.");
// Try to log the user in
if (!Auth::attempt(Input::only('username', 'password'), Input::get('remember-me', 0))) {
LOG::debug("Local authentication failed.");
// throw new Cartalyst\Sentry\Users\UserNotFoundException();
return redirect()->back()->withInput()->with('error', trans('auth/message.account_not_found'));
// If the user wasn't authenticated via LDAP, skip to local auth
if(!$user) {
LOG::debug("Authenticating user against database.");
// Try to log the user in
if (!Auth::attempt(Input::only('username', 'password'), Input::get('remember-me', 0))) {
LOG::debug("Local authentication failed.");
return redirect()->back()->withInput()->with('error', trans('auth/message.account_not_found'));
}
}
// Get the page we were before
@@ -160,25 +153,93 @@ class AuthController extends Controller
// Unset the page we were before from the session
\Session::forget('loginRedirect');
// Redirect to the users page
return redirect()->to($redirect)->with('success', trans('auth/message.signin.success'));
// Ooops.. something went wrong
return redirect()->back()->withInput()->withErrors($this->messageBag);
}
/**
* Two factor enrollment page
*
* @return Redirect
*/
public function getTwoFactorEnroll()
{
if (!Auth::check()) {
return redirect()->route('login')->with('error', 'You must be logged in.');
}
$user = Auth::user();
$google2fa = app()->make('PragmaRX\Google2FA\Contracts\Google2FA');
if ($user->two_factor_secret=='') {
$user->two_factor_secret = $google2fa->generateSecretKey(32);
$user->save();
}
$google2fa_url = $google2fa->getQRCodeGoogleUrl(
Setting::getSettings()->site_name,
$user->username,
$user->two_factor_secret
);
return View::make('auth.two_factor_enroll')->with('google2fa_url',$google2fa_url);
}
/**
* Two factor code form page
*
* @return Redirect
*/
public function getTwoFactorAuth() {
return View::make('auth.two_factor');
}
/**
* Two factor code submission
*
* @return Redirect
*/
public function postTwoFactorAuth(Request $request) {
if (!Auth::check()) {
return redirect()->route('login')->with('error', 'You must be logged in.');
}
$user = Auth::user();
$secret = $request->get('two_factor_secret');
$google2fa = app()->make('PragmaRX\Google2FA\Contracts\Google2FA');
$valid = $google2fa->verifyKey($user->two_factor_secret, $secret);
if ($valid) {
$user->two_factor_enrolled = 1;
$user->save();
$request->session()->put('2fa_authed', 'true');
return redirect()->route('home')->with('success', 'You are logged in!');
}
return redirect()->route('two-factor')->with('error', 'Invalid two-factor code');
}
/**
* Logout page.
*
* @return Redirect
*/
public function logout()
public function logout(Request $request)
{
// Log the user out
$request->session()->forget('2fa_authed');
Auth::logout();
// Redirect to the users page
return redirect()->route('home')->with('success', 'You have successfully logged out!');
return redirect()->route('login')->with('success', 'You have successfully logged out!');
}

View File

@@ -37,4 +37,13 @@ class PasswordController extends Controller
{
$this->middleware('guest');
}
/**
* Get the e-mail subject line to be used for the reset link email.
* Overriding method "getEmailSubject()" from trait "use ResetsPasswords"
* @return string
*/
public function getEmailSubject(){
return property_exists($this, 'subject') ? $this->subject : \Lang::get('mail.reset_link');
}
}

View File

@@ -7,6 +7,8 @@ use App\Models\Company;
use App\Models\Setting;
use Auth;
use DB;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
use Input;
use Lang;
use Redirect;
@@ -133,7 +135,7 @@ class CategoriesController extends Controller
* @since [v1.0]
* @return Redirect
*/
public function postEdit($categoryId = null)
public function postEdit(Request $request, $categoryId = null)
{
// Check if the blog post exists
if (is_null($category = Category::find($categoryId))) {
@@ -142,12 +144,14 @@ class CategoriesController extends Controller
}
// Update the category data
$category->name = e(Input::get('name'));
$category->category_type = e(Input::get('category_type'));
$category->eula_text = e(Input::get('eula_text'));
$category->use_default_eula = e(Input::get('use_default_eula', '0'));
$category->require_acceptance = e(Input::get('require_acceptance', '0'));
$category->checkin_email = e(Input::get('checkin_email', '0'));
$category->name = e($request->input('name'));
// If the item count is > 0, we disable the category type in the edit. Disabled items
// don't POST, so if the category_type is blank we just set it to the default.
$category->category_type = e($request->input('category_type', $category->category_type));
$category->eula_text = e($request->input('eula_text'));
$category->use_default_eula = e($request->input('use_default_eula', '0'));
$category->require_acceptance = e($request->input('require_acceptance', '0'));
$category->checkin_email = e($request->input('checkin_email', '0'));
if ($category->save()) {
// Redirect to the new category page
@@ -303,9 +307,9 @@ class CategoriesController extends Controller
public function getDataViewAssets($categoryID)
{
$category = Category::with('assets.company')->find($categoryID);
$category = Category::find($categoryID);
$category = $category->load('assets.company', 'assets.model', 'assets.assetstatus', 'assets.assigneduser');
$category_assets = $category->assets();
if (Input::has('search')) {
$category_assets = $category_assets->TextSearch(e(Input::get('search')));
}
@@ -329,7 +333,6 @@ class CategoriesController extends Controller
$count = $category_assets->count();
$category_assets = $category_assets->skip($offset)->take($limit)->get();
$rows = array();
foreach ($category_assets as $asset) {
$actions = '';
@@ -341,13 +344,13 @@ class CategoriesController extends Controller
$actions = '<a href="'.route('restore/hardware', $asset->id).'" class="btn btn-warning btn-sm"><i class="fa fa-recycle icon-white"></i></a>';
}
if ($asset->assetstatus) {
if ($asset->assetstatus->deployable != 0) {
if (($asset->assigned_to !='') && ($asset->assigned_to > 0)) {
$inout = '<a href="'.route('checkin/hardware', $asset->id).'" class="btn btn-primary btn-sm">'.trans('general.checkin').'</a>';
} else {
$inout = '<a href="'.route('checkout/hardware', $asset->id).'" class="btn btn-info btn-sm">'.trans('general.checkout').'</a>';
}
if ($asset->availableForCheckout()) {
if (Gate::allows('assets.checkout')) {
$inout = '<a href="'.route('checkout/hardware', $asset->id).'" class="btn btn-info btn-sm">'.trans('general.checkout').'</a>';
}
} else {
if (Gate::allows('assets.checkin')) {
$inout = '<a href="'.route('checkin/hardware', $asset->id).'" class="btn btn-primary btn-sm">'.trans('general.checkin').'</a>';
}
}
@@ -360,7 +363,7 @@ class CategoriesController extends Controller
'assigned_to' => ($asset->assigneduser) ? (string)link_to('/admin/users/'.$asset->assigneduser->id.'/view', $asset->assigneduser->fullName()): '',
'change' => $inout,
'actions' => $actions,
'companyName' => Company::getName($asset),
'companyName' => is_null($asset->company) ? '' : e($asset->company->name)
);
}

View File

@@ -20,6 +20,7 @@ use Str;
use View;
use Validator;
use Illuminate\Http\Request;
use Gate;
/**
* This class controls all actions related to Components for
@@ -88,6 +89,7 @@ class ComponentsController extends Controller
$component->company_id = Company::getIdForCurrentUser(Input::get('company_id'));
$component->order_number = e(Input::get('order_number'));
$component->min_amt = e(Input::get('min_amt'));
$component->serial_number = e(Input::get('serial_number'));
if (e(Input::get('purchase_date')) == '') {
$component->purchase_date = null;
@@ -98,7 +100,7 @@ class ComponentsController extends Controller
if (e(Input::get('purchase_cost')) == '0.00') {
$component->purchase_cost = null;
} else {
$component->purchase_cost = e(Input::get('purchase_cost'));
$component->purchase_cost = Helper::ParseFloat(e(Input::get('purchase_cost')));
}
$component->total_qty = e(Input::get('total_qty'));
@@ -106,6 +108,7 @@ class ComponentsController extends Controller
// Was the component created?
if ($component->save()) {
$component->logCreate();
// Redirect to the new component page
return redirect()->to("admin/components")->with('success', trans('admin/components/message.create.success'));
}
@@ -172,6 +175,7 @@ class ComponentsController extends Controller
$component->company_id = Company::getIdForCurrentUser(Input::get('company_id'));
$component->order_number = e(Input::get('order_number'));
$component->min_amt = e(Input::get('min_amt'));
$component->serial_number = e(Input::get('serial_number'));
if (e(Input::get('purchase_date')) == '') {
$component->purchase_date = null;
@@ -182,7 +186,7 @@ class ComponentsController extends Controller
if (e(Input::get('purchase_cost')) == '0.00') {
$component->purchase_cost = null;
} else {
$component->purchase_cost = e(Input::get('purchase_cost'));
$component->purchase_cost = Helper::ParseFloat(e(Input::get('purchase_cost')));
}
$component->total_qty = e(Input::get('total_qty'));
@@ -344,17 +348,11 @@ class ComponentsController extends Controller
$component->assets()->attach($component->id, array(
'component_id' => $component->id,
'user_id' => $admin_user->id,
'created_at' => date('Y-m-d h:i:s'),
'created_at' => date('Y-m-d H:i:s'),
'assigned_qty' => e(Input::get('assigned_qty')),
'asset_id' => $asset_id));
$logaction = new Actionlog();
$logaction->component_id = $component->id;
$logaction->asset_id = $asset_id;
$logaction->asset_type = 'component';
$logaction->location_id = $asset->location_id;
$logaction->user_id = Auth::user()->id;
$logaction->note = e(Input::get('note'));
$logaction = $component->logCheckout(e(Input::get('note')), $asset_id);
$settings = Setting::getSettings();
@@ -374,7 +372,7 @@ class ComponentsController extends Controller
'fields' => [
[
'title' => 'Checked Out:',
'value' => strtoupper($logaction->asset_type).' <'.config('app.url').'/admin/components/'.$component->id.'/view'.'|'.$component->name.'> checked out to <'.config('app.url').'/hardware/'.$asset->id.'/view|'.$asset->name.'> by <'.config('app.url').'/admin/users/'.$admin_user->id.'/view'.'|'.$admin_user->fullName().'>.'
'value' => class_basename(strtoupper($logaction->item_type)).' <'.config('app.url').'/admin/components/'.$component->id.'/view'.'|'.$component->name.'> checked out to <'.config('app.url').'/hardware/'.$asset->id.'/view|'.$asset->showAssetName().'> by <'.config('app.url').'/admin/users/'.$admin_user->id.'/view'.'|'.$admin_user->fullName().'>.'
],
[
'title' => 'Note:',
@@ -388,9 +386,6 @@ class ComponentsController extends Controller
}
}
$log = $logaction->logaction('checkout');
// Redirect to the new component page
return redirect()->to("admin/components")->with('success', trans('admin/components/message.checkout.success'));
@@ -410,8 +405,8 @@ class ComponentsController extends Controller
**/
public function getDatatable()
{
$components = Component::select('components.*')->whereNull('components.deleted_at')
->with('company', 'location', 'category');
$components = Company::scopeCompanyables(Component::select('components.*')->whereNull('components.deleted_at')
->with('company', 'location', 'category'));
if (Input::has('search')) {
$components = $components->TextSearch(Input::get('search'));
@@ -429,7 +424,7 @@ class ComponentsController extends Controller
$limit = 50;
}
$allowed_columns = ['id','name','min_amt','order_number','purchase_date','purchase_cost','companyName','category','total_qty'];
$allowed_columns = ['id','name','min_amt','order_number','serial_number','purchase_date','purchase_cost','companyName','category','total_qty'];
$order = Input::get('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at';
@@ -454,20 +449,37 @@ class ComponentsController extends Controller
$rows = array();
foreach ($components as $component) {
$actions = '<nobr><a href="'.route('checkout/component', $component->id).'" style="margin-right:5px;" class="btn btn-info btn-sm '.(($component->numRemaining() > 0 ) ? '' : ' disabled').'" '.(($component->numRemaining() > 0 ) ? '' : ' disabled').'>'.trans('general.checkout').'</a><a href="'.route('update/component', $component->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/component', $component->id).'" data-content="'.trans('admin/components/message.delete.confirm').'" data-title="'.trans('general.delete').' '.htmlspecialchars($component->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a></nobr>';
$actions = '<nobr>';
if (Gate::allows('components.checkout')) {
$actions .= '<a href="' . route('checkout/component',
$component->id) . '" style="margin-right:5px;" class="btn btn-info btn-sm ' . (($component->numRemaining() > 0) ? '' : ' disabled') . '" ' . (($component->numRemaining() > 0) ? '' : ' disabled') . '>' . trans('general.checkout') . '</a>';
}
if (Gate::allows('components.edit')) {
$actions .= '<a href="' . route('update/component',
$component->id) . '" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a>';
}
if (Gate::allows('components.delete')) {
$actions .= '<a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="' . route('delete/component',
$component->id) . '" data-content="' . trans('admin/components/message.delete.confirm') . '" data-title="' . trans('general.delete') . ' ' . htmlspecialchars($component->name) . '?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>';
}
$actions .='</nobr>';
$company = $component->company;
$rows[] = array(
'checkbox' =>'<div class="text-center"><input type="checkbox" name="component['.$component->id.']" class="one_required"></div>',
'id' => $component->id,
'name' => (string)link_to('admin/components/'.$component->id.'/view', e($component->name)),
'serial_number' => $component->serial_number,
'location' => ($component->location) ? e($component->location->name) : '',
'total_qty' => e($component->total_qty),
'min_amt' => e($component->min_amt),
'category' => ($component->category) ? e($component->category->name) : 'Missing category',
'order_number' => e($component->order_number),
'purchase_date' => e($component->purchase_date),
'purchase_cost' => ($component->purchase_cost!='') ? number_format($component->purchase_cost, 2): '' ,
'purchase_cost' => Helper::formatCurrencyOutput($component->purchase_cost),
'numRemaining' => $component->numRemaining(),
'actions' => $actions,
'companyName' => is_null($company) ? '' : e($company->name),
@@ -503,7 +515,7 @@ class ComponentsController extends Controller
foreach ($component->assets as $component_assignment) {
$rows[] = array(
'name' => (string)link_to('/hardware/'.$component_assignment->id.'/view', e($component_assignment->name)),
'name' => (string)link_to('/hardware/'.$component_assignment->id.'/view', e($component_assignment->showAssetName())),
'qty' => e($component_assignment->pivot->assigned_qty),
'created_at' => ($component_assignment->created_at->format('Y-m-d H:i:s')=='-0001-11-30 00:00:00') ? '' : $component_assignment->created_at->format('Y-m-d H:i:s'),
);

View File

@@ -18,6 +18,7 @@ use Redirect;
use Slack;
use Str;
use View;
use Gate;
/**
* This controller handles all actions related to Consumables for
@@ -96,7 +97,7 @@ class ConsumablesController extends Controller
if (e(Input::get('purchase_cost')) == '0.00') {
$consumable->purchase_cost = null;
} else {
$consumable->purchase_cost = e(Input::get('purchase_cost'));
$consumable->purchase_cost = Helper::ParseFloat(e(Input::get('purchase_cost')));
}
$consumable->qty = e(Input::get('qty'));
@@ -104,6 +105,7 @@ class ConsumablesController extends Controller
// Was the consumable created?
if ($consumable->save()) {
$consumable->logCreate();
// Redirect to the new consumable page
return redirect()->to("admin/consumables")->with('success', trans('admin/consumables/message.create.success'));
}
@@ -181,10 +183,10 @@ class ConsumablesController extends Controller
if (e(Input::get('purchase_cost')) == '0.00') {
$consumable->purchase_cost = null;
} else {
$consumable->purchase_cost = e(Input::get('purchase_cost'));
$consumable->purchase_cost = Helper::ParseFloat(e(Input::get('purchase_cost')));
}
$consumable->qty = e(Input::get('qty'));
$consumable->qty = Helper::ParseFloat(e(Input::get('qty')));
if ($consumable->save()) {
return redirect()->to("admin/consumables")->with('success', trans('admin/consumables/message.update.success'));
@@ -315,14 +317,7 @@ class ConsumablesController extends Controller
'user_id' => $admin_user->id,
'assigned_to' => e(Input::get('assigned_to'))));
$logaction = new Actionlog();
$logaction->consumable_id = $consumable->id;
$logaction->checkedout_to = $consumable->assigned_to;
$logaction->asset_type = 'consumable';
$logaction->asset_id = 0;
$logaction->location_id = $user->location_id;
$logaction->user_id = Auth::user()->id;
$logaction->note = e(Input::get('note'));
$logaction = $consumable->logCheckout(e(Input::get('note')));
$settings = Setting::getSettings();
@@ -342,7 +337,7 @@ class ConsumablesController extends Controller
'fields' => [
[
'title' => 'Checked Out:',
'value' => strtoupper($logaction->asset_type).' <'.config('app.url').'/admin/consumables/'.$consumable->id.'/view'.'|'.$consumable->name.'> checked out to <'.config('app.url').'/admin/users/'.$user->id.'/view|'.$user->fullName().'> by <'.config('app.url').'/admin/users/'.$admin_user->id.'/view'.'|'.$admin_user->fullName().'>.'
'value' => 'Consumable <'.config('app.url').'/admin/consumables/'.$consumable->id.'/view'.'|'.$consumable->name.'> checked out to <'.config('app.url').'/admin/users/'.$user->id.'/view|'.$user->fullName().'> by <'.config('app.url').'/admin/users/'.$admin_user->id.'/view'.'|'.$admin_user->fullName().'>.'
],
[
'title' => 'Note:',
@@ -356,9 +351,6 @@ class ConsumablesController extends Controller
}
}
$log = $logaction->logaction('checkout');
$consumable_user = DB::table('consumables_users')->where('assigned_to', '=', $consumable->assigned_to)->where('consumable_id', '=', $consumable->id)->first();
$data['log_id'] = $logaction->id;
@@ -374,7 +366,8 @@ class ConsumablesController extends Controller
Mail::send('emails.accept-asset', $data, function ($m) use ($user) {
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
$m->subject('Confirm consumable delivery');
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.Confirm_consumable_delivery'));
});
}
@@ -397,8 +390,11 @@ class ConsumablesController extends Controller
*/
public function getDatatable()
{
$consumables = Consumable::select('consumables.*')->whereNull('consumables.deleted_at')
->with('company', 'location', 'category', 'users');
$consumables = Company::scopeCompanyables(
Consumable::select('consumables.*')
->whereNull('consumables.deleted_at')
->with('company', 'location', 'category', 'users', 'manufacturer')
);
if (Input::has('search')) {
$consumables = $consumables->TextSearch(e(Input::get('search')));
@@ -444,7 +440,23 @@ class ConsumablesController extends Controller
$rows = array();
foreach ($consumables as $consumable) {
$actions = '<nobr><a href="'.route('checkout/consumable', $consumable->id).'" style="margin-right:5px;" class="btn btn-info btn-sm" '.(($consumable->numRemaining() > 0 ) ? '' : ' disabled').'>'.trans('general.checkout').'</a><a href="'.route('update/consumable', $consumable->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/consumable', $consumable->id).'" data-content="'.trans('admin/consumables/message.delete.confirm').'" data-title="'.trans('general.delete').' '.htmlspecialchars($consumable->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a></nobr>';
$actions = '<nobr>';
if (Gate::allows('consumables.checkout')) {
$actions .= '<a href="' . route('checkout/consumable',
$consumable->id) . '" style="margin-right:5px;" class="btn btn-info btn-sm" ' . (($consumable->numRemaining() > 0) ? '' : ' disabled') . '>' . trans('general.checkout') . '</a>';
}
if (Gate::allows('consumables.edit')) {
$actions .= '<a href="' . route('update/consumable',
$consumable->id) . '" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a>';
}
if (Gate::allows('consumables.delete')) {
$actions .= '<a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="' . route('delete/consumable',
$consumable->id) . '" data-content="' . trans('admin/consumables/message.delete.confirm') . '" data-title="' . trans('general.delete') . ' ' . htmlspecialchars($consumable->name) . '?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>';
}
$actions .='</nobr>';
$company = $consumable->company;
$rows[] = array(
@@ -453,13 +465,13 @@ class ConsumablesController extends Controller
'location' => ($consumable->location) ? e($consumable->location->name) : '',
'min_amt' => e($consumable->min_amt),
'qty' => e($consumable->qty),
'manufacturer' => ($consumable->manufacturer) ? e($consumable->manufacturer->name) : '',
'model_no' => e($consumable->model_no),
'item_no' => e($consumable->item_no),
'category' => ($consumable->category) ? e($consumable->category->name) : 'Missing category',
'manufacturer' => ($consumable->manufacturer) ? (string) link_to('/admin/settings/manufacturers/'.$consumable->manufacturer_id.'/view', $consumable->manufacturer->name): '',
'model_no' => e($consumable->model_no),
'item_no' => e($consumable->item_no),
'category' => ($consumable->category) ? (string) link_to('/admin/settings/categories/'.$consumable->category_id.'/view', $consumable->category->name) : 'Missing category',
'order_number' => e($consumable->order_number),
'purchase_date' => e($consumable->purchase_date),
'purchase_cost' => ($consumable->purchase_cost!='') ? number_format($consumable->purchase_cost, 2): '' ,
'purchase_cost' => Helper::formatCurrencyOutput($consumable->purchase_cost),
'numRemaining' => $consumable->numRemaining(),
'actions' => $actions,
'companyName' => is_null($company) ? '' : e($company->name),

View File

@@ -10,6 +10,7 @@ use Redirect;
use App\Models\AssetModel;
use Lang;
use Auth;
use Illuminate\Http\Request;
/**
* This controller handles all actions related to Custom Asset Fields for
@@ -63,10 +64,15 @@ class CustomFieldsController extends Controller
* @since [v1.8]
* @return Redirect
*/
public function store()
public function store(Request $request)
{
//
$cfset=new CustomFieldset(["name" => Input::get("name"),"user_id" => Auth::user()->id]);
$cfset = new CustomFieldset(
[
"name" => e($request->get("name")),
"user_id" => Auth::user()->id]
);
$validator=Validator::make(Input::all(), $cfset->rules);
if ($validator->passes()) {
$cfset->save();
@@ -122,24 +128,33 @@ class CustomFieldsController extends Controller
* @since [v1.8]
* @return Redirect
*/
public function storeField()
public function storeField(Request $request)
{
$field=new CustomField(["name" => Input::get("name"),"element" => Input::get("element"),"user_id" => Auth::user()->id]);
$field = new CustomField([
"name" => e($request->get("name")),
"element" => e($request->get("element")),
"field_values" => e($request->get("field_values")),
"field_encrypted" => e($request->get("field_encrypted", 0)),
"user_id" => Auth::user()->id
]);
if (!in_array(Input::get('format'), array_keys(CustomField::$PredefinedFormats))) {
$field->format=Input::get("custom_format");
$field->format = e($request->get("custom_format"));
} else {
$field->format=Input::get('format');
$field->format = e($request->get("format"));
}
$validator=Validator::make(Input::all(), $field->rules);
if ($validator->passes()) {
$results=$field->save();
//return "postCreateField: $results";
$results = $field->save();
if ($results) {
return redirect()->route("admin.custom_fields.index")->with("success", trans('admin/custom_fields/message.field.create.success'));
} else {
dd($field);
return redirect()->back()->withInput()->with('error', trans('admin/custom_fields/message.field.create.error'));
}
} else {
@@ -147,6 +162,25 @@ class CustomFieldsController extends Controller
}
}
/**
* Detach a custom field from a fieldset.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return Redirect
*/
public function deleteFieldFromFieldset($field_id, $fieldset_id)
{
$field = CustomField::find($field_id);
if ($field->fieldset()->detach($fieldset_id)) {
return redirect()->route("admin.custom_fields.index")->with("success", trans('admin/custom_fields/message.field.delete.success'));
}
return redirect()->back()->withErrors(['message' => "Field is in-use"]);
}
/**
* Delete a custom field.
*
@@ -156,7 +190,7 @@ class CustomFieldsController extends Controller
*/
public function deleteField($field_id)
{
$field=CustomField::find($field_id);
$field = CustomField::find($field_id);
if ($field->fieldset->count()>0) {
return redirect()->back()->withErrors(['message' => "Field is in-use"]);

View File

@@ -30,12 +30,6 @@ class DashboardController extends Controller
// Show the page
if (Auth::user()->hasAccess('admin')) {
$recent_activity = Actionlog::orderBy('created_at', 'DESC')
->with('accessorylog', 'consumablelog', 'licenselog', 'assetlog', 'adminlog', 'userlog', 'componentlog')
->take(30)
->get();
$asset_stats['total'] = Asset::Hardware()->count();
$asset_stats['rtd']['total'] = Asset::Hardware()->RTD()->count();
@@ -82,10 +76,10 @@ class DashboardController extends Controller
}
return View::make('dashboard')->with('asset_stats', $asset_stats)->with('recent_activity', $recent_activity);
return View::make('dashboard')->with('asset_stats', $asset_stats);
} else {
// Redirect to the profile page
return redirect()->route('view-assets');
return redirect()->intended('account/view-assets');
}
}
}

View File

@@ -23,6 +23,7 @@ use Config;
use Session;
use App\Helpers\Helper;
use Auth;
use Gate;
/**
* This controller handles all actions related to Licenses for
@@ -60,18 +61,17 @@ class LicensesController extends Controller
public function getCreate()
{
$depreciation_list = Helper::depreciationList();
$supplier_list = Helper::suppliersList();
$maintained_list = array('' => 'Maintained', '1' => 'Yes', '0' => 'No');
$company_list = Helper::companyList();
return View::make('licenses/edit')
//->with('license_options',$license_options)
->with('depreciation_list', $depreciation_list)
->with('supplier_list', $supplier_list)
->with('depreciation_list', Helper::depreciationList())
->with('supplier_list', Helper::suppliersList())
->with('maintained_list', $maintained_list)
->with('company_list', $company_list)
->with('company_list', Helper::companyList())
->with('manufacturer_list', Helper::manufacturerList())
->with('license', new License);
}
@@ -87,17 +87,13 @@ class LicensesController extends Controller
public function postCreate()
{
// get the POST data
$new = Input::all();
// create a new model instance
$license = new License();
if (e(Input::get('purchase_cost')) == '') {
$license->purchase_cost = null;
} else {
$license->purchase_cost = e(Input::get('purchase_cost'));
$license->purchase_cost = Helper::ParseFloat(e(Input::get('purchase_cost')));
}
if (e(Input::get('supplier_id')) == '') {
@@ -124,6 +120,12 @@ class LicensesController extends Controller
$license->purchase_order = e(Input::get('purchase_order'));
}
if (empty(e(Input::get('manufacturer_id')))) {
$license->manufacturer_id = null;
} else {
$license->manufacturer_id = e(Input::get('manufacturer_id'));
}
// Save the license data
$license->name = e(Input::get('name'));
$license->serial = e(Input::get('serial'));
@@ -153,7 +155,7 @@ class LicensesController extends Controller
// Was the license created?
if ($license->save()) {
$license->logCreate();
$insertedId = $license->id;
// Save the license seat data
DB::transaction(function () use (&$insertedId, &$license) {
@@ -205,17 +207,15 @@ class LicensesController extends Controller
// Show the page
$license_options = array('' => 'Top Level') + DB::table('assets')->where('id', '!=', $licenseId)->pluck('name', 'id');
$depreciation_list = array('0' => trans('admin/licenses/form.no_depreciation')) + Depreciation::pluck('name', 'id')->toArray();
$supplier_list = array('' => 'Select Supplier') + Supplier::orderBy('name', 'asc')->pluck('name', 'id')->toArray();
$maintained_list = array('' => 'Maintained', '1' => 'Yes', '0' => 'No');
$company_list = Helper::companyList();
return View::make('licenses/edit', compact('license'))
->with('license_options', $license_options)
->with('depreciation_list', $depreciation_list)
->with('supplier_list', $supplier_list)
->with('company_list', $company_list)
->with('maintained_list', $maintained_list);
->with('depreciation_list', Helper::depreciationList())
->with('supplier_list', Helper::suppliersList())
->with('company_list', Helper::companyList())
->with('maintained_list', $maintained_list)
->with('manufacturer_list', Helper::manufacturerList());
}
@@ -252,6 +252,13 @@ class LicensesController extends Controller
$license->maintained = e(Input::get('maintained'));
$license->reassignable = e(Input::get('reassignable'));
if (empty(e(Input::get('manufacturer_id')))) {
$license->manufacturer_id = null;
} else {
$license->manufacturer_id = e(Input::get('manufacturer_id'));
}
if (e(Input::get('supplier_id')) == '') {
$license->supplier_id = null;
} else {
@@ -278,10 +285,9 @@ class LicensesController extends Controller
}
if (e(Input::get('purchase_cost')) == '') {
$license->purchase_cost = null;
$license->purchase_cost = null;
} else {
$license->purchase_cost = e(Input::get('purchase_cost'));
//$license->purchase_cost = e(Input::get('purchase_cost'));
$license->purchase_cost = Helper::ParseFloat(e(Input::get('purchase_cost')));
}
if (e(Input::get('maintained')) == '') {
@@ -323,11 +329,11 @@ class LicensesController extends Controller
//Log the deletion of seats to the log
$logaction = new Actionlog();
$logaction->asset_id = $license->id;
$logaction->asset_type = 'software';
$logaction->item_type = License::class;
$logaction->item_id = $license->id;
$logaction->user_id = Auth::user()->id;
$logaction->note = abs($difference)." seats";
$logaction->checkedout_to = null;
$logaction->note = '-'.abs($difference)." seats";
$logaction->target_id = null;
$log = $logaction->logaction('delete seats');
} else {
@@ -348,10 +354,11 @@ class LicensesController extends Controller
//Log the addition of license to the log.
$logaction = new Actionlog();
$logaction->asset_id = $license->id;
$logaction->asset_type = 'software';
$logaction->item_type = License::class;
$logaction->item_id = $license->id;
$logaction->user_id = Auth::user()->id;
$logaction->note = abs($difference)." seats";
$logaction->note = '+'.abs($difference)." seats";
$logaction->target_id = null;
$log = $logaction->logaction('add seats');
}
$license->seats = e(Input::get('seats'));
@@ -501,7 +508,7 @@ class LicensesController extends Controller
}
if (($asset->assigned_to!='') && (($asset->assigned_to!=$assigned_to)) && ($assigned_to!='') ) {
if (($asset->assigned_to!='') && (($asset->assigned_to!=$assigned_to)) && ($assigned_to!='')) {
return redirect()->to('admin/licenses')->with('error', trans('admin/licenses/message.owner_doesnt_match_asset'));
}
@@ -532,14 +539,10 @@ class LicensesController extends Controller
// Was the asset updated?
if ($licenseseat->save()) {
$logaction = new Actionlog();
//$logaction->location_id = $assigned_to->location_id;
$logaction->asset_type = 'software';
$logaction->user_id = Auth::user()->id;
$logaction->note = e(Input::get('note'));
$logaction->asset_id = $licenseseat->license_id;
$licenseseat->logCheckout(e(Input::get('note')));
$data['license_id'] =$licenseseat->license_id;
$data['note'] = e(Input::get('note'));
$license = License::find($licenseseat->license_id);
$settings = Setting::getSettings();
@@ -547,11 +550,9 @@ class LicensesController extends Controller
// Update the asset data
if (e(Input::get('assigned_to')) == '') {
$logaction->checkedout_to = null;
$slack_msg = strtoupper($logaction->asset_type).' license <'.config('app.url').'/admin/licenses/'.$license->id.'/view'.'|'.$license->name.'> checked out to <'.config('app.url').'/hardware/'.$asset->id.'/view|'.$asset->showAssetName().'> by <'.config('app.url').'/admin/users/'.$user->id.'/view'.'|'.$user->fullName().'>.';
$slack_msg = 'License <'.config('app.url').'/admin/licenses/'.$license->id.'/view'.'|'.$license->name.'> checked out to <'.config('app.url').'/hardware/'.$asset->id.'/view|'.$asset->showAssetName().'> by <'.config('app.url').'/admin/users/'.$user->id.'/view'.'|'.$user->fullName().'>.';
} else {
$logaction->checkedout_to = e(Input::get('assigned_to'));
$slack_msg = strtoupper($logaction->asset_type).' license <'.config('app.url').'/admin/licenses/'.$license->id.'/view'.'|'.$license->name.'> checked out to <'.config('app.url').'/admin/users/'.$asset->id.'/view|'.$is_assigned_to->fullName().'> by <'.config('app.url').'/admin/users/'.$user->id.'/view'.'|'.$user->fullName().'>.';
$slack_msg = 'License <'.config('app.url').'/admin/licenses/'.$license->id.'/view'.'|'.$license->name.'> checked out to <'.config('app.url').'/admin/users/'.$user->id.'/view|'.$is_assigned_to->fullName().'> by <'.config('app.url').'/admin/users/'.$user->id.'/view'.'|'.$user->fullName().'>.';
}
@@ -577,7 +578,7 @@ class LicensesController extends Controller
],
[
'title' => 'Note:',
'value' => e($logaction->note)
'value' => e(Input::get('note'))
],
@@ -591,9 +592,6 @@ class LicensesController extends Controller
}
$log = $logaction->logaction('checkout');
// Redirect to the new asset page
return redirect()->to("admin/licenses")->with('success', trans('admin/licenses/message.checkout.success'));
}
@@ -672,8 +670,6 @@ class LicensesController extends Controller
return redirect()->back()->withInput()->withErrors($validator);
}
$return_to = $licenseseat->assigned_to;
$logaction = new Actionlog();
$logaction->checkedout_to = $licenseseat->assigned_to;
// Update the asset data
$licenseseat->assigned_to = null;
@@ -683,11 +679,7 @@ class LicensesController extends Controller
// Was the asset updated?
if ($licenseseat->save()) {
$logaction->asset_id = $licenseseat->license_id;
$logaction->location_id = null;
$logaction->asset_type = 'software';
$logaction->note = e(Input::get('note'));
$logaction->user_id = $user->id;
$licenseseat->logCheckin(e(Input::get('note')));
$settings = Setting::getSettings();
@@ -708,11 +700,11 @@ class LicensesController extends Controller
'fields' => [
[
'title' => 'Checked In:',
'value' => strtoupper($logaction->asset_type).' <'.config('app.url').'/admin/licenses/'.$license->id.'/view'.'|'.$license->name.'> checked in by <'.config('app.url').'/admin/users/'.$user->id.'/view'.'|'.$user->fullName().'>.'
'value' => 'License: <'.config('app.url').'/admin/licenses/'.$license->id.'/view'.'|'.$license->name.'> checked in by <'.config('app.url').'/admin/users/'.$user->id.'/view'.'|'.$user->fullName().'>.'
],
[
'title' => 'Note:',
'value' => e($logaction->note)
'value' => e(Input::get('note'))
],
]
@@ -725,9 +717,6 @@ class LicensesController extends Controller
}
$log = $logaction->logaction('checkin from');
if ($backto=='user') {
return redirect()->to("admin/users/".$return_to.'/view')->with('success', trans('admin/licenses/message.checkin.success'));
@@ -753,6 +742,7 @@ class LicensesController extends Controller
{
$license = License::find($licenseId);
$license = $license->load('assignedusers', 'licenseSeats.user', 'licenseSeats.asset');
if (isset($license->id)) {
@@ -798,7 +788,8 @@ class LicensesController extends Controller
->with('supplier_list', $supplier_list)
->with('license', $license)
->with('maintained_list', $maintained_list)
->with('company_list', $company_list);
->with('company_list', $company_list)
->with('manufacturer_list', Helper::manufacturerList());
}
@@ -831,7 +822,7 @@ class LicensesController extends Controller
foreach (Input::file('licensefile') as $file) {
$rules = array(
'licensefile' => 'required|mimes:png,gif,jpg,jpeg,doc,docx,pdf,txt,zip,rar|max:2000'
'licensefile' => 'required|mimes:png,gif,jpg,jpeg,doc,docx,pdf,txt,zip,rar,rtf|max:2000'
);
$validator = Validator::make(array('licensefile'=> $file), $rules);
@@ -842,16 +833,8 @@ class LicensesController extends Controller
$filename .= '-'.str_slug($file->getClientOriginalName()).'.'.$extension;
$upload_success = $file->move($destinationPath, $filename);
//Log the deletion of seats to the log
$logaction = new Actionlog();
$logaction->asset_id = $license->id;
$logaction->asset_type = 'software';
$logaction->user_id = Auth::user()->id;
$logaction->note = e(Input::get('notes'));
$logaction->checkedout_to = null;
$logaction->created_at = date("Y-m-d h:i:s");
$logaction->filename = $filename;
$log = $logaction->logaction('uploaded');
//Log the upload to the log
$license->logUpload($filename, e(Input::get('notes')));
} else {
return redirect()->back()->with('error', trans('admin/licenses/message.upload.invalidfiles'));
}
@@ -965,7 +948,7 @@ class LicensesController extends Controller
*/
public function getDatatable()
{
$licenses = License::with('company');
$licenses = Company::scopeCompanyables(License::with('company', 'licenseSeatsRelation', 'manufacturer'));
if (Input::has('search')) {
$licenses = $licenses->TextSearch(Input::get('search'));
@@ -983,24 +966,45 @@ class LicensesController extends Controller
$rows = array();
foreach ($licenses as $license) {
$actions = '<span style="white-space: nowrap;"><a href="'.route('freecheckout/license', $license->id).'" class="btn btn-primary btn-sm'.(($license->remaincount() > 0) ? '' : ' disabled').'" style="margin-right:5px;">'.trans('general.checkout').'</a> <a href="'.route('clone/license', $license->id).'" class="btn btn-info btn-sm" style="margin-right:5px;" title="Clone asset"><i class="fa fa-files-o"></i></a><a href="'.route('update/license', $license->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/license', $license->id).'" data-content="'.trans('admin/licenses/message.delete.confirm').'" data-title="'.trans('general.delete').' '.htmlspecialchars($license->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a></span>';
$actions = '<span style="white-space: nowrap;">';
if (Gate::allows('licenses.checkout')) {
$actions .= '<a href="' . route('freecheckout/license', $license->id)
. '" class="btn btn-primary btn-sm' . (($license->remaincount() > 0) ? '' : ' disabled') . '" style="margin-right:5px;">' . trans('general.checkout') . '</a> ';
}
if (Gate::allows('licenses.create')) {
$actions .= '<a href="' . route('clone/license', $license->id)
. '" class="btn btn-info btn-sm" style="margin-right:5px;" title="Clone license"><i class="fa fa-files-o"></i></a>';
}
if (Gate::allows('licenses.edit')) {
$actions .= '<a href="' . route('update/license', $license->id)
. '" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a>';
}
if (Gate::allows('licenses.delete')) {
$actions .= '<a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'
. route('delete/license', $license->id)
. '" data-content="' . trans('admin/licenses/message.delete.confirm') . '" data-title="' . trans('general.delete') . ' ' . htmlspecialchars($license->name) . '?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>';
}
$actions .='</span>';
$rows[] = array(
'id' => $license->id,
'name' => (string) link_to('/admin/licenses/'.$license->id.'/view', $license->name),
'serial' => (string) link_to('/admin/licenses/'.$license->id.'/view', mb_strimwidth($license->serial, 0, 50, "...")),
'totalSeats' => $license->totalSeatsByLicenseID(),
'totalSeats' => $license->licenseSeatsCount,
'remaining' => $license->remaincount(),
'license_name' => e($license->license_name),
'license_email' => e($license->license_email),
'license_email' => e($license->license_email),
'purchase_date' => ($license->purchase_date) ? $license->purchase_date : '',
'expiration_date' => ($license->expiration_date) ? $license->expiration_date : '',
'purchase_cost' => ($license->purchase_cost) ? number_format($license->purchase_cost, 2) : '',
'purchase_cost' => Helper::formatCurrencyOutput($license->purchase_cost),
'purchase_order' => ($license->purchase_order) ? e($license->purchase_order) : '',
'order_number' => ($license->order_number) ? e($license->order_number) : '',
'notes' => ($license->notes) ? e($license->notes) : '',
'actions' => $actions,
'companyName' => is_null($license->company) ? '' : e($license->company->name)
'companyName' => is_null($license->company) ? '' : e($license->company->name),
'manufacturer' => $license->manufacturer ? (string) link_to('/admin/settings/manufacturers/'.$license->manufacturer_id.'/view', $license->manufacturer->name) : ''
);
}

View File

@@ -2,14 +2,15 @@
namespace App\Http\Controllers;
use App\Models\Company;
use App\Models\Manufacturer;
use App\Models\Setting;
use Auth;
use Gate;
use Input;
use Lang;
use App\Models\Manufacturer;
use Redirect;
use App\Models\Setting;
use Str;
use View;
use Auth;
/**
* This controller handles all actions related to Manufacturers for
@@ -254,10 +255,28 @@ class ManufacturersController extends Controller
* @since [v1.0]
* @return String JSON
*/
public function getDataView($manufacturerId)
public function getDataView($manufacturerId, $itemtype = null)
{
$manufacturer = Manufacturer::find($manufacturerId);
$manufacturer = Manufacturer::with('assets.company')->find($manufacturerId);
switch ($itemtype) {
case "assets":
return $this->getDataAssetsView($manufacturer);
case "licenses":
return $this->getDataLicensesView($manufacturer);
case "accessories":
return $this->getDataAccessoriesView($manufacturer);
case "consumables":
return $this->getDataConsumablesView($manufacturer);
}
throw new Exception("We shouldn't be here");
}
protected function getDataAssetsView(Manufacturer $manufacturer)
{
$manufacturer = $manufacturer->load('assets.model', 'assets.assigneduser', 'assets.assetstatus', 'assets.company');
$manufacturer_assets = $manufacturer->assets;
if (Input::has('search')) {
@@ -293,35 +312,229 @@ class ManufacturersController extends Controller
$actions = '<a href="'.route('restore/hardware', $asset->id).'" class="btn btn-warning btn-sm"><i class="fa fa-recycle icon-white"></i></a>';
}
if ($asset->assetstatus) {
if ($asset->assetstatus->deployable != 0) {
if (($asset->assigned_to !='') && ($asset->assigned_to > 0)) {
$inout = '<a href="'.route('checkin/hardware', $asset->id).'" class="btn btn-primary btn-sm">'.trans('general.checkin').'</a>';
} else {
$inout = '<a href="'.route('checkout/hardware', $asset->id).'" class="btn btn-info btn-sm">'.trans('general.checkout').'</a>';
}
if ($asset->availableForCheckout()) {
if (Gate::allows('assets.checkout')) {
$inout = '<a href="'.route('checkout/hardware', $asset->id).'" class="btn btn-info btn-sm">'.trans('general.checkout').'</a>';
}
} else {
if (Gate::allows('assets.checkin')) {
$inout = '<a href="'.route('checkin/hardware', $asset->id).'" class="btn btn-primary btn-sm">'.trans('general.checkin').'</a>';
}
}
$row = array(
'id' => $asset->id,
'name' => (string)link_to('/hardware/'.$asset->id.'/view', e($asset->showAssetName())),
'model' => e($asset->model->name),
'asset_tag' => e($asset->asset_tag),
'serial' => e($asset->serial),
'assigned_to' => ($asset->assigneduser) ? (string)link_to('/admin/users/'.$asset->assigneduser->id.'/view', e($asset->assigneduser->fullName())): '',
'actions' => $actions,
'companyName' => e(Company::getName($asset)),
);
$rows[] = array(
'id' => $asset->id,
'name' => (string)link_to('/hardware/'.$asset->id.'/view', e($asset->showAssetName())),
'model' => e($asset->model->name),
'asset_tag' => e($asset->asset_tag),
'serial' => e($asset->serial),
'assigned_to' => ($asset->assigneduser) ? (string)link_to('/admin/users/'.$asset->assigneduser->id.'/view', e($asset->assigneduser->fullName())): '',
'actions' => $actions,
// 'companyName' => e(Company::getName($asset)),
'companyName' => is_null($asset->company) ? '' : $asset->company->name
);
if (isset($inout)) {
$row['change'] = $inout;
}
$rows[] = $row;
}
$data = array('total' => $count, 'rows' => $rows);
return $data;
}
protected function getDataLicensesView(Manufacturer $manufacturer)
{
$manufacturer = $manufacturer->load('licenses.company', 'licenses.manufacturer', 'licenses.licenseSeatsRelation');
$licenses = $manufacturer->licenses;
if (Input::has('search')) {
$licenses = $licenses->TextSearch(Input::get('search'));
}
$licenseCount = $licenses->count();
$rows = array();
foreach ($licenses as $license) {
$actions = '<span style="white-space: nowrap;">';
if (Gate::allows('licenses.checkout')) {
$actions .= '<a href="' . route('freecheckout/license', $license->id)
. '" class="btn btn-primary btn-sm' . (($license->remaincount() > 0) ? '' : ' disabled') . '" style="margin-right:5px;">' . trans('general.checkout') . '</a> ';
}
if (Gate::allows('licenses.create')) {
$actions .= '<a href="' . route('clone/license', $license->id)
. '" class="btn btn-info btn-sm" style="margin-right:5px;" title="Clone asset"><i class="fa fa-files-o"></i></a>';
}
if (Gate::allows('licenses.edit')) {
$actions .= '<a href="' . route('update/license', $license->id)
. '" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a>';
}
if (Gate::allows('licenses.delete')) {
$actions .= '<a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'
. route('delete/license', $license->id)
. '" data-content="' . trans('admin/licenses/message.delete.confirm') . '" data-title="' . trans('general.delete') . ' ' . htmlspecialchars($license->name) . '?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>';
}
$actions .='</span>';
$rows[] = array(
'id' => $license->id,
'name' => (string) link_to('/admin/licenses/'.$license->id.'/view', $license->name),
'serial' => (string) link_to('/admin/licenses/'.$license->id.'/view', mb_strimwidth($license->serial, 0, 50, "...")),
'totalSeats' => $license->licenseSeatCount,
'remaining' => $license->remaincount(),
'license_name' => e($license->license_name),
'license_email' => e($license->license_email),
'purchase_date' => ($license->purchase_date) ? $license->purchase_date : '',
'expiration_date' => ($license->expiration_date) ? $license->expiration_date : '',
'purchase_cost' => ($license->purchase_cost) ? number_format($license->purchase_cost, 2) : '',
'purchase_order' => ($license->purchase_order) ? e($license->purchase_order) : '',
'order_number' => ($license->order_number) ? e($license->order_number) : '',
'notes' => ($license->notes) ? e($license->notes) : '',
'actions' => $actions,
'companyName' => is_null($license->company) ? '' : e($license->company->name),
'manufacturer' => $license->manufacturer ? (string) link_to('/admin/settings/manufacturers/'.$license->manufacturer_id.'/view', $license->manufacturer->name) : ''
);
}
$data = array('total' => $licenseCount, 'rows' => $rows);
return $data;
}
public function getDataAccessoriesView(Manufacturer $manufacturer)
{
$manufacturer = $manufacturer->load(
'accessories.location',
'accessories.company',
'accessories.category',
'accessories.manufacturer',
'accessories.users'
);
$accessories = $manufacturer->accessories;
if (Input::has('search')) {
$accessories = $accessories->TextSearch(e(Input::get('search')));
}
if (Input::has('limit')) {
$limit = e(Input::get('limit'));
} else {
$limit = 50;
}
$accessCount = $accessories->count();
$rows = array();
foreach ($accessories as $accessory) {
$actions = '<nobr>';
if (Gate::allows('accessories.checkout')) {
$actions .= '<a href="' . route('checkout/accessory',
$accessory->id) . '" style="margin-right:5px;" class="btn btn-info btn-sm" ' . (($accessory->numRemaining() > 0) ? '' : ' disabled') . '>' . trans('general.checkout') . '</a>';
}
if (Gate::allows('accessories.edit')) {
$actions .= '<a href="' . route('update/accessory',
$accessory->id) . '" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a>';
}
if (Gate::allows('accessories.delete')) {
$actions .= '<a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="' . route('delete/accessory',
$accessory->id) . '" data-content="' . trans('admin/accessories/message.delete.confirm') . '" data-title="' . trans('general.delete') . ' ' . htmlspecialchars($accessory->name) . '?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>';
}
$actions .= '</nobr>';
$company = $accessory->company;
$rows[] = array(
'name' => '<a href="'.url('admin/accessories/'.$accessory->id).'/view">'. $accessory->name.'</a>',
'category' => ($accessory->category) ? (string)link_to('admin/settings/categories/'.$accessory->category->id.'/view', $accessory->category->name) : '',
'qty' => e($accessory->qty),
'order_number' => e($accessory->order_number),
'min_amt' => e($accessory->min_amt),
'location' => ($accessory->location) ? e($accessory->location->name): '',
'purchase_date' => e($accessory->purchase_date),
'purchase_cost' => number_format($accessory->purchase_cost, 2),
'numRemaining' => $accessory->numRemaining(),
'actions' => $actions,
'companyName' => is_null($company) ? '' : e($company->name),
'manufacturer' => $accessory->manufacturer ? (string) link_to('/admin/settings/manufacturers/'.$accessory->manufacturer_id.'/view', $accessory->manufacturer->name) : ''
);
}
$data = array('total'=>$accessCount, 'rows'=>$rows);
return $data;
}
public function getDataConsumablesView($manufacturer)
{
$manufacturer = $manufacturer->load(
'consumables.location',
'consumables.company',
'consumables.category',
'consumables.manufacturer',
'consumables.users'
);
$consumables = $manufacturer->consumables;
if (Input::has('search')) {
$consumables = $consumables->TextSearch(e(Input::get('search')));
}
if (Input::has('limit')) {
$limit = e(Input::get('limit'));
} else {
$limit = 50;
}
$consumCount = $consumables->count();
$rows = array();
foreach ($consumables as $consumable) {
$actions = '<nobr>';
if (Gate::allows('consumables.checkout')) {
$actions .= '<a href="' . route('checkout/consumable',
$consumable->id) . '" style="margin-right:5px;" class="btn btn-info btn-sm" ' . (($consumable->numRemaining() > 0) ? '' : ' disabled') . '>' . trans('general.checkout') . '</a>';
}
if (Gate::allows('consumables.edit')) {
$actions .= '<a href="' . route('update/consumable',
$consumable->id) . '" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a>';
}
if (Gate::allows('consumables.delete')) {
$actions .= '<a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="' . route('delete/consumable',
$consumable->id) . '" data-content="' . trans('admin/consumables/message.delete.confirm') . '" data-title="' . trans('general.delete') . ' ' . htmlspecialchars($consumable->name) . '?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>';
}
$actions .='</nobr>';
$company = $consumable->company;
$rows[] = array(
'id' => $consumable->id,
'name' => (string)link_to('admin/consumables/'.$consumable->id.'/view', e($consumable->name)),
'location' => ($consumable->location) ? e($consumable->location->name) : '',
'min_amt' => e($consumable->min_amt),
'qty' => e($consumable->qty),
'manufacturer' => ($consumable->manufacturer) ? (string) link_to('/admin/settings/manufacturers/'.$consumable->manufacturer_id.'/view', $consumable->manufacturer->name): '',
'model_no' => e($consumable->model_no),
'item_no' => e($consumable->item_no),
'category' => ($consumable->category) ? (string) link_to('/admin/settings/categories/'.$consumable->category_id.'/view', $consumable->category->name) : 'Missing category',
'order_number' => e($consumable->order_number),
'purchase_date' => e($consumable->purchase_date),
'purchase_cost' => ($consumable->purchase_cost!='') ? number_format($consumable->purchase_cost, 2): '' ,
'numRemaining' => $consumable->numRemaining(),
'actions' => $actions,
'companyName' => is_null($company) ? '' : e($company->name),
);
}
$data = array('total' => $consumCount, 'rows' => $rows);
return $data;
}
}

View File

@@ -8,6 +8,8 @@ use App\Models\Location;
use View;
use Auth;
use App\Helpers\Helper;
use App\Models\Setting;
use Gate;
/**
* This controller handles all actions related to User Profiles for
@@ -53,9 +55,14 @@ class ProfileController extends Controller
$user->gravatar = e(Input::get('gravatar'));
$user->locale = e(Input::get('locale'));
if ((Gate::allows('self.two_factor')) && ((Setting::getSettings()->two_factor_enabled=='1') && (!config('app.lock_passwords')))) {
$user->two_factor_optin = e(Input::get('two_factor_optin', '0'));
}
if (Input::file('avatar')) {
$image = Input::file('avatar');
$file_name = $user->first_name."-".$user->last_name.".".$image->getClientOriginalExtension();
$file_name = str_slug($user->first_name."-".$user->last_name).".".$image->getClientOriginalExtension();
$path = public_path('uploads/avatars/'.$file_name);
Image::make($image->getRealPath())->resize(84, 84)->save($path);
$user->avatar = $file_name;

View File

@@ -1,25 +1,27 @@
<?php
namespace App\Http\Controllers;
use App\Helpers\Helper;
use App\Models\Accessory;
use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\AssetMaintenance;
use Carbon\Carbon;
use Category;
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 App\Models\License;
use App\Models\Location;
use App\Models\AssetModel;
use Redirect;
use App\Models\Setting;
use App\Models\User;
use Symfony\Component\HttpFoundation\StreamedResponse;
/**
* This controller handles all actions related to Reports for
@@ -31,7 +33,7 @@ class ReportsController extends Controller
{
/**
* Returns a view that displaysthe accessories report.
* Returns a view that displays the accessories report.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
@@ -87,7 +89,7 @@ class ReportsController extends Controller
}
/**
* Display asset report.
* Display asset report view.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
@@ -96,23 +98,11 @@ class ReportsController extends Controller
public function getAssetsReport()
{
$settings = \App\Models\Setting::first();
// Grab all the assets
$assets = Asset::with(
'model',
'assigneduser.userLoc',
'assetstatus',
'defaultLoc',
'assetlog',
'supplier',
'model.manufacturer',
'company'
)
->orderBy('created_at', 'DESC')
->get();
return View::make('reports/asset', compact('assets'))->with('settings', $settings);
}
/**
* Exports the assets to CSV
*
@@ -122,103 +112,76 @@ class ReportsController extends Controller
*/
public function exportAssetReport()
{
// Grab all the assets
$assets = Asset::orderBy('created_at', 'DESC')->get();
$rows = [ ];
\Debugbar::disable();
// Create the header row
$header = [
trans('admin/hardware/table.asset_tag'),
trans('admin/hardware/form.manufacturer'),
trans('admin/hardware/form.model'),
trans('general.model_no'),
trans('general.name'),
trans('admin/hardware/table.serial'),
trans('general.status'),
trans('admin/hardware/table.purchase_date'),
trans('admin/hardware/table.purchase_cost'),
trans('admin/hardware/form.order'),
trans('admin/hardware/form.supplier'),
trans('admin/hardware/table.checkoutto'),
trans('admin/hardware/table.location'),
trans('general.notes'),
];
$header = array_map('trim', $header);
$rows[] = implode($header, ',');
$customfields = CustomField::get();
// Create a row per asset
foreach ($assets as $asset) {
$row = [ ];
$row[] = e($asset->asset_tag);
if ($asset->model->manufacturer) {
$row[] = e($asset->model->manufacturer->name);
} else {
$row[] = '';
}
$row[] = '"' . e($asset->model->name) . '"';
$row[] = '"' . e($asset->model->modelno) . '"';
$row[] = e($asset->name);
$row[] = e($asset->serial);
if ($asset->assetstatus) {
$row[] = e($asset->assetstatus->name);
} else {
$row[] = '';
}
$row[] = $asset->purchase_date;
$row[] = '"' . number_format($asset->purchase_cost, 2) . '"';
if ($asset->order_number) {
$row[] = e($asset->order_number);
} else {
$row[] = '';
}
if ($asset->supplier_id) {
$row[] = e($asset->supplier->name);
} else {
$row[] = '';
}
$response = new StreamedResponse(function() use ($customfields) {
// Open output stream
$handle = fopen('php://output', 'w');
if ($asset->assigned_to > 0) {
$user = User::find($asset->assigned_to);
$row[] = e($user->fullName());
} else {
$row[] = ''; // Empty string if unassigned
}
if (( $asset->assigned_to > 0 ) && ( $asset->assigneduser->location_id > 0 )) {
$location = Location::find($asset->assigneduser->location_id);
if ($location) {
$row[] = e($location->name);
} else {
$row[] = '';
Asset::with('assigneduser', 'assetloc','defaultLoc','assigneduser.userloc','model','supplier','assetstatus','model.manufacturer')->orderBy('created_at', 'DESC')->chunk(500, function($assets) use($handle, $customfields) {
$headers=[
trans('general.company'),
trans('admin/hardware/table.asset_tag'),
trans('admin/hardware/form.manufacturer'),
trans('admin/hardware/form.model'),
trans('general.model_no'),
trans('general.name'),
trans('admin/hardware/table.serial'),
trans('general.status'),
trans('admin/hardware/table.purchase_date'),
trans('admin/hardware/table.purchase_cost'),
trans('admin/hardware/form.order'),
trans('admin/hardware/form.supplier'),
trans('admin/hardware/table.checkoutto'),
trans('admin/hardware/table.checkout_date'),
trans('admin/hardware/table.location'),
trans('general.notes'),
];
foreach($customfields as $field) {
$headers[]=$field->name;
}
} elseif ($asset->rtd_location_id) {
$location = Location::find($asset->rtd_location_id);
if ($location->name) {
$row[] = e($location->name);
} else {
$row[] = '';
fputcsv($handle, $headers);
foreach ($assets as $asset) {
// Add a new row with data
$values=[
($asset->company) ? $asset->company->name : '',
$asset->asset_tag,
($asset->model->manufacturer) ? $asset->model->manufacturer->name : '',
($asset->model) ? $asset->model->name : '',
($asset->model->modelno) ? $asset->model->modelno : '',
($asset->name) ? $asset->name : '',
($asset->serial) ? $asset->serial : '',
($asset->assetstatus) ? e($asset->assetstatus->name) : '',
($asset->purchase_date) ? e($asset->purchase_date) : '',
($asset->purchase_cost > 0) ? Helper::formatCurrencyOutput($asset->purchase_cost) : '',
($asset->order_number) ? e($asset->order_number) : '',
($asset->supplier) ? e($asset->supplier->name) : '',
($asset->assigneduser) ? e($asset->assigneduser->fullName()) : '',
($asset->last_checkout!='') ? e($asset->last_checkout) : '',
($asset->assigneduser && $asset->assigneduser->userloc!='') ?
e($asset->assigneduser->userloc->name) : ( ($asset->defaultLoc!='') ? e($asset->defaultLoc->name) : ''),
($asset->notes) ? e($asset->notes) : '',
];
foreach($customfields as $field) {
$values[]=$asset->{$field->db_column_name()};
}
fputcsv($handle, $values);
}
} else {
$row[] = ''; // Empty string if location is not set
}
});
if ($asset->notes) {
$row[] = '"' . e($asset->notes) . '"';
} else {
$row[] = '';
}
$rows[] = implode($row, ',');
}
// spit out a csv
$csv = implode($rows, "\n");
$response = Response::make($csv, 200);
$response->header('Content-Type', 'text/csv');
$response->header('Content-disposition', 'attachment;filename=report.csv');
// Close the output stream
fclose($handle);
}, 200, [
'Content-Type' => 'text/csv',
'Content-Disposition' => 'attachment; filename="assets-'.date('Y-m-d-his').'.csv"',
]);
return $response;
}
/**
@@ -308,9 +271,9 @@ class ReportsController extends Controller
}
$row[] = $asset->purchase_date;
$row[] = $currency . number_format($asset->purchase_cost, 2);
$row[] = $currency . number_format($asset->getDepreciatedValue(), 2);
$row[] = $currency . number_format(( $asset->purchase_cost - $asset->getDepreciatedValue() ), 2);
$row[] = $currency . Helper::formatCurrencyOutput($asset->purchase_cost);
$row[] = $currency . Helper::formatCurrencyOutput($asset->getDepreciatedValue());
$row[] = $currency . Helper::formatCurrencyOutput(( $asset->purchase_cost - $asset->getDepreciatedValue() ));
$csv->insertOne($row);
}
@@ -329,11 +292,7 @@ class ReportsController extends Controller
public function getActivityReport()
{
$log_actions = Actionlog::orderBy('created_at', 'DESC')
->with('adminlog')
->with('accessorylog')
->with('assetlog')
->with('licenselog')
->with('userlog')
->with('item')
->orderBy('created_at', 'DESC')
->get();
@@ -341,16 +300,134 @@ class ReportsController extends Controller
}
/**
* Displays license report
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
* 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')) {
$activity = $activity->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) {
if ($activity->itemType() == "asset") {
$activity_icons = '<i class="fa fa-barcode"></i>';
} elseif ($activity->itemType() == "accessory") {
$activity_icons = '<i class="fa fa-keyboard-o"></i>';
} elseif ($activity->itemType()=="consumable") {
$activity_icons = '<i class="fa fa-tint"></i>';
} elseif ($activity->itemType()=="license"){
$activity_icons = '<i class="fa fa-floppy-o"></i>';
} elseif ($activity->itemType()=="component") {
$activity_icons = '<i class="fa fa-hdd-o"></i>';
} else {
$activity_icons = '<i class="fa fa-paperclip"></i>';
}
if (($activity->item) && ($activity->itemType()=="asset")) {
$activity_item = '<a href="'.route('view/hardware', $activity->item_id).'">'.e($activity->item->asset_tag).' - '. e($activity->item->showAssetName()).'</a>';
$item_type = 'asset';
} elseif ($activity->item) {
$activity_item = '<a href="' . route('view/' . $activity->itemType(),
$activity->item_id) . '">' . e($activity->item->name) . '</a>';
$item_type = $activity->itemType();
} else {
$activity_item = "unkonwn";
$item_type = "null";
}
if (($activity->user) && ($activity->action_type=="uploaded") && ($activity->itemType()=="user")) {
$activity_target = '<a href="'.route('view/user', $activity->target_id).'">'.$activity->user->fullName().'</a>';
} elseif ($activity->target_type === "App\Models\Asset") {
if($activity->target) {
$activity_target = '<a href="'.route('view/hardware', $activity->target_id).'">'.$activity->target->showAssetName().'</a>';
} else {
$activity_target = "";
}
} elseif ( $activity->target_type === "App\Models\User") {
if($activity->target) {
$activity_target = '<a href="'.route('view/user', $activity->target_id).'">'.$activity->target->fullName().'</a>';
} else {
$activity_target = '';
}
} elseif (($activity->action_type=='accepted') || ($activity->action_type=='declined')) {
$activity_target = '<a href="' . route('view/user', $activity->item->assigneduser->id) . '">' . e($activity->item->assigneduser->fullName()) . '</a>';
} elseif ($activity->action_type=='requested') {
if ($activity->user) {
$activity_target = '<a href="'.route('view/user', $activity->user_id).'">'.$activity->user->fullName().'</a>';
} else {
$activity_target = '';
}
} else {
if($activity->target) {
$activity_target = $activity->target->id;
} else {
$activity_target = "";
}
}
$rows[] = array(
'icon' => $activity_icons,
'created_at' => date("M d, Y g:iA", strtotime($activity->created_at)),
'action_type' => strtolower(trans('general.'.str_replace(' ','_',$activity->action_type))),
'admin' => $activity->user ? (string) link_to('/admin/users/'.$activity->user_id.'/view', $activity->user->fullName()) : '',
'target' => $activity_target,
'item' => $activity_item,
'item_type' => $item_type,
'note' => e($activity->note),
);
}
$data = array('total'=>$activityCount, 'rows'=>$rows);
return $data;
}
/**
* Displays license report
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
public function getLicenseReport()
{
$licenses = License::orderBy('created_at', 'DESC')
$licenses = License::with('depreciation')->orderBy('created_at', 'DESC')
->with('company')
->get();
@@ -377,6 +454,7 @@ class ReportsController extends Controller
trans('admin/licenses/form.remaining_seats'),
trans('admin/licenses/form.expiration'),
trans('admin/licenses/form.date'),
trans('admin/licenses/form.depreciation'),
trans('admin/licenses/form.cost')
];
@@ -392,7 +470,8 @@ class ReportsController extends Controller
$row[] = $license->remaincount();
$row[] = $license->expiration_date;
$row[] = $license->purchase_date;
$row[] = '"' . number_format($license->purchase_cost, 2) . '"';
$row[] = ($license->depreciation!='') ? '' : e($license->depreciation->name);
$row[] = '"' . Helper::formatCurrencyOutput($license->purchase_cost) . '"';
$rows[] = implode($row, ',');
}
@@ -415,25 +494,30 @@ class ReportsController extends Controller
*/
public function getCustomReport()
{
return View::make('reports/custom');
$customfields = CustomField::get();
return View::make('reports/custom')->with('customfields', $customfields);
}
/**
* Exports the custom report to CSV
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see ReportsController::getCustomReport() method that generates form view
* @since [v1.0]
* @return \Illuminate\Http\Response
*/
* Exports the custom report to CSV
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see ReportsController::getCustomReport() method that generates form view
* @since [v1.0]
* @return \Illuminate\Http\Response
*/
public function postCustom()
{
$assets = Asset::orderBy('created_at', 'DESC')->get();
$assets = Asset::orderBy('created_at', 'DESC')->with('company','assigneduser', 'assetloc','defaultLoc','assigneduser.userloc','model','supplier','assetstatus','model.manufacturer')->get();
$customfields = CustomField::get();
$rows = [ ];
$header = [ ];
if (e(Input::get('company')) == '1') {
$header[] = 'Company Name';
}
if (e(Input::get('asset_name')) == '1') {
$header[] = 'Asset Name';
}
@@ -459,6 +543,9 @@ class ReportsController extends Controller
if (( e(Input::get('purchase_cost')) == '1' ) && ( e(Input::get('depreciation')) != '1' )) {
$header[] = 'Purchase Cost';
}
if (e(Input::get('eol')) == '1') {
$header[] = 'EOL';
}
if (e(Input::get('order')) == '1') {
$header[] = 'Order Number';
}
@@ -471,6 +558,9 @@ class ReportsController extends Controller
if (e(Input::get('assigned_to')) == '1') {
$header[] = 'Assigned To';
}
if (e(Input::get('username')) == '1') {
$header[] = 'Username';
}
if (e(Input::get('status')) == '1') {
$header[] = 'Status';
}
@@ -484,11 +574,23 @@ class ReportsController extends Controller
$header[] = 'Diff';
}
foreach ($customfields as $customfield) {
if (e(Input::get($customfield->db_column_name())) == '1') {
$header[] = $customfield->name;
}
}
$header = array_map('trim', $header);
$rows[] = implode($header, ',');
foreach ($assets as $asset) {
$row = [ ];
if (e(Input::get('company')) == '1') {
$row[] = is_null($asset->company) ? '' : '"'.$asset->company->name.'"';
}
if (e(Input::get('asset_name')) == '1') {
$row[] = '"' .e($asset->name) . '"';
}
@@ -517,7 +619,10 @@ class ReportsController extends Controller
$row[] = e($asset->purchase_date);
}
if (e(Input::get('purchase_cost')) == '1' && ( e(Input::get('depreciation')) != '1' )) {
$row[] = '"' . number_format($asset->purchase_cost, 2) . '"';
$row[] = '"' . Helper::formatCurrencyOutput($asset->purchase_cost) . '"';
}
if (e(Input::get('eol')) == '1') {
$row[] = '"' .($asset->eol_date()) ? $asset->eol_date() : ''. '"';
}
if (e(Input::get('order')) == '1') {
if ($asset->order_number) {
@@ -527,21 +632,19 @@ class ReportsController extends Controller
}
}
if (e(Input::get('supplier')) == '1') {
if ($asset->supplier_id) {
if ($asset->supplier) {
$row[] = '"' .e($asset->supplier->name) . '"';
} else {
$row[] = '';
}
}
if (e(Input::get('location')) == '1') {
$show_loc = '';
if (( $asset->assigned_to > 0 ) && ( $asset->assigneduser->location_id !='' )) {
$location = Location::find($asset->assigneduser->location_id);
if ($location) {
$show_loc .= '"' .e($location->name). '"';
} else {
$show_loc .= 'User location '.$asset->assigneduser->location_id.' is invalid';
}
if (($asset->assigned_to > 0) && ($asset->assigneduser) && ($asset->assigneduser->location)) {
$show_loc .= '"' .e($asset->assigneduser->location->name). '"';
} elseif ($asset->rtd_location_id!='') {
$location = Location::find($asset->rtd_location_id);
if ($location) {
@@ -554,14 +657,24 @@ class ReportsController extends Controller
$row[] = $show_loc;
}
if (e(Input::get('assigned_to')) == '1') {
if ($asset->assigned_to > 0) {
$user = User::find($asset->assigned_to);
$row[] = '"' .e($user->fullName()). '"';
if ($asset->assigneduser) {
$row[] = '"' .e($asset->assigneduser->fullName()). '"';
} else {
$row[] = ''; // Empty string if unassigned
}
}
if (e(Input::get('username')) == '1') {
if ($asset->assigneduser) {
$row[] = '"' .e($asset->assigneduser->username). '"';
} else {
$row[] = ''; // Empty string if unassigned
}
}
if (e(Input::get('status')) == '1') {
if (( $asset->status_id == '0' ) && ( $asset->assigned_to == '0' )) {
$row[] = trans('general.ready_to_deploy');
@@ -584,10 +697,19 @@ class ReportsController extends Controller
}
if (e(Input::get('depreciation')) == '1') {
$depreciation = $asset->getDepreciatedValue();
$row[] = '"' . number_format($asset->purchase_cost, 2) . '"';
$row[] = '"' . number_format($depreciation, 2) . '"';
$row[] = '"' . number_format($asset->purchase_cost - $depreciation, 2) . '"';
$row[] = '"' . Helper::formatCurrencyOutput($asset->purchase_cost) . '"';
$row[] = '"' . Helper::formatCurrencyOutput($depreciation) . '"';
$row[] = '"' . Helper::formatCurrencyOutput($asset->purchase_cost) . '"';
}
foreach ($customfields as $customfield) {
$column_name = $customfield->db_column_name();
if (e(Input::get($customfield->db_column_name())) == '1') {
$row[] = str_replace(",", "\,", $asset->$column_name);
}
}
$rows[] = implode($row, ',');
}
@@ -596,14 +718,15 @@ class ReportsController extends Controller
$csv = implode($rows, "\n");
$response = Response::make($csv, 200);
$response->header('Content-Type', 'text/csv');
$response->header('Content-disposition', 'attachment;filename=report.csv');
$response->header('Content-disposition', 'attachment;filename='.date('Y-m-d-His').'-custom-asset-report.csv');
return $response;
} else {
return redirect()->to("reports/custom")
->with('error', trans('admin/reports/message.error'));
->with('error', trans('admin/reports/message.error'));
}
}
/**
* getImprovementsReport
@@ -640,6 +763,7 @@ class ReportsController extends Controller
$rows = [ ];
$header = [
trans('admin/hardware/table.asset_tag'),
trans('admin/asset_maintenances/table.asset_name'),
trans('admin/asset_maintenances/table.supplier_name'),
trans('admin/asset_maintenances/form.asset_maintenance_type'),
@@ -655,6 +779,7 @@ class ReportsController extends Controller
foreach ($assetMaintenances as $assetMaintenance) {
$row = [ ];
$row[] = str_replace(',', '', e($assetMaintenance->asset->asset_tag));
$row[] = str_replace(',', '', e($assetMaintenance->asset->name));
$row[] = str_replace(',', '', e($assetMaintenance->supplier->name));
$row[] = e($assetMaintenance->improvement_type);
@@ -668,7 +793,7 @@ class ReportsController extends Controller
$improvementTime = intval($assetMaintenance->asset_maintenance_time);
}
$row[] = $improvementTime;
$row[] = trans('general.currency') . number_format($assetMaintenance->cost, 2);
$row[] = trans('general.currency') . Helper::formatCurrencyOutput($assetMaintenance->cost);
$rows[] = implode($row, ',');
}

View File

@@ -52,29 +52,18 @@ class SettingsController extends Controller
$protocol = array_key_exists('HTTPS', $_SERVER) && ( $_SERVER['HTTPS'] == "on") ? 'https://' : 'http://';
$pageURL = $protocol;
if ($_SERVER["SERVER_PORT"] != "80") {
$main_page = $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"];
$pageURL .= $main_page.$_SERVER["REQUEST_URI"];
} else {
$main_page = $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
$pageURL .= $main_page;
$host = $_SERVER['SERVER_NAME'];
if (($protocol === 'http://' && $_SERVER['SERVER_PORT'] != '80') || ($protocol === 'https://' && $_SERVER['SERVER_PORT'] != '443')) {
$host .= ':' . $_SERVER['SERVER_PORT'];
}
$pageURL = $protocol . $host . $_SERVER['REQUEST_URI'];
$start_settings['env_location'] = $pageURL.'../.env';
$start_settings['url_valid'] = (config('app.url').'/setup' === $pageURL);
$start_settings['url_config'] = config('app.url');
$start_settings['real_url'] = $pageURL;
if (config('app.url').'/setup'!=$pageURL) {
$start_settings['url_valid']= false;
} else {
$start_settings['url_valid']= true;
}
$start_settings['url_config']= config('app.url');
$start_settings['real_url']= $pageURL;
$exposed_env = @file_get_contents($main_page.'/.env');
$exposed_env = @file_get_contents($protocol . $host.'/.env');
if ($exposed_env) {
$start_settings['env_exposed'] = true;
@@ -147,7 +136,8 @@ class SettingsController extends Controller
try {
Mail::send('emails.test', [], function ($m) {
$m->to(config('mail.from.address'), config('mail.from.name'));
$m->subject('Test Email from Snipe-IT');
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.test_email'));
});
return 'success';
} catch (Exception $e) {
@@ -195,11 +185,12 @@ class SettingsController extends Controller
} else {
$user->save();
$settings->save();
if (Input::get('email_creds')=='1') {
Mail::send(['text' => 'emails.firstadmin'], $data, function ($m) use ($data) {
$m->to($data['email'], $data['first_name']);
$m->subject('Your Snipe-IT credentials');
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.your_credentials'));
});
}
@@ -269,10 +260,7 @@ class SettingsController extends Controller
*/
public function getIndex()
{
// Grab all the settings
$settings = Setting::all();
// Show the page
return View::make('settings/index', compact('settings'));
}
@@ -323,12 +311,19 @@ class SettingsController extends Controller
$setting->logo = $file_name;
}
}
if (config('app.lock_passwords')==false) {
if (!config('app.lock_passwords')) {
$setting->site_name = e(Input::get('site_name'));
$setting->brand = e(Input::get('brand'));
$setting->custom_css = e(Input::get('custom_css'));
if (Input::get('two_factor_enabled')=='') {
$setting->two_factor_enabled = null;
} else {
$setting->two_factor_enabled = e(Input::get('two_factor_enabled'));
}
}
if (Input::get('per_page')!='') {
@@ -348,11 +343,13 @@ class SettingsController extends Controller
$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'));
@@ -368,6 +365,7 @@ class SettingsController extends Controller
$setting->labels_pagewidth = e(Input::get('labels_pagewidth'));
$setting->labels_pageheight = e(Input::get('labels_pageheight'));
if (Input::has('labels_display_name')) {
$setting->labels_display_name = 1;
} else {
@@ -387,7 +385,7 @@ class SettingsController extends Controller
}
$alert_email = rtrim(Input::get('alert_email'), ',');
$alert_email = trim(Input::get('alert_email'));
$alert_email = trim($alert_email);
$setting->alert_email = e($alert_email);
$setting->alerts_enabled = e(Input::get('alerts_enabled', '0'));
@@ -415,11 +413,11 @@ class SettingsController extends Controller
$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'));
// If validation fails, we'll exit the operation now.
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());
}
@@ -479,7 +477,7 @@ class SettingsController extends Controller
}
closedir($handle);
$files = array_reverse($files);
rsort($files);
}

View File

@@ -47,23 +47,32 @@ class StatuslabelsController extends Controller
{
$colors = [];
$statuslabels = Statuslabel::get();
$statuslabels = Statuslabel::with('assets')->get();
$labels=[];
$points=[];
$colors=[];
foreach ($statuslabels as $statuslabel) {
$labels[]=$statuslabel->name;
$points[]=$statuslabel->assets()->whereNull('assigned_to')->count();
if ($statuslabel->assets->count() > 0) {
$labels[]=$statuslabel->name;
$points[]=$statuslabel->assets()->whereNull('assigned_to')->count();
if ($statuslabel->color!='') {
$colors[]=$statuslabel->color;
}
}
}
$labels[]='Deployed';
$points[]=Asset::whereNotNull('assigned_to')->count();
$colors_array = array_merge($colors, Helper::chartColors());
$result= [
"labels" => $labels,
"datasets" => [ [
"data" => $points,
"backgroundColor" => Helper::chartColors(),
"hoverBackgroundColor" => Helper::chartColors()
"backgroundColor" => $colors_array,
"hoverBackgroundColor" => $colors_array
]]
];
return $result;
@@ -110,6 +119,8 @@ class StatuslabelsController extends Controller
$statuslabel->deployable = $statustype['deployable'];
$statuslabel->pending = $statustype['pending'];
$statuslabel->archived = $statustype['archived'];
$statuslabel->color = e(Input::get('color'));
$statuslabel->show_in_nav = e(Input::get('show_in_nav'),0);
// Was the asset created?
@@ -197,6 +208,8 @@ class StatuslabelsController extends Controller
$statuslabel->deployable = $statustype['deployable'];
$statuslabel->pending = $statustype['pending'];
$statuslabel->archived = $statustype['archived'];
$statuslabel->color = e(Input::get('color'));
$statuslabel->show_in_nav = e(Input::get('show_in_nav'),0);
// Was the asset created?
@@ -247,7 +260,7 @@ class StatuslabelsController extends Controller
public function getDatatable()
{
$statuslabels = Statuslabel::select(array('id','name','deployable','pending','archived'))
$statuslabels = Statuslabel::select(array('id','name','deployable','pending','archived','color','show_in_nav'))
->whereNull('deleted_at');
if (Input::has('search')) {
@@ -291,10 +304,19 @@ class StatuslabelsController extends Controller
$actions = '<a href="'.route('update/statuslabel', $statuslabel->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/statuslabel', $statuslabel->id).'" data-content="'.trans('admin/statuslabels/message.delete.confirm').'" data-title="'.trans('general.delete').' '.htmlspecialchars($statuslabel->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>';
if ($statuslabel->color!='') {
$color = '<div class="pull-left" style="margin-right: 5px; height: 20px; width: 20px; background-color: '.e($statuslabel->color).'"></div>'.e($statuslabel->color);
} else {
$color = '';
}
$rows[] = array(
'id' => e($statuslabel->id),
'type' => e($label_type),
'name' => e($statuslabel->name),
'color' => $color,
'show_in_nav' => ($statuslabel->show_in_nav=='1') ? trans('general.yes') : trans('general.no'),
'actions' => $actions
);
}

View File

@@ -242,7 +242,7 @@ class SuppliersController extends Controller
public function getDatatable()
{
$suppliers = Supplier::select(array('id','name','address','address2','city','state','country','fax', 'phone','email','contact'))
$suppliers = Supplier::with('assets', 'licenses')->select(array('id','name','address','address2','city','state','country','fax', 'phone','email','contact'))
->whereNull('deleted_at');
if (Input::has('search')) {
@@ -283,8 +283,8 @@ class SuppliersController extends Controller
'phone' => e($supplier->phone),
'fax' => e($supplier->fax),
'email' => ($supplier->email!='') ? '<a href="mailto:'.e($supplier->email).'">'.e($supplier->email).'</a>' : '',
'assets' => $supplier->num_assets(),
'licenses' => $supplier->num_licenses(),
'assets' => $supplier->assets->count(),
'licenses' => $supplier->licenses->count(),
'actions' => $actions
);
}

View File

@@ -14,6 +14,7 @@ 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;
use Auth;
@@ -33,6 +34,7 @@ use Symfony\Component\HttpFoundation\JsonResponse;
use URL;
use View;
use Illuminate\Http\Request;
use Gate;
/**
* This controller handles all actions related to Users for
@@ -80,6 +82,7 @@ class UsersController extends Controller
$permissions = config('permissions');
$userPermissions = Helper::selectedPermissionsArray($permissions, Input::old('permissions', array()));
$permissions = $this->filterDisplayable($permissions);
$location_list = Helper::locationsList();
$manager_list = Helper::managerList();
@@ -122,7 +125,16 @@ class UsersController extends Controller
$user->company_id = e(Company::getIdForUser($request->input('company_id')));
$user->manager_id = e($request->input('manager_id'));
$user->notes = e($request->input('notes'));
$user->permissions = json_encode($request->input('permission'));
// Strip out the superuser permission if the user isn't a superadmin
$permissions_array = $request->input('permission');
if (!Auth::user()->isSuperUser()) {
unset($permissions_array['superuser']);
}
$user->permissions = json_encode($permissions_array);
if ($user->manager_id == "") {
@@ -145,7 +157,7 @@ class UsersController extends Controller
} else {
$user->groups()->sync(array());
}
if (($request->input('email_user') == 1) && ($request->has('email'))) {
// Send the credentials through email
$data = array();
@@ -156,7 +168,8 @@ class UsersController extends Controller
Mail::send('emails.send-login', $data, function ($m) use ($user) {
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
$m->subject('Welcome ' . $user->first_name);
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.welcome', ['name' => $user->first_name]));
});
}
return redirect::route('users')->with('success', trans('admin/users/message.success.create'));
@@ -208,7 +221,8 @@ class UsersController extends Controller
Mail::send('emails.send-login', $data, function ($m) use ($user) {
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
$m->subject('Welcome ' . $user->first_name);
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.welcome', ['name' => $user->first_name]));
});
}
@@ -230,6 +244,17 @@ class UsersController extends Controller
* @param int $id
* @return View
*/
private function filterDisplayable($permissions) {
$output = null;
foreach($permissions as $key=>$permission) {
$output[$key] = array_filter($permission, function($p) {
return $p['display'] === true;
});
}
return $output;
}
public function getEdit($id = null)
{
try {
@@ -246,7 +271,7 @@ class UsersController extends Controller
$userGroups = $user->groups()->pluck('name', 'id');
$user->permissions = $user->decodePermissions();
$userPermissions = Helper::selectedPermissionsArray($permissions, $user->permissions);
$permissions = $this->filterDisplayable($permissions);
$location_list = Helper::locationsList();
$company_list = Helper::companyList();
$manager_list = Helper::managerList();
@@ -279,7 +304,6 @@ class UsersController extends Controller
// permissions here before we update the user.
$permissions = $request->input('permissions', array());
app('request')->request->set('permissions', $permissions);
// Only update the email address if locking is set to false
if (config('app.lock_passwords')) {
return redirect()->route('users')->with('error', 'Denied! You cannot update user information on the demo.');
@@ -289,6 +313,15 @@ class UsersController extends Controller
// Get the user information
$user = User::find($id);
// Figure out of this user was an admin before this edit
$orig_permissions_array = $user->decodePermissions();
if (array_key_exists('superuser', $orig_permissions_array)) {
$orig_superuser = $orig_permissions_array['superuser'];
} else {
$orig_superuser = '0';
}
if (!Company::isCurrentUserHasAccess($user)) {
return redirect()->route('users')->with('error', trans('general.insufficient_permissions'));
}
@@ -300,12 +333,16 @@ class UsersController extends Controller
return redirect()->route('users')->with('error', $error);
}
// First handle anything exclusive to editing.
if ($request->has('groups')) {
$user->groups()->sync($request->input('groups'));
} else {
$user->groups()->sync(array());
// Only save groups if the user is a super user
if (Auth::user()->isSuperUser()) {
if ($request->has('groups')) {
$user->groups()->sync($request->input('groups'));
} else {
$user->groups()->sync(array());
}
}
// Do we want to update the user password?
if ($request->has('password')) {
$user->password = bcrypt($request->input('password'));
@@ -319,6 +356,7 @@ class UsersController extends Controller
// Update the user
$user->first_name = e($request->input('first_name'));
$user->last_name = e($request->input('last_name'));
$user->two_factor_optin = e($request->input('two_factor_optin'));
$user->locale = e($request->input('locale'));
$user->employee_num = e($request->input('employee_num'));
$user->activated = e($request->input('activated', $user->activated));
@@ -328,8 +366,17 @@ class UsersController extends Controller
$user->company_id = e(Company::getIdForUser($request->input('company_id')));
$user->manager_id = e($request->input('manager_id'));
$user->notes = e($request->input('notes'));
$user->permissions = json_encode($request->input('permission'));
// Strip out the superuser permission if the user isn't a superadmin
$permissions_array = $request->input('permission');
if (!Auth::user()->isSuperUser()) {
unset($permissions_array['superuser']);
$permissions_array['superuser'] = $orig_superuser;
}
$user->permissions = json_encode($permissions_array);
if ($user->manager_id == "") {
$user->manager_id = null;
@@ -494,9 +541,10 @@ class UsersController extends Controller
// Update the asset log
$logaction = new Actionlog();
$logaction->asset_id = $asset->id;
$logaction->checkedout_to = $asset->assigned_to;
$logaction->asset_type = 'hardware';
$logaction->item_id = $asset->id;
$logaction->item_type = Asset::class;
$logaction->target_id = $asset->assigned_to;
$logaction->target_type = User::class;
$logaction->user_id = Auth::user()->id;
$logaction->note = 'Bulk checkin asset and delete user';
$logaction->logaction('checkin from');
@@ -513,9 +561,10 @@ class UsersController extends Controller
$accessory_array[] = $accessory->accessory_id;
// Update the asset log
$logaction = new Actionlog();
$logaction->accessory_id = $accessory->id;
$logaction->checkedout_to = $accessory->assigned_to;
$logaction->asset_type = 'accessory';
$logaction->item_id = $accessory->id;
$logaction->item_type = Accessory::class;
$logaction->target_id = $accessory->assigned_to;
$logaction->target_type = User::class;
$logaction->user_id = Auth::user()->id;
$logaction->note = 'Bulk checkin accessory and delete user';
$logaction->logaction('checkin from');
@@ -527,9 +576,10 @@ class UsersController extends Controller
$license_array[] = $license->id;
// Update the asset log
$logaction = new Actionlog();
$logaction->asset_id = $license->id;
$logaction->checkedout_to = $license->assigned_to;
$logaction->asset_type = 'software';
$logaction->item_id = $license->id;
$logaction->item_type = License::class;
$logaction->target_id = $license->assigned_to;
$logaction->target_type = User::class;
$logaction->user_id = Auth::user()->id;
$logaction->note = 'Bulk checkin license and delete user';
$logaction->logaction('checkin from');
@@ -597,7 +647,7 @@ class UsersController extends Controller
$user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find($userId);
$userlog = $user->userlog->load('assetlog', 'consumablelog', 'assetlog.model', 'licenselog', 'accessorylog', 'userlog', 'adminlog');
$userlog = $user->userlog->load('item');
if (isset($user->id)) {
@@ -808,7 +858,7 @@ class UsersController extends Controller
'phone' => trim(e($row[5])),
'jobtitle' => trim(e($row[6])),
'employee_num' => trim(e($row[7])),
//'company_id' => Company::getIdForUser($row[8]),
'company_id' => Company::getIdForUser($row[8]),
'permissions' => '{"user":1}',
'notes' => 'Imported user'
);
@@ -828,7 +878,8 @@ class UsersController extends Controller
if ($newuser['email']) {
Mail::send('emails.send-login', $data, function ($m) use ($newuser) {
$m->to($newuser['email'], $newuser['first_name'] . ' ' . $newuser['last_name']);
$m->subject('Welcome ' . $newuser['first_name']);
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.welcome', ['name' => $newuser['first_name']]));
});
}
}
@@ -853,7 +904,7 @@ class UsersController extends Controller
* @see UsersController::getIndex() method that consumed this JSON response
* @return string JSON
*/
public function getDatatable($status = null)
public function getDatatable(Request $request, $status = null)
{
if (Input::has('offset')) {
@@ -874,8 +925,8 @@ class UsersController extends Controller
$sort = e(Input::get('sort'));
}
$users = User::select(array('users.id','users.employee_num','users.email','users.username','users.location_id','users.manager_id','users.first_name','users.last_name','users.created_at','users.notes','users.company_id', 'users.deleted_at','users.activated'))
->with('assets', 'accessories', 'consumables', 'licenses', 'manager', 'groups', 'userloc', 'company');
$users = User::select(array('users.id','users.employee_num','users.two_factor_enrolled','users.jobtitle','users.email','users.username','users.location_id','users.manager_id','users.first_name','users.last_name','users.created_at','users.notes','users.company_id', 'users.deleted_at','users.activated'))
->with('assets', 'accessories', 'consumables', 'licenses', 'manager', 'groups', 'userloc', 'company','throttle');
$users = Company::scopeCompanyables($users);
switch ($status) {
@@ -900,8 +951,9 @@ class UsersController extends Controller
default:
$allowed_columns =
[
'last_name','first_name','email','username','employee_num',
'assets','accessories', 'consumables','licenses','groups','activated','created_at'
'last_name','first_name','email','jobtitle','username','employee_num',
'assets','accessories', 'consumables','licenses','groups','activated','created_at',
'two_factor_enrolled','two_factor_optin'
];
$sort = in_array($sort, $allowed_columns) ? $sort : 'first_name';
@@ -923,38 +975,52 @@ class UsersController extends Controller
}
if (!is_null($user->deleted_at)) {
$actions .= '<a href="' . route('restore/user', $user->id) . '" class="btn btn-warning btn-sm"><i class="fa fa-share icon-white"></i></a> ';
} else {
if ($user->accountStatus() == 'suspended') {
$actions .= '<a href="' . route('unsuspend/user', $user->id) . '" class="btn btn-default btn-sm"><span class="fa fa-clock-o"></span></a> ';
}
$actions .= '<a href="' . route('update/user', $user->id) . '" class="btn btn-warning btn-sm"><i class="fa fa-pencil icon-white"></i></a> ';
$actions .= '<a href="' . route('clone/user', $user->id) . '" class="btn btn-info btn-sm"><i class="fa fa-clone"></i></a>';
if ((Auth::user()->id !== $user->id) && (!config('app.lock_passwords'))) {
$actions .= '<a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="' . route('delete/user', $user->id) . '" data-content="Are you sure you wish to delete this user?" data-title="Delete ' . htmlspecialchars($user->first_name) . '?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a> ';
if (!is_null($user->deleted_at)) {
if (Gate::allows('users.delete')) {
$actions .= '<a href="' . route('restore/user',
$user->id) . '" class="btn btn-warning btn-sm"><i class="fa fa-share icon-white"></i></a> ';
}
} else {
$actions .= ' <span class="btn delete-asset btn-danger btn-sm disabled"><i class="fa fa-trash icon-white"></i></span>';
if (Gate::allows('users.delete')) {
if ($user->accountStatus() == 'suspended') {
$actions .= '<a href="' . route('unsuspend/user',
$user->id) . '" class="btn btn-default btn-sm"><span class="fa fa-clock-o"></span></a> ';
}
}
if (Gate::allows('users.edit')) {
$actions .= '<a href="' . route('update/user',
$user->id) . '" class="btn btn-warning btn-sm"><i class="fa fa-pencil icon-white"></i></a> ';
$actions .= '<a href="' . route('clone/user',
$user->id) . '" class="btn btn-info btn-sm"><i class="fa fa-clone"></i></a>';
}
if (Gate::allows('users.delete')) {
if ((Auth::user()->id !== $user->id) && (!config('app.lock_passwords'))) {
$actions .= '<a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="' . route('delete/user',
$user->id) . '" data-content="Are you sure you wish to delete this user?" data-title="Delete ' . htmlspecialchars($user->first_name) . '?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a> ';
} else {
$actions .= ' <span class="btn delete-asset btn-danger btn-sm disabled"><i class="fa fa-trash icon-white"></i></span>';
}
} else {
$actions.='foo';
}
}
}
$actions .= '</nobr>';
$rows[] = array(
'id' => $user->id,
'checkbox' => ($status!='deleted') ? '<div class="text-center hidden-xs hidden-sm"><input type="checkbox" name="edit_user['.e($user->id).']" class="one_required"></div>' : '',
'name' => '<a title="'.e($user->fullName()).'" href="../admin/users/'.e($user->id).'/view">'.e($user->fullName()).'</a>',
'name' => '<a title="'.e($user->fullName()).'" href="'.config('app.url').'/admin/users/'.e($user->id).'/view">'.e($user->fullName()).'</a>',
'jobtitle' => e($user->jobtitle),
'email' => ($user->email!='') ?
'<a href="mailto:'.e($user->email).'" class="hidden-md hidden-lg">'.e($user->email).'</a>'
.'<a href="mailto:'.e($user->email).'" class="hidden-xs hidden-sm"><i class="fa fa-envelope"></i></a>'
.'</span>' : '',
'username' => e($user->username),
'location' => ($user->userloc) ? e($user->userloc->name) : '',
'manager' => ($user->manager) ? '<a title="' . e($user->manager->fullName()) . '" href="users/' . e($user->manager->id) . '/view">' . e($user->manager->fullName()) . '</a>' : '',
'manager' => ($user->manager) ? '<a title="' . e($user->manager->fullName()) . '" href="'.config('app.url').'/' . e($user->manager->id) . '/view">' . e($user->manager->fullName()) . '</a>' : '',
'assets' => $user->assets->count(),
'employee_num' => e($user->employee_num),
'licenses' => $user->licenses->count(),
@@ -962,8 +1028,10 @@ class UsersController extends Controller
'consumables' => $user->consumables->count(),
'groups' => $group_names,
'notes' => e($user->notes),
'two_factor_enrolled' => ($user->two_factor_enrolled=='1') ? '<i class="fa fa-check text-success"></i>' : '<i class="fa fa-times text-danger"></i>',
'two_factor_optin' => (($user->two_factor_optin=='1') || (Setting::getSettings()->two_factor_enabled=='2') ) ? '<i class="fa fa-check text-success"></i>' : '<i class="fa fa-times text-danger"></i>',
'created_at' => ($user->created_at!='') ? e($user->created_at->format('F j, Y h:iA')) : '',
'activated' => ($user->activated=='1') ? '<i class="fa fa-check"></i>' : '<i class="fa fa-times"></i>',
'activated' => ($user->activated=='1') ? '<i class="fa fa-check text-success"></i>' : '<i class="fa fa-times text-danger"></i>',
'actions' => ($actions) ? $actions : '',
'companyName' => is_null($user->company) ? '' : e($user->company->name)
);
@@ -1003,12 +1071,12 @@ class UsersController extends Controller
//Log the deletion of seats to the log
$logaction = new Actionlog();
$logaction->asset_id = $user->id;
$logaction->asset_type = 'user';
$logaction->item_id = $user->id;
$logaction->item_type = User::class;
$logaction->user_id = Auth::user()->id;
$logaction->note = e(Input::get('notes'));
$logaction->checkedout_to = null;
$logaction->created_at = date("Y-m-d h:i:s");
$logaction->target_id = null;
$logaction->created_at = date("Y-m-d H:i:s");
$logaction->filename = $filename;
$logaction->action_type = 'uploaded';
$logaction->save();
@@ -1079,7 +1147,7 @@ class UsersController extends Controller
return redirect()->route('users')->with('error', trans('general.insufficient_permissions'));
} else {
$log = Actionlog::find($fileId);
$file = $log->get_src();
$file = $log->get_src('users');
return Response::download($file);
}
} else {
@@ -1135,7 +1203,6 @@ class UsersController extends Controller
protected $ldapValidationRules = array(
'firstname' => 'required|string|min:2',
'lastname' => 'required|string|min:2',
'employee_number' => 'string',
'username' => 'required|min:2|unique:users,username',
'email' => 'email|unique:users,email',
@@ -1148,7 +1215,7 @@ class UsersController extends Controller
* @since [v1.8]
* @return Redirect
*/
public function postLDAP()
public function postLDAP(Request $request)
{
ini_set('max_execution_time', 600); //600 seconds = 10 minutes
ini_set('memory_limit', '500M');
@@ -1161,9 +1228,6 @@ class UsersController extends Controller
$ldap_result_emp_num = Setting::getSettings()->ldap_emp_num;
$ldap_result_email = Setting::getSettings()->ldap_email;
$location_id = e(Input::get('location_id'));
try {
$ldapconn = Ldap::connectToLdap();
} catch (\Exception $e) {
@@ -1180,6 +1244,10 @@ class UsersController extends Controller
$results = Ldap::findLdapUsers();
$tmp_pass = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 20);
$pass = bcrypt($tmp_pass);
for ($i = 0; $i < $results["count"]; $i++) {
if (empty($ldap_result_active_flag) || $results[$i][$ldap_result_active_flag][0] == "TRUE") {
@@ -1194,21 +1262,22 @@ class UsersController extends Controller
$item["createorupdate"] = 'updated';
if (!$user = User::where('username', $item["username"])->first()) {
$user = new User;
$user->password = $pass;
$item["createorupdate"] = 'created';
}
// Create the user if they don't exist.
$pass = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 20);
$user->first_name = e($item["firstname"]);
$user->last_name = e($item["lastname"]);
$user->username = e($item["username"]);
$user->email = e($item["email"]);
$user->employee_num = e($item["employee_number"]);
$user->password = bcrypt($pass);
$user->activated = 1;
$user->location_id = e($location_id);
if ($request->input('location_id')!='') {
$user->location_id = e($request->input('location_id'));
}
$user->notes = 'Imported from LDAP';
$user->ldap_import = 1;
@@ -1218,9 +1287,7 @@ class UsersController extends Controller
$item["note"] = $item["createorupdate"];
$item["status"]='success';
} else {
//$errors_array = array($user->getErrors());
foreach ($user->getErrors()->getMessages() as $key => $err) {
//echo $user->getErrors();
$errors .='<li>'.$err[0];
}
$item["note"] = $errors;
@@ -1234,7 +1301,7 @@ class UsersController extends Controller
return redirect()->route('ldap/user')->with('success', "OK")->with('summary', $summary);
return redirect()->route('ldap/user')->with('success', "LDAP Import successful.")->with('summary', $summary);
}
/**
@@ -1246,9 +1313,113 @@ class UsersController extends Controller
*/
public function getAssetList($userId)
{
$assets = Asset::where('assigned_to', '=', $userId)->get();
$assets = Asset::where('assigned_to', '=', $userId)->with('model')->get();
return response()->json($assets);
//$foo = Asset::where('assigned_to','=',$userId)->get();
//print_r($foo);
}
/**
* Exports users to CSV
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.5]
* @return \Illuminate\Http\Response
*/
public function getExportUserCsv()
{
\Debugbar::disable();
$response = new StreamedResponse(function() {
// Open output stream
$handle = fopen('php://output', 'w');
User::with('assets', 'accessories', 'consumables', 'licenses', 'manager', 'groups', 'userloc', 'company','throttle')->orderBy('created_at', 'DESC')->chunk(500, function($users) use($handle) {
$headers=[
// strtolower to prevent Excel from trying to open it as a SYLK file
strtolower(trans('general.id')),
trans('admin/companies/table.title'),
trans('admin/users/table.title'),
trans('admin/users/table.employee_num'),
trans('admin/users/table.name'),
trans('admin/users/table.username'),
trans('admin/users/table.email'),
trans('admin/users/table.manager'),
trans('admin/users/table.location'),
trans('general.assets'),
trans('general.licenses'),
trans('general.accessories'),
trans('general.consumables'),
trans('admin/users/table.groups'),
trans('general.notes'),
trans('admin/users/table.activated'),
trans('general.created_at')
];
fputcsv($handle, $headers);
foreach ($users as $user) {
$user_groups = '';
foreach ($user->groups as $user_group) {
$user_groups .= $user_group->name.', ';
}
// Add a new row with data
$values = [
$user->id,
($user->company) ? $user->company->name : '',
$user->jobtitle,
$user->employee_num,
$user->fullName(),
$user->username,
$user->email,
($user->manager) ? $user->manager->fullName() : '',
($user->location) ? $user->location->name : '',
$user->assets->count(),
$user->licenses->count(),
$user->accessories->count(),
$user->consumables->count(),
$user_groups,
$user->notes,
($user->activated=='1') ? trans('general.yes') : trans('general.no'),
$user->created_at,
];
fputcsv($handle, $values);
}
});
// Close the output stream
fclose($handle);
}, 200, [
'Content-Type' => 'text/csv',
'Content-Disposition' => 'attachment; filename="users-'.date('Y-m-d-his').'.csv"',
]);
return $response;
}
public function postTwoFactorReset(Request $request)
{
if (Gate::denies('users.edit')) {
return response()->json(['message' => trans('general.insufficient_permissions')], 500);
}
try {
$user = User::find($request->get('id'));
$user->two_factor_secret = null;
$user->two_factor_enrolled = 0;
$user->save();
return response()->json(['message' => trans('admin/settings/general.two_factor_reset_success')], 200);
} catch (\Exception $e) {
return response()->json(['message' => trans('admin/settings/general.two_factor_reset_error')], 500);
}
}
}

View File

@@ -4,12 +4,14 @@ namespace App\Http\Controllers;
use App\Models\Accessory;
use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\AssetModel;
use App\Models\CheckoutRequest;
use App\Models\Company;
use App\Models\Consumable;
use App\Models\Component;
use App\Models\Consumable;
use App\Models\License;
use App\Models\Setting;
use App\Models\User;
use App\Models\License;
use Auth;
use Config;
use DB;
@@ -20,6 +22,7 @@ use Redirect;
use Slack;
use Validator;
use View;
use Illuminate\Http\Request;
/**
* This controller handles all actions related to the ability for users
@@ -37,11 +40,18 @@ class ViewAssetsController extends Controller
public function getIndex()
{
$user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find(Auth::user()->id);
$userlog = $user->userlog->load('assetlog', 'consumablelog', 'assetlog.model', 'licenselog', 'accessorylog', 'userlog', 'adminlog');
$user = User::with(
'assets',
'assets.model',
'consumables',
'accessories',
'licenses',
'userloc',
'userlog'
)->withTrashed()->find(Auth::user()->id);
$userlog = $user->userlog->load('item', 'user', 'target');
if (isset($user->id)) {
return View::make('account/view-assets', compact('user', 'userlog'));
@@ -60,11 +70,132 @@ class ViewAssetsController extends Controller
{
$assets = Asset::with('model', 'defaultLoc', 'assetloc', 'assigneduser')->Hardware()->RequestableAssets()->get();
$models = AssetModel::with('category')->RequestableModels()->get();
return View::make('account/requestable-assets', compact('user', 'assets'));
return View::make('account/requestable-assets', compact('user', 'assets', 'models'));
}
public function getRequestedIndex()
{
$requestedItems = CheckoutRequest::with('user', 'requestedItem')->get();
return View::make('admin/requested-assets', compact('requestedItems'));
}
public function getRequestItem($itemType, $itemId = null)
{
$item = null;
$fullItemType = 'App\\Models\\' . studly_case($itemType);
if ($itemType == "asset_model") {
$itemType = "model";
}
$item = call_user_func(array($fullItemType, 'find'), $itemId);
$user = Auth::user();
$quantity = $data['item_quantity'] = Input::has('request-quantity') ? e(Input::get('request-quantity')) : 1;
$logaction = new Actionlog();
$logaction->item_id = $data['asset_id'] = $item->id;
$logaction->item_type = $fullItemType;
$logaction->created_at = $data['requested_date'] = date("Y-m-d H:i:s");
if ($user->location_id) {
$logaction->location_id = $user->location_id;
}
$logaction->target_id = $data['user_id'] = Auth::user()->id;
$logaction->target_type = User::class;
$data['requested_by'] = $user->fullName();
$data['item_name'] = $item->name;
$data['item_type'] = $itemType;
if ($fullItemType == Asset::class) {
$data['item_url'] = route('view/hardware', $item->id);
$slackMessage = ' Asset <'.config('app.url').'/hardware/'.$item->id.'/view'.'|'.$item->showAssetName().'> requested by <'.config('app.url').'/users/'.$item->user_id.'/view'.'|'.$user->fullName().'>.';
} else {
$data['item_url'] = route("view/${itemType}", $item->id);
$slackMessage = $quantity. ' ' . class_basename(strtoupper($logaction->item_type)).' <'.$data['item_url'].'|'.$item->name.'> requested by <'.config('app.url').'/user/'.$item->id.'/view'.'|'.$user->fullName().'>.';
}
$settings = Setting::getSettings();
if ($settings->slack_endpoint) {
$slack_settings = [
'username' => $settings->botname,
'channel' => $settings->slack_channel,
'link_names' => true
];
$slackClient = new \Maknz\Slack\Client($settings->slack_endpoint, $slack_settings);
}
if ($item->isRequestedBy($user)) {
$item->cancelRequest();
$log = $logaction->logaction('request_canceled');
if (($settings->alert_email!='') && ($settings->alerts_enabled=='1') && (!config('app.lock_passwords'))) {
Mail::send('emails.asset-canceled', $data, function ($m) use ($user, $settings) {
$m->to(explode(',', $settings->alert_email), $settings->site_name);
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.Item_Request_Canceled'));
});
}
if ($settings->slack_endpoint) {
try {
$slackClient->attach([
'color' => 'good',
'fields' => [
[
'title' => 'CANCELED:',
'value' => $slackMessage
]
]
])->send('Item Request Canceled');
} catch (Exception $e) {
}
}
return redirect()->route('requestable-assets')->with('success')->with('success', trans('admin/hardware/message.requests.canceled'));
} else {
$item->request();
$log = $logaction->logaction('requested');
if (($settings->alert_email!='') && ($settings->alerts_enabled=='1') && (!config('app.lock_passwords'))) {
Mail::send('emails.asset-requested', $data, function ($m) use ($user, $settings) {
$m->to(explode(',', $settings->alert_email), $settings->site_name);
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.Item_Requested'));
});
}
if ($settings->slack_endpoint) {
try {
$slackClient->attach([
'color' => 'good',
'fields' => [
[
'title' => 'REQUESTED:',
'value' => $slackMessage
]
]
])->send('Item Requested');
} catch (Exception $e) {
}
}
return redirect()->route('requestable-assets')->with('success')->with('success', trans('admin/hardware/message.requests.success'));
}
}
public function getRequestAsset($assetId = null)
{
@@ -76,17 +207,23 @@ class ViewAssetsController extends Controller
return redirect()->route('requestable-assets')->with('error', trans('admin/hardware/message.does_not_exist_or_not_requestable'));
} elseif (!Company::isCurrentUserHasAccess($asset)) {
return redirect()->route('requestable-assets')->with('error', trans('general.insufficient_permissions'));
}
// If it's requested, cancel the request.
if ($asset->isRequestedBy(Auth::user())) {
$asset->cancelRequest();
return redirect()->route('requestable-assets')->with('success')->with('success', trans('admin/hardware/message.requests.success'));
} else {
$logaction = new Actionlog();
$logaction->asset_id = $data['asset_id'] = $asset->id;
$logaction->asset_type = $data['asset_type'] = 'hardware';
$logaction->created_at = $data['requested_date'] = date("Y-m-d h:i:s");
$logaction->item_id = $data['asset_id'] = $asset->id;
$logaction->item_type = Asset::class;
$logaction->created_at = $data['requested_date'] = date("Y-m-d H:i:s");
$data['asset_type'] = 'hardware';
if ($user->location_id) {
$logaction->location_id = $user->location_id;
}
$logaction->user_id = $data['user_id'] = Auth::user()->id;
$logaction->target_id = $data['user_id'] = Auth::user()->id;
$logaction->target_type = User::class;
$log = $logaction->logaction('requested');
$data['requested_by'] = $user->fullName();
@@ -97,10 +234,13 @@ class ViewAssetsController extends Controller
if (($settings->alert_email!='') && ($settings->alerts_enabled=='1') && (!config('app.lock_passwords'))) {
Mail::send('emails.asset-requested', $data, function ($m) use ($user, $settings) {
$m->to(explode(',', $settings->alert_email), $settings->site_name);
$m->subject('Asset Requested');
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.asset_requested'));
});
}
$asset->request();
if ($settings->slack_endpoint) {
@@ -119,7 +259,7 @@ class ViewAssetsController extends Controller
'fields' => [
[
'title' => 'REQUESTED:',
'value' => strtoupper($logaction->asset_type).' asset <'.config('app.url').'/hardware/'.$asset->id.'/view'.'|'.$asset->showAssetName().'> requested by <'.config('app.url').'/hardware/'.$asset->id.'/view'.'|'.Auth::user()->fullName().'>.'
'value' => class_basename(strtoupper($logaction->item_type)).' asset <'.config('app.url').'/hardware/'.$asset->id.'/view'.'|'.$asset->showAssetName().'> requested by <'.config('app.url').'/hardware/'.$asset->id.'/view'.'|'.Auth::user()->fullName().'>.'
]
]
@@ -137,41 +277,36 @@ class ViewAssetsController extends Controller
}
public function getRequestedAssets()
{
$checkoutrequests = CheckoutRequest::all();
return View::make('account/requested-items', compact($checkoutrequests));
}
// Get the acceptance screen
public function getAcceptAsset($logID = null)
{
if (!$findlog = DB::table('asset_logs')->where('id', '=', $logID)->first()) {
if (!$findlog = Actionlog::where('id', $logID)->first()) {
echo 'no record';
//return redirect()->to('account')->with('error', trans('admin/hardware/message.does_not_exist'));
}
if ($findlog->accepted_id!='') {
return redirect()->to('account/view-assets')->with('error', trans('admin/users/message.error.asset_already_accepted'));
}
$user = Auth::user();
if ($user->id != $findlog->checkedout_to) {
if ($user->id != $findlog->item->assigned_to) {
return redirect()->to('account/view-assets')->with('error', trans('admin/users/message.error.incorrect_user_accepted'));
}
// Asset
if (($findlog->asset_id!='') && ($findlog->asset_type=='hardware')) {
$item = Asset::find($findlog->asset_id);
// software
} elseif (($findlog->asset_id!='') && ($findlog->asset_type=='software')) {
$item = License::find($findlog->asset_id);
// accessories
} elseif ($findlog->accessory_id!='') {
$item = Accessory::find($findlog->accessory_id);
// consumable
} elseif ($findlog->consumable_id!='') {
$item = Consumable::find($findlog->consumable_id);
// components
} elseif ($findlog->component_id!='') {
$item = Component::find($findlog->component_id);
}
$item = $findlog->item;
// Check if the asset exists
if (is_null($item)) {
@@ -180,20 +315,20 @@ 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);
return View::make('account/accept-asset', compact('item'))->with('findlog', $findlog)->with('item',$item);
}
}
// Save the acceptance
public function postAcceptAsset($logID = null)
public function postAcceptAsset(Request $request, $logID = null)
{
// Check if the asset exists
if (is_null($findlog = DB::table('asset_logs')->where('id', '=', $logID)->first())) {
if (is_null($findlog = Actionlog::where('id', $logID)->first())) {
// Redirect to the asset management page
return redirect()->to('account/view-assets')->with('error', trans('admin/hardware/message.does_not_exist'));
}
if ($findlog->accepted_id!='') {
// Redirect to the asset management page
@@ -201,15 +336,25 @@ class ViewAssetsController extends Controller
}
if (!Input::has('asset_acceptance')) {
return redirect()->to('account/view-assets')->with('error', trans('admin/users/message.error.accept_or_decline'));
return redirect()->back()->with('error', trans('admin/users/message.error.accept_or_decline'));
}
$user = Auth::user();
if ($user->id != $findlog->checkedout_to) {
if ($user->id != $findlog->item->assigned_to) {
return redirect()->to('account/view-assets')->with('error', trans('admin/users/message.error.incorrect_user_accepted'));
}
if ($request->has('signature_output')) {
$path = config('app.private_uploads').'/signatures';
$sig_filename = "siglog-".$findlog->id.'-'.date('Y-m-d-his').".png";
$data_uri = e($request->get('signature_output'));
$encoded_image = explode(",", $data_uri);
$decoded_image = base64_decode($encoded_image[1]);
file_put_contents($path."/".$sig_filename, $decoded_image);
}
$logaction = new Actionlog();
if (Input::get('asset_acceptance')=='accepted') {
@@ -221,61 +366,34 @@ class ViewAssetsController extends Controller
$accepted="rejected";
$return_msg = trans('admin/users/message.declined');
}
$logaction->item_id = $findlog->item_id;
$logaction->item_type = $findlog->item_type;
// Asset
if (($findlog->asset_id!='') && ($findlog->asset_type=='hardware')) {
$logaction->asset_id = $findlog->asset_id;
$logaction->accessory_id = null;
$logaction->asset_type = 'hardware';
if (($findlog->item_id!='') && ($findlog->item_type==Asset::class)) {
if (Input::get('asset_acceptance')!='accepted') {
DB::table('assets')
->where('id', $findlog->asset_id)
->where('id', $findlog->item_id)
->update(array('assigned_to' => null));
}
// software
} elseif (($findlog->asset_id!='') && ($findlog->asset_type=='software')) {
$logaction->asset_id = $findlog->asset_id;
$logaction->accessory_id = null;
$logaction->component_id = null;
$logaction->asset_type = 'software';
// accessories
} elseif ($findlog->accessory_id!='') {
$logaction->asset_id = null;
$logaction->component_id = null;
$logaction->accessory_id = $findlog->accessory_id;
$logaction->asset_type = 'accessory';
// accessories
} elseif ($findlog->consumable_id!='') {
$logaction->asset_id = null;
$logaction->accessory_id = null;
$logaction->component_id = null;
$logaction->consumable_id = $findlog->consumable_id;
$logaction->asset_type = 'consumable';
} elseif ($findlog->component_id!='') {
$logaction->asset_id = null;
$logaction->accessory_id = null;
$logaction->consumable_id = null;
$logaction->component_id = $findlog->component_id;
$logaction->asset_type = 'component';
}
$logaction->checkedout_to = $findlog->checkedout_to;
$logaction->target_id = $findlog->target_id;
$logaction->note = e(Input::get('note'));
$logaction->user_id = $user->id;
$logaction->accepted_at = date("Y-m-d h:i:s");
$logaction->updated_at = date("Y-m-d H:i:s");
if ($sig_filename) {
$logaction->accept_signature = $sig_filename;
}
$log = $logaction->logaction($logaction_msg);
$update_checkout = DB::table('asset_logs')
$update_checkout = DB::table('action_logs')
->where('id', $findlog->id)
->update(array('accepted_id' => $logaction->id));
$affected_asset=$logaction->assetlog;
$affected_asset->accepted=$accepted;
$affected_asset = $logaction->item;
$affected_asset->accepted = $accepted;
$affected_asset->save();
if ($update_checkout) {

View File

@@ -14,7 +14,7 @@ class Kernel extends HttpKernel
* @var array
*/
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\MisterPhilip\MaintenanceMode\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\FrameGuard::class,
@@ -35,6 +35,7 @@ class Kernel extends HttpKernel
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\App\Http\Middleware\CheckLocale::class,
\App\Http\Middleware\CheckForTwoFactor::class,
],
'api' => [

View File

@@ -23,7 +23,7 @@ class CheckForSetup
}
} else {
if (!$request->is('setup*')) {
if (!($request->is('setup*')) && !($request->is('.env'))) {
return redirect(config('app.url').'/setup')->with('Request', $request);
}

View File

@@ -0,0 +1,51 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Auth;
use Log;
use App\Models\Setting;
class CheckForTwoFactor
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
// Skip the logic if the user is on the two factor pages
if (($request->route()->getName()=='two-factor') || ($request->route()->getName()=='two-factor-enroll') || ($request->route()->getName()=='logout')) {
return $next($request);
}
// Two-factor is enabled (either optional or required)
if (Auth::check() && (Setting::getSettings()->two_factor_enabled!='')) {
// This user is already 2fa-authed
if ($request->session()->get('2fa_authed')){
return $next($request);
}
// Two-factor is optional and the user has NOT opted in, let them through
if ((Setting::getSettings()->two_factor_enabled=='1') && (Auth::user()->two_factor_optin!='1')) {
return $next($request);
}
// Otherwise make sure they're enrolled and show them the 2FA code screen
if ((Auth::user()->two_factor_secret!='') && (Auth::user()->two_factor_enrolled=='1')) {
return redirect()->route('two-factor')->with('info', 'Please enter your two-factor authentication code.');
}
return redirect()->route('two-factor-enroll')->with('success', 'Please enroll a device in two-factor authentication.');
}
return $next($request);
}
}

View File

@@ -22,7 +22,8 @@ class CheckPermissions
*/
public function handle($request, Closure $next, $section = null)
{
if (Gate::allows($section)) {
return $next($request);
}

View File

@@ -15,7 +15,10 @@ class FrameGuard
public function handle($request, Closure $next)
{
$response = $next($request);
$response->headers->set('X-Frame-Options', 'SAMEORIGIN', false);
if (config('app.allow_iframing') == false) {
$response->headers->set('X-Frame-Options', 'SAMEORIGIN', false);
}
return $response;
}
}

View File

@@ -18,7 +18,7 @@ class RedirectIfAuthenticated
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect('/');
return redirect()->intended('/');
}
return $next($request);

View File

@@ -37,6 +37,7 @@ class AssetRequest extends Request
'supplier_id' => 'integer',
'status' => 'integer',
'asset_tag' => 'required',
'purchase_cost' => 'numeric',
];

View File

@@ -25,11 +25,10 @@ class SaveUserRequest extends Request
{
return [
'first_name' => 'required|string|min:1',
'last_name' => 'required|string|min:1',
'username' => 'required|string|min:2|unique:users,username,NULL,deleted_at',
'email' => 'email',
'password' => 'required|min:6',
'password_confirm' => 'sometimes|required_with:password',
'username' => 'required|string|min:2|unique:users,username,NULL,deleted_at',
];
}
}

View File

@@ -25,7 +25,6 @@ class UpdateUserRequest extends Request
{
return [
'first_name' => 'required|string|min:1',
'last_name' => 'required|string|min:1',
'email' => 'email',
'password_confirm' => 'sometimes|required_with:password',
];

View File

@@ -0,0 +1,23 @@
<?php
namespace App\Http\Traits;
trait UniqueUndeletedTrait
{
/**
* Prepare a unique_ids rule, adding a model identifier if required.
*
* @param array $parameters
* @param string $field
* @return string
*/
protected function prepareUniqueUndeletedRule($parameters, $field)
{
// Only perform a replacement if the model has been persisted.
if ($this->exists) {
return 'unique_undeleted:'.$this->table.','. $this->getKey();
}
return 'unique_undeleted:'.$this->table.',0';
}
}

View File

@@ -1,6 +1,7 @@
<?php
use App\Models\Statuslabel;
use App\Models\CheckoutRequest;
use App\Models\Location;
use App\Models\Statuslabel;
/*
|--------------------------------------------------------------------------
@@ -78,7 +79,7 @@ Route::group([ 'prefix' => 'api', 'middleware' => 'auth' ], function () {
/*---Manufacturers API---*/
Route::group(array('prefix'=>'manufacturers'), function () {
Route::get('list', array('as'=>'api.manufacturers.list', 'uses'=>'ManufacturersController@getDatatable'));
Route::get('{manufacturerID}/view', array('as'=>'api.manufacturers.view', 'uses'=>'ManufacturersController@getDataView'));
Route::get('{manufacturerID}/view/{itemtype}', array('as'=>'api.manufacturers.view', 'uses'=>'ManufacturersController@getDataView'));
});
/*---Suppliers API---*/
@@ -89,6 +90,7 @@ Route::group([ 'prefix' => 'api', 'middleware' => 'auth' ], function () {
/*---Users API---*/
Route::group([ 'prefix' => 'users' ], function () {
Route::post('/', [ 'as' => 'api.users.store', 'uses' => 'UsersController@store' ]);
Route::post('two_factor_reset', [ 'as' => 'api.users.two_factor_reset', 'uses' => 'UsersController@postTwoFactorReset' ]);
Route::get('list/{status?}', [ 'as' => 'api.users.list', 'uses' => 'UsersController@getDatatable' ]);
Route::get('{userId}/assets', [ 'as' => 'api.users.assetlist', 'uses' => 'UsersController@getAssetList' ]);
Route::post('{userId}/upload', [ 'as' => 'upload/user', 'uses' => 'UsersController@postUpload' ]);
@@ -184,79 +186,142 @@ Route::group([ 'prefix' => 'api', 'middleware' => 'auth' ], function () {
Route::group(
[ 'prefix' => 'hardware',
'middleware' => ['web',
'auth',
'authorize:assets.view']],
'auth']],
function () {
Route::get('history', [
'as' => 'asset.import-history',
'middleware' => 'authorize:assets.checkout',
'uses' => 'AssetsController@getImportHistory'
]);
Route::post('history', [
'as' => 'asset.process-import-history',
'middleware' => 'authorize:assets.checkout',
'uses' => 'AssetsController@postImportHistory'
]);
Route::get('create/{model?}', [
'as' => 'create/hardware',
'middleware' => 'authorize:assets.create',
'uses' => 'AssetsController@getCreate'
]);
Route::post('create', [
'as' => 'savenew/hardware',
'middleware' => 'authorize:assets.create',
'uses' => 'AssetsController@postCreate'
]);
Route::get('{assetId}/edit', [
'as' => 'update/hardware',
'middleware' => 'authorize:assets.edit',
'uses' => 'AssetsController@getEdit'
]);
Route::get('/bytag', [
'as' => 'findbytag/hardware',
'middleware' => 'authorize:assets.view',
'uses' => 'AssetsController@getAssetByTag'
]);
Route::get('{assetId}/clone', [ 'as' => 'clone/hardware', 'uses' => 'AssetsController@getClone' ]);
Route::get('{assetId}/clone', [
'as' => 'clone/hardware',
'middleware' => 'authorize:assets.create',
'uses' => 'AssetsController@getClone'
]);
Route::post('{assetId}/clone', 'AssetsController@postCreate');
Route::get('{assetId}/delete', [ 'as' => 'delete/hardware', 'uses' => 'AssetsController@getDelete' ]);
Route::get(
'{assetId}/checkout',
[ 'as' => 'checkout/hardware', 'uses' => 'AssetsController@getCheckout' ]
);
Route::post('{assetId}/checkout', 'AssetsController@postCheckout');
Route::get(
'{assetId}/checkin/{backto?}',
[ 'as' => 'checkin/hardware', 'uses' => 'AssetsController@getCheckin' ]
);
Route::post('{assetId}/checkin/{backto?}', 'AssetsController@postCheckin');
Route::get('{assetId}/view', [ 'as' => 'view/hardware', 'uses' => 'AssetsController@getView' ]);
Route::get('{assetId}/delete', [
'as' => 'delete/hardware',
'middleware' => 'authorize:assets.delete',
'uses' => 'AssetsController@getDelete'
]);
Route::get('{assetId}/checkout', [
'as' => 'checkout/hardware',
'middleware' => 'authorize:assets.checkout',
'uses' => 'AssetsController@getCheckout'
]);
Route::post('{assetId}/checkout', [
'as' => 'checkout/hardware',
'middleware' => 'authorize:assets.checkout',
'uses' => 'AssetsController@postCheckout'
]);
Route::get('{assetId}/checkin/{backto?}', [
'as' => 'checkin/hardware',
'middleware' => 'authorize:assets.checkin',
'uses' => 'AssetsController@getCheckin'
]);
Route::post('{assetId}/checkin/{backto?}', [
'as' => 'checkin/hardware',
'middleware' => 'authorize:assets.checkin',
'uses' => 'AssetsController@postCheckin'
]);
Route::get('{assetId}/view', [
'as' => 'view/hardware',
'middleware' => ['authorize:assets.view'],
'uses' => 'AssetsController@getView'
]);
Route::get('{assetId}/qr-view', [ 'as' => 'qr-view/hardware', 'uses' => 'AssetsController@getView' ]);
Route::get('{assetId}/qr_code', [ 'as' => 'qr_code/hardware', 'uses' => 'AssetsController@getQrCode' ]);
Route::get('{assetId}/barcode', [ 'as' => 'barcode/hardware', 'uses' => 'AssetsController@getBarCode' ]);
Route::get('{assetId}/restore', [ 'as' => 'restore/hardware', 'uses' => 'AssetsController@getRestore' ]);
Route::post('{assetId}/upload', [ 'as' => 'upload/asset', 'uses' => 'AssetsController@postUpload' ]);
Route::get(
'{assetId}/deletefile/{fileId}',
[ 'as' => 'delete/assetfile', 'uses' => 'AssetsController@getDeleteFile' ]
);
Route::get(
'{assetId}/showfile/{fileId}',
[ 'as' => 'show/assetfile', 'uses' => 'AssetsController@displayFile' ]
);
Route::get('{assetId}/restore', [
'as' => 'restore/hardware',
'middleware' => 'authorize:assets.delete',
'uses' => 'AssetsController@getRestore'
]);
Route::post('{assetId}/upload', [
'as' => 'upload/asset',
'middleware' => 'authorize:assets.edit',
'uses' => 'AssetsController@postUpload'
]);
Route::get(
'import/delete-import/{filename}',
[ 'as' => 'assets/import/delete-file', 'uses' => 'AssetsController@getDeleteImportFile' ]
);
Route::get('{assetId}/deletefile/{fileId}', [
'as' => 'delete/assetfile',
'middleware' => 'authorize:assets.edit',
'uses' => 'AssetsController@getDeleteFile'
]);
Route::get(
'import/process/{filename}',
[ 'as' => 'assets/import/process-file', 'uses' => 'AssetsController@getProcessImportFile' ]
);
Route::get('{assetId}/showfile/{fileId}', [
'as' => 'show/assetfile',
'middleware' => 'authorize:assets.view',
'uses' => 'AssetsController@displayFile'
]);
Route::get(
'import',
[ 'as' => 'assets/import', 'uses' => 'AssetsController@getImportUpload' ]
);
Route::get('import/delete-import/{filename}', [
'as' => 'assets/import/delete-file',
'middleware' => 'authorize:assets.create',
'uses' => 'AssetsController@getDeleteImportFile'
]);
Route::post( 'import/process/', [ 'as' => 'assets/import/process-file',
'middleware' => 'authorize:assets.create',
'uses' => 'AssetsController@postProcessImportFile'
]);
Route::get( 'import/delete/{filename}', [ 'as' => 'assets/import/delete-file',
'middleware' => 'authorize:assets.create', // TODO What permissions should this require?
'uses' => 'AssetsController@getDeleteImportFile'
]);
Route::get('import',[
'as' => 'assets/import',
'middleware' => 'authorize:assets.create',
'uses' => 'AssetsController@getImportUpload'
]);
Route::post('{assetId}/edit', 'AssetsController@postEdit');
Route::post('{assetId}/edit',[
'as' => 'assets/import',
'middleware' => 'authorize:assets.edit',
'uses' => 'AssetsController@postEdit'
]);
Route::post(
'bulkedit',
[
'as' => 'hardware/bulkedit',
'middleware' => 'authorize:assets.edit',
'uses' => 'AssetsController@postBulkEdit'
]
);
@@ -264,6 +329,7 @@ Route::group(
'bulkdelete',
[
'as' => 'hardware/bulkdelete',
'middleware' => 'authorize:assets.delete',
'uses' => 'AssetsController@postBulkDelete'
]
);
@@ -271,34 +337,72 @@ Route::group(
'bulksave',
[
'as' => 'hardware/bulksave',
'middleware' => 'authorize:assets.edit',
'uses' => 'AssetsController@postBulkSave'
]
);
# Asset Model Management
Route::group([ 'prefix' => 'models', 'middleware' => 'auth' ], function () {
# Bulk checkout / checkin
Route::get( 'bulkcheckout', [
'as' => 'hardware/bulkcheckout',
'middleware' => 'authorize:assets.checkout',
'uses' => 'AssetsController@getBulkCheckout'
]);
Route::post( 'bulkcheckout', [
'as' => 'hardware/bulkcheckout',
'middleware' => 'authorize:assets.checkout',
'uses' => 'AssetsController@postBulkCheckout'
]);
Route::get('/', [ 'as' => 'models', 'uses' => 'AssetModelsController@getIndex' ]);
Route::get('create', [ 'as' => 'create/model', 'uses' => 'AssetModelsController@getCreate' ]);
# Asset Model Management
Route::group([ 'prefix' => 'models', 'middleware' => ['auth'] ], function () {
Route::get('create', [ 'as' => 'create/model', 'uses' => 'AssetModelsController@getCreate', 'middleware' => ['authorize:superuser'] ]);
Route::post('create', 'AssetModelsController@postCreate');
Route::get('{modelId}/edit', [ 'as' => 'update/model', 'uses' => 'AssetModelsController@getEdit' ]);
Route::post('{modelId}/edit', 'AssetModelsController@postEdit');
Route::get('{modelId}/edit', [ 'as' => 'update/model', 'uses' => 'AssetModelsController@getEdit' , 'middleware' => ['authorize:superuser']]);
Route::post('{modelId}/edit', [ 'uses' => 'AssetModelsController@postEdit', 'middleware' => ['authorize:superuser']]);
Route::get('{modelId}/clone', [ 'as' => 'clone/model', 'uses' => 'AssetModelsController@getClone' ]);
Route::post('{modelId}/clone', 'AssetModelsController@postCreate');
Route::get('{modelId}/delete', [ 'as' => 'delete/model', 'uses' => 'AssetModelsController@getDelete' ]);
Route::get('{modelId}/delete', [ 'as' => 'delete/model', 'uses' => 'AssetModelsController@getDelete', 'middleware' => ['authorize:superuser'] ]);
Route::get('{modelId}/view', [ 'as' => 'view/model', 'uses' => 'AssetModelsController@getView' ]);
Route::get('{modelID}/restore', [ 'as' => 'restore/model', 'uses' => 'AssetModelsController@getRestore' ]);
Route::get('{modelID}/restore', [ 'as' => 'restore/model', 'uses' => 'AssetModelsController@getRestore', 'middleware' => ['authorize:superuser'] ]);
Route::get('{modelId}/custom_fields', ['as' => 'custom_fields/model','uses' => 'AssetModelsController@getCustomFields']);
Route::get('/', [ 'as' => 'models', 'uses' => 'AssetModelsController@getIndex' ,'middleware' => ['authorize:superuser'] ]);
});
Route::get('/', [
'as' => 'hardware',
'middleware' => 'authorize:assets.view',
'uses' => 'AssetsController@getIndex'
]);
}
);
/*
|--------------------------------------------------------------------------
| Log Routes
|--------------------------------------------------------------------------
|
| Register all the admin routes.
|
*/
Route::group(['middleware' => 'auth'], function () {
Route::get(
'display-sig/{filename}',
[
'as' => 'log.signature.view',
'middleware' => 'authorize:assets.view',
'uses' => 'ActionlogController@displaySig' ]
);
});
/*
|--------------------------------------------------------------------------
| Admin Routes
@@ -310,44 +414,68 @@ Route::group(
Route::group([ 'prefix' => 'admin','middleware' => ['web','auth']], function () {
Route::get('requests',
// foreach( CheckoutRequest::with('user')->get() as $requestedItem) {
// echo $requestedItem->user->username . ' requested ' . $requestedItem->requestedItem->name;
[
'as' => 'requests',
'middleware' => 'authorize:admin',
'uses' => 'ViewAssetsController@getRequestedIndex'
]);
# Licenses
Route::group([ 'prefix' => 'licenses', 'middleware'=>'authorize:licenses.view' ], function () {
Route::get('create', [ 'as' => 'create/licenses', 'uses' => 'LicensesController@getCreate' ]);
Route::post('create', 'LicensesController@postCreate');
Route::get('{licenseId}/edit', [ 'as' => 'update/license', 'uses' => 'LicensesController@getEdit' ]);
Route::post('{licenseId}/edit', 'LicensesController@postEdit');
Route::get('{licenseId}/clone', [ 'as' => 'clone/license', 'uses' => 'LicensesController@getClone' ]);
Route::post('{licenseId}/clone', 'LicensesController@postCreate');
Route::get('{licenseId}/delete', [ 'as' => 'delete/license', 'uses' => 'LicensesController@getDelete' ]);
Route::get(
'{licenseId}/freecheckout',
[ 'as' => 'freecheckout/license', 'uses' => 'LicensesController@getFreeLicense' ]
);
Route::get('create', [ 'as' => 'create/licenses', 'middleware' => 'authorize:licenses.create','uses' => 'LicensesController@getCreate' ]);
Route::post('create', [ 'as' => 'create/licenses', 'middleware' => 'authorize:licenses.create','uses' => 'LicensesController@postCreate' ]);
Route::get('{licenseId}/edit', [ 'as' => 'update/license', 'middleware' => 'authorize:licenses.edit', 'uses' => 'LicensesController@getEdit' ]);
Route::post('{licenseId}/edit', [ 'as' => 'update/license', 'middleware' => 'authorize:licenses.edit', 'uses' => 'LicensesController@postEdit' ]);
Route::get('{licenseId}/clone', [ 'as' => 'clone/license', 'middleware' => 'authorize:licenses.create', 'uses' => 'LicensesController@getClone' ]);
Route::post('{licenseId}/clone', [ 'as' => 'clone/license', 'middleware' => 'authorize:licenses.create', 'uses' => 'LicensesController@postCreate' ]);
Route::get('{licenseId}/delete', [ 'as' => 'delete/license', 'middleware' => 'authorize:licenses.delete', 'uses' => 'LicensesController@getDelete' ]);
Route::get('{licenseId}/freecheckout', [
'as' => 'freecheckout/license',
'middleware' => 'authorize:licenses.checkout',
'uses' => 'LicensesController@getFreeLicense'
]);
Route::get(
'{licenseId}/checkout',
[ 'as' => 'checkout/license', 'uses' => 'LicensesController@getCheckout' ]
[ 'as' => 'checkout/license', 'middleware' => 'authorize:licenses.checkout','uses' => 'LicensesController@getCheckout' ]
);
Route::post('{licenseId}/checkout', 'LicensesController@postCheckout');
Route::get(
'{licenseId}/checkin/{backto?}',
[ 'as' => 'checkin/license', 'uses' => 'LicensesController@getCheckin' ]
Route::post(
'{licenseId}/checkout',
[ 'as' => 'checkout/license', 'middleware' => 'authorize:licenses.checkout','uses' => 'LicensesController@postCheckout' ]
);
Route::post('{licenseId}/checkin/{backto?}', 'LicensesController@postCheckin');
Route::get('{licenseId}/view', [ 'as' => 'view/license', 'uses' => 'LicensesController@getView' ]);
Route::get('{licenseId}/checkin/{backto?}', [
'as' => 'checkin/license',
'middleware' => 'authorize:licenses.checkin',
'uses' => 'LicensesController@getCheckin'
]);
Route::post('{licenseId}/checkin/{backto?}', [
'as' => 'checkin/license',
'middleware' => 'authorize:licenses.checkin',
'uses' => 'LicensesController@postCheckin'
]);
Route::get('{licenseId}/view', [
'as' => 'view/license',
'middleware' => 'authorize:licenses.view',
'uses' => 'LicensesController@getView'
]);
Route::post(
'{licenseId}/upload',
[ 'as' => 'upload/license', 'uses' => 'LicensesController@postUpload' ]
[ 'as' => 'upload/license', 'middleware' => 'authorize:licenses.edit','uses' => 'LicensesController@postUpload' ]
);
Route::get(
'{licenseId}/deletefile/{fileId}',
[ 'as' => 'delete/licensefile', 'uses' => 'LicensesController@getDeleteFile' ]
[ 'as' => 'delete/licensefile', 'middleware' => 'authorize:licenses.edit', 'uses' => 'LicensesController@getDeleteFile' ]
);
Route::get(
'{licenseId}/showfile/{fileId}',
[ 'as' => 'show/licensefile', 'uses' => 'LicensesController@displayFile' ]
[ 'as' => 'show/licensefile', 'middleware' => 'authorize:licenses.view','uses' => 'LicensesController@displayFile' ]
);
Route::get('/', [ 'as' => 'licenses', 'uses' => 'LicensesController@getIndex' ]);
Route::get('/', [ 'as' => 'licenses', 'middleware' => 'authorize:licenses.view','uses' => 'LicensesController@getIndex' ]);
});
# Asset Maintenances
@@ -377,84 +505,103 @@ Route::group([ 'prefix' => 'admin','middleware' => ['web','auth']], function ()
# Accessories
Route::group([ 'prefix' => 'accessories', 'middleware'=>'authorize:accessories.view' ], function () {
Route::get('create', [ 'as' => 'create/accessory', 'uses' => 'AccessoriesController@getCreate' ]);
Route::get('create', [ 'as' => 'create/accessory', 'middleware' => 'authorize:accessories.create','uses' => 'AccessoriesController@getCreate' ]);
Route::post('create', 'AccessoriesController@postCreate');
Route::get(
'{accessoryID}/edit',
[ 'as' => 'update/accessory', 'uses' => 'AccessoriesController@getEdit' ]
[ 'as' => 'update/accessory', 'middleware' => 'authorize:accessories.edit','uses' => 'AccessoriesController@getEdit' ]
);
Route::post('{accessoryID}/edit', 'AccessoriesController@postEdit');
Route::get(
'{accessoryID}/delete',
[ 'as' => 'delete/accessory', 'uses' => 'AccessoriesController@getDelete' ]
[ 'as' => 'delete/accessory', 'middleware' => 'authorize:accessories.delete','uses' => 'AccessoriesController@getDelete' ]
);
Route::get('{accessoryID}/view', [ 'as' => 'view/accessory', 'uses' => 'AccessoriesController@getView' ]);
Route::get('{accessoryID}/view', [ 'as' => 'view/accessory', 'middleware' => 'authorize:accessories.view','uses' => 'AccessoriesController@getView' ]);
Route::get(
'{accessoryID}/checkout',
[ 'as' => 'checkout/accessory', 'uses' => 'AccessoriesController@getCheckout' ]
[ 'as' => 'checkout/accessory', 'middleware' => 'authorize:accessories.checkout','uses' => 'AccessoriesController@getCheckout' ]
);
Route::post('{accessoryID}/checkout', 'AccessoriesController@postCheckout');
Route::post(
'{accessoryID}/checkout',
[ 'as' => 'checkout/accessory', 'middleware' => 'authorize:accessories.checkout','uses' => 'AccessoriesController@postCheckout' ]
);
Route::get(
'{accessoryID}/checkin/{backto?}',
[ 'as' => 'checkin/accessory', 'uses' => 'AccessoriesController@getCheckin' ]
[ 'as' => 'checkin/accessory', 'middleware' => 'authorize:accessories.checkin','uses' => 'AccessoriesController@getCheckin' ]
);
Route::post(
'{accessoryID}/checkin/{backto?}',
[ 'as' => 'checkin/accessory', 'middleware' => 'authorize:accessories.checkin','uses' => 'AccessoriesController@postCheckin' ]
);
Route::post('{accessoryID}/checkin/{backto?}', 'AccessoriesController@postCheckin');
Route::get('/', [ 'as' => 'accessories', 'uses' => 'AccessoriesController@getIndex' ]);
Route::get('/', [ 'as' => 'accessories', 'middleware'=>'authorize:accessories.view', 'uses' => 'AccessoriesController@getIndex' ]);
});
# Consumables
Route::group([ 'prefix' => 'consumables', 'middleware'=>'authorize:consumables.view' ], function () {
Route::get('create', [ 'as' => 'create/consumable', 'uses' => 'ConsumablesController@getCreate' ]);
Route::post('create', 'ConsumablesController@postCreate');
Route::get('create', [ 'as' => 'create/consumable','middleware'=>'authorize:consumables.create', 'uses' => 'ConsumablesController@getCreate' ]);
Route::post('create', [ 'as' => 'create/consumable','middleware'=>'authorize:consumables.create', 'uses' => 'ConsumablesController@postCreate' ]);
Route::get(
'{consumableID}/edit',
[ 'as' => 'update/consumable', 'uses' => 'ConsumablesController@getEdit' ]
[ 'as' => 'update/consumable', 'middleware'=>'authorize:consumables.edit', 'uses' => 'ConsumablesController@getEdit' ]
);
Route::post(
'{consumableID}/edit',
[ 'as' => 'update/consumable', 'middleware'=>'authorize:consumables.edit', 'uses' => 'ConsumablesController@postEdit' ]
);
Route::post('{consumableID}/edit', 'ConsumablesController@postEdit');
Route::get(
'{consumableID}/delete',
[ 'as' => 'delete/consumable', 'uses' => 'ConsumablesController@getDelete' ]
[ 'as' => 'delete/consumable', 'middleware'=>'authorize:consumables.delete','uses' => 'ConsumablesController@getDelete' ]
);
Route::get(
'{consumableID}/view',
[ 'as' => 'view/consumable', 'uses' => 'ConsumablesController@getView' ]
[ 'as' => 'view/consumable', 'middleware'=>'authorize:consumables.view','uses' => 'ConsumablesController@getView' ]
);
Route::get(
'{consumableID}/checkout',
[ 'as' => 'checkout/consumable', 'uses' => 'ConsumablesController@getCheckout' ]
[ 'as' => 'checkout/consumable', 'middleware'=>'authorize:consumables.checkout','uses' => 'ConsumablesController@getCheckout' ]
);
Route::post('{consumableID}/checkout', 'ConsumablesController@postCheckout');
Route::get('/', [ 'as' => 'consumables', 'uses' => 'ConsumablesController@getIndex' ]);
Route::post(
'{consumableID}/checkout',
[ 'as' => 'checkout/consumable', 'middleware'=>'authorize:consumables.checkout','uses' => 'ConsumablesController@postCheckout' ]
);
Route::get('/', [ 'as' => 'consumables', 'middleware'=>'authorize:consumables.view','uses' => 'ConsumablesController@getIndex' ]);
});
# Components
Route::group([ 'prefix' => 'components', 'middleware'=>'authorize:components.view' ], function () {
Route::get('create', [ 'as' => 'create/component', 'uses' => 'ComponentsController@getCreate' ]);
Route::post('create', 'ComponentsController@postCreate');
Route::get('create', [ 'as' => 'create/component', 'middleware'=>'authorize:components.create','uses' => 'ComponentsController@getCreate' ]);
Route::post('create', [ 'as' => 'create/component', 'middleware'=>'authorize:components.create','uses' => 'ComponentsController@postCreate' ]);
Route::get(
'{componentID}/edit',
[ 'as' => 'update/component', 'uses' => 'ComponentsController@getEdit' ]
[ 'as' => 'update/component', 'middleware'=>'authorize:components.edit','uses' => 'ComponentsController@getEdit' ]
);
Route::post(
'{componentID}/edit',
[ 'as' => 'update/component', 'middleware'=>'authorize:components.edit','uses' => 'ComponentsController@postEdit' ]
);
Route::post('{componentID}/edit', 'ComponentsController@postEdit');
Route::get(
'{componentID}/delete',
[ 'as' => 'delete/component', 'uses' => 'ComponentsController@getDelete' ]
[ 'as' => 'delete/component', 'middleware'=>'authorize:components.delete','uses' => 'ComponentsController@getDelete' ]
);
Route::get(
'{componentID}/view',
[ 'as' => 'view/component', 'uses' => 'ComponentsController@getView' ]
[ 'as' => 'view/component', 'middleware'=>'authorize:components.view','uses' => 'ComponentsController@getView' ]
);
Route::get(
'{componentID}/checkout',
[ 'as' => 'checkout/component', 'uses' => 'ComponentsController@getCheckout' ]
[ 'as' => 'checkout/component', 'middleware'=>'authorize:components.checkout','uses' => 'ComponentsController@getCheckout' ]
);
Route::post('{componentID}/checkout', 'ComponentsController@postCheckout');
Route::post('bulk', [ 'as' => 'component/bulk-form', 'uses' => 'ComponentsController@postBulk' ]);
Route::post('bulksave', [ 'as' => 'component/bulk-save', 'uses' => 'ComponentsController@postBulkSave' ]);
Route::get('/', [ 'as' => 'components', 'uses' => 'ComponentsController@getIndex' ]);
Route::post(
'{componentID}/checkout',
[ 'as' => 'checkout/component', 'middleware'=>'authorize:components.checkout','uses' => 'ComponentsController@postCheckout' ]
);
Route::post('bulk', [ 'as' => 'component/bulk-form', 'middleware'=>'authorize:components.checkout','uses' => 'ComponentsController@postBulk' ]);
Route::post('bulksave', [ 'as' => 'component/bulk-save', 'middleware'=>'authorize:components.edit','uses' => 'ComponentsController@postBulkSave' ]);
Route::get('/', [ 'as' => 'components', 'middleware'=>'authorize:components.view','uses' => 'ComponentsController@getIndex' ]);
});
# Admin Settings Routes (for categories, maufactureres, etc)
@@ -608,7 +755,7 @@ Route::group([ 'prefix' => 'admin','middleware' => ['web','auth']], function ()
[ 'as' => 'update/location', 'uses' => 'LocationsController@getEdit' ]
);
Route::post('{locationId}/edit', 'LocationsController@postEdit');
Route::get('{locationId}/view', 'LocationsController@getView');
Route::get('{locationId}/view', [ 'as' => 'view/location', 'uses' => 'LocationsController@getView' ]);
Route::get(
'{locationId}/delete',
[ 'as' => 'delete/location', 'uses' => 'LocationsController@getDelete' ]
@@ -638,27 +785,29 @@ Route::group([ 'prefix' => 'admin','middleware' => ['web','auth']], function ()
Route::get('custom_fields/create-field', ['uses' =>'CustomFieldsController@createField','as' => 'admin.custom_fields.create-field']);
Route::post('custom_fields/create-field', ['uses' => 'CustomFieldsController@storeField','as' => 'admin.custom_fields.store-field']);
Route::post('custom_fields/{id}/associate', ['uses' => 'CustomFieldsController@associate','as' => 'admin.custom_fields.associate']);
Route::get('custom_fields/{field_id}/{fieldset_id}/disassociate', ['uses' => 'CustomFieldsController@deleteFieldFromFieldset','as' => 'admin.custom_fields.disassociate']);
Route::match(['DELETE'], 'custom_fields/delete-field/{id}', ['uses' => 'CustomFieldsController@deleteField','as' => 'admin.custom_fields.delete-field']);
Route::resource('custom_fields', 'CustomFieldsController');
# User Management
Route::group([ 'prefix' => 'users', 'middleware' => ['web','auth','authorize:users.view']], function () {
Route::get('ldap', ['as' => 'ldap/user', 'uses' => 'UsersController@getLDAP' ]);
Route::get('ldap', ['as' => 'ldap/user', 'uses' => 'UsersController@getLDAP', 'middleware' => ['authorize:users.edit'] ]);
Route::post('ldap', 'UsersController@postLDAP');
Route::get('create', [ 'as' => 'create/user', 'uses' => 'UsersController@getCreate' ]);
Route::post('create', 'UsersController@postCreate');
Route::get('import', [ 'as' => 'import/user', 'uses' => 'UsersController@getImport' ]);
Route::post('import', 'UsersController@postImport');
Route::get('{userId}/edit', [ 'as' => 'update/user', 'uses' => 'UsersController@getEdit' ]);
Route::post('{userId}/edit', 'UsersController@postEdit');
Route::get('{userId}/clone', [ 'as' => 'clone/user', 'uses' => 'UsersController@getClone' ]);
Route::post('{userId}/clone', 'UsersController@postCreate');
Route::get('{userId}/delete', [ 'as' => 'delete/user', 'uses' => 'UsersController@getDelete' ]);
Route::get('{userId}/restore', [ 'as' => 'restore/user', 'uses' => 'UsersController@getRestore' ]);
Route::get('{userId}/view', [ 'as' => 'view/user', 'uses' => 'UsersController@getView' ]);
Route::get('{userId}/unsuspend', [ 'as' => 'unsuspend/user', 'uses' => 'UsersController@getUnsuspend' ]);
Route::get('create', [ 'as' => 'create/user', 'uses' => 'UsersController@getCreate', 'middleware' => ['authorize:users.edit'] ]);
Route::post('create', [ 'uses' => 'UsersController@postCreate', 'middleware' => ['authorize:users.edit'] ]);
Route::get('import', [ 'as' => 'import/user', 'uses' => 'UsersController@getImport', 'middleware' => ['authorize:users.edit'] ]);
Route::post('import', [ 'uses' => 'UsersController@postImport', 'middleware' => ['authorize:users.edit'] ]);
Route::get('export', [ 'uses' => 'UsersController@getExportUserCsv', 'middleware' => ['authorize:users.view'] ]);
Route::get('{userId}/edit', [ 'as' => 'update/user', 'uses' => 'UsersController@getEdit', 'middleware' => ['authorize:users.edit'] ]);
Route::post('{userId}/edit', [ 'uses' => 'UsersController@postEdit', 'middleware' => ['authorize:users.edit'] ]);
Route::get('{userId}/clone', [ 'as' => 'clone/user', 'uses' => 'UsersController@getClone', 'middleware' => ['authorize:users.edit'] ]);
Route::post('{userId}/clone', [ 'uses' => 'UsersController@postCreate', 'middleware' => ['authorize:users.edit'] ]);
Route::get('{userId}/delete', [ 'as' => 'delete/user', 'uses' => 'UsersController@getDelete', 'middleware' => ['authorize:users.edit'] ]);
Route::get('{userId}/restore', [ 'as' => 'restore/user', 'uses' => 'UsersController@getRestore', 'middleware' => ['authorize:users.edit'] ]);
Route::get('{userId}/view', [ 'as' => 'view/user', 'uses' => 'UsersController@getView' , 'middleware' => ['authorize:users.view'] ]);
Route::get('{userId}/unsuspend', [ 'as' => 'unsuspend/user', 'uses' => 'UsersController@getUnsuspend', 'middleware' => ['authorize:users.edit'] ]);
Route::get(
'{userId}/deletefile/{fileId}',
[ 'as' => 'delete/userfile', 'uses' => 'UsersController@getDeleteFile' ]
@@ -672,14 +821,16 @@ Route::group([ 'prefix' => 'admin','middleware' => ['web','auth']], function ()
'bulkedit',
[
'as' => 'users/bulkedit',
'uses' => 'UsersController@postBulkEdit'
'uses' => 'UsersController@postBulkEdit',
'middleware' => ['authorize:users.edit'],
]
);
Route::post(
'bulksave',
[
'as' => 'users/bulksave',
'uses' => 'UsersController@postBulkSave'
'uses' => 'UsersController@postBulkSave',
'middleware' => ['authorize:users.edit'],
]
);
@@ -742,6 +893,11 @@ Route::group([ 'prefix' => 'account', 'middleware' => ['web', 'auth']], function
[ 'as' => 'account/request-asset', 'uses' => 'ViewAssetsController@getRequestAsset' ]
);
Route::post(
'request/{itemType}/{itemId}',
[ 'as' => 'account/request-item', 'uses' => 'ViewAssetsController@getRequestItem']
);
# Account Dashboard
Route::get('/', [ 'as' => 'account', 'uses' => 'ViewAssetsController@getIndex' ]);
@@ -794,6 +950,12 @@ Route::group(['middleware' => ['web','auth','authorize:reports.view']], function
'reports/activity',
[ 'as' => 'reports/activity', 'uses' => 'ReportsController@getActivityReport' ]
);
Route::get(
'reports/activity/json',
[ 'as' => 'api.activity.list', 'uses' => 'ReportsController@getActivityReportDataTable' ]
);
Route::get(
'reports/unaccepted_assets',
[ 'as' => 'reports/unaccepted_assets', 'uses' => 'ReportsController@getAssetAcceptanceReport' ]
@@ -860,6 +1022,29 @@ Route::group([ 'prefix' => 'setup', 'middleware' => 'web'], function () {
});
Route::get(
'two-factor-enroll',
[
'as' => 'two-factor-enroll',
'middleware' => ['web'],
'uses' => 'Auth\AuthController@getTwoFactorEnroll' ]
);
Route::get(
'two-factor',
[
'as' => 'two-factor',
'middleware' => ['web'],
'uses' => 'Auth\AuthController@getTwoFactorAuth' ]
);
Route::post(
'two-factor',
[
'as' => 'two-factor',
'middleware' => ['web'],
'uses' => 'Auth\AuthController@postTwoFactorAuth' ]
);
Route::get(
'/',
@@ -869,8 +1054,24 @@ Route::get(
'uses' => 'DashboardController@getIndex' ]
);
Route::group(['middleware' => 'web'], function () {
Route::auth();
Route::get(
'login',
[
'as' => 'login',
'middleware' => ['web'],
'uses' => 'Auth\AuthController@showLoginForm' ]
);
Route::get(
'logout',
[
'as' => 'logout',
'uses' => 'Auth\AuthController@logout' ]
);
});
Route::get('home', function () {

View File

@@ -1,6 +1,7 @@
<?php
namespace App\Models;
use App\Models\Loggable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
@@ -12,8 +13,9 @@ use Watson\Validating\ValidatingTrait;
*/
class Accessory extends Model
{
use SoftDeletes;
use CompanyableTrait;
use Loggable;
use SoftDeletes;
protected $dates = ['deleted_at'];
protected $table = 'accessories';
@@ -22,11 +24,12 @@ class Accessory extends Model
* Accessory validation rules
*/
public $rules = array(
'name' => 'required|min:3|max:255',
'qty' => 'required|integer|min:1',
'category_id' => 'required|integer',
'company_id' => 'integer',
'min_amt' => 'integer|min:1',
'name' => 'required|min:3|max:255',
'qty' => 'required|integer|min:1',
'category_id' => 'required|integer',
'company_id' => 'integer',
'min_amt' => 'integer|min:0',
'purchase_cost' => 'numeric',
);
@@ -67,7 +70,7 @@ class Accessory extends Model
*/
public function assetlog()
{
return $this->hasMany('\App\Models\Actionlog', 'accessory_id')->where('asset_type', '=', 'accessory')->orderBy('created_at', 'desc')->withTrashed();
return $this->hasMany('\App\Models\Actionlog', 'item_id')->where('item_type', Accessory::class)->orderBy('created_at', 'desc')->withTrashed();
}
@@ -81,6 +84,11 @@ class Accessory extends Model
return $this->belongsToMany('\App\Models\User', 'accessories_users', 'accessory_id', 'assigned_to')->count();
}
public function manufacturer()
{
return $this->belongsTo('\App\Models\Manufacturer', 'manufacturer_id');
}
public function checkin_email()
{
return $this->category->checkin_email;

View File

@@ -2,9 +2,9 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Auth;
use Response;
/**
* Model for the Actionlog (the table that keeps a historical log of
@@ -12,103 +12,92 @@ use Illuminate\Database\Eloquent\SoftDeletes;
*
* @version v1.0
*/
class Actionlog extends Model implements ICompanyableChild
class Actionlog extends Model
{
use SoftDeletes;
use CompanyableChildTrait;
protected $dates = [ 'deleted_at' ];
protected $table = 'asset_logs';
protected $table = 'action_logs';
public $timestamps = true;
protected $fillable = [ 'created_at', 'asset_type' ];
protected $fillable = [ 'created_at', 'item_type','user_id','item_id','action_type','note','target_id', 'target_type' ];
public function getCompanyableParents()
// Overridden from Builder to automatically add the company
public static function boot()
{
return [ 'accessorylog', 'assetlog', 'licenselog', 'consumablelog' ];
parent::boot();
static::creating( function (Actionlog $actionlog) {
// If the admin is a superadmin, let's see if the target instead has a company.
if (Auth::user() && Auth::user()->isSuperUser()) {
if ($actionlog->target) {
$actionlog->company_id = $actionlog->target->company_id;
} else if ($actionlog->item) {
$actionlog->company_id = $actionlog->item->company_id;
}
} else if (Auth::user() && Auth::user()->company) {
$actionlog->company_id = Auth::user()->company_id;
}
});
}
// Eloquent Relationships below
public function item()
{
return $this->morphTo('item')->withTrashed();
}
public function assetlog()
public function itemType()
{
return $this->belongsTo('\App\Models\Asset', 'asset_id')
->withTrashed();
if($this->item_type == AssetModel::class) {
return "model";
}
return camel_case(class_basename($this->item_type));
}
public function uploads()
{
return $this->belongsTo('\App\Models\Asset', 'asset_id')
return $this->morphTo('item')
->where('action_type', '=', 'uploaded')
->withTrashed();
}
public function licenselog()
{
return $this->belongsTo('\App\Models\License', 'asset_id')
->withTrashed();
}
public function componentlog()
{
return $this->belongsTo('\App\Models\Component', 'component_id')
->withTrashed();
}
public function accessorylog()
{
return $this->belongsTo('\App\Models\Accessory', 'accessory_id')
->withTrashed();
}
public function consumablelog()
{
return $this->belongsTo('\App\Models\Consumable', 'consumable_id')
->withTrashed();
}
public function adminlog()
{
return $this->belongsTo('\App\Models\User', 'user_id')
->withTrashed();
}
public function userlog()
{
return $this->target();
}
return $this->belongsTo('\App\Models\User', 'checkedout_to')
public function user()
{
return $this->belongsTo(User::class, 'user_id')
->withTrashed();
}
public function target()
{
return $this->morphTo('target');
}
public function childlogs()
{
return $this->hasMany('\App\Models\ActionLog', 'thread_id');
}
public function parentlog()
{
return $this->belongsTo('\App\Models\ActionLog', 'thread_id');
}
/**
* Check if the file exists, and if it does, force a download
**/
public function get_src($type = 'assets')
public function get_src($type = 'assets', $fieldname = 'filename')
{
$file = config('app.private_uploads') . '/' . $type . '/' . $this->filename;
$file = config('app.private_uploads') . '/' . $type . '/' . $this->{$fieldname};
return $file;
}
/**
* Get the parent category name
*/
@@ -134,44 +123,10 @@ class Actionlog extends Model implements ICompanyableChild
public function getListingOfActionLogsChronologicalOrder()
{
return DB::table('asset_logs')
->select('*')
return $this->all()
->where('action_type', '!=', 'uploaded')
->orderBy('asset_id', 'asc')
->orderBy('item_id', 'asc')
->orderBy('created_at', 'asc')
->get();
}
/**
* getLatestCheckoutActionForAssets
*
* @return mixed
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
*/
public function getLatestCheckoutActionForAssets()
{
return DB::table('asset_logs')
->select(DB::raw('asset_id, MAX(created_at) as last_created'))
->where('action_type', '=', 'checkout')
->groupBy('asset_id')
->get();
}
/**
* scopeCheckoutWithoutAcceptance
*
* @param $query
*
* @return mixed
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
*/
public function scopeCheckoutWithoutAcceptance($query)
{
return $query->where('action_type', '=', 'checkout')
->where('accepted_id', '=', null);
}
}

View File

@@ -1,19 +1,22 @@
<?php
namespace App\Models;
use App\Helpers\Helper;
use App\Http\Traits\UniqueUndeletedTrait;
use App\Models\Actionlog;
use App\Models\Company;
use App\Models\Location;
use App\Models\Loggable;
use App\Models\Requestable;
use App\Models\Setting;
use Auth;
use Config;
use DateTime;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Log;
use Parsedown;
use Watson\Validating\ValidatingTrait;
use DateTime;
use App\Models\Setting;
use App\Helpers\Helper;
use Auth;
/**
* Model for Assets.
@@ -22,7 +25,9 @@ use Auth;
*/
class Asset extends Depreciable
{
use Loggable;
use SoftDeletes;
use Requestable;
/**
* The database table used by the model.
@@ -40,6 +45,7 @@ class Asset extends Depreciable
*/
protected $injectUniqueIdentifier = true;
use ValidatingTrait;
use UniqueUndeletedTrait;
protected $rules = [
'name' => 'min:2|max:255',
@@ -51,8 +57,9 @@ class Asset extends Depreciable
'checkout_date' => 'date|max:10|min:10',
'checkin_date' => 'date|max:10|min:10',
'supplier_id' => 'integer',
'asset_tag' => 'required|min:1|max:255|unique:assets,asset_tag,NULL,deleted_at',
'asset_tag' => 'required|min:1|max:255|unique_undeleted',
'status' => 'integer',
'purchase_cost' => 'numeric',
];
@@ -70,20 +77,36 @@ class Asset extends Depreciable
}
public function availableForCheckout()
{
return (
empty($this->assigned_to) &&
$this->assetstatus->deployable == 1 &&
empty($this->deleted_at)
);
}
/**
* Checkout asset
*/
public function checkOutToUser($user, $admin, $checkout_at = null, $expected_checkin = null, $note = null, $name = null)
{
if (!$user) {
return false;
}
if ($expected_checkin) {
$this->expected_checkin = $expected_checkin ;
$this->expected_checkin = $expected_checkin;
}
$this->last_checkout = $checkout_at;
$this->assigneduser()->associate($user);
$this->name = $name;
if($name != null)
{
$this->name = $name;
}
$settings = Setting::getSettings();
@@ -91,9 +114,7 @@ class Asset extends Depreciable
$this->accepted="pending";
}
if (!$user) {
return false;
}
if ($this->save()) {
@@ -131,7 +152,8 @@ class Asset extends Depreciable
\Mail::send('emails.accept-asset', $data, function ($m) use ($user) {
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
$m->subject('Confirm asset delivery');
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.Confirm_asset_delivery'));
});
}
@@ -175,8 +197,8 @@ class Asset extends Depreciable
public function getDetailedNameAttribute()
{
if ($this->assigned_user) {
$user_name = $user->fullName();
if ($this->assignedUser) {
$user_name = $this->assignedUser->fullName();
} else {
$user_name = "Unassigned";
}
@@ -192,10 +214,12 @@ class Asset extends Depreciable
{
$logaction = new Actionlog();
$logaction->asset_id = $this->id;
$logaction->checkedout_to = $this->assigned_to;
$logaction->asset_type = 'hardware';
$logaction->item_type = Asset::class;
$logaction->item_id = $this->id;
$logaction->target_type = User::class;
$logaction->target_id = $this->assigned_to;
$logaction->note = $note;
$logaction->user_id = $admin->id;
if ($checkout_at!='') {
$logaction->created_at = \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', date('Y-m-d H:i:s', strtotime($checkout_at)));
} else {
@@ -208,15 +232,10 @@ class Asset extends Depreciable
}
} else {
// Update the asset data to null, since it's being checked in
$logaction->checkedout_to = $asset->assigned_to;
$logaction->checkedout_to = '';
$logaction->asset_id = $asset->id;
$logaction->target_id = '';
$logaction->location_id = null;
$logaction->asset_type = 'hardware';
$logaction->note = $note;
$logaction->user_id = $admin->id;
}
$logaction->adminlog()->associate($admin);
$logaction->user()->associate($admin);
$log = $logaction->logaction($action);
return $logaction;
@@ -253,8 +272,8 @@ class Asset extends Depreciable
public function uploads()
{
return $this->hasMany('\App\Models\Actionlog', 'asset_id')
->where('asset_type', '=', 'hardware')
return $this->hasMany('\App\Models\Actionlog', 'item_id')
->where('item_type', '=', Asset::class)
->where('action_type', '=', 'uploaded')
->whereNotNull('filename')
->orderBy('created_at', 'desc');
@@ -291,8 +310,8 @@ class Asset extends Depreciable
*/
public function assetlog()
{
return $this->hasMany('\App\Models\Actionlog', 'asset_id')
->where('asset_type', '=', 'hardware')
return $this->hasMany('\App\Models\Actionlog', 'item_id')
->where('item_type', '=', Asset::class)
->orderBy('created_at', 'desc')
->withTrashed();
}
@@ -328,7 +347,7 @@ class Asset extends Depreciable
public static function assetcount()
{
return Asset::where('physical', '=', '1')
return Company::scopeCompanyables(Asset::where('physical', '=', '1'))
->whereNull('deleted_at', 'and')
->count();
}
@@ -372,7 +391,10 @@ class Asset extends Depreciable
{
if ($this->name == '') {
return $this->model->name;
if ($this->model) {
return $this->model->name.' ('.$this->asset_tag.')';
}
return $this->asset_tag;
} else {
return $this->name;
}
@@ -462,13 +484,24 @@ class Asset extends Depreciable
$asset_tag = \DB::table('assets')
->where('physical', '=', '1')
->max('id');
if ($settings->zerofill_count > 0) {
return $settings->auto_increment_prefix.Asset::zerofill(($asset_tag + 1),$settings->zerofill_count);
}
return $settings->auto_increment_prefix.($asset_tag + 1);
} else {
return false;
}
}
public function checkin_email()
public static function zerofill ($num, $zerofill = 3)
{
return str_pad($num, $zerofill, '0', STR_PAD_LEFT);
}
public function checkin_email()
{
return $this->model->category->checkin_email;
}
@@ -545,12 +578,12 @@ class Asset extends Depreciable
public function scopeAssetsByLocation($query, $location)
{
return $query->where(function ($query) use ($location) {
$query->whereHas('assigneduser', function ($query) use ($location) {
$query->where('users.location_id', '=', $location->id);
})->orWhere(function ($query) use ($location) {
$query->where('assets.rtd_location_id', '=', $location->id);
$query->whereNull('assets.assigned_to');
});
@@ -597,6 +630,23 @@ class Asset extends Depreciable
});
}
/**
* Query builder scope for non-Archived assets
*
* @param Illuminate\Database\Query\Builder $query Query builder instance
*
* @return Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeNotArchived($query)
{
return $query->whereHas('assetstatus', function ($query) {
$query->where('archived', '=', 0);
});
}
/**
* Query builder scope for Archived assets
*
@@ -641,7 +691,7 @@ class Asset extends Depreciable
public function scopeRequestableAssets($query)
{
return $query->where('requestable', '=', 1)
return Company::scopeCompanyables($query->where('requestable', '=', 1))
->whereHas('assetstatus', function ($query) {
$query->where('deployable', '=', 1)

View File

@@ -1,6 +1,7 @@
<?php
namespace App\Models;
use App\Models\Requestable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
@@ -14,6 +15,7 @@ use Watson\Validating\ValidatingTrait;
class AssetModel extends Model
{
use SoftDeletes;
use Requestable;
protected $dates = ['deleted_at'];
protected $table = 'models';
@@ -131,6 +133,22 @@ class AssetModel extends Model
return $query->whereIn('category_id', $categoryIdListing);
}
/**
* scopeRequestable
* Get all models that are requestable by a user.
*
* @param $query
*
* @return $query
* @author Daniel Meltzer <parallelgrapefruit@gmail.com
* @version v3.5
*/
public function scopeRequestableModels($query)
{
return $query->where('requestable', '1');
}
/**
* Query builder scope to search on text
*

View File

@@ -4,6 +4,7 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
use App\Http\Traits\UniqueUndeletedTrait;
/**
* Model for Categories. Categories are a higher-level group
@@ -25,7 +26,7 @@ class Category extends Model
*/
public $rules = array(
'user_id' => 'numeric',
'name' => 'required|min:1|max:255|unique:categories,name,NULL,deleted_at',
'name' => 'required|min:1|max:255|unique_undeleted',
'category_type' => 'required',
);
@@ -38,6 +39,7 @@ class Category extends Model
*/
protected $injectUniqueIdentifier = true;
use ValidatingTrait;
use UniqueUndeletedTrait;
/**

View File

@@ -0,0 +1,59 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class CheckoutRequest extends Model
{
//
protected $fillable = ['user_id'];
protected $table = 'checkout_requests';
public function user()
{
return $this->belongsTo(User::class);
}
public function requestingUser()
{
return $this->user()->first();
}
public function requestedItem()
{
return $this->morphTo('requestable');
}
public function itemRequested() // Workaround for laravel polymorphic issue that's not being solved :(
{
return $this->requestedItem()->first();
}
public function itemType()
{
return snake_case(class_basename($this->requestable_type));
}
public function location()
{
if ($this->itemType() == "asset") {
$asset = $this->itemRequested();
if ($asset->assigneduser && $asset->assetloc) {
return $asset->assetloc;
} elseif ($asset->defaultLoc) {
return $asset->defaultLoc;
}
}
return $this->itemRequested()->location;
}
public function name()
{
if ($this->itemType() == "asset") {
return $this->itemRequested()->showAssetName();
}
return $this->itemRequested()->name;
}
}

View File

@@ -16,7 +16,11 @@ final class Company extends Model
protected $table = 'companies';
// Declare the rules for the model validation
protected $rules = ['name' => 'required|min:1|max:255|unique:companies,name'];
protected $rules = [
'name' => 'required|min:1|max:255|unique:companies,name'
];
/**
* Whether the model should inject it's identifier to the unique
* validation rules before attempting validation. If this property
@@ -55,11 +59,7 @@ final class Company extends Model
$company_id = null;
}
if ($company_id == null) {
return $query;
} else {
return $query->where($column, '=', $company_id);
}
return $query->where($column, '=', $company_id);
}
public static function getSelectList()
@@ -86,11 +86,17 @@ final class Company extends Model
} else {
$current_user = Auth::user();
if ($current_user->company_id != null) {
return $current_user->company_id;
} else {
// Super users should be able to set a company to whatever they need
if ($current_user->isSuperUser()) {
return static::getIdFromInput($unescaped_input);
} else {
if ($current_user->company_id != null) {
return $current_user->company_id;
} else {
return static::getIdFromInput($unescaped_input);
}
}
}
}
@@ -110,7 +116,7 @@ final class Company extends Model
public static function isCurrentUserAuthorized()
{
return ((!static::isFullMultipleCompanySupportEnabled()) || (Auth::user()->company_id == null) || (Auth::user()->isSuperUser()));
return ((!static::isFullMultipleCompanySupportEnabled()) || (Auth::user()->isSuperUser()));
}
public static function canManageUsersCompanies()
@@ -130,7 +136,8 @@ final class Company extends Model
public static function scopeCompanyables($query, $column = 'company_id')
{
if (!static::isFullMultipleCompanySupportEnabled() || (Auth::check() && Auth::user()->isSuperUser())) {
// If not logged in and hitting this, assume we are on the command line and don't scope?'
if (!static::isFullMultipleCompanySupportEnabled() || (Auth::check() && Auth::user()->isSuperUser()) || (!Auth::check())) {
return $query;
} else {
return static::scopeCompanyablesDirectly($query, $column);
@@ -141,7 +148,7 @@ final class Company extends Model
{
if (count($companyable_names) == 0) {
throw new Exception('No Companyable Children to scope');
} elseif (!static::isFullMultipleCompanySupportEnabled()) {
} elseif (!static::isFullMultipleCompanySupportEnabled() || (Auth::check() && Auth::user()->isSuperUser())) {
return $query;
} else {
$f = function ($q) {
@@ -170,4 +177,27 @@ final class Company extends Model
return e($company->name);
}
}
public function users() {
return $this->hasMany(User::class);
}
public function assets() {
return $this->hasMany(Asset::class);
}
public function licenses() {
return $this->hasMany(License::class);
}
public function accessories() {
return $this->hasMany(Accessory::class);
}
public function consumables() {
return $this->hasMany(Consumable::class);
}
public function components() {
return $this->hasMany(Component::class);
}
}

View File

@@ -1,12 +1,13 @@
<?php
namespace App\Models;
use App\Models\User;
use App\Models\ConsumableAssignment;
use App\Models\Company;
use App\Models\Location;
use App\Models\Category;
use App\Models\ActionLog;
use App\Models\Category;
use App\Models\Company;
use App\Models\ConsumableAssignment;
use App\Models\Location;
use App\Models\Loggable;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
@@ -18,8 +19,9 @@ use Watson\Validating\ValidatingTrait;
*/
class Component extends Model
{
use SoftDeletes;
use CompanyableTrait;
use Loggable;
use SoftDeletes;
protected $dates = ['deleted_at'];
protected $table = 'components';
@@ -34,6 +36,7 @@ class Component extends Model
'category_id' => 'required|integer',
'company_id' => 'integer',
'purchase_date' => 'date',
'purchase_cost' => 'numeric',
);
/**
@@ -84,7 +87,7 @@ class Component extends Model
*/
public function assetlog()
{
return $this->hasMany('\App\Models\Actionlog', 'component_id')->where('asset_type', '=', 'component')->orderBy('created_at', 'desc')->withTrashed();
return $this->hasMany('\App\Models\Actionlog', 'item_id')->where('item_type', Component::class)->orderBy('created_at', 'desc')->withTrashed();
}
@@ -138,6 +141,7 @@ class Component extends Model
});
})->orWhere('components.name', 'LIKE', '%'.$search.'%')
->orWhere('components.order_number', 'LIKE', '%'.$search.'%')
->orWhere('components.serial_number', 'LIKE', '%'.$search.'%')
->orWhere('components.purchase_cost', 'LIKE', '%'.$search.'%')
->orWhere('components.purchase_date', 'LIKE', '%'.$search.'%');
}

View File

@@ -1,20 +1,22 @@
<?php
namespace App\Models;
use App\Models\User;
use App\Models\ConsumableAssignment;
use App\Models\Company;
use App\Models\Location;
use App\Models\Category;
use App\Models\ActionLog;
use App\Models\Category;
use App\Models\Company;
use App\Models\ConsumableAssignment;
use App\Models\Location;
use App\Models\Loggable;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
class Consumable extends Model
{
use SoftDeletes;
use CompanyableTrait;
use Loggable;
use SoftDeletes;
protected $dates = ['deleted_at'];
protected $table = 'consumables';
@@ -29,6 +31,7 @@ class Consumable extends Model
'category_id' => 'required|integer',
'company_id' => 'integer',
'min_amt' => 'integer|min:1',
'purchase_cost' => 'numeric',
);
/**
@@ -84,7 +87,7 @@ class Consumable extends Model
*/
public function assetlog()
{
return $this->hasMany('\App\Models\Actionlog', 'consumable_id')->where('asset_type', '=', 'consumable')->orderBy('created_at', 'desc')->withTrashed();
return $this->hasMany('\App\Models\Actionlog', 'item_id')->where('item_type', Consumable::class)->orderBy('created_at', 'desc')->withTrashed();
}

View File

@@ -11,14 +11,14 @@ class CustomField extends Model
*/
public static $PredefinedFormats=[
"ANY" => "",
"ALPHA" => "alpha",
"EMAIL" => "email",
"DATE" => "date",
"URL" => "url",
"NUMERIC" => "numeric",
"MAC" => "regex:/^[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}$/",
"IP" => "ip"
"ANY" => "",
"ALPHA" => "alpha",
"EMAIL" => "email",
"DATE" => "date",
"URL" => "url",
"NUMERIC" => "numeric",
"MAC" => "regex:/^[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}$/",
"IP" => "ip",
];
public $rules=[
@@ -109,4 +109,43 @@ class CustomField extends Model
$this->attributes['format']=$value;
}
}
/**
* Format a value string as an array for select boxes and checkboxes.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.4]
* @return Array
*/
public function formatFieldValuesAsArray() {
$arr = preg_split("/\\r\\n|\\r|\\n/", $this->field_values);
$result[''] = 'Select '.strtolower($this->format);
for ($x = 0; $x < count($arr); $x++) {
$arr_parts = explode('|', $arr[$x]);
if ($arr_parts[0]!='') {
if (key_exists('1',$arr_parts)) {
$result[$arr_parts[0]] = $arr_parts[1];
} else {
$result[$arr_parts[0]] = $arr_parts[0];
}
}
}
return $result;
}
public function isFieldDecryptable($string) {
if (($this->field_encrypted=='1') && ($string!='')) {
return true;
}
return false;
}
}

View File

@@ -2,6 +2,7 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Gate;
class CustomFieldset extends Model
{
@@ -30,16 +31,21 @@ class CustomFieldset extends Model
{
$rules=[];
foreach ($this->fields as $field) {
$rule=[];
if ($field->pivot->required) {
$rule[]="required";
$rule = [];
if (($field->field_encrypted!='1') ||
(($field->field_encrypted =='1') && (Gate::allows('admin')) ))
{
if ($field->pivot->required) {
$rule[]="required";
}
}
array_push($rule, $field->attributes['format']);
$rules[$field->db_column_name()]=$rule;
}
return $rules;
}
//requiredness goes *here*
//sequence goes here?
}

View File

@@ -26,25 +26,34 @@ class Ldap extends Model
$ldap_host = Setting::getSettings()->ldap_server;
$ldap_version = Setting::getSettings()->ldap_version;
$ldap_server_cert_ignore = Setting::getSettings()->ldap_server_cert_ignore;
$ldap_use_tls = Setting::getSettings()->ldap_tls;
// If we are ignoring the SSL cert we need to setup the environment variable
// before we create the connection
if ($ldap_server_cert_ignore) {
if ($ldap_server_cert_ignore=='1') {
putenv('LDAPTLS_REQCERT=never');
}
// Connecting to LDAP
$connection = @ldap_connect($ldap_host) or die("Could not connect to {$ldap_host}");
// If the user specifies where CA Certs are, make sure to use them
if(env("LDAPTLS_CACERT")) {
putenv("LDAPTLS_CACERT=".env("LDAPTLS_CACERT"));
}
$connection = @ldap_connect($ldap_host);
if (!$connection) {
throw new Exception('Could not connect to LDAP server at '.$ldap_host.': '.ldap_error($connection));
throw new Exception('Could not connect to LDAP server at '.$ldap_host.'. Please check your LDAP server name and port number in your settings.');
}
// Needed for AD
ldap_set_option($connection, LDAP_OPT_REFERRALS, 0);
ldap_set_option($connection, LDAP_OPT_PROTOCOL_VERSION, $ldap_version);
if ($ldap_use_tls=='1') {
ldap_start_tls($connection);
}
return $connection;
}
@@ -72,11 +81,18 @@ class Ldap extends Model
if ($settings->is_ad =='1')
{
// In case they haven't added an AD domain
if ($settings->ad_domain == '') {
$userDn = $username.'@'.$settings->email_domain;
// Check if they are using the userprincipalname for the username field.
// If they are, we can skip building the UPN to authenticate against AD
if ($ldap_username_field=='userprincipalname')
{
$userDn = $username;
} else {
$userDn = $username.'@'.$settings->ad_domain;
// In case they haven't added an AD domain
if ($settings->ad_domain == '') {
$userDn = $username.'@'.$settings->email_domain;
} else {
$userDn = $username.'@'.$settings->ad_domain;
}
}
} else {
@@ -182,6 +198,7 @@ class Ldap extends Model
{
$item = Ldap::parseAndMapLdapAttributes($ldapatttibutes);
// Create user from LDAP data
if (!empty($item["username"])) {
$user = new User;
@@ -189,7 +206,14 @@ class Ldap extends Model
$user->last_name = $item["lastname"];
$user->username = $item["username"];
$user->email = $item["email"];
$user->password = bcrypt(Input::get("password"));
if (Setting::getSettings()->ldap_pw_sync=='1') {
$user->password = bcrypt(Input::get("password"));
} else {
$pass = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 25);
$user->password = bcrypt($pass);
}
$user->activated = 1;
$user->ldap_import = 1;
$user->notes = 'Imported on first login from LDAP';
@@ -198,7 +222,7 @@ class Ldap extends Model
return true;
} else {
LOG::debug('Could not create user.'.$user->getErrors());
exit;
throw new Exception("Could not create user: ".$user->getErrors());
}
}
@@ -230,8 +254,12 @@ class Ldap extends Model
// Perform the search
do {
// Paginate (non-critical, if not supported by server)
ldap_control_paged_result($ldapconn, $page_size, false, $cookie);
if (!$ldap_paging = @ldap_control_paged_result($ldapconn, $page_size, false, $cookie)) {
throw new Exception('Problem with your LDAP connection. Try checking the Use TLS setting in Admin > Settings. ');
}
$search_results = ldap_search($ldapconn, $base_dn, '('.$filter.')');

View File

@@ -2,15 +2,16 @@
namespace App\Models;
use App\Models\Company;
use App\Models\Loggable;
use DB;
use Watson\Validating\ValidatingTrait;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
class License extends Depreciable
{
use SoftDeletes;
use CompanyableTrait;
use Loggable;
protected $injectUniqueIdentifier = true;
use ValidatingTrait;
@@ -36,6 +37,11 @@ class License extends Depreciable
return $this->belongsTo('\App\Models\Company', 'company_id');
}
public function manufacturer()
{
return $this->belongsTo('\App\Models\Manufacturer', 'manufacturer_id');
}
/**
* Get the assigned user
*/
@@ -49,8 +55,8 @@ class License extends Depreciable
*/
public function assetlog()
{
return $this->hasMany('\App\Models\Actionlog', 'asset_id')
->where('asset_type', '=', 'software')
return $this->hasMany('\App\Models\Actionlog', 'item_id')
->where('item_type', '=', License::class)
->orderBy('created_at', 'desc');
}
@@ -59,8 +65,8 @@ class License extends Depreciable
*/
public function uploads()
{
return $this->hasMany('\App\Models\Actionlog', 'asset_id')
->where('asset_type', '=', 'software')
return $this->hasMany('\App\Models\Actionlog', 'item_id')
->where('item_type', '=', License::class)
->where('action_type', '=', 'uploaded')
->whereNotNull('filename')
->orderBy('created_at', 'desc');
@@ -95,6 +101,20 @@ class License extends Depreciable
->count();
}
// We do this to eager load the "count" of seats from the controller. Otherwise calling "count()" on each model results in n+1
public function licenseSeatsRelation()
{
return $this->hasMany(LicenseSeat::class)->whereNull('deleted_at')->selectRaw('license_id, count(*) as count')->groupBy('license_id');
}
public function getLicenseSeatsCountAttribute()
{
if ($this->licenseSeatsRelation->first()) {
return $this->licenseSeatsRelation->first()->count;
}
return 0;
}
/**
* Get total licenses not checked out
@@ -110,37 +130,47 @@ class License extends Depreciable
/**
* Get the number of available seats
*/
public function availcount()
public function availCount()
{
return LicenseSeat::whereNull('assigned_to')
->whereNull('asset_id')
->where('license_id', '=', $this->id)
->whereNull('deleted_at')
->count();
return $this->licenseSeatsRelation()
->whereNull('asset_id');
}
public function getAvailSeatsCountAttribute()
{
if ($this->availCount->first()) {
return $this->availCount->first()->count;
}
return 0;
}
/**
* Get the number of assigned seats
*
*/
public function assignedcount()
public function assignedCount()
{
return $this->licenseSeatsRelation()->where(function ($query) {
$query->whereNotNull('assigned_to')
->orWhereNotNull('asset_id');
});
}
return \App\Models\LicenseSeat::where('license_id', '=', $this->id)
->where(function ($query) {
$query->whereNotNull('assigned_to')
->orWhereNotNull('asset_id');
})
->count();
public function getAssignedSeatsCountAttribute()
{
// dd($this->licenseSeatsRelation->first());
if ($this->assignedCount->first()) {
return $this->assignedCount->first()->count;
}
return 0;
}
public function remaincount()
{
$total = $this->totalSeatsByLicenseID();
$taken = $this->assignedcount();
$total = $this->licenseSeatsCount;
$taken = $this->assigned_seats;
$diff = ($total - $taken);
return $diff;
}
@@ -150,7 +180,7 @@ class License extends Depreciable
*/
public function totalcount()
{
$avail = $this->availcount();
$avail = $this->availSeatsCount;
$taken = $this->assignedcount();
$diff = ($avail + $taken);
return $diff;
@@ -208,6 +238,7 @@ class License extends Depreciable
->orWhere('serial', 'LIKE', '%'.$search.'%')
->orWhere('notes', 'LIKE', '%'.$search.'%')
->orWhere('order_number', 'LIKE', '%'.$search.'%')
->orWhere('purchase_order', 'LIKE', '%'.$search.'%')
->orWhere('purchase_date', 'LIKE', '%'.$search.'%')
->orWhere('purchase_cost', 'LIKE', '%'.$search.'%');
});

View File

@@ -1,6 +1,7 @@
<?php
namespace App\Models;
use App\Models\Loggable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
@@ -8,6 +9,7 @@ class LicenseSeat extends Model implements ICompanyableChild
{
use CompanyableChildTrait;
use SoftDeletes;
use Loggable;
protected $dates = ['deleted_at'];
protected $guarded = 'id';

View File

@@ -6,6 +6,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
use App\Models\User;
use App\Models\Asset;
use Watson\Validating\ValidatingTrait;
use App\Http\Traits\UniqueUndeletedTrait;
class Location extends Model
{
@@ -13,7 +14,7 @@ class Location extends Model
protected $dates = ['deleted_at'];
protected $table = 'locations';
protected $rules = array(
'name' => 'required|min:3|max:255|unique:locations,name,NULL,deleted_at',
'name' => 'required|min:3|max:255|unique_undeleted',
'city' => 'min:3|max:255',
'state' => 'min:2|max:32',
'country' => 'min:2|max:2|max:2',
@@ -31,6 +32,7 @@ class Location extends Model
*/
protected $injectUniqueIdentifier = true;
use ValidatingTrait;
use UniqueUndeletedTrait;
/**

135
app/Models/Loggable.php Normal file
View File

@@ -0,0 +1,135 @@
<?php
namespace App\Models;
use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\CheckoutRequest;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
trait Loggable
{
/**
* @author Daniel Meltzer <parallelgrapefruit@gmail.com
* @since [v3.4]
* @return \App\Models\Actionlog
*/
public function log()
{
return $this->morphMany(Actionlog::class, 'item');
}
/**
* @author Daniel Meltzer <parallelgrapefruit@gmail.com
* @since [v3.4]
* @return \App\Models\Actionlog
*/
public function logCheckout($note, $target = null /*target is overridable for components*/)
{
$log = new Actionlog;
// We need to special case licenses because of license_seat vs license. So much for clean polymorphism :)
if (static::class == LicenseSeat::class) {
$log->item_type = License::class;
$log->item_id = $this->license_id;
} else {
$log->item_type = static::class;
$log->item_id = $this->id;
}
$log->user_id = Auth::user()->id;
if (!is_null($this->asset_id) || isset($target)) {
$log->target_type = Asset::class;
$log->target_id = $this->asset_id;
} else if (!is_null($this->assigned_to)) {
$log->target_type = User::class;
$log->target_id = $this->assigned_to;
}
$item = call_user_func(array($log->target_type, 'find'), $log->target_id);
$log->location_id = $item->location_id;
$log->note = $note;
$log->logaction('checkout');
return $log;
}
/**
* @author Daniel Meltzer <parallelgrapefruit@gmail.com
* @since [v3.4]
* @return \App\Models\Actionlog
*/
public function logCheckin($note)
{
$log = new Actionlog;
if (static::class == LicenseSeat::class) {
$log->item_type = License::class;
$log->item_id = $this->license_id;
} else {
$log->item_type = static::class;
$log->item_id = $this->id;
}
$log->location_id = null;
$log->note = $note;
$log->user_id = Auth::user()->id;
$log->logaction('checkin from');
return $log;
}
/**
* @author Daniel Meltzer <parallelgrapefruit@gmail.com
* @since [v3.5]
* @return \App\Models\Actionlog
*/
public function logCreate($note = null)
{
$user_id = -1;
if (Auth::user()) {
$user_id = Auth::user()->id;
}
$log = new Actionlog;
if (static::class == LicenseSeat::class) {
$log->item_type = License::class;
$log->item_id = $this->license_id;
} else {
$log->item_type = static::class;
$log->item_id = $this->id;
}
$log->location_id = null;
$log->note = $note;
$log->user_id = $user_id;
$log->logaction('created');
$log->save();
return $log;
}
/**
* @author Daniel Meltzer <parallelgrapefruit@gmail.com
* @since [v3.4]
* @return \App\Models\Actionlog
*/
public function logUpload($filename, $note)
{
$log = new Actionlog;
if (static::class == LicenseSeat::class) {
$log->item_type = License::class;
$log->item_id = $this->license_id;
} else {
$log->item_type = static::class;
$log->item_id = $this->id;
}
$log->user_id = Auth::user()->id;
$log->note = $note;
$log->target_id = null;
$log->created_at = date("Y-m-d h:i:s");
$log->filename = $filename;
$log->logaction('uploaded');
return $log;
}
}

View File

@@ -46,6 +46,21 @@ class Manufacturer extends Model
return $this->hasManyThrough('\App\Models\Asset', '\App\Models\AssetModel', 'manufacturer_id', 'model_id');
}
public function licenses()
{
return $this->hasMany('\App\Models\License', 'manufacturer_id');
}
public function accessories()
{
return $this->hasMany('\App\Models\Accessory', 'manufacturer_id');
}
public function consumables()
{
return $this->hasMany('\App\Models\Consumable', 'manufacturer_id');
}
/**
* Query builder scope to search on text
*

View File

@@ -0,0 +1,45 @@
<?php
namespace App\Models;
use App\Models\CheckoutRequest;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
// $asset->requests
// $asset->isRequestedBy($user)
// $asset->whereRequestedBy($user)
trait Requestable
{
public function requests()
{
return $this->morphMany(CheckoutRequest::class, 'requestable');
}
public function isRequestedBy(User $user)
{
return $this->requests()
->where('user_id', $user->id)
->exists();
}
public function scopeRequestedBy($query, User $user)
{
return $query->whereHas('requests', function ($query) use ($user) {
$query->where('user_id', $user->id);
});
}
public function request()
{
$this->requests()->save(
new CheckoutRequest(['user_id' => Auth::id()])
);
}
public function cancelRequest()
{
$this->requests()->where('user_id', Auth::id())->delete();
}
}

View File

@@ -4,11 +4,13 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
use App\Http\Traits\UniqueUndeletedTrait;
class Statuslabel extends Model
{
use SoftDeletes;
use ValidatingTrait;
use UniqueUndeletedTrait;
protected $injectUniqueIdentifier = true;
protected $dates = ['deleted_at'];
@@ -16,14 +18,14 @@ class Statuslabel extends Model
protected $rules = array(
'name' => 'required|string|unique:status_labels,name,NULL,deleted_at',
'name' => 'required|string|unique_undeleted',
'notes' => 'string',
'deployable' => 'required',
'pending' => 'required',
'archived' => 'required',
);
protected $fillable = ['name'];
protected $fillable = ['name', 'deployable', 'pending', 'archived'];
/**
* Show count of assets with status label

View File

@@ -4,14 +4,16 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
use App\Http\Traits\UniqueUndeletedTrait;
class Supplier extends Model
{
use SoftDeletes;
protected $dates = ['deleted_at'];
protected $table = 'suppliers';
protected $rules = array(
'name' => 'required|min:3|max:255|unique:suppliers,name,NULL,deleted_at',
'name' => 'required|min:3|max:255|unique_undeleted',
'address' => 'min:3|max:255',
'address2' => 'min:2|max:255',
'city' => 'min:3|max:255',
@@ -35,6 +37,7 @@ class Supplier extends Model
*/
protected $injectUniqueIdentifier = true;
use ValidatingTrait;
use UniqueUndeletedTrait;
/**
* The attributes that are mass assignable.
@@ -44,6 +47,21 @@ class Supplier extends Model
protected $fillable = ['name'];
// Eager load counts.
// We do this to eager load the "count" of seats from the controller. Otherwise calling "count()" on each model results in n+1
public function assetsRelation()
{
return $this->hasMany(Asset::class)->whereNull('deleted_at')->selectRaw('supplier_id, count(*) as count')->groupBy('supplier_id');
}
public function getLicenseSeatsCountAttribute()
{
if ($this->licenseSeatsRelation->first()) {
return $this->licenseSeatsRelation->first()->count;
}
return 0;
}
public function assets()
{
return $this->hasMany('\App\Models\Asset', 'supplier_id');
@@ -56,7 +74,11 @@ class Supplier extends Model
public function num_assets()
{
return $this->hasMany('\App\Models\Asset', 'supplier_id')->count();
if ($this->assetsRelation->first()) {
return $this->assetsRelation->first()->count;
}
return 0;
}
public function licenses()
@@ -66,7 +88,7 @@ class Supplier extends Model
public function num_licenses()
{
return $this->hasMany('\App\Models\License', 'supplier_id')->count();
return $this->licenses()->count();
}
public function addhttp($url)

View File

@@ -7,8 +7,9 @@ use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use Watson\Validating\ValidatingTrait;
use App\Models\Company;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Http\Traits\UniqueUndeletedTrait;
use App\Models\Setting;
class User extends Model implements AuthenticatableContract, CanResetPasswordContract
{
@@ -17,6 +18,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
use ValidatingTrait;
use Authenticatable;
use CanResetPassword;
use UniqueUndeletedTrait;
protected $dates = ['deleted_at'];
protected $table = 'users';
@@ -32,8 +34,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
protected $rules = [
'first_name' => 'required|string|min:1',
'last_name' => 'required|string|min:1',
'username' => 'required|string|min:2|unique:users,username,NULL,deleted_at',
'username' => 'required|string|min:2|unique_undeleted',
'email' => 'email',
'password' => 'required|min:6',
];
@@ -55,7 +56,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
$user_permissions = json_decode($this->permissions, true);
//If the user is explicitly granted, return false
//If the user is explicitly granted, return true
if (($user_permissions!='') && ((array_key_exists($section, $user_permissions)) && ($user_permissions[$section]=='1'))) {
return true;
}
@@ -67,7 +68,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
// Loop through the groups to see if any of them grant this permission
foreach ($user_groups as $user_group) {
$group_permissions = json_decode($user_group->permissions, true);
$group_permissions = (array) json_decode($user_group->permissions, true);
if (((array_key_exists($section, $group_permissions)) && ($group_permissions[$section]=='1'))) {
return true;
}
@@ -84,7 +85,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
foreach ($this->groups as $user_group) {
$group_permissions = json_decode($user_group->permissions, true);
$group_array = $group_permissions;
$group_array = (array)$group_permissions;
if ((array_key_exists('superuser', $group_array)) && ($group_permissions['superuser']=='1')) {
return true;
}
@@ -146,10 +147,8 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
return config('app.url').'/uploads/avatars/'.$this->avatar;
}
if ($this->email) {
// Generate the Gravatar hash
if ((Setting::getSettings()->load_remote=='1') && ($this->email!='')) {
$gravatar = md5(strtolower(trim($this->email)));
// Return the Gravatar url
return "//gravatar.com/avatar/".$gravatar;
}
@@ -202,7 +201,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
*/
public function userlog()
{
return $this->hasMany('\App\Models\Actionlog', 'checkedout_to')->orderBy('created_at', 'DESC')->withTrashed();
return $this->hasMany('\App\Models\Actionlog', 'target_id')->orderBy('created_at', 'DESC')->withTrashed();
}
/**
@@ -232,10 +231,10 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
public function accountStatus()
{
if ($this->sentryThrottle) {
if ($this->sentryThrottle->suspended==1) {
if ($this->throttle) {
if ($this->throttle->suspended==1) {
return 'suspended';
} elseif ($this->sentryThrottle->banned==1) {
} elseif ($this->throttle->banned==1) {
return 'banned';
} else {
return false;
@@ -255,14 +254,22 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
*/
public function uploads()
{
return $this->hasMany('\App\Models\Actionlog', 'asset_id')
->where('asset_type', '=', 'user')
return $this->hasMany('\App\Models\Actionlog', 'item_id')
->where('item_type', User::class)
->where('action_type', '=', 'uploaded')
->whereNotNull('filename')
->orderBy('created_at', 'desc');
}
public function sentryThrottle()
/**
* Fetch Items User has requested
*/
public function checkoutRequests()
{
return $this->belongsToMany(Asset::class, 'checkout_requests');
}
public function throttle()
{
return $this->hasOne('\App\Models\Throttle');
}
@@ -302,6 +309,10 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
->orWhere('username', '=', $user_email);
}
public static function generateEmailFromFullName($name) {
$username = User::generateFormattedNameFromFullName(Setting::getSettings()->email_format, $name);
return $username['username'].'@'.Setting::getSettings()->email_domain;
}
public static function generateFormattedNameFromFullName($format = 'filastname', $users_name)
{
@@ -333,8 +344,9 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
} elseif ($format=='firstname') {
$email_last_name.=str_replace(' ', '', $last_name);
$email_prefix = $first_name;
}
}
$user_username = $email_prefix;
@@ -370,12 +382,18 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
->orWhere('users.email', 'LIKE', "%$search%")
->orWhere('users.username', 'LIKE', "%$search%")
->orWhere('users.notes', 'LIKE', "%$search%")
->orWhere('users.jobtitle', 'LIKE', "%$search%")
->orWhere('users.employee_num', 'LIKE', "%$search%")
->orWhere(function ($query) use ($search) {
$query->whereHas('userloc', function ($query) use ($search) {
$query->where('locations.name', 'LIKE', '%'.$search.'%');
});
})
->orWhere(function ($query) use ($search) {
$query->whereHas('groups', function ($query) use ($search) {
$query->where('groups.name', 'LIKE', '%'.$search.'%');
});
})
// Ugly, ugly code because Laravel sucks at self-joins
->orWhere(function ($query) use ($search) {

View File

@@ -3,6 +3,8 @@ namespace App\Providers;
use Validator;
use Illuminate\Support\ServiceProvider;
use DB;
/**
* This service provider handles a few custom validation rules.
@@ -47,6 +49,21 @@ class AppServiceProvider extends ServiceProvider
}
});
// Unique only if undeleted
// This works around the use case where multiple deleted items have the same unique attribute.
// (I think this is a bug in Laravel's validator?)
Validator::extend('unique_undeleted', function($attribute, $value, $parameters, $validator) {
$count = DB::table($parameters[0])->select('id')->where($attribute,'=',$value)->whereNull('deleted_at')->where('id','!=',$parameters[1])->count();
if ($count < 1) {
return true;
} else {
return false;
}
});
}
/**

View File

@@ -91,6 +91,19 @@ class AuthServiceProvider extends ServiceProvider
}
});
$gate->define('assets.edit', function ($user) {
if (($user->hasAccess('assets.edit')) || ($user->hasAccess('admin'))) {
return true;
}
});
// Checks for some level of management
$gate->define('assets.manage', function ($user) {
if (($user->hasAccess('assets.checkin')) || ($user->hasAccess('assets.edit')) || ($user->hasAccess('assets.delete')) || ($user->hasAccess('assets.checkout')) || ($user->hasAccess('admin'))) {
return true;
}
});
# -----------------------------------------
# Accessories
@@ -131,6 +144,13 @@ class AuthServiceProvider extends ServiceProvider
}
});
// Checks for some level of management
$gate->define('accessories.manage', function ($user) {
if (($user->hasAccess('accessories.checkin')) || ($user->hasAccess('accessories.edit')) || ($user->hasAccess('accessories.checkout')) || ($user->hasAccess('admin'))) {
return true;
}
});
# -----------------------------------------
# Consumables
# -----------------------------------------
@@ -170,6 +190,13 @@ class AuthServiceProvider extends ServiceProvider
}
});
// Checks for some level of management
$gate->define('consumables.manage', function ($user) {
if (($user->hasAccess('consumables.checkin')) || ($user->hasAccess('consumables.edit')) || ($user->hasAccess('consumables.delete')) || ($user->hasAccess('consumables.checkout')) || ($user->hasAccess('admin'))) {
return true;
}
});
# -----------------------------------------
@@ -205,7 +232,7 @@ class AuthServiceProvider extends ServiceProvider
# Components
# -----------------------------------------
$gate->define('components.view', function ($user) {
if (($user->hasAccess('components.create')) || ($user->hasAccess('admin'))) {
if (($user->hasAccess('components.view')) || ($user->hasAccess('admin'))) {
return true;
}
});
@@ -228,6 +255,25 @@ class AuthServiceProvider extends ServiceProvider
}
});
$gate->define('components.checkout', function ($user) {
if (($user->hasAccess('components.checkout')) || ($user->hasAccess('admin'))) {
return true;
}
});
$gate->define('components.checkout', function ($user) {
if (($user->hasAccess('components.checkout')) || ($user->hasAccess('admin'))) {
return true;
}
});
// Checks for some level of management
$gate->define('components.manage', function ($user) {
if (($user->hasAccess('components.edit')) || ($user->hasAccess('components.delete')) || ($user->hasAccess('components.checkout')) || ($user->hasAccess('admin'))) {
return true;
}
});
# -----------------------------------------
# Licenses
@@ -268,6 +314,29 @@ class AuthServiceProvider extends ServiceProvider
}
});
$gate->define('licenses.keys', function ($user) {
if (($user->hasAccess('licenses.keys')) || ($user->hasAccess('admin'))) {
return true;
}
});
// Checks for some level of management
$gate->define('licenses.manage', function ($user) {
if (($user->hasAccess('licenses.checkin')) || ($user->hasAccess('licenses.edit')) || ($user->hasAccess('licenses.delete')) || ($user->hasAccess('licenses.checkout')) || ($user->hasAccess('admin'))) {
return true;
}
});
# -----------------------------------------
# Self
# -----------------------------------------
$gate->define('self.two_factor', function ($user) {
if (($user->hasAccess('self.two_factor')) || ($user->hasAccess('admin'))) {
return true;
}
});
}
}

View File

@@ -21,7 +21,10 @@
"doctrine/common": "v2.5.3",
"doctrine/dbal": "v2.4.2",
"barryvdh/laravel-debugbar": "^2.1",
"spatie/laravel-backup": "3.8.1"
"spatie/laravel-backup": "3.8.1",
"misterphilip/maintenance-mode": "1.0.*",
"neitanod/forceutf8": "dev-master",
"pragmarx/google2fa": "^1.0"
},
"require-dev": {
"fzaninotto/faker": "~1.4",

526
composer.lock generated

File diff suppressed because it is too large Load Diff

22
config/app.php Normal file → Executable file
View File

@@ -117,7 +117,7 @@ return [
|--------------------------------------------------------------------------
| This is the path for any uploaded files that have to be run through the
| auth system to ensure they are not visible to the public. These should be
| stored somewhere outside of the web root so that an unautenticated user
| stored somewhere outside of the web root so that an unauthenticated user
| cannot access them.
|
| For example: license keys, contracts, etc.
@@ -127,6 +127,20 @@ return [
'private_uploads' => storage_path().'/private_uploads',
/*
|--------------------------------------------------------------------------
| ALLOW I-FRAMING
|--------------------------------------------------------------------------
|
| Normal users will never need to edit this. This option lets you run
| Snipe-IT within an I-Frame, which is normally disabled by default for
| security reasons, to prevent clickjacking. It should normally be set to false.
|
*/
'allow_iframing' => env('ALLOW_IFRAMING', false),
/*
|--------------------------------------------------------------------------
| Demo Mode Lockdown
@@ -140,7 +154,6 @@ return [
'lock_passwords' => env('APP_LOCKED', false),
/*
|--------------------------------------------------------------------------
| Autoloaded Service Providers
@@ -197,7 +210,9 @@ return [
Collective\Html\HtmlServiceProvider::class,
Spatie\Backup\BackupServiceProvider::class,
Fideloper\Proxy\TrustedProxyServiceProvider::class,
MisterPhilip\MaintenanceMode\MaintenanceModeServiceProvider::class,
MisterPhilip\MaintenanceMode\MaintenanceCommandServiceProvider::class,
PragmaRX\Google2FA\Vendor\Laravel\ServiceProvider::class,
/*
* Custom service provider
*/
@@ -254,6 +269,7 @@ return [
'View' => Illuminate\Support\Facades\View::class,
'Form' => 'Collective\Html\FormFacade',
'Html' => 'Collective\Html\HtmlFacade',
'Google2FA' => PragmaRX\Google2FA\Vendor\Laravel\Facade::class,
],
];

0
config/database.php Normal file → Executable file
View File

24
config/mail.php Normal file → Executable file
View File

@@ -3,6 +3,12 @@
return [
/*
| ***************************************************************************
| DO NOT MAKE CHANGES DIRECTLY TO THIS FILE.
|
| Instead use your .env file to set your application configuration settings.
| See https://snipe-it.readme.io/docs/configuration for more info.
|
|--------------------------------------------------------------------------
| Mail Driver
|--------------------------------------------------------------------------
@@ -11,6 +17,7 @@ return [
| sending of e-mail. You may specify which one you're using throughout
| your application here. By default, Laravel is setup for SMTP mail.
|
|
| Supported: "smtp", "mail", "sendmail", "mailgun", "mandrill", "ses", "log"
|
*/
@@ -56,6 +63,23 @@ return [
'from' => ['address' => env('MAIL_FROM_ADDR', null), 'name' => env('MAIL_FROM_NAME', null)],
/*
|--------------------------------------------------------------------------
| Global "Reply-To" Address
|--------------------------------------------------------------------------
|
| You may wish for all e-mails sent by your application to have a different "Reply-to"
| address than the "From" address. If this is left blank, the application will use
| your MAIL_FROM information.
|
*/
'reply_to' => [
'address' => env('MAIL_REPLYTO_ADDR', env('MAIL_FROM_ADDR', null)),
'name' => env('MAIL_REPLYTO_NAME', env('MAIL_FROM_NAME', null))
],
/*
|--------------------------------------------------------------------------
| E-Mail Encryption Protocol

View File

@@ -46,19 +46,19 @@ return array(
'permission' => 'assets.create',
'label' => 'Create ',
'note' => '',
'display' => false,
'display' => true,
),
array(
'permission' => 'assets.edit',
'label' => 'Edit ',
'label' => 'Edit ',
'note' => '',
'display' => false,
'display' => true,
),
array(
'permission' => 'assets.delete',
'label' => 'Delete ',
'note' => '',
'display' => false,
'display' => true,
),
array(
'permission' => 'assets.checkout',
@@ -71,7 +71,14 @@ return array(
'permission' => 'assets.checkin',
'label' => 'Checkin ',
'note' => '',
'display' => false,
'display' => true,
),
array(
'permission' => 'assets.checkout',
'label' => 'Checkout ',
'note' => '',
'display' => true,
),
array(
@@ -88,6 +95,7 @@ return array(
'note' => '',
'display' => true,
),
),
'Accessories' => array(
@@ -98,34 +106,34 @@ return array(
'display' => true,
),
array(
'permission' => 'accessory.create',
'permission' => 'accessories.create',
'label' => 'Create ',
'note' => '',
'display' => false,
'display' => true,
),
array(
'permission' => 'accessories.edit',
'label' => 'Edit ',
'note' => '',
'display' => false,
'display' => true,
),
array(
'permission' => 'accessories.delete',
'label' => 'Delete ',
'note' => '',
'display' => false,
'display' => true,
),
array(
'permission' => 'accessories.checkout',
'label' => 'Checkout ',
'note' => '',
'display' => false,
'display' => true,
),
array(
'permission' => 'accessories.checkin',
'label' => 'Checkin ',
'note' => '',
'display' => false,
'display' => true,
),
),
@@ -140,25 +148,25 @@ return array(
'permission' => 'consumables.create',
'label' => 'Create ',
'note' => '',
'display' => false,
'display' => true,
),
array(
'permission' => 'consumables.edit',
'label' => 'Edit ',
'note' => '',
'display' => false,
'display' => true,
),
array(
'permission' => 'consumables.delete',
'label' => 'Delete ',
'note' => '',
'display' => false,
'display' => true,
),
array(
'permission' => 'consumables.checkout',
'label' => 'Checkout ',
'note' => '',
'display' => false,
'display' => true,
),
),
@@ -172,27 +180,27 @@ return array(
),
array(
'permission' => 'licenses.create',
'label' => 'Create Licenses',
'label' => 'Create ',
'note' => '',
'display' => false,
'display' => true,
),
array(
'permission' => 'licenses.edit',
'label' => 'Edit Licenses',
'label' => 'Edit ',
'note' => '',
'display' => false,
'display' => true,
),
array(
'permission' => 'licenses.delete',
'label' => 'Delete Licenses',
'label' => 'Delete ',
'note' => '',
'display' => false,
'display' => true,
),
array(
'permission' => 'licenses.checkout',
'label' => 'Checkout Licenses',
'label' => 'Checkout ',
'note' => '',
'display' => false,
'display' => true,
),
array(
'permission' => 'licenses.keys',
@@ -212,33 +220,33 @@ return array(
),
array(
'permission' => 'components.create',
'label' => 'Create Components',
'label' => 'Create ',
'note' => '',
'display' => false,
'display' => true,
),
array(
'permission' => 'components.edit',
'label' => 'Edit Components',
'label' => 'Edit ',
'note' => '',
'display' => false,
'display' => true,
),
array(
'permission' => 'components.delete',
'label' => 'Delete Components',
'label' => 'Delete ',
'note' => '',
'display' => false,
'display' => true,
),
array(
'permission' => 'components.checkout',
'label' => 'Checkout Components',
'label' => 'Checkout ',
'note' => '',
'display' => false,
'display' => true,
),
array(
'permission' => 'components.checkin',
'label' => 'Checkin Components',
'label' => 'Checkin ',
'note' => '',
'display' => false,
'display' => true,
),
),
@@ -254,19 +262,29 @@ return array(
'permission' => 'users.create',
'label' => 'Create Users',
'note' => '',
'display' => false,
'display' => true,
),
array(
'permission' => 'users.edit',
'label' => 'Edit Users',
'note' => '',
'display' => false,
'display' => true,
),
array(
'permission' => 'users.delete',
'label' => 'Delete Users',
'note' => '',
'display' => false,
'display' => true,
),
),
'Self' => array(
array(
'permission' => 'self.two_factor',
'label' => 'Two-Factor Authentication',
'note' => 'The user may disable/enable two-factor authentication themselves if two-factor is enabled and set to selective.',
'display' => true,
),
),

View File

@@ -1,5 +1,5 @@
<?php
return array (
'app_version' => 'v3.0',
'hash_version' => 'v3.0-ebc74a65',
'app_version' => 'v3.6.0-pre',
'hash_version' => 'v3.6.0-pre-41-ga914dac',
);

View File

@@ -1,636 +0,0 @@
<?php
//
// NOTE Migration Created: 2016-02-13 07:10:06
// --------------------------------------------------
class CreateSnipeitLaravelDatabase {
//
// NOTE - Make changes to the database.
// --------------------------------------------------
public function up()
{
//
// NOTE -- accessories
// --------------------------------------------------
Schema::create('accessories', function($table) {
$table->increments('id')->unsigned();
$table->string('name', 255)->nullable();
$table->integer('category_id')->nullable();
$table->integer('user_id')->nullable();
$table->integer('qty');
$table->boolean('requestable');
$table->timestamp('created_at')->default("0000-00-00 00:00:00");
$table->timestamp('updated_at')->default("0000-00-00 00:00:00");
$table->timestamp('deleted_at')->nullable();
$table->integer('location_id')->nullable();
$table->date('purchase_date')->nullable();
$table->decimal('purchase_cost', 13,4)->nullable();
$table->string('order_number', 255)->nullable();
$table->integer('company_id')->nullable()->unsigned();
});
//
// NOTE -- accessories_users
// --------------------------------------------------
Schema::create('accessories_users', function($table) {
$table->increments('id')->unsigned();
$table->integer('user_id')->nullable();
$table->integer('accessory_id')->nullable();
$table->integer('assigned_to')->nullable();
$table->timestamp('created_at')->default("0000-00-00 00:00:00");
$table->timestamp('updated_at')->default("0000-00-00 00:00:00");
});
//
// NOTE -- asset_logs
// --------------------------------------------------
Schema::create('asset_logs', function($table) {
$table->increments('id')->unsigned();
$table->integer('user_id');
$table->string('action_type', 255);
$table->integer('asset_id')->nullable();
$table->integer('checkedout_to')->nullable();
$table->integer('location_id')->nullable();
$table->dateTime('created_at')->default("0000-00-00 00:00:00");
$table->string('asset_type', 100)->nullable();
$table->text('note')->nullable();
$table->text('filename')->nullable();
$table->timestamp('updated_at')->default("0000-00-00 00:00:00");
$table->timestamp('deleted_at')->nullable();
$table->dateTime('requested_at')->nullable();
$table->dateTime('accepted_at')->nullable();
$table->integer('accessory_id')->nullable();
$table->integer('accepted_id')->nullable();
$table->integer('consumable_id')->nullable();
$table->date('expected_checkin')->nullable();
$table->integer('thread_id')->nullable();
});
//
// NOTE -- asset_maintenances
// --------------------------------------------------
Schema::create('asset_maintenances', function($table) {
$table->increments('id')->unsigned();
$table->integer('asset_id')->unsigned();
$table->integer('supplier_id')->unsigned();
$table->enum('asset_maintenance_type', array('Maintenance','Repair','Upgrade'));
$table->string('title', 100);
$table->boolean('is_warranty');
$table->date('start_date');
$table->date('completion_date')->nullable();
$table->integer('asset_maintenance_time')->nullable();
$table->string('notes')->nullable();
$table->decimal('cost', 10,2)->nullable();
$table->dateTime('deleted_at')->nullable();
$table->timestamp('created_at')->default("0000-00-00 00:00:00");
$table->timestamp('updated_at')->default("0000-00-00 00:00:00");
});
//
// NOTE -- asset_uploads
// --------------------------------------------------
Schema::create('asset_uploads', function($table) {
$table->increments('id')->unsigned();
$table->integer('user_id');
$table->string('filename', 255);
$table->integer('asset_id');
$table->string('filenotes', 255);
$table->timestamp('created_at')->default("0000-00-00 00:00:00");
$table->timestamp('updated_at')->default("0000-00-00 00:00:00");
$table->timestamp('deleted_at')->nullable();
});
//
// NOTE -- assets
// --------------------------------------------------
Schema::create('assets', function($table) {
$table->increments('id')->unsigned();
$table->string('name', 255)->nullable();
$table->string('asset_tag', 255);
$table->integer('model_id');
$table->string('serial', 255);
$table->date('purchase_date')->nullable();
$table->decimal('purchase_cost', 13,4)->default("0.0000");
$table->string('order_number', 255)->nullable();
$table->integer('assigned_to')->nullable();
$table->text('notes')->nullable();
$table->text('image')->nullable();
$table->integer('user_id');
$table->timestamp('created_at')->default("0000-00-00 00:00:00");
$table->timestamp('updated_at')->default("0000-00-00 00:00:00");
$table->boolean('physical')->default("1");
$table->timestamp('deleted_at')->nullable();
$table->integer('status_id')->nullable();
$table->boolean('archived');
$table->integer('warranty_months')->nullable();
$table->boolean('depreciate');
$table->integer('supplier_id')->nullable();
$table->boolean('requestable');
$table->integer('rtd_location_id')->nullable();
$table->string('_snipeit_mac_address', 255)->nullable();
$table->enum('accepted', array('pending','accepted','rejected'))->nullable();
$table->dateTime('last_checkout')->nullable();
$table->date('expected_checkin')->nullable();
$table->integer('company_id')->nullable()->unsigned();
});
//
// NOTE -- categories
// --------------------------------------------------
Schema::create('categories', function($table) {
$table->increments('id')->unsigned();
$table->string('name', 255);
$table->timestamp('created_at')->default("0000-00-00 00:00:00");
$table->timestamp('updated_at')->default("0000-00-00 00:00:00");
$table->integer('user_id');
$table->timestamp('deleted_at')->nullable();
$table->text('eula_text')->nullable();
$table->boolean('use_default_eula');
$table->boolean('require_acceptance');
$table->string('category_type', 255)->nullable()->default("asset");
$table->boolean('checkin_email');
});
//
// NOTE -- companies
// --------------------------------------------------
Schema::create('companies', function($table) {
$table->increments('id')->unsigned();
$table->string('name', 255)->unique();
$table->timestamp('created_at')->default("0000-00-00 00:00:00");
$table->timestamp('updated_at')->default("0000-00-00 00:00:00");
});
//
// NOTE -- consumables
// --------------------------------------------------
Schema::create('consumables', function($table) {
$table->increments('id')->unsigned();
$table->string('name', 255)->nullable();
$table->integer('category_id')->nullable();
$table->integer('location_id')->nullable();
$table->integer('user_id')->nullable();
$table->integer('qty');
$table->boolean('requestable');
$table->timestamp('created_at')->default("0000-00-00 00:00:00");
$table->timestamp('updated_at')->default("0000-00-00 00:00:00");
$table->timestamp('deleted_at')->nullable();
$table->date('purchase_date')->nullable();
$table->decimal('purchase_cost', 13,4)->nullable();
$table->string('order_number', 255)->nullable();
$table->integer('company_id')->nullable()->unsigned();
});
//
// NOTE -- consumables_users
// --------------------------------------------------
Schema::create('consumables_users', function($table) {
$table->increments('id')->unsigned();
$table->integer('user_id')->nullable();
$table->integer('consumable_id')->nullable();
$table->integer('assigned_to')->nullable();
$table->timestamp('created_at')->default("0000-00-00 00:00:00");
$table->timestamp('updated_at')->default("0000-00-00 00:00:00");
});
//
// NOTE -- custom_field_custom_fieldset
// --------------------------------------------------
Schema::create('custom_field_custom_fieldset', function($table) {
$table->integer('custom_field_id');
$table->integer('custom_fieldset_id');
$table->integer('order');
$table->boolean('required');
});
//
// NOTE -- custom_fields
// --------------------------------------------------
Schema::create('custom_fields', function($table) {
$table->increments('id')->unsigned();
$table->string('name', 255);
$table->string('format', 255);
$table->string('element', 255);
$table->timestamp('created_at')->default("0000-00-00 00:00:00");
$table->timestamp('updated_at')->default("0000-00-00 00:00:00");
$table->integer('user_id')->nullable();
});
//
// NOTE -- custom_fieldsets
// --------------------------------------------------
Schema::create('custom_fieldsets', function($table) {
$table->increments('id')->unsigned();
$table->string('name', 255);
$table->timestamp('created_at')->default("0000-00-00 00:00:00");
$table->timestamp('updated_at')->default("0000-00-00 00:00:00");
$table->integer('user_id')->nullable();
});
//
// NOTE -- depreciations
// --------------------------------------------------
Schema::create('depreciations', function($table) {
$table->increments('id')->unsigned();
$table->string('name', 255);
$table->integer('months');
$table->timestamp('created_at')->default("0000-00-00 00:00:00");
$table->timestamp('updated_at')->default("0000-00-00 00:00:00");
$table->integer('user_id');
});
//
// NOTE -- groups
// --------------------------------------------------
Schema::create('groups', function($table) {
$table->increments('id')->unsigned();
$table->string('name', 255)->unique();
$table->text('permissions')->nullable();
$table->timestamp('created_at')->default("0000-00-00 00:00:00");
$table->timestamp('updated_at')->default("0000-00-00 00:00:00");
});
//
// NOTE -- history
// --------------------------------------------------
Schema::create('history', function($table) {
$table->increments('id')->unsigned();
$table->integer('checkedout_to');
$table->integer('location_id');
$table->timestamp('created_at')->default("0000-00-00 00:00:00");
$table->timestamp('updated_at')->default("0000-00-00 00:00:00");
$table->integer('user_id');
});
//
// NOTE -- license_seats
// --------------------------------------------------
Schema::create('license_seats', function($table) {
$table->increments('id')->unsigned();
$table->integer('license_id');
$table->integer('assigned_to')->nullable();
$table->text('notes')->nullable();
$table->integer('user_id');
$table->timestamp('created_at')->default("0000-00-00 00:00:00");
$table->timestamp('updated_at')->default("0000-00-00 00:00:00");
$table->timestamp('deleted_at')->nullable();
$table->integer('asset_id')->nullable();
});
//
// NOTE -- licenses
// --------------------------------------------------
Schema::create('licenses', function($table) {
$table->increments('id')->unsigned();
$table->string('name', 255);
$table->text('serial')->nullable();
$table->date('purchase_date')->nullable();
$table->decimal('purchase_cost', 13,4)->nullable();
$table->string('order_number', 50)->nullable();
$table->integer('seats')->default("1");
$table->text('notes')->nullable();
$table->integer('user_id');
$table->boolean('depreciation_id');
$table->timestamp('created_at')->default("0000-00-00 00:00:00");
$table->timestamp('updated_at')->default("0000-00-00 00:00:00");
$table->timestamp('deleted_at')->nullable();
$table->string('license_name', 100)->nullable();
$table->string('license_email', 120)->nullable();
$table->boolean('depreciate')->nullable();
$table->integer('supplier_id')->nullable();
$table->date('expiration_date')->nullable();
$table->string('purchase_order', 255)->nullable();
$table->date('termination_date')->nullable();
$table->boolean('maintained');
$table->boolean('reassignable')->default("1");
$table->integer('company_id')->nullable()->unsigned();
});
//
// NOTE -- locations
// --------------------------------------------------
Schema::create('locations', function($table) {
$table->increments('id')->unsigned();
$table->string('name', 255);
$table->string('city', 255);
$table->string('state', 255);
$table->string('country', 2);
$table->timestamp('created_at')->default("0000-00-00 00:00:00");
$table->timestamp('updated_at')->default("0000-00-00 00:00:00");
$table->integer('user_id');
$table->string('address', 80);
$table->string('address2', 255)->nullable();
$table->string('zip', 10)->nullable();
$table->timestamp('deleted_at')->nullable();
$table->integer('parent_id')->nullable();
$table->string('currency', 10)->nullable();
});
//
// NOTE -- manufacturers
// --------------------------------------------------
Schema::create('manufacturers', function($table) {
$table->increments('id')->unsigned();
$table->string('name', 255);
$table->timestamp('created_at')->default("0000-00-00 00:00:00");
$table->timestamp('updated_at')->default("0000-00-00 00:00:00");
$table->integer('user_id');
$table->timestamp('deleted_at')->nullable();
});
//
// NOTE -- models
// --------------------------------------------------
Schema::create('models', function($table) {
$table->increments('id')->unsigned();
$table->string('name', 255);
$table->string('modelno', 255)->nullable();
$table->integer('manufacturer_id');
$table->integer('category_id');
$table->timestamp('created_at')->default("0000-00-00 00:00:00");
$table->timestamp('updated_at')->default("0000-00-00 00:00:00");
$table->integer('depreciation_id');
$table->integer('user_id');
$table->integer('eol')->nullable();
$table->string('image', 255)->nullable();
$table->boolean('deprecated_mac_address');
$table->timestamp('deleted_at')->nullable();
$table->integer('fieldset_id')->nullable();
$table->text('note')->nullable();
});
//
// NOTE -- requested_assets
// --------------------------------------------------
Schema::create('requested_assets', function($table) {
$table->increments('id')->unsigned();
$table->integer('asset_id');
$table->integer('user_id');
$table->dateTime('accepted_at')->nullable();
$table->dateTime('denied_at')->nullable();
$table->string('notes', 255);
$table->timestamp('created_at')->default("0000-00-00 00:00:00");
$table->timestamp('updated_at')->default("0000-00-00 00:00:00");
});
//
// NOTE -- requests
// --------------------------------------------------
Schema::create('requests', function($table) {
$table->increments('id')->unsigned();
$table->integer('asset_id');
$table->integer('user_id');
$table->text('request_code');
$table->timestamp('created_at')->default("0000-00-00 00:00:00");
$table->timestamp('updated_at')->default("0000-00-00 00:00:00");
$table->timestamp('deleted_at')->nullable();
});
//
// NOTE -- settings
// --------------------------------------------------
Schema::create('settings', function($table) {
$table->increments('id')->unsigned();
$table->timestamp('created_at')->default("0000-00-00 00:00:00");
$table->timestamp('updated_at')->default("0000-00-00 00:00:00");
$table->integer('user_id');
$table->integer('per_page')->default("20");
$table->string('site_name', 100)->default("Snipe IT Asset Management");
$table->integer('qr_code')->nullable();
$table->string('qr_text', 32)->nullable();
$table->integer('display_asset_name')->nullable();
$table->integer('display_checkout_date')->nullable();
$table->integer('display_eol')->nullable();
$table->integer('auto_increment_assets');
$table->string('auto_increment_prefix', 255);
$table->boolean('load_remote')->default("1");
$table->string('logo', 255)->nullable();
$table->string('header_color', 255)->nullable();
$table->string('alert_email', 255)->nullable();
$table->boolean('alerts_enabled')->default("1");
$table->text('default_eula_text')->nullable();
$table->string('barcode_type', 255)->nullable()->default("QRCODE");
$table->string('slack_endpoint', 255)->nullable();
$table->string('slack_channel', 255)->nullable();
$table->string('slack_botname', 255)->nullable();
$table->string('default_currency', 10)->nullable();
$table->text('custom_css')->nullable();
$table->boolean('brand')->default("1");
$table->string('ldap_enabled', 255)->nullable();
$table->string('ldap_server', 255)->nullable();
$table->string('ldap_uname', 255)->nullable();
$table->string('ldap_pword')->nullable();
$table->string('ldap_basedn', 255)->nullable();
$table->string('ldap_filter', 255)->nullable()->default("cn=*");
$table->string('ldap_username_field', 255)->nullable()->default("samaccountname");
$table->string('ldap_lname_field', 255)->nullable()->default("sn");
$table->string('ldap_fname_field', 255)->nullable()->default("givenname");
$table->string('ldap_auth_filter_query', 255)->nullable()->default("uid=samaccountname");
$table->integer('ldap_version')->nullable()->default("3");
$table->string('ldap_active_flag', 255)->nullable();
$table->string('ldap_emp_num', 255)->nullable();
$table->string('ldap_email', 255)->nullable();
$table->boolean('full_multiple_companies_support');
$table->boolean('ldap_server_cert_ignore');
});
//
// NOTE -- status_labels
// --------------------------------------------------
Schema::create('status_labels', function($table) {
$table->increments('id')->unsigned();
$table->string('name', 100);
$table->integer('user_id');
$table->timestamp('created_at')->default("0000-00-00 00:00:00");
$table->timestamp('updated_at')->default("0000-00-00 00:00:00");
$table->timestamp('deleted_at')->nullable();
$table->boolean('deployable');
$table->boolean('pending');
$table->boolean('archived');
$table->text('notes')->nullable();
});
//
// NOTE -- suppliers
// --------------------------------------------------
Schema::create('suppliers', function($table) {
$table->increments('id')->unsigned();
$table->string('name', 255);
$table->string('address', 50)->nullable();
$table->string('address2', 50)->nullable();
$table->string('city', 255)->nullable();
$table->string('state', 32)->nullable();
$table->string('country', 2)->nullable();
$table->string('phone', 20)->nullable();
$table->string('fax', 20)->nullable();
$table->string('email', 150)->nullable();
$table->string('contact', 100)->nullable();
$table->string('notes', 255)->nullable();
$table->timestamp('created_at')->default("0000-00-00 00:00:00");
$table->timestamp('updated_at')->default("0000-00-00 00:00:00");
$table->integer('user_id');
$table->timestamp('deleted_at')->nullable();
$table->string('zip', 10)->nullable();
$table->string('url', 250)->nullable();
$table->string('image', 255)->nullable();
});
//
// NOTE -- throttle
// --------------------------------------------------
Schema::create('throttle', function($table) {
$table->increments('id')->unsigned();
$table->integer('user_id')->nullable()->unsigned();
$table->string('ip_address', 255)->nullable();
$table->integer('attempts');
$table->boolean('suspended');
$table->boolean('banned');
$table->timestamp('last_attempt_at')->nullable();
$table->timestamp('suspended_at')->nullable();
$table->timestamp('banned_at')->nullable();
});
//
// NOTE -- users
// --------------------------------------------------
Schema::create('users', function($table) {
$table->increments('id')->unsigned();
$table->string('email', 255)->nullable();
$table->string('password', 255);
$table->text('permissions')->nullable();
$table->boolean('activated');
$table->string('activation_code', 255)->nullable();
$table->timestamp('activated_at')->nullable();
$table->timestamp('last_login')->nullable();
$table->string('persist_code', 255)->nullable();
$table->string('reset_password_code', 255)->nullable();
$table->string('first_name', 255);
$table->string('last_name', 255);
$table->timestamp('created_at')->default("0000-00-00 00:00:00");
$table->timestamp('updated_at')->default("0000-00-00 00:00:00");
$table->timestamp('deleted_at')->nullable();
$table->string('website', 255)->nullable();
$table->string('country', 255)->nullable();
$table->string('gravatar', 255)->nullable();
$table->integer('location_id')->nullable();
$table->string('phone', 20)->nullable();
$table->string('jobtitle', 100)->nullable();
$table->integer('manager_id')->nullable();
$table->text('employee_num')->nullable();
$table->string('avatar', 255)->nullable();
$table->string('username', 255)->nullable();
$table->string('notes', 255)->nullable();
$table->integer('company_id')->nullable()->unsigned();
});
//
// NOTE -- users_groups
// --------------------------------------------------
Schema::create('users_groups', function($table) {
$table->increments('user_id')->unsigned();
$table->integer('group_id')->unsigned();
});
}
//
// NOTE - Revert the changes to the database.
// --------------------------------------------------
public function down()
{
Schema::drop('accessories');
Schema::drop('accessories_users');
Schema::drop('asset_logs');
Schema::drop('asset_maintenances');
Schema::drop('asset_uploads');
Schema::drop('assets');
Schema::drop('categories');
Schema::drop('companies');
Schema::drop('consumables');
Schema::drop('consumables_users');
Schema::drop('custom_field_custom_fieldset');
Schema::drop('custom_fields');
Schema::drop('custom_fieldsets');
Schema::drop('depreciations');
Schema::drop('groups');
Schema::drop('history');
Schema::drop('license_seats');
Schema::drop('licenses');
Schema::drop('locations');
Schema::drop('manufacturers');
Schema::drop('models');
Schema::drop('requested_assets');
Schema::drop('requests');
Schema::drop('settings');
Schema::drop('status_labels');
Schema::drop('suppliers');
Schema::drop('throttle');
Schema::drop('users');
Schema::drop('users_groups');
}
}

View File

@@ -25,6 +25,7 @@ $factory->defineAs(App\Models\Asset::class, 'asset', function (Faker\Generator $
'order_number' => $faker->numberBetween(1000000,50000000),
'supplier_id' => $faker->numberBetween(1,5),
'requestable' => $faker->numberBetween(0,1),
'company_id' => \App\Models\Company::inRandomOrder()->first()->id
];
});
@@ -96,6 +97,7 @@ $factory->defineAs(App\Models\Component::class, 'component', function (Faker\Gen
'category_id' => $faker->numberBetween(21,25),
'total_qty' => $faker->numberBetween(3, 10),
'min_amt' => $faker->numberBetween($min = 1, $max = 2),
'company_id' => \App\Models\Company::inRandomOrder()->first()->id
];
});
@@ -113,6 +115,7 @@ $factory->defineAs(App\Models\Accessory::class, 'accessory', function (Faker\Gen
'qty' => $faker->numberBetween(5, 10),
'location_id' => $faker->numberBetween(1,5),
'min_amt' => $faker->numberBetween($min = 1, $max = 2),
'company_id' => \App\Models\Company::inRandomOrder()->first()->id
];
});
@@ -138,6 +141,7 @@ $factory->defineAs(App\Models\Consumable::class, 'consumable', function (Faker\G
'company_id' => $faker->numberBetween(1, 10),
'qty' => $faker->numberBetween(5, 10),
'min_amt' => $faker->numberBetween($min = 1, $max = 2),
'company_id' => \App\Models\Company::inRandomOrder()->first()->id
];
});
@@ -251,6 +255,7 @@ $factory->defineAs(App\Models\License::class, 'license', function (Faker\Generat
'purchase_date' => $faker->dateTime(),
'purchase_cost' => $faker->randomFloat(2),
'notes' => $faker->sentence,
'company_id' => \App\Models\Company::inRandomOrder()->first()->id
];
});
@@ -265,18 +270,82 @@ $factory->defineAs(App\Models\LicenseSeat::class, 'license-seat', function (Fake
});
$factory->defineAs(App\Models\Actionlog::class, 'asset-checkout', function (Faker\Generator $faker) {
$company = \App\Models\Company::has('users')->has('assets')->inRandomOrder()->first();
return [
'user_id' => 1,
'user_id' => $company->users()->inRandomOrder()->first()->id,
'action_type' => 'checkout',
'asset_id' => $faker->numberBetween(1, 10),
'checkedout_to' => 1,
'item_id' => $company->assets()->inRandomOrder()->first()->id,
'target_id' => $company->users()->inRandomOrder()->first()->id,
'target_type' => 'App\\Models\\User',
'created_at' => $faker->dateTime(),
'asset_type' => 'hardware',
'item_type' => 'App\\Models\\Asset',
'note' => $faker->sentence,
'user_id' => '1',
'company_id' => $company->id
];
});
$factory->defineAs(App\Models\Actionlog::class, 'license-checkout-asset', function (Faker\Generator $faker) {
$company = \App\Models\Company::has('users')->has('licenses')->inRandomOrder()->first();
return [
'user_id' => $company->users()->inRandomOrder()->first()->id,
'action_type' => 'checkout',
'item_id' => $company->licenses()->whereNotNull('company_id')->inRandomOrder()->first()->id,
'target_id' => $company->assets()->inRandomOrder()->first()->id,
'target_type' => 'App\\Models\\Asset',
'created_at' => $faker->dateTime(),
'item_type' => 'App\\Models\\License',
'note' => $faker->sentence,
'company_id' => $company->id
];
});
$factory->defineAs(App\Models\Actionlog::class, 'accessory-checkout', function (Faker\Generator $faker) {
$company = \App\Models\Company::has('users')->has('accessories')->inRandomOrder()->first();
return [
'user_id' => $company->users()->inRandomOrder()->first()->id,
'action_type' => 'checkout',
'item_id' => $company->accessories()->whereNotNull('company_id')->inRandomOrder()->first()->id,
'target_id' => $company->users()->inRandomOrder()->first()->id,
'target_type' => 'App\\Models\\User',
'created_at' => $faker->dateTime(),
'item_type' => 'App\\Models\\Accessory',
'note' => $faker->sentence,
'company_id' => $company->id
];
});
$factory->defineAs(App\Models\Actionlog::class, 'consumable-checkout', function (Faker\Generator $faker) {
$company = \App\Models\Company::has('users')->has('consumables')->inRandomOrder()->first();
return [
'user_id' => $company->users()->inRandomOrder()->first()->id,
'action_type' => 'checkout',
'item_id' => $company->consumables()->whereNotNull('company_id')->inRandomOrder()->first()->id,
'target_id' => $company->users()->inRandomOrder()->first()->id,
'target_type' => 'App\\Models\\User',
'created_at' => $faker->dateTime(),
'item_type' => 'App\\Models\\Consumable',
'note' => $faker->sentence,
'company_id' => $company->id
];
});
$factory->defineAs(App\Models\Actionlog::class, 'component-checkout', function (Faker\Generator $faker) {
$company = \App\Models\Company::has('users')->has('components')->inRandomOrder()->first();
return [
'user_id' => $company->users()->inRandomOrder()->first()->id,
'action_type' => 'checkout',
'item_id' => $company->components()->whereNotNull('company_id')->inRandomOrder()->first()->id,
'target_id' => $company->users()->inRandomOrder()->first()->id,
'target_type' => 'App\\Models\\User',
'created_at' => $faker->dateTime(),
'item_type' => 'App\\Models\\Component',
'note' => $faker->sentence,
'company_id' => $company->id
];
});
$factory->defineAs(App\Models\CustomField::class, 'customfield-ip', function (Faker\Generator $faker) {
return [
@@ -294,5 +363,6 @@ $factory->defineAs(App\Models\User::class, 'valid-user', function (Faker\Generat
'email' => $faker->safeEmail,
'password' => $faker->password,
'username' => $faker->username,
'company_id' => \App\Models\Company::inRandomOrder()->first()->id
];
});

View File

@@ -18,9 +18,9 @@ class UpdateGroupFieldForReporting extends Migration {
// //
// });
DB::update('update groups set permissions = ? where id = ?', ['{"admin":1,"users":1,"reports":1}', 1]);
DB::update('update '.DB::getTablePrefix().'groups set permissions = ? where id = ?', ['{"admin":1,"users":1,"reports":1}', 1]);
DB::update('update groups set permissions = ? where id = ?', ['{"users":1,"reports":1}', 2]);
DB::update('update '.DB::getTablePrefix().'groups set permissions = ? where id = ?', ['{"users":1,"reports":1}', 2]);
// DB::statement('UPDATE '.$prefix.'groups SET permissions="{\"admin\":1,\"users\":1,\"reports\":1}" where id=1');
// DB::statement('UPDATE '.$prefix.'groups SET permissions="{\"users\":1,\"reports\":1}" where id=2');

View File

@@ -18,11 +18,11 @@ class UpdateAcceptedAtToAcceptanceId extends Migration {
$table->integer('accepted_id')->nullable()->default(NULL);
});
$results = DB::select('select invitation.id AS invitation_id, acceptance.id AS acceptance_id FROM asset_logs invitation INNER JOIN asset_logs acceptance ON (invitation.checkedout_to=acceptance.checkedout_to AND invitation.asset_id=acceptance.asset_id) WHERE invitation.action_type="checkout" AND acceptance.action_type="accepted"');
$results = DB::select('select invitation.id AS invitation_id, acceptance.id AS acceptance_id FROM '.DB::getTablePrefix().'asset_logs invitation INNER JOIN '.DB::getTablePrefix().'asset_logs acceptance ON (invitation.checkedout_to=acceptance.checkedout_to AND invitation.asset_id=acceptance.asset_id) WHERE invitation.action_type="checkout" AND acceptance.action_type="accepted"');
foreach ($results as $result) {
$update = DB::update('update asset_logs set accepted_id=? where id=?', [$result->acceptance_id, $result->invitation_id]);
$update = DB::update('update '.DB::getTablePrefix().'asset_logs set accepted_id=? where id=?', [$result->acceptance_id, $result->invitation_id]);
}
}

View File

@@ -64,39 +64,39 @@
public function up()
{
if (!Schema::hasColumn('asset_logs', 'thread_id')) {
// if (!Schema::hasColumn('asset_logs', 'thread_id')) {
Schema::table( 'asset_logs', function ( Blueprint $table ) {
// Schema::table( 'asset_logs', function ( Blueprint $table ) {
$table->integer( 'thread_id' )
->nullable()
->default( null );
$table->index( 'thread_id' );
} );
}
// $table->integer( 'thread_id' )
// ->nullable()
// ->default( null );
// $table->index( 'thread_id' );
// } );
// }
$this->actionlog = new App\Models\Actionlog();
$this->assetLogs = $this->actionlog->getListingOfActionLogsChronologicalOrder();
// $this->actionlog = new App\Models\Actionlog();
// $this->assetLogs = $this->actionlog->getListingOfActionLogsChronologicalOrder();
foreach ($this->assetLogs as $assetLog) {
// foreach ($this->assetLogs as $assetLog) {
if ($this->hasAssetChanged( $assetLog )) {
$this->resetCurrentAssetInformation( $assetLog );
}
// if ($this->hasAssetChanged( $assetLog )) {
// $this->resetCurrentAssetInformation( $assetLog );
// }
if ($this->hasBegunNewChain( $assetLog )) {
$this->startOfCurrentThread = false;
continue;
}
// if ($this->hasBegunNewChain( $assetLog )) {
// $this->startOfCurrentThread = false;
// continue;
// }
$this->updateAssetLogWithThreadInformation( $assetLog );
// $this->updateAssetLogWithThreadInformation( $assetLog );
if ($this->hasReachedEndOfChain( $assetLog )
) {
$this->clearCurrentAssetInformation();
}
// if ($this->hasReachedEndOfChain( $assetLog )
// ) {
// $this->clearCurrentAssetInformation();
// }
}
// }
}

View File

@@ -18,8 +18,8 @@ class AddCheckoutTimeAndExpectedCheckoutDateToAssets extends Migration {
$answer=$table->dateTime('last_checkout')->nullable();
$table->date('expected_checkin')->nullable();
});
DB::statement("UPDATE assets SET last_checkout=(SELECT MAX(created_at) FROM asset_logs WHERE asset_logs.id=assets.id AND action_type='checkout') WHERE assigned_to IS NOT NULL");
DB::statement("UPDATE assets SET expected_checkin=(SELECT expected_checkin FROM asset_logs WHERE asset_logs.id=assets.id AND action_type='checkout' ORDER BY id DESC limit 1) WHERE assigned_to IS NOT NULL");
DB::statement("UPDATE ".DB::getTablePrefix()."assets SET last_checkout=(SELECT MAX(created_at) FROM ".DB::getTablePrefix()."asset_logs WHERE ".DB::getTablePrefix()."asset_logs.id=".DB::getTablePrefix()."assets.id AND action_type='checkout') WHERE assigned_to IS NOT NULL");
DB::statement("UPDATE ".DB::getTablePrefix()."assets SET expected_checkin=(SELECT expected_checkin FROM ".DB::getTablePrefix()."asset_logs WHERE ".DB::getTablePrefix()."asset_logs.id=".DB::getTablePrefix()."assets.id AND action_type='checkout' ORDER BY id DESC limit 1) WHERE assigned_to IS NOT NULL");
}
/**

View File

@@ -0,0 +1,78 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class FixCustomFieldsRegexStuff extends Migration
{
/**
* Run the migrations.
* "ANY" => "",
* "ALPHA" => "alpha",
* "EMAIL" => "email",
* "DATE" => "date",
* "URL" => "url",
* "NUMERIC" => "numeric",
* "MAC" => "regex:/^[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}$/",
* "IP" => "ip"
*
* @return void
*/
public function up()
{
foreach(\App\Models\CustomField::all() as $custom_field) {
// Handle alphanumeric
if (stripos($custom_field->format, 'ALPHA') !== false) {
$custom_field->format='alpha';
// Numeric
} elseif (stripos($custom_field->format, 'NUMERIC') !== false) {
$custom_field->format='numeric';
// IP
} elseif (stripos($custom_field->format, 'IP') !== false) {
$custom_field->format='ip';
// Email
} elseif (stripos($custom_field->format, 'EMAIL') !== false) {
$custom_field->format='email';
// MAC
} elseif (stripos($custom_field->format, 'regex:/^[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}$/') !== false) {
$custom_field->format='regex:/^[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}$/';
// Date
} elseif (stripos($custom_field->format, 'DATE') !== false) {
$custom_field->format='date';
// URL
} elseif (stripos($custom_field->format, 'URL') !== false) {
$custom_field->format='url';
// ANY
} elseif (stripos($custom_field->format, 'ANY') !== false) {
$custom_field->format='';
// Fix any custom regexes
} else {
$tmp_custom = str_replace('regex:/^', '', $custom_field->format);
$tmp_custom = str_replace('$/', '', $tmp_custom);
$custom_field->format = 'regex:/^'.$tmp_custom.'$/';
}
$custom_field->save();
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}

View File

@@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class OneMoreMacAddrFix extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
foreach(\App\Models\CustomField::all() as $custom_field) {
if ($custom_field->format=='regex:/^MAC$/') {
$custom_field->format = 'regex:/^[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}$/';
}
$custom_field->save();
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}

View File

@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddPortToLdapSettings extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('settings', function (Blueprint $table) {
$table->string('ldap_port', 5)->default('389');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('settings', function ($table) {
$table->dropColumn('ldap_port');
});
}
}

View File

@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddTlsToLdapSettings extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('settings', function (Blueprint $table) {
$table->boolean('ldap_tls')->default(0);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('settings', function ($table) {
$table->dropColumn('ldap_tls');
});
}
}

View File

@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddZerofillToSettings extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('settings', function (Blueprint $table) {
$table->integer('zerofill_count')->default(5);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('settings', function ($table) {
$table->dropColumn('zerofill_count');
});
}
}

View File

@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddColorToStatuslabel extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('status_labels', function (Blueprint $table) {
$table->string('color', 10)->nullable()->default(NULL);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('status_labels', function ($table) {
$table->dropColumn('color');
});
}
}

View File

@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddDisallowLdapPwSyncToSettings extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('settings', function (Blueprint $table) {
$table->boolean('ldap_pw_sync')->default(1);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('settings', function ($table) {
$table->dropColumn('ldap_pw_sync');
});
}
}

View File

@@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddManufacturerToLicenses extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('licenses', function (Blueprint $table) {
//
$table->integer('manufacturer_id')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('licenses', function (Blueprint $table) {
//
});
}
}

View File

@@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddManufacturerToAccessoriesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('accessories', function (Blueprint $table) {
//
$table->integer('manufacturer_id')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('accessories', function (Blueprint $table) {
//
$table->dropColumn('manufacturer_id');
});
}
}

View File

@@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddNewFieldsToCustomFields extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('custom_fields', function (Blueprint $table) {
//
$table->string('field_values')->nullable()->default(null);
$table->boolean('field_encrypted')->default(0);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('custom_fields', function (Blueprint $table) {
//
$table->dropColumn('field_values', 'field_encrypted');
});
}
}

View File

@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddShowInNavToStatusLabels extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('status_labels', function (Blueprint $table) {
$table->boolean('show_in_nav')->default(0);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('status_labels', function (Blueprint $table) {
$table->dropColumn('show_in_nav', 'field_encrypted');
});
}
}

View File

@@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class MakePurchaseCostNullable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
$platform = Schema::getConnection()->getDoctrineSchemaManager()->getDatabasePlatform();
$platform->registerDoctrineTypeMapping('enum', 'string');
Schema::table('assets', function ($table) {
$table->decimal('purchase_cost',8,2)->nullable()->default(null)->change();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}

View File

@@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddRequestableToAssetModel extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
//
Schema::table('models', function ($table) {
$table->tinyInteger('requestable')->default(0);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
Schema::table('models', function ($table) {
$table->dropColumn('requestable');
});
}
}

View File

@@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateCheckoutRequestsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('checkout_requests', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id');
$table->integer('requestable_id');
$table->string('requestable_type');
$table->integer('quantity')->default(1);
$table->timestamps();
$table->unique(['user_id', 'requestable_id', 'requestable_type']);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('checkout_requests');
}
}

View File

@@ -0,0 +1,49 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateActionlogTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
if (!Schema::hasTable('action_logs')) {
Schema::create('action_logs', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->nullable();
$table->string('action_type');
$table->integer('target_id')->nullable(); // Was checkedout_to
$table->string('target_type')->nullable(); // For polymorphic thingies
$table->integer('location_id')->nullable();
$table->text('note')->nullable();
$table->text('filename')->nullable();
$table->string('item_type');
$table->integer('item_id'); // Replaces asset_id, accessory_id, etc.
$table->date('expected_checkin')->nullable()->default(null);
$table->integer('accepted_id')->nullable();
$table->timestamps();
$table->softDeletes();
$table->integer('thread_id')
->nullable()
->default(null);
$table->index('thread_id');
});
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('action_logs');
}
}

View File

@@ -0,0 +1,79 @@
<?php
use App\Models\Actionlog;
use App\Models\User;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class MigrateAssetLogToActionLog extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
//
$logs = DB::table('asset_logs')->get();
foreach ($logs as $log) {
// protected $fillable = [ 'created_at', 'asset_type','user_id','asset_id','action_type','note','checkedout_to' ];
$a = new Actionlog(compact($log));
// var_dump($log);
$a->user_id = $log->user_id;
if (!is_null($log->asset_id)) {
$a->item_id = $log->asset_id;
if ($log->asset_type == "hardware") {
$a->item_type = 'App\\Models\\Asset';
} else {
$a->item_type = 'App\\Models\\License';
}
}
if (!is_null($log->accessory_id)) {
$a->item_id = $log->accessory_id;
$a->item_type = 'App\\Models\\Accessory';
} else if (!is_null($log->consumable_id)) {
$a->item_id = $log->consumable_id;
$a->item_type = 'App\\Models\\Consumable';
} else if (!is_null($log->component_id)) {
$a->item_id = $log->component_id;
$a->item_type = 'App\\Models\\Component';
}
$a->action_type = $log->action_type;
// $a->checkout_to = $log->checkout_to;
if(!is_null($log->checkedout_to)) {
$a->target_id = $log->checkedout_to;
$a->target_type = User::class;
}
if(!is_null($log->accepted_id)) {
$a->target_id = $log->accepted_id;
$a->target_type = User::class;
}
$a->location_id = $log->location_id;
$a->created_at = $log->created_at;
$a->updated_at = $log->updated_at;
$a->deleted_at = $log->deleted_at;
$a->note = $log->note;
$a->expected_checkin = $log->expected_checkin;
$a->thread_id = $log->thread_id;
$a->accepted_id = $log->accepted_id;
$a->filename = $log->filename;
$a->save();
}
// dd($logs);
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}

View File

@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class FixFieldtypeForTargetType extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('action_logs', function ($table) {
$table->string('target_type')->nullable()->default(null)->change();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('action_logs', function ($table) {
$table->integer('target_type')->nullable()->default(null)->change();
});
}
}

View File

@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class FixModelnoInConsumablesToString extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('consumables', function ($table) {
$table->string('model_no')->nullable()->default(null)->change();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('consumables', function ($table) {
$table->integer('model_no')->nullable()->default(null)->change();
});
}
}

View File

@@ -0,0 +1,44 @@
<?php
use App\Models\Actionlog;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class AddCompanyToLogs extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('action_logs', function (Blueprint $table) {
//
$table->integer('company_id')->nullable()->default(null);
});
$logs = Actionlog::with('item')->get();
foreach ($logs as $log) {
if($log->item) {
$log->company_id = $log->item->company_id;
$log->save();
} else {
var_dump($log);
}
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('action_logs', function (Blueprint $table) {
//
$table->dropColumn('company_id');
});
}
}

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