Compare commits

..

316 Commits

Author SHA1 Message Date
snipe
08ef78356d Update Crowdin configuration file 2017-04-06 20:59:25 -07:00
Manasses Ferreira
47ac59abef We noted that the barcode folder was not being created. (what is done now in the entrypoint.sh) At the same time, a wrong directory was being created. (which explains the deleted line in Dockerfile) (#3456) 2017-03-31 13:48:50 -07:00
snipe
265a896211 Bumped version 2017-02-22 22:38:33 -08:00
snipe
f7e4fca70d Add model_number to accessory search 2017-02-22 22:34:56 -08:00
snipe
bb4c443cd9 Added notes to custom report 2017-02-03 02:20:56 -08:00
snipe
7b1d2ee050 Fixed typo 2017-01-17 11:57:24 -08:00
snipe
b3f70a046f Don’t require superadmin for checkin and delete user 2017-01-17 09:19:14 -08:00
morph027
734e87f85f Installer fine tuning (#2993)
* used shellcheck to lint snipeit.sh

* do not depend on lsb-release command

* add lsb codename

* really use perms()

* more fixes

* quiet apt

* silent logging using log()

* start mysql if not running

* added curl to ubuntu

* added logfile to log function

* update apt index after adding mariadb repo

* fixed typo

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

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

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

If we're using a debian base image for sizing reasons, we may as well go the full distance and use debian-slim.
2017-01-10 16:22:06 -08:00
snipe
9fd3a9a82d Removed logging 2017-01-06 03:12:49 -08:00
snipe
a6e6991a2d Removed second number_format 2017-01-06 03:11:27 -08:00
snipe
93ba0717d8 Removed number_format 2017-01-06 03:02:38 -08:00
snipe
a8839e0ef4 Fixes #3104, #2914 and #2918 - auto-increment incorrectly generating next ID 2017-01-06 02:52:10 -08:00
snipe
3e4152c966 Bumped version 2017-01-06 00:04:26 -08:00
snipe
1bf34d73f5 Use correct authorize rule in middleware for user delete 2017-01-06 00:02:46 -08:00
snipe
d1e360d64d Fix logic to use gate instead of asking if superuser 2017-01-06 00:02:19 -08:00
snipe
3b5b19848c Added oauth keys to gitignore 2017-01-06 00:01:55 -08:00
snipe
93ba90e837 Merge remote-tracking branch 'origin/develop' 2016-12-12 19:24:00 -08:00
snipe
dd28c5709e Add action=“” to form (possible IE11 fix) 2016-12-12 19:23:41 -08:00
snipe
fc70d79a17 Merge remote-tracking branch 'origin/develop' 2016-12-12 19:07:07 -08:00
snipe
42fe481f71 Bumped hash 2016-12-12 19:06:36 -08:00
snipe
95f1a98b96 Removed extraneous closing label tags 2016-12-12 19:03:45 -08:00
snipe
6f1e0d6d9f Updated readme with security notice 2016-12-12 19:03:12 -08:00
snipe
ae66bba0f1 Fixes #3015 - increase size of state field in suppliers 2016-12-07 17:50:20 -08:00
snipe
32c5a258a7 Updated hash 2016-12-07 17:14:48 -08:00
snipe
e7ac860f77 Supress error if pagination isn’t set up on the server 2016-12-07 17:07:48 -08:00
snipe
899a991a3b Added package.json 2016-12-07 17:07:07 -08:00
snipe
f26d86dff2 Updated gulpfile 2016-12-07 17:06:48 -08:00
snipe
84317f7f50 Fixes #2990 - disabled autocomplete on login 2016-12-06 11:50:20 -08:00
snipe
65016a2383 Merge remote-tracking branch 'origin/develop' 2016-12-05 16:12:41 -08:00
snipe
eb48e5ed1c Bumped hash 2016-12-05 16:12:05 -08:00
snipe
dbcb2ccb46 Merge remote-tracking branch 'origin/develop' 2016-12-05 15:09:49 -08:00
Daniel Meltzer
927a12f78d Fix #2985. Missed in the field rename (#3014) 2016-12-05 15:09:14 -08:00
Brady Wetherington
dd52b4828c Make .gitignore and .gitkeep files permissions match their directories (#3018) 2016-12-05 15:08:37 -08:00
snipe
6273e313bc Set DB_SSL to false for config 2016-12-03 17:33:36 -08:00
snipe
2afcfcc87c Set DB_SSL to false for config 2016-12-03 17:32:44 -08:00
snipe
1afef9416a Merge remote-tracking branch 'origin/develop'
# Conflicts:
#	config/version.php
2016-12-03 17:15:02 -08:00
snipe
77685fd52b Bumped version 2016-12-03 17:13:09 -08:00
snipe
f532abebd4 Updated translations 2016-12-03 17:10:05 -08:00
Brady Wetherington
6f9a82f4ea On a succesful LDAP user-creation, we should return the $user, not (#3008)
just 'true'.
2016-12-01 15:54:13 -08:00
snipe
4049143ebf Bumped version 2016-12-01 06:11:03 -08:00
snipe
4df53bdf8d Merge remote-tracking branch 'origin/develop'
# Conflicts:
#	config/version.php
#	resources/views/account/view-assets.blade.php
2016-12-01 06:10:50 -08:00
snipe
d49a1ea304 More graceful error message if log doesn’t exist 2016-12-01 06:05:14 -08:00
snipe
521f4facd5 Bumped version 2016-12-01 05:56:24 -08:00
snipe
b4653dfc15 Ignore npm log 2016-12-01 05:55:29 -08:00
snipe
659d9c10ca Bumped hash 2016-12-01 05:54:21 -08:00
snipe
2ab0594530 Prevent errors if company support conflict prevents viewing the item 2016-12-01 05:54:14 -08:00
snipe
8a81b29901 Fixed missing closing angle bracket 2016-12-01 05:53:20 -08:00
snipe
93d9a6e4bb Ignore npm log 2016-12-01 05:52:50 -08:00
snipe
99e79a02d6 Revert "Halp! Stuck in pre-commit loop hell. :("
This reverts commit 47c77fe042.
2016-12-01 03:08:14 -08:00
snipe
47c77fe042 Halp! Stuck in pre-commit loop hell. :( 2016-12-01 03:07:47 -08:00
snipe
e42da293ee Updated version for pre-release 2016-12-01 03:07:21 -08:00
snipe
a2ffe77d55 Automatically updated version hash 2016-12-01 03:07:12 -08:00
snipe
a7a9f027fb Automatically updated version hash 2016-12-01 03:00:18 -08:00
snipe
e587b2dcee Automatically updated version hash 2016-12-01 03:00:02 -08:00
snipe
c3b4342df4 Automatically updated version hash 2016-12-01 02:59:17 -08:00
snipe
5a7ea0e908 Updated hash 2016-12-01 02:59:11 -08:00
snipe
59617cc7d3 Updated version in settings 2016-12-01 02:57:47 -08:00
snipe
1be22cf051 Improved versioning script 2016-12-01 02:53:41 -08:00
snipe
e62f3f9fb4 Bumped hash 2016-12-01 02:27:12 -08:00
snipe
7ccef51a4f Removed some dumb comments 2016-12-01 02:25:53 -08:00
snipe
4c418bf622 Remove unused $request variable 2016-12-01 02:13:00 -08:00
snipe
16cfdbaa93 Redirect the lost password success back to login 2016-12-01 02:04:43 -08:00
snipe
3f8f6ad981 Fixes #2995 - adds max login attempts/duration as .env option 2016-12-01 02:04:15 -08:00
snipe
d8d800bb7a Fixes #2997 - don’t include soft-deleted maintenances 2016-12-01 00:55:00 -08:00
snipe
5bca1ed2b6 Allow supression of debug warning for demo 2016-12-01 00:48:43 -08:00
snipe
68b9ffb908 Only allow login via LDAP if the user was already imported or created via LDAP 2016-12-01 00:29:45 -08:00
snipe
d03c167d3b Switch string to product key 2016-12-01 00:15:48 -08:00
snipe
2ec7c0bf1d Hide edit actions from asset sidebar if user cannot edit assets 2016-12-01 00:00:48 -08:00
snipe
7513c99dd0 Fixed supplier string in hardware view 2016-11-30 23:19:13 -08:00
snipe
6c366eb112 Fixes potential login issue if password syncing is set to true 2016-11-30 20:39:43 -08:00
snipe
820d37cabb Custom logging to only show debug info if the app is in debug mode
or if the user has overridden the APP_LOG_LEVEL in their env
2016-11-30 20:38:46 -08:00
snipe
b614470b21 Updated serial text to product key 2016-11-29 21:45:49 -08:00
snipe
ce056c39e5 Removed requirement for serial number
Some folks will use a license file instead
2016-11-29 14:06:33 -08:00
snipe
b6ffb8b3df Protect edit route as well 2016-11-29 13:40:00 -08:00
snipe
f5e100a6a5 Only allow asset files to be deleted, maintenances to be added if user has assets.edit permission 2016-11-29 13:37:45 -08:00
snipe
abcc01f5e0 More language string corrections 2016-11-29 12:48:00 -08:00
snipe
4dbe8fad30 More language string fixes 2016-11-29 08:46:33 -08:00
snipe
7bf1664b8f Allow XML mimetypes 2016-11-29 08:01:08 -08:00
snipe
92ace8582d Fixed notes column header language string 2016-11-29 07:57:02 -08:00
snipe
507040976a Fixed incorrect license field text strings 2016-11-29 07:52:00 -08:00
snipe
b0d8711002 Add .lic as possible license file type 2016-11-29 07:22:45 -08:00
snipe
227ac94aa2 Bumped version hash 2016-11-29 06:21:37 -08:00
snipe
53404f3d1c Fixes asset model clone 2016-11-29 06:16:52 -08:00
snipe
f605821143 Remove unneeded use statements 2016-11-29 06:14:33 -08:00
snipe
cab331f3f8 Link model name in category view 2016-11-29 06:14:20 -08:00
snipe
eb340b0fa9 Add fieldset to asset model listing 2016-11-29 06:06:52 -08:00
snipe
3acc4065ce Merge branch 'develop' of github.com:snipe/snipe-it into develop 2016-11-29 05:19:24 -08:00
snipe
2ce67e9443 Derp. 2016-11-29 05:19:18 -08:00
Daniel Meltzer
263f19bdad Fix error in partializing with creating an asset maintenance. (#2987) 2016-11-29 05:02:48 -08:00
snipe
4fc88f673d Only check if table exists if there is not a value for the static cache yet 2016-11-29 05:02:14 -08:00
snipe
c72954b671 Fixes #2959 - fixed error with custom fields not populating correctly 2016-11-29 01:59:18 -08:00
snipe
dbb2b62223 Fixed cranky Codacy result 2016-11-29 01:44:24 -08:00
snipe
7393f0bbea Fixes snipeSettings error if the user was created but the settings table isn’t populated yet 2016-11-29 01:20:51 -08:00
snipe
2603488bd6 Removed settings middlware
(Already handled via AppServiceProvider)
2016-11-29 01:19:52 -08:00
snipe
81a0e06c40 Automatically log the user in after user creation 2016-11-29 01:19:25 -08:00
snipe
0d6b160b61 Fix mail test script 2016-11-29 01:19:05 -08:00
snipe
16a24b7fb8 Use getSettings() to check for locale to take advantage of cached value 2016-11-29 00:21:58 -08:00
snipe
ba23952852 Add red banner if app is in production mode and debugging is turned on 2016-11-29 00:08:20 -08:00
snipe
4c08331c9d Get settings in middleware, makr available in views 2016-11-28 22:53:16 -08:00
snipe
cc943e22db Fixes #2970
Should probably override this later using the global settings variable
2016-11-28 22:38:11 -08:00
snipe
6bb5555a73 Fixes #2980 - enable MySQL SSL settings 2016-11-28 19:25:26 -08:00
Daniel Meltzer
3592bdb2e1 Assocate a locations asset with User, not log. (#2973)
This fixes an issue where locations could not be deleted if at any point
they had an associated log entry.  Fixes #2916
2016-11-24 12:48:22 -08:00
Daniel Meltzer
b8cbf0022e Log fixes (#2972)
* Make sure we set target_type when creating an accept asset log, and add a migration to fix older ones.

* On a declined log, we don't have an assigned user.

 Guard against this conditional (which realistically should never be hit?)
Should fix #2940

* Fix codacy issues with migration.
2016-11-24 12:48:14 -08:00
Brady Wetherington
dd3718489a Attempt to fix #2961. Also inadvertently added the ability to rename (#2974)
and delete custom fields, as well. Bonus!
2016-11-24 12:48:03 -08:00
Daniel Meltzer
7214920563 Update index.blade.php (#2963)
Asset maintences should be searchable.
2016-11-23 06:15:40 -08:00
Daniel Meltzer
8c549c47e4 Update bootstrap-table.blade.php (#2964)
Fix error when search is not passed through.
2016-11-23 05:56:08 -08:00
snipe
45c789021e Add employee number option to custom report 2016-11-23 05:17:54 -08:00
snipe
1d2ae84572 Fixes #2953 - re-adding the CoC 2016-11-21 18:51:42 -08:00
snipe
54dec2147c Merge branch 'develop' of github.com:snipe/snipe-it into develop 2016-11-21 18:40:38 -08:00
snipe
bc84f80e20 Check if sig_filename exists 2016-11-21 18:40:26 -08:00
Daniel Meltzer
ac9fd3b3bb Update LicensesController.php (#2948)
* Update LicensesController.php

Should fix #2939.  Cannot test at the moment, so please check :)

* Add delete tests.  Improve test item generation.

* Add relationship here.

* Fix some issues with seeding.
2016-11-20 19:59:57 -08:00
snipe
d8eb68af83 Merge branch 'hotfixes/accessory_model_number' into develop
# Conflicts:
#	resources/views/accessories/edit.blade.php
2016-11-17 20:01:01 -08:00
snipe
dcc000284f Add accessory model to accessories 2016-11-17 20:00:08 -08:00
snipe
d0d9d82579 Add model number to accessories 2016-11-17 19:57:53 -08:00
snipe
54848b5edf Added enum conversion 2016-11-17 16:56:08 -08:00
snipe
eb4562a28b Add enum conversation
Tho I don’t know why we need this. I don’t see any enums left in the DB structure.
2016-11-17 16:55:22 -08:00
snipe
e8f45555ff Make length match validation 2016-11-17 16:18:39 -08:00
snipe
554a6e4fd6 Make length match validation 2016-11-17 16:18:15 -08:00
snipe
7efe3a3207 Merge branch 'hotfixes/state_length' into develop 2016-11-17 16:16:47 -08:00
snipe
f77cb3d0f5 Increase DB size of state field in locations 2016-11-17 16:16:33 -08:00
Daniel Meltzer
55ccc000eb Fix loggable checkin (#2935)
* Log the user items are checked in from

This restores functionality that was lost in the port to loggable.
I'd still like to figure out a better term for the table, currently it says to, but I wonder if target is a better choice?

* Fix display of remaining seats on license view
2016-11-17 15:54:29 -08:00
snipe
19592814d9 Merge branch 'hotfixes/purchase_cost_standardized' into develop 2016-11-16 17:35:03 -08:00
snipe
5c70898dbf Derp. Not a string. 2016-11-16 17:32:25 -08:00
snipe
08c7701f17 Make purchase cost longer and more standardized 2016-11-16 17:31:11 -08:00
Daniel Meltzer
d722ed3823 Partialize forms (#2884)
* Consolidate edit form elements into reusable partials.

This is a large code change that doesn't do much immediately.  It
refactors all of the various edit.blade.php files to reference
standardized partials, so that they all reference the same base html
layout. This has the side effect of moving everything to the new fancy
"required" indicators, and making things look consistent.

In addition, I've gone ahead and renamed a few database fields.  We had
Assetmodel::modelno and Consumable::model_no, I've renamed both to
model_number.  We had items using ::note and ::notes, I've standardized
on ::notes.  Component used total_qty where consumables and accessories
used qty, so I've moved everything to qty (And fixed a few bugs in the
helper file in the process.

TODO includes looking at how/where to place the modal javascripts to
allow for on the fly creation from all places, rather than just the
asset page.

Rename assetmodel::modelno to model_number for clarity and consistency

Rename consumable::model_no to model_number for clarity and consistency

Rename assetmodel::note to notes for clarity and consistency

Port asset and assetmodel to new partials layout.  Adapt all code to the renamed model_number and notes database changes.  Fix some stying.

* Share a settings variable with all views.

* Allow editing the per_page setting.  We showed the value, but we never showed it on the edit page..

* use snipeSettings in all views instead of the long ugly path.

* War on partials. Centralize all bootstrap table javascript

* Use model_number instead of modelno in importer

* Codacy fix.

* More unification/deduplication.  Create an edit form template layout that we use as the base for all edit forms.  This gives the same interface for editing everything and makes the edit.blade.* files much easier to read.

* Use a ViewComposer instead of sharing the variable directly.  Fixes artisan optimize trying to hit the db--which ruins new installs

* Fix DB seeder.

* Base sql dump and csv's to import data from for tests.

* Start some functional tests for creating items.

* Add functional tests for all create methods.  Still need to do tests for edits, deletes, and lots of other things

* Improvements to functional tests.

Use the built in DB seeding mechanism instead of doing it ourselves.
Break the tests into multiple units, rather than testing everything in
each function.

* Some improvements to acceptance tests.

Make sure we're only looking at the "trs" within the bootstrap table.
Creation of assets is now tested at the functional level (and is faster)
so ignore it here.

I'm testing acceptance tests with the
IMPORT_{ASSETS,ACCESSORIES,CONSUMABLES}.csv in the tests/_data folder
imported.

* A few things to make acceptance tests work.  Add a name to the companies table, and make the locations table have the correct name

* Use a .env.tests file for testing functional and unit to allow a separate database.

* Add functional tests for compoents, groups, and licenses.

* Now that the config is in the functional.yml, this just confuses things.

* Start some functional tests for creating items.

* Add functional tests for all create methods.  Still need to do tests for edits, deletes, and lots of other things

* Improvements to functional tests.

Use the built in DB seeding mechanism instead of doing it ourselves.
Break the tests into multiple units, rather than testing everything in
each function.

* Some improvements to acceptance tests.

Make sure we're only looking at the "trs" within the bootstrap table.
Creation of assets is now tested at the functional level (and is faster)
so ignore it here.

I'm testing acceptance tests with the
IMPORT_{ASSETS,ACCESSORIES,CONSUMABLES}.csv in the tests/_data folder
imported.

* update db dump

* Update tests to new reality

* env for the test setup

* only load the database at beginning of tests, not between each Functional test.

* Fix a miss from renaming note to notes.

* Set Termination date when creating an asset.  It was only set on edit.

* Rename serial_number to serial in components for consistency.

* Update validation rules to match limits in database.  Currently we just accepted the values and they were truncated when adding to DB.

* Much more detailed functional testing of creating items.  This checks to make sure all values on form have been successfully persisted to database.
2016-11-16 16:56:57 -08:00
snipe
84e06f4642 Add postal code to locations listing 2016-11-16 08:22:54 -08:00
snipe
2ef4b58a8c Bumped version 2016-11-15 17:49:24 -08:00
snipe
91caba05b7 Merge remote-tracking branch 'origin/develop'
# Conflicts:
#	Dockerfile
#	resources/views/auth/login.blade.php
2016-11-15 17:46:05 -08:00
snipe
37a6599978 Adds expected checkin to custom reports 2016-11-15 01:55:27 -08:00
snipe
cbabcb9197 Fixes #2875 - use leftJoin so as to not filter out unassigned assets when sorting by assigned 2016-11-11 20:50:10 -08:00
snipe
369715b7c7 Starter text search scope for activity report
(This will be messy)
2016-11-11 20:30:26 -08:00
snipe
e74a0171a6 Fixes dockerfile for persistent assets 2016-11-11 20:30:04 -08:00
snipe
b854689d3d Urlencode username in case it has spaces 2016-11-11 20:09:22 -08:00
snipe
1543c03624 Removed stray foo 2016-11-11 20:09:07 -08:00
snipe
7667fca691 Fixes #2894 - set whether or not the user was originally a superuser 2016-11-11 19:48:39 -08:00
snipe
9db28cf6d6 Fixed dumb indenting 2016-11-11 19:46:25 -08:00
snipe
2ddee9b44c Fixes #2906 - adds manufacturer searching to licenses 2016-11-11 19:46:18 -08:00
snipe
49ce630bb8 Make company name sortable 2016-11-11 19:33:13 -08:00
fvleminckx
10d37abe6c fix: persistency in docker of assets, barcodes, logo (#2902) 2016-11-11 19:24:16 -08:00
snipe
2f05b83e0b Fixes #2912 - Reordering of custom fields now saving correctly 2016-11-11 18:33:59 -08:00
Daniel Meltzer
f4fc783026 Check for setup to have completed before running the 2fa middleware. Otherwise new installs fail (#2885) 2016-11-06 18:08:13 +01:00
itsupportcmsukorg
96ad5fb77b Add back forgotten filename to Action Logs with a migration (#2865)
This fixes the issue where the filename wasn't migrated when people who upgraded from 3.4 to 3.5.
This only updates the new log's "filename" field where it's missing a value, so no danger of overwriting anything.

Commit 140bac2 already fixed it for new upgraders (see pull #2854) but didn't help anyone who had already upgraded.
2016-11-02 01:17:42 -07:00
snipe
4747a4c03f Added urlencode to site name 2016-10-31 22:34:57 -07:00
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
62f5a1b2c7 Tidy up login form 2016-10-29 06:44: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
46b00b6fb6 Merge remote-tracking branch 'origin/develop' 2016-10-27 22:17:52 -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
0f47ddbeb1 Merge remote-tracking branch 'origin/develop' 2016-10-27 21:40:06 -07:00
snipe
066d947f1a Fixes #2535 - increased varachar limit to 2048 for serial 2016-10-27 21:39:46 -07:00
snipe
683b3bcdc1 Merge remote-tracking branch 'origin/develop' 2016-10-27 15:34:03 -07:00
snipe
a929b635ff Fixes #2809 - adds serial number to components 2016-10-27 15:33:48 -07:00
snipe
d7296462ac Merge remote-tracking branch 'origin/develop' 2016-10-27 15:03:03 -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
2f72d97f24 Merge remote-tracking branch 'origin/develop' 2016-10-27 14:33:24 -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
61ecbf91bc Merge remote-tracking branch 'origin/develop' 2016-10-26 11:28:14 -07:00
snipe
691f9b621e Fixes #2821 2016-10-26 11:27:37 -07:00
snipe
52b6298098 Merge remote-tracking branch 'origin/develop' 2016-10-26 11:23:03 -07:00
snipe
ccb844acd6 Fixed #2800 - use DBTablePrefix() for raw queries 2016-10-26 11:21:36 -07:00
snipe
a0a6a23232 Merge remote-tracking branch 'origin/develop' 2016-10-26 10:32:50 -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
snipe
ad1d6529a7 Merge branch 'master' of github.com:snipe/snipe-it 2016-10-26 10:09:59 -07:00
Daniel Meltzer
7790f9e91f Fix #2813 (#2819)
Looks like a copypasta miss.  Should fix the exception thrown in #2813.
2016-10-26 10:01:24 -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
1267 changed files with 19151 additions and 11226 deletions

View File

@@ -20,6 +20,16 @@ DB_PASSWORD=null
DB_PREFIX=null
DB_DUMP_PATH='/usr/bin'
# --------------------------------------------
# OPTIONAL: SSL DATABASE SETTINGS
# --------------------------------------------
DB_SSL=false
DB_SSL_KEY_PATH=null
DB_SSL_CERT_PATH=null
DB_SSL_CA_PATH=null
DB_SSL_CIPHER=null
# --------------------------------------------
# REQUIRED: OUTGOING MAIL SERVER SETTINGS
# --------------------------------------------
@@ -31,6 +41,8 @@ MAIL_PASSWORD=YOURPASSWORD
MAIL_ENCRYPTION=null
MAIL_FROM_ADDR=you@example.com
MAIL_FROM_NAME='Snipe-IT'
MAIL_REPLYTO_ADDR=you@example.com
MAIL_REPLYTO_NAME='Snipe-IT'
# --------------------------------------------
@@ -67,6 +79,11 @@ AWS_KEY=null
AWS_REGION=null
AWS_BUCKET=null
# --------------------------------------------
# OPTIONAL: LOGIN THROTTLING
# --------------------------------------------
LOGIN_MAX_ATTEMPTS=5
LOGIN_LOCKOUT_DURATION=60
# --------------------------------------------
# OPTIONAL: MISC

9
.env.tests Normal file
View File

@@ -0,0 +1,9 @@
APP_ENV=local
APP_DEBUG=true
APP_URL=http://snipe-it.localapp
DB_CONNECTION=mysql
DB_HOST=localhost
DB_DATABASE=snipeittests
DB_USERNAME=snipeit
DB_PASSWORD=snipe
APP_KEY=base64:tu9NRh/a6+dCXBDGvg0Gv/0TcABnFsbT4AKxrr8mwQo=

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.

3
.gitignore vendored
View File

@@ -37,3 +37,6 @@ storage/private_uploads/users/*
tests/_data/scenarios
tests/_output/*
tests/_support/_generated/*
/npm-debug.log
/storage/oauth-private.key
/storage/oauth-public.key

74
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,74 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at [INSERT EMAIL ADDRESS]. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

View File

@@ -1,4 +1,4 @@
FROM ubuntu:trusty
FROM debian:jessie-slim
MAINTAINER Brady Wetherington <uberbrady@gmail.com>
RUN apt-get update && apt-get install -y \
@@ -13,7 +13,9 @@ patch \
curl \
vim \
git \
mysql-client
mysql-client \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
RUN php5enmod mcrypt
RUN php5enmod gd
@@ -54,12 +56,9 @@ COPY docker/docker.env /var/www/html/.env
RUN chown -R docker /var/www/html
RUN \
rm -r "/var/www/html/storage/private_uploads" && ln -fs "/var/lib/snipeit/data/private_uploads" "/var/www/html/storage/private_uploads" && \
mkdir -p "/var/www/html/public/uploads" && \
rm -rf "/var/www/html/public/uploads/avatars" && ln -fs "/var/lib/snipeit/data/uploads/avatars" "/var/www/html/public/uploads/avatars" && \
rm -rf "/var/www/html/public/uploads/models" && ln -fs "/var/lib/snipeit/data/uploads/models" "/var/www/html/public/uploads/models" && \
rm -rf "/var/www/html/public/uploads/suppliers" && ln -fs "/var/lib/snipeit/data/uploads/suppliers" "/var/www/html/public/uploads/suppliers" && \
rm -r "/var/www/html/storage/app/backups" && ln -fs "/var/lib/snipeit/dumps" "/var/www/html/storage/app/backups"
rm -r "/var/www/html/storage/private_uploads" && ln -fs "/var/lib/snipeit/data/private_uploads" "/var/www/html/storage/private_uploads" \
&& rm -rf "/var/www/html/public/uploads" && ln -fs "/var/lib/snipeit/data/uploads" "/var/www/html/public/uploads" \
&& rm -r "/var/www/html/storage/app/backups" && ln -fs "/var/lib/snipeit/dumps" "/var/www/html/storage/app/backups"
############## DEPENDENCIES via COMPOSER ###################

View File

@@ -53,3 +53,7 @@ Please see the documentation on [contributing and developing for Snipe-IT](https
Please note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.
### Security
To report a security vulnerability, please email security@snipeitapp.com instead of using the issue tracker.

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

@@ -68,7 +68,7 @@ class ObjectImportCommand extends Command
$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);
@@ -100,7 +100,7 @@ class ObjectImportCommand extends Command
$this->locations = Location::All(['name', 'id']);
$this->categories = Category::All(['name', 'category_type', 'id']);
$this->manufacturers = Manufacturer::All(['name', 'id']);
$this->asset_models = AssetModel::All(['name','modelno','category_id','manufacturer_id', 'id']);
$this->asset_models = AssetModel::All(['name','model_number','category_id','manufacturer_id', 'id']);
$this->companies = Company::All(['name', 'id']);
$this->status_labels = Statuslabel::All(['name', 'id']);
$this->suppliers = Supplier::All(['name', 'id']);
@@ -138,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");
@@ -162,6 +162,7 @@ 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);
@@ -170,12 +171,22 @@ class ObjectImportCommand extends Command
$item["user"] = $this->createOrFetchUser($row, $password);
$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);
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);
}
$item["status_label"] = $this->createOrFetchStatusLabel($item_status_name);
if (!($this->updating && empty($item_status_name))) {
$item["status_label"] = $this->createOrFetchStatusLabel($item_status_name);
}
switch ($item_type) {
case "asset":
@@ -236,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;
@@ -322,7 +333,9 @@ 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)) {
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)) {
@@ -331,27 +344,39 @@ 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->model_number == $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->model_number = $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 {
@@ -498,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;
}
}
@@ -522,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')) {
@@ -602,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());
@@ -768,8 +789,17 @@ 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']);
@@ -778,13 +808,13 @@ class ObjectImportCommand extends Command
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;
}
if (!$editingAsset) {
@@ -819,7 +849,7 @@ class ObjectImportCommand extends Command
$asset->warranty_months = $asset_warranty_months;
}
if ($asset_model) {
if (isset($asset_model)) {
$asset->model_id = $asset_model->id;
}
@@ -827,21 +857,21 @@ class ObjectImportCommand extends Command
$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');
if (!empty($status_id)) {
if (isset($status_id)) {
$asset->status_id = $status_id;
}
if ($item["company"]) {
if (isset($item["company"])) {
$asset->company_id = $item["company"]->id;
}
if ($item["order_number"]) {
$asset->order_number = $item["order_number"];
}
if ($supplier) {
if (isset($supplier)) {
$asset->supplier_id = $supplier->id;
}
if ($item["notes"]) {
@@ -856,6 +886,7 @@ class ObjectImportCommand extends Command
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());
@@ -910,17 +941,17 @@ class ObjectImportCommand extends Command
$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;
}
if (!empty($item["order_number"])) {
$accessory->order_number = $item["order_number"];
}
if ($item["category"]) {
if (isset($item["category"])) {
$accessory->category_id = $item["category"]->id;
}
@@ -941,6 +972,7 @@ class ObjectImportCommand extends Command
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');
@@ -995,17 +1027,17 @@ class ObjectImportCommand extends Command
if (!empty($item["purchase_cost"])) {
$consumable->purchase_cost = Helper::ParseFloat($item["purchase_cost"]);
}
if ($item["location"]) {
if (isset($item["location"])) {
$consumable->location_id = $item["location"]->id;
}
$consumable->user_id = $this->option('user_id');
if ($item["company"]) {
if (isset($item["company"])) {
$consumable->company_id = $item["company"]->id;
}
if (!empty($item["order_number"])) {
$consumable->order_number = $item["order_number"];
}
if ($item["category"]) {
if (isset($item["category"])) {
$consumable->category_id = $item["category"]->id;
}
// TODO:Implement
@@ -1025,6 +1057,7 @@ class ObjectImportCommand extends Command
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');

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

@@ -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

@@ -40,20 +40,19 @@ class Versioning extends Command
*/
public function fire()
{
// Path to the file containing your version
// This will be overwritten everything you commit a message
$versionFile = 'config/version.php';
$hash_version = str_replace("\n",'',shell_exec('git describe --tags'));
// The git's output
// get the argument passed in the git command
$hash_version = $this->argument('app_version');
$version = explode('-', $hash_version);
// discard the commit hash
$version = explode('-', $hash_version);
$realVersion = $version[0];
// save the version array to a variable
$array = var_export(array('app_version' => $realVersion,'hash_version' => $hash_version), true);
$array = var_export(
array(
'app_version' => $version[0],
'build_version' => $version[1],
'hash_version' => $version[2],
'full_hash' => $hash_version),
true);
// Construct our file content
@@ -64,7 +63,7 @@ CON;
// And finally write the file and output the current version
\File::put($versionFile, $content);
$this->line('Setting version: '. \config('version.latest'));
$this->line('Setting version: '. config('version.app_version').' build '.config('version.build_version').' ('.config('version.hash_version').')');
}
/**
@@ -75,7 +74,6 @@ CON;
protected function getArguments()
{
return array(
array('app_version', InputArgument::REQUIRED, 'version number is required.'),
);
}

View File

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

View File

@@ -20,15 +20,17 @@ 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();
@@ -38,17 +40,17 @@ class Helper
}
// This doesn't do anything yet
public static function parseEmailList($emails)
{
$emails_array = explode(',', $emails);
return array_walk($emails_array, 'trim_value');
}
/**
* 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)
{
// 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
if (is_numeric($cost)) {
return number_format($cost, 2, '.', '');
}
@@ -56,13 +58,15 @@ class Helper
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 = [
@@ -80,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 = [
@@ -100,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);
@@ -111,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();
@@ -121,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')
@@ -130,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')
@@ -141,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')
@@ -149,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')
@@ -156,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')
@@ -163,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')) +
@@ -171,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')) +
@@ -188,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')
@@ -195,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()
@@ -213,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')
@@ -221,20 +331,40 @@ 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);
@@ -242,6 +372,13 @@ class Helper
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') {
@@ -257,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';
@@ -268,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();
@@ -285,8 +434,8 @@ class Helper
foreach ($consumables as $consumable) {
$avail = $consumable->numRemaining();
if ($avail < ($consumable->min_amt) + \App\Models\Setting::getSettings()->alert_threshold) {
if ($consumable->total_qty > 0) {
$percent = number_format((($consumable->numRemaining() / $consumable->total_qty) * 100), 0);
if ($consumable->qty > 0) {
$percent = number_format((($consumable->numRemaining() / $consumable->qty) * 100), 0);
} else {
$percent = 100;
}
@@ -307,8 +456,8 @@ class Helper
$avail = $accessory->numRemaining();
if ($avail < ($accessory->min_amt) + \App\Models\Setting::getSettings()->alert_threshold) {
if ($accessory->total_qty > 0) {
$percent = number_format((($accessory->numRemaining() / $accessory->total_qty) * 100), 0);
if ($accessory->qty > 0) {
$percent = number_format((($accessory->numRemaining() / $accessory->qty) * 100), 0);
} else {
$percent = 100;
}
@@ -327,8 +476,8 @@ class Helper
foreach ($components as $component) {
$avail = $component->numRemaining();
if ($avail < ($component->min_amt) + \App\Models\Setting::getSettings()->alert_threshold) {
if ($component->total_qty > 0) {
$percent = number_format((($component->numRemaining() / $component->total_qty) * 100), 0);
if ($component->qty > 0) {
$percent = number_format((($component->numRemaining() / $component->qty) * 100), 0);
} else {
$percent = 100;
}
@@ -352,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);
@@ -478,6 +634,18 @@ class Helper
}
/**
* 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)) {
@@ -495,4 +663,26 @@ class Helper
}
/**
* 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

@@ -7,19 +7,19 @@ use App\Models\Actionlog;
use App\Models\Company;
use App\Models\Setting;
use App\Models\User;
use Auth;
use Carbon\Carbon;
use Config;
use DB;
use Gate;
use Input;
use Lang;
use Mail;
use Redirect;
use Request;
use Slack;
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.
@@ -54,7 +54,7 @@ class AccessoriesController extends Controller
{
// Show the page
return View::make('accessories/edit')
->with('accessory', new Accessory)
->with('item', new Accessory)
->with('category_list', Helper::categoryList('accessory'))
->with('company_list', Helper::companyList())
->with('location_list', Helper::locationsList())
@@ -82,6 +82,7 @@ class AccessoriesController extends Controller
$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'));
$accessory->model_number = e(Input::get('model_number'));
if (e(Input::get('purchase_date')) == '') {
$accessory->purchase_date = null;
@@ -92,7 +93,7 @@ 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'));
@@ -100,6 +101,7 @@ class AccessoriesController extends Controller
// 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'));
}
@@ -118,14 +120,14 @@ class AccessoriesController extends Controller
public function getEdit(Request $request, $accessoryId = null)
{
// Check if the accessory exists
if (is_null($accessory = Accessory::find($accessoryId))) {
if (is_null($item = Accessory::find($accessoryId))) {
// Redirect to the blogs management page
return redirect()->to('admin/accessories')->with('error', trans('admin/accessories/message.does_not_exist'));
} elseif (!Company::isCurrentUserHasAccess($accessory)) {
} elseif (!Company::isCurrentUserHasAccess($item)) {
return redirect()->to('admin/accessories')->with('error', trans('general.insufficient_permissions'));
}
return View::make('accessories/edit', compact('accessory'))
return View::make('accessories/edit', compact('item'))
->with('category_list', Helper::categoryList('accessory'))
->with('company_list', Helper::companyList())
->with('location_list', Helper::locationsList())
@@ -163,6 +165,7 @@ class AccessoriesController extends Controller
$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'));
$accessory->model_number = e(Input::get('model_number'));
if (e(Input::get('purchase_date')) == '') {
$accessory->purchase_date = null;
@@ -309,14 +312,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')));
@@ -340,11 +336,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');
@@ -355,9 +351,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;
@@ -375,7 +368,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'));
});
}
@@ -435,21 +429,14 @@ 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);
$return_to = e($accessory_user->assigned_to);
$logaction = $accessory->logCheckin(User::find($return_to), e(Input::get('note')));
$admin_user = Auth::user();
// 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) {
@@ -469,7 +456,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:',
@@ -485,9 +472,6 @@ class AccessoriesController extends Controller
}
$log = $logaction->logaction('checkin from');
if (!is_null($accessory_user->assigned_to)) {
$user = User::find($accessory_user->assigned_to);
}
@@ -503,7 +487,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'));
});
}
@@ -547,9 +532,11 @@ class AccessoriesController extends Controller
**/
public function getDatatable(Request $request)
{
$accessories = Company::scopeCompanyables(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')));
}
@@ -567,7 +554,7 @@ class AccessoriesController extends Controller
}
$allowed_columns = ['name','min_amt','order_number','purchase_date','purchase_cost','companyName','category'];
$allowed_columns = ['name','min_amt','order_number','purchase_date','purchase_cost','companyName','category','model_number'];
$order = Input::get('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array(Input::get('sort'), $allowed_columns) ? e(Input::get('sort')) : 'created_at';
@@ -609,6 +596,7 @@ class AccessoriesController extends Controller
$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) : '',
'model_number' => e($accessory->model_number),
'qty' => e($accessory->qty),
'order_number' => e($accessory->order_number),
'min_amt' => e($accessory->min_amt),

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

@@ -21,6 +21,7 @@ use App\Models\Setting;
use App\Models\Asset;
use App\Helpers\Helper;
use Auth;
use Gate;
/**
* This controller handles all actions related to Asset Maintenance for
@@ -75,8 +76,7 @@ class AssetMaintenancesController extends Controller
*/
public function getDatatable()
{
$maintenances = AssetMaintenance::with('asset', 'supplier', 'asset.company','admin')
->withTrashed();
$maintenances = AssetMaintenance::with('asset', 'supplier', 'asset.company','admin');
if (Input::has('search')) {
$maintenances = $maintenances->TextSearch(e(Input::get('search')));
@@ -119,8 +119,12 @@ class AssetMaintenancesController extends Controller
$settings = Setting::getSettings();
foreach ($maintenances as $maintenance) {
$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>';
$actions = '';
if (Gate::allows('assets.edit')) {
$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) && (isset($maintenance->asset)) && ($maintenance->asset->assetloc) && ($maintenance->asset->assetloc->currency!='')) {
$maintenance_cost = $maintenance->asset->assetloc->currency.$maintenance->cost;
@@ -141,7 +145,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' => ($maintenance->asset) ? $maintenance->asset->company->name : ''
'companyName' => ($maintenance->asset->company) ? $maintenance->asset->company->name : ''
);
}
@@ -178,7 +182,7 @@ class AssetMaintenancesController extends Controller
->with('selectedAsset', $selectedAsset)
->with('supplier_list', $supplier_list)
->with('assetMaintenanceType', $assetMaintenanceType)
->with('assetMaintenance', new AssetMaintenance);
->with('item', new AssetMaintenance);
}
/**
@@ -215,7 +219,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')) == '') {
@@ -317,7 +321,7 @@ class AssetMaintenancesController extends Controller
->with('selectedAsset', null)
->with('supplier_list', $supplier_list)
->with('assetMaintenanceType', $assetMaintenanceType)
->with('assetMaintenance', $assetMaintenance);
->with('item', $assetMaintenance);
}
@@ -363,7 +367,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

@@ -6,11 +6,8 @@ use Input;
use Lang;
use App\Models\AssetModel;
use Redirect;
use App\Models\Setting;
use Auth;
use DB;
use App\Models\Depreciation;
use App\Models\Manufacturer;
use Str;
use Validator;
use View;
@@ -62,7 +59,7 @@ class AssetModelsController extends Controller
->with('category_list', $category_list)
->with('depreciation_list', $depreciation_list)
->with('manufacturer_list', $manufacturer_list)
->with('model', new AssetModel);
->with('item', new AssetModel);
}
@@ -92,19 +89,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->model_number = e(Input::get('model_number'));
$model->manufacturer_id = e(Input::get('manufacturer_id'));
$model->category_id = e(Input::get('category_id'));
$model->notes = e(Input::get('notes'));
$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,15 +138,15 @@ 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'));
$model->category_id = e(Input::get('category_id'));
$model->modelno = e(Input::get('modelno'));
$model->model_number = e(Input::get('model_number'));
$model->user_id = Auth::user()->id;
$model->note = e(Input::get('note'));
$model->eol=0;
$model->notes = e(Input::get('notes'));
$model->eol= null;
if (Input::get('fieldset_id')=='') {
$model->fieldset_id = null;
@@ -176,7 +173,7 @@ class AssetModelsController extends Controller
public function getEdit($modelId = null)
{
// Check if the model exists
if (is_null($model = AssetModel::find($modelId))) {
if (is_null($item = AssetModel::find($modelId))) {
// Redirect to the model management page
return redirect()->to('assets/models')->with('error', trans('admin/models/message.does_not_exist'));
}
@@ -184,7 +181,8 @@ class AssetModelsController extends Controller
$depreciation_list = Helper::depreciationList();
$manufacturer_list = Helper::manufacturerList();
$category_list = Helper::categoryList('asset');
$view = View::make('models/edit', compact('model'));
$view = View::make('models/edit', compact('item'));
$view->with('category_list', $category_list);
$view->with('depreciation_list', $depreciation_list);
$view->with('manufacturer_list', $manufacturer_list);
@@ -217,17 +215,19 @@ class AssetModelsController extends Controller
}
if (e(Input::get('eol')) == '') {
$model->eol = 0;
$model->eol = null;
} else {
$model->eol = e(Input::get('eol'));
}
// Update the model data
$model->name = e(Input::get('name'));
$model->modelno = e(Input::get('modelno'));
$model->model_number = e(Input::get('model_number'));
$model->manufacturer_id = e(Input::get('manufacturer_id'));
$model->category_id = e(Input::get('category_id'));
$model->note = e(Input::get('note'));
$model->notes = e(Input::get('notes'));
$model->requestable = Input::has('requestable');
if (Input::get('custom_fieldset')=='') {
$model->fieldset_id = null;
} else {
@@ -378,7 +378,7 @@ class AssetModelsController extends Controller
$view->with('category_list', $category_list);
$view->with('depreciation_list', $depreciation_list);
$view->with('manufacturer_list', $manufacturer_list);
$view->with('model', $model);
$view->with('item', $model);
$view->with('clone_model', $model_to_clone);
return $view;
@@ -395,7 +395,7 @@ class AssetModelsController extends Controller
*/
public function getCustomFields($modelId)
{
$model=AssetModel::find($modelId);
$model = AssetModel::find($modelId);
return View::make("models.custom_fields_form")->with("model", $model);
}
@@ -413,7 +413,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':
@@ -439,7 +439,7 @@ class AssetModelsController extends Controller
}
$allowed_columns = ['id','name','modelno'];
$allowed_columns = ['id','name','model_number'];
$order = Input::get('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array(Input::get('sort'), $allowed_columns) ? e(Input::get('sort')) : 'created_at';
@@ -462,12 +462,13 @@ class AssetModelsController extends Controller
'manufacturer' => (string)link_to('/admin/settings/manufacturers/'.$model->manufacturer->id.'/view', $model->manufacturer->name),
'name' => (string)link_to('/hardware/models/'.$model->id.'/view', $model->name),
'image' => ($model->image!='') ? '<img src="'.config('app.url').'/uploads/models/'.$model->image.'" height=50 width=50>' : '',
'modelnumber' => $model->modelno,
'modelnumber' => $model->model_number,
'numassets' => $model->assets->count(),
'depreciation' => (($model->depreciation)&&($model->depreciation->id > 0)) ? $model->depreciation->name.' ('.$model->depreciation->months.')' : trans('general.no_depreciation'),
'category' => ($model->category) ? $model->category->name : '',
'depreciation' => (($model->depreciation) && ($model->depreciation->id > 0)) ? $model->depreciation->name.' ('.$model->depreciation->months.')' : trans('general.no_depreciation'),
'category' => ($model->category) ? (string)link_to('admin/settings/categories/'.$model->category->id.'/view', $model->category->name) : '',
'eol' => ($model->eol) ? $model->eol.' '.trans('general.months') : '',
'note' => $model->getNote(),
'note' => $model->getNote(),
'fieldset' => ($model->fieldset) ? (string)link_to('admin/custom_fields/'.$model->fieldset->id, $model->fieldset->name) : '',
'actions' => $actions
);
}
@@ -488,7 +489,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

@@ -124,7 +124,7 @@ class AssetsController extends Controller
$view->with('statuslabel_list', $statuslabel_list);
$view->with('assigned_to', $assigned_to);
$view->with('location_list', $location_list);
$view->with('asset', new Asset);
$view->with('item', new Asset);
$view->with('manufacturer', $manufacturer_list);
$view->with('category', $category_list);
$view->with('statuslabel_types', $statuslabel_types);
@@ -178,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')) == '') {
@@ -231,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 {
@@ -264,10 +264,10 @@ class AssetsController extends Controller
// Was the asset created?
if ($asset->save()) {
$asset->logCreate();
if (Input::get('assigned_to')!='') {
$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')));
$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'));
@@ -288,12 +288,12 @@ class AssetsController extends Controller
*/
public function getEdit($assetId = null)
{
// Check if the asset exists
if (!$asset = Asset::find($assetId)) {
if (!$item = Asset::find($assetId)) {
// Redirect to the asset management page
return redirect()->to('hardware')->with('error', trans('admin/hardware/message.does_not_exist'));
} elseif (!Company::isCurrentUserHasAccess($asset)) {
} elseif (!Company::isCurrentUserHasAccess($item)) {
return redirect()->to('hardware')->with('error', trans('general.insufficient_permissions'));
}
@@ -308,7 +308,7 @@ class AssetsController extends Controller
$assigned_to = Helper::usersList();
$statuslabel_types =Helper::statusTypeList();
return View::make('hardware/edit', compact('asset'))
return View::make('hardware/edit', compact('item'))
->with('model_list', $model_list)
->with('supplier_list', $supplier_list)
->with('company_list', $company_list)
@@ -354,7 +354,7 @@ class AssetsController extends Controller
}
if ($request->has('purchase_cost')) {
$asset->purchase_cost = e(Helper::formatCurrencyOutput($request->input('purchase_cost')));
$asset->purchase_cost = Helper::ParseFloat(e($request->input('purchase_cost')));
} else {
$asset->purchase_cost = null;
}
@@ -407,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;
@@ -659,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:',
@@ -686,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'));
});
}
@@ -839,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)) {
@@ -1037,7 +1038,7 @@ class AssetsController extends Controller
->with('statuslabel_list', $statuslabel_list)
->with('statuslabel_types', $statuslabel_types)
->with('assigned_to', $assigned_to)
->with('asset', $asset)
->with('item', $asset)
->with('location_list', $location_list)
->with('manufacturer', $manufacturer_list)
->with('category', $category_list)
@@ -1086,6 +1087,8 @@ class AssetsController extends Controller
$results = $csv->fetchAssoc();
$item = array();
$status = array();
$status['error'] = array();
$status['success'] = array();
foreach($results as $row) {
@@ -1105,74 +1108,79 @@ class AssetsController extends Controller
$item[$asset_tag][$batch_counter]['name'] = Helper::array_smart_fetch($row, "name");
$item[$asset_tag][$batch_counter]['email'] = Helper::array_smart_fetch($row, "email");
$asset = Asset::where('asset_tag','=',$asset_tag)->first();
$item[$asset_tag][$batch_counter]['asset_id'] = $asset->id;
if ($asset = Asset::where('asset_tag','=',$asset_tag)->first()) {
$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'];
$item[$asset_tag][$batch_counter]['asset_id'] = $asset->id;
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'];
}
$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_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;
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'];
}
}
// A matching user was found
if ($user = $user->first()) {
$item[$asset_tag][$batch_counter]['checkedout_to'] = $user->id;
$status['success'][] = 'Found user '.Helper::array_smart_fetch($row, "name").$user_query;
if ($asset) {
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(
'asset_id' => $asset->id,
'asset_type' => 'hardware',
'user_id' => Auth::user()->id,
'note' => 'Checkout imported by '.Auth::user()->fullName().' from history importer',
'checkedout_to' => $item[$asset_tag][$batch_counter]['user_id'],
'created_at' => $item[$asset_tag][$batch_counter]['checkout_date'],
'action_type' => 'checkout'
'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;
$asset->save();
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 {
$status['error'][] = 'Asset does not exist so no checkin log was created.';
$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]['checkedout_to'] = null;
$status['error'][] = 'No matching user for '.Helper::array_smart_fetch($row, "name");
$item[$asset_tag][$batch_counter]['asset_id'] = null;
$status['error'][]['asset'][$asset_tag]['msg'] = 'Asset does not exist so no match was attempted.';
}
}
}
@@ -1183,18 +1191,18 @@ class AssetsController extends Controller
$next = $x + 1;
// Only do this if a matching user was found
if ($asset_batch[$x]['checkedout_to']!='') {
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(
'asset_id' => $asset_batch[$x]['asset_id'],
'asset_type' => 'hardware',
'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',
'checkedout_to' => null,
'target_id' => null,
'created_at' => $checkin_date,
'action_type' => 'checkin'
)
@@ -1272,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'));
@@ -1423,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') {
@@ -1491,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')) {
@@ -1537,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')) {
@@ -1587,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')
@@ -1595,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');
@@ -1676,10 +1677,6 @@ class AssetsController extends Controller
case 'Deployed':
$assets->Deployed();
break;
default:
$assets->NotArchived();
break;
}
if ($request->has('status_id')) {
@@ -1801,10 +1798,10 @@ class AssetsController extends Controller
'asset_tag' => '<a title="'.e($asset->asset_tag).'" href="hardware/'.$asset->id.'/view">'.e($asset->asset_tag).'</a>',
'serial' => e($asset->serial),
'model' => ($asset->model) ? (string)link_to('/hardware/models/'.$asset->model->id.'/view', e($asset->model->name)) : 'No model',
'model_number' => ($asset->model && $asset->model->modelno) ? (string)$asset->model->modelno : '',
'model_number' => ($asset->model && $asset->model->model_number) ? (string)$asset->model->model_number : '',
'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() : '',
@@ -1843,7 +1840,13 @@ class AssetsController extends Controller
}
}
$rows[]=$row;
if (($request->has('report')) && ($request->get('report')=='true')) {
$rows[]= Helper::stripTagsFromJSON($row);
} else {
$rows[]= $row;
}
}
$data = array('total'=>$assetCount, 'rows'=>$rows);
@@ -1857,12 +1860,12 @@ class AssetsController extends Controller
$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)
{
@@ -1872,31 +1875,31 @@ class AssetsController extends Controller
$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;
@@ -1904,12 +1907,12 @@ class AssetsController extends Controller
}
}
});
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

@@ -5,6 +5,7 @@ namespace App\Http\Controllers\Auth;
use Validator;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
use App\Models\Setting;
use App\Models\Ldap;
use App\Models\User;
@@ -15,6 +16,7 @@ use Input;
use Redirect;
use Log;
use View;
use PragmaRX\Google2FA\Google2FA;
@@ -29,7 +31,7 @@ use View;
class AuthController extends Controller
{
use ThrottlesLogins;
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
// This tells the auth controller to use username instead of email address
protected $username = 'username';
@@ -48,22 +50,65 @@ class AuthController extends Controller
*/
public function __construct()
{
$this->middleware('guest', ['except' => 'logout']);
$this->middleware('guest', ['except' => ['logout','postTwoFactorAuth','getTwoFactorAuth','getTwoFactorEnroll']]);
}
function showLoginForm()
{
// Is the user logged in?
if (Auth::check()) {
return redirect()->intended('dashboard');
}
// Show the page
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 already exists in the database and was imported via LDAP
$user = User::where('username', '=', Input::get('username'))->whereNull('deleted_at')->where('ldap_import','=',1)->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;
}
/**
* Account sign in form processing.
@@ -78,94 +123,54 @@ class AuthController extends Controller
return redirect()->back()->withInput()->withErrors($validator);
}
// If the class is using the ThrottlesLogins trait, we can automatically throttle
// the login attempts for this application. We'll key this by the username and
// the IP address of the client making these requests into this application.
$throttles = $this->isUsingThrottlesLoginsTrait();
$this->maxLoginAttempts = config('auth.throttle.max_attempts');
$this->lockoutTime = config('auth.throttle.lockout_duration');
if ($throttles && $lockedOut = $this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
$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);
// If the user was unable to login via LDAP, log the error and let them fall through to
// local authentication.
} 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());
LOG::error("There was an error authenticating the LDAP user: ".$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.");
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();
if (Setting::getSettings()->ldap_pw_sync!='1') {
Auth::login($user, true);
// Redirect to the users page
return redirect()->to('/home')->with('success', trans('auth/message.signin.success'));
}
} 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
}
// 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("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 ($throttles && ! $lockedOut) {
$this->incrementLoginAttempts($request);
}
LOG::debug("Local authentication failed.");
return redirect()->back()->withInput()->with('error', trans('auth/message.account_not_found'));
} else {
if ($throttles) {
$this->clearLoginAttempts($request);
}
}
}
// Get the page we were before
$redirect = \Session::get('loginRedirect', 'home');
@@ -174,23 +179,89 @@ class AuthController extends Controller
// 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(
urlencode(Setting::getSettings()->site_name),
urlencode($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!');
}
@@ -207,4 +278,19 @@ class AuthController extends Controller
'password' => 'required',
]);
}
/**
* Get the login lockout error message.
*
* @param int $seconds
* @return string
*/
protected function getLockoutErrorMessage($seconds)
{
return \Lang::has('auth/message.throttle')
? \Lang::get('auth/message.throttle', ['seconds' => $seconds])
: 'Too many login attempts. Please try again in '.$seconds.' seconds.';
}
}

View File

@@ -37,4 +37,24 @@ 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');
}
/**
* Get the response for after the reset link has been successfully sent.
*
* @param string $response
* @return \Symfony\Component\HttpFoundation\Response
*/
protected function getSendResetLinkEmailSuccessResponse($response)
{
return redirect()->route('login')->with('status', trans($response));
}
}

View File

@@ -53,7 +53,7 @@ class CategoriesController extends Controller
{
// Show the page
$category_types= Helper::categoryTypeList();
return View::make('categories/edit')->with('category', new Category)
return View::make('categories/edit')->with('item', new Category)
->with('category_types', $category_types);
}
@@ -109,7 +109,7 @@ class CategoriesController extends Controller
public function getEdit($categoryId = null)
{
// Check if the category exists
if (is_null($category = Category::find($categoryId))) {
if (is_null($item = Category::find($categoryId))) {
// Redirect to the blogs management page
return redirect()->to('admin/settings/categories')->with('error', trans('admin/categories/message.does_not_exist'));
}
@@ -120,7 +120,7 @@ class CategoriesController extends Controller
$category_options = array('' => 'Top Level') + DB::table('categories')->where('id', '!=', $categoryId)->lists('name', 'id');
$category_types= Helper::categoryTypeList();
return View::make('categories/edit', compact('category'))
return View::make('categories/edit', compact('item'))
->with('category_options', $category_options)
->with('category_types', $category_types);
}
@@ -293,7 +293,6 @@ class CategoriesController extends Controller
'category_type' => ucwords($category->category_type),
'count' => $category->itemCount(),
'acceptance' => ($category->require_acceptance=='1') ? '<i class="fa fa-check"></i>' : '',
//EULA is still not working correctly
'eula' => ($category->getEula()) ? '<i class="fa fa-check"></i>' : '',
'actions' => $actions
);
@@ -307,9 +306,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')));
}
@@ -333,7 +332,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 = '';
@@ -358,13 +356,13 @@ class CategoriesController extends Controller
$rows[] = array(
'id' => $asset->id,
'name' => (string)link_to('/hardware/'.$asset->id.'/view', $asset->showAssetName()),
'model' => $asset->model->name,
'model' => ($asset->model) ? (string)link_to('hardware/models/'.$asset->model->id.'/view', $asset->model->name) : '',
'asset_tag' => $asset->asset_tag,
'serial' => $asset->serial,
'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

@@ -38,7 +38,7 @@ final class CompaniesController extends Controller
*/
public function getCreate()
{
return View::make('companies/edit')->with('company', new Company);
return View::make('companies/edit')->with('item', new Company);
}
/**
@@ -74,11 +74,11 @@ final class CompaniesController extends Controller
*/
public function getEdit($companyId)
{
if (is_null($company = Company::find($companyId))) {
if (is_null($item = Company::find($companyId))) {
return redirect()->to('admin/settings/companies')
->with('error', trans('admin/companies/message.does_not_exist'));
} else {
return View::make('companies/edit')->with('company', $company);
return View::make('companies/edit')->with('item', $item);
}
}

View File

@@ -61,7 +61,7 @@ class ComponentsController extends Controller
$location_list = Helper::locationsList();
return View::make('components/edit')
->with('component', new Component)
->with('item', new Component)
->with('category_list', $category_list)
->with('company_list', $company_list)
->with('location_list', $location_list);
@@ -89,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 = e(Input::get('serial'));
if (e(Input::get('purchase_date')) == '') {
$component->purchase_date = null;
@@ -99,14 +100,15 @@ 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'));
$component->qty = e(Input::get('qty'));
$component->user_id = Auth::user()->id;
// 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'));
}
@@ -128,10 +130,10 @@ class ComponentsController extends Controller
public function getEdit($componentId = null)
{
// Check if the component exists
if (is_null($component = Component::find($componentId))) {
if (is_null($item = Component::find($componentId))) {
// Redirect to the blogs management page
return redirect()->to('admin/components')->with('error', trans('admin/components/message.does_not_exist'));
} elseif (!Company::isCurrentUserHasAccess($component)) {
} elseif (!Company::isCurrentUserHasAccess($item)) {
return redirect()->to('admin/components')->with('error', trans('general.insufficient_permissions'));
}
@@ -139,7 +141,7 @@ class ComponentsController extends Controller
$company_list = Helper::companyList();
$location_list = Helper::locationsList();
return View::make('components/edit', compact('component'))
return View::make('components/edit', compact('item'))
->with('category_list', $category_list)
->with('company_list', $company_list)
->with('location_list', $location_list);
@@ -172,7 +174,8 @@ class ComponentsController extends Controller
$component->location_id = e(Input::get('location_id'));
$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->min_amt = e(Input::get('min_amt'));
$component->serial = e(Input::get('serial'));
if (e(Input::get('purchase_date')) == '') {
$component->purchase_date = null;
@@ -183,10 +186,10 @@ 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'));
$component->qty = e(Input::get('qty'));
// Was the component created?
if ($component->save()) {
@@ -345,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();
@@ -375,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->showAssetName().'> 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:',
@@ -389,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'));
@@ -430,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','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';
@@ -478,8 +472,9 @@ class ComponentsController extends Controller
'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,
'location' => ($component->location) ? e($component->location->name) : '',
'total_qty' => e($component->total_qty),
'qty' => e($component->qty),
'min_amt' => e($component->min_amt),
'category' => ($component->category) ? e($component->category->name) : 'Missing category',
'order_number' => e($component->order_number),

View File

@@ -59,7 +59,7 @@ class ConsumablesController extends Controller
$manufacturer_list = Helper::manufacturerList();
return View::make('consumables/edit')
->with('consumable', new Consumable)
->with('item', new Consumable)
->with('category_list', $category_list)
->with('company_list', $company_list)
->with('location_list', $location_list)
@@ -85,7 +85,7 @@ class ConsumablesController extends Controller
$consumable->order_number = e(Input::get('order_number'));
$consumable->min_amt = e(Input::get('min_amt'));
$consumable->manufacturer_id = e(Input::get('manufacturer_id'));
$consumable->model_no = e(Input::get('model_no'));
$consumable->model_number = e(Input::get('model_number'));
$consumable->item_no = e(Input::get('item_no'));
if (e(Input::get('purchase_date')) == '') {
@@ -97,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'));
@@ -105,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'));
}
@@ -126,10 +127,10 @@ class ConsumablesController extends Controller
public function getEdit($consumableId = null)
{
// Check if the consumable exists
if (is_null($consumable = Consumable::find($consumableId))) {
if (is_null($item = Consumable::find($consumableId))) {
// Redirect to the blogs management page
return redirect()->to('admin/consumables')->with('error', trans('admin/consumables/message.does_not_exist'));
} elseif (!Company::isCurrentUserHasAccess($consumable)) {
} elseif (!Company::isCurrentUserHasAccess($item)) {
return redirect()->to('admin/consumables')->with('error', trans('general.insufficient_permissions'));
}
@@ -138,7 +139,7 @@ class ConsumablesController extends Controller
$location_list = Helper::locationsList();
$manufacturer_list = Helper::manufacturerList();
return View::make('consumables/edit', compact('consumable'))
return View::make('consumables/edit', compact('item'))
->with('category_list', $category_list)
->with('company_list', $company_list)
->with('location_list', $location_list)
@@ -170,7 +171,7 @@ class ConsumablesController extends Controller
$consumable->order_number = e(Input::get('order_number'));
$consumable->min_amt = e(Input::get('min_amt'));
$consumable->manufacturer_id = e(Input::get('manufacturer_id'));
$consumable->model_no = e(Input::get('model_no'));
$consumable->model_number = e(Input::get('model_number'));
$consumable->item_no = e(Input::get('item_no'));
if (e(Input::get('purchase_date')) == '') {
@@ -182,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'));
@@ -316,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();
@@ -343,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:',
@@ -357,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;
@@ -375,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'));
});
}
@@ -398,8 +390,11 @@ class ConsumablesController extends Controller
*/
public function getDatatable()
{
$consumables = Company::scopeCompanyables(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')));
@@ -417,7 +412,7 @@ class ConsumablesController extends Controller
$limit = 50;
}
$allowed_columns = ['id','name','order_number','min_amt','purchase_date','purchase_cost','companyName','category','model_no', 'item_no', 'manufacturer'];
$allowed_columns = ['id','name','order_number','min_amt','purchase_date','purchase_cost','companyName','category','model_number', 'item_no', 'manufacturer'];
$order = Input::get('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at';
@@ -471,7 +466,7 @@ class ConsumablesController extends Controller
'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),
'model_number' => e($consumable->model_number),
'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),

View File

@@ -11,6 +11,7 @@ use App\Models\AssetModel;
use Lang;
use Auth;
use Illuminate\Http\Request;
use Log;
/**
* This controller handles all actions related to Custom Asset Fields for
@@ -210,21 +211,15 @@ class CustomFieldsController extends Controller
*/
public function show($id)
{
//$id=$parameters[0];
$cfset=CustomFieldset::find($id);
$cfset = CustomFieldset::with('fields')->where('id','=',$id)->orderBy('id','ASC')->first();
$custom_fields_list = ["" => "Add New Field to Fieldset"] + CustomField::lists("name", "id")->toArray();
//print_r($parameters);
//
$custom_fields_list=["" => "Add New Field to Fieldset"] + CustomField::lists("name", "id")->toArray();
// print_r($custom_fields_list);
$maxid=0;
foreach ($cfset->fields as $field) {
// print "Looking for: ".$field->id;
$maxid = 0;
foreach ($cfset->fields() as $field) {
if ($field->pivot->order > $maxid) {
$maxid=$field->pivot->order;
}
if (isset($custom_fields_list[$field->id])) {
// print "Found ".$field->id.", so removing it.<br>";
unset($custom_fields_list[$field->id]);
}
}
@@ -274,14 +269,14 @@ class CustomFieldsController extends Controller
public function destroy($id)
{
//
$fieldset=CustomFieldset::find($id);
$fieldset = CustomFieldset::find($id);
$models = AssetModel::where("fieldset_id", "=", $id);
if ($models->count()==0) {
if ($models->count() == 0) {
$fieldset->delete();
return redirect()->route("admin.custom_fields.index")->with("success", trans('admin/custom_fields/message.fieldset.delete.success'));
} else {
return redirect()->route("admin.custom_fields.index")->with("error", trans('admin/custom_fields/message.fieldset.delete.in_use')); //->with("models",$models);
return redirect()->route("admin.custom_fields.index")->with("error", trans('admin/custom_fields/message.fieldset.delete.in_use'));
}
}
@@ -294,18 +289,23 @@ class CustomFieldsController extends Controller
* @since [v3.0]
* @return Array
*/
public function postReorder($id)
public function postReorder(Request $request, $id)
{
$fieldset=CustomFieldset::find($id);
$fieldset = CustomFieldset::find($id);
$fields = array();
$order_array = array();
$items = Input::get('item');
foreach ($fieldset->fields as $field) {
$value = array_shift($items);
$fields[$field->id] = ['required' => $field->pivot->required, 'order' => $value];
$items = $request->input('item');
foreach ($items as $order => $field_id) {
$order_array[$field_id] = $order;
}
return $fieldset->fields()->sync($fields);
foreach ($fieldset->fields as $field) {
$fields[$field->id] = ['required' => $field->pivot->required, 'order' => $order_array[$field->id]];
}
return $fieldset->fields()->sync($fields);
}
}

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(20)
->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

@@ -46,7 +46,7 @@ class DepreciationsController extends Controller
public function getCreate()
{
// Show the page
return View::make('depreciations/edit')->with('depreciation', new Depreciation);
return View::make('depreciations/edit')->with('item', new Depreciation);
}
@@ -94,12 +94,12 @@ class DepreciationsController extends Controller
public function getEdit($depreciationId = null)
{
// Check if the depreciation exists
if (is_null($depreciation = Depreciation::find($depreciationId))) {
if (is_null($item = Depreciation::find($depreciationId))) {
// Redirect to the blogs management page
return redirect()->to('admin/settings/depreciations')->with('error', trans('admin/depreciations/message.does_not_exist'));
}
return View::make('depreciations/edit', compact('depreciation'));
return View::make('depreciations/edit', compact('item'));
}

View File

@@ -70,7 +70,7 @@ class LicensesController extends Controller
->with('maintained_list', $maintained_list)
->with('company_list', Helper::companyList())
->with('manufacturer_list', Helper::manufacturerList())
->with('license', new License);
->with('item', 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')) == '') {
@@ -143,6 +139,7 @@ class LicensesController extends Controller
$license->depreciation_id = e(Input::get('depreciation_id'));
$license->company_id = Company::getIdForCurrentUser(Input::get('company_id'));
$license->expiration_date = e(Input::get('expiration_date'));
$license->termination_date = e(Input::get('termination_date'));
$license->user_id = Auth::user()->id;
if (($license->purchase_date == "") || ($license->purchase_date == "0000-00-00")) {
@@ -159,7 +156,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) {
@@ -194,26 +191,26 @@ class LicensesController extends Controller
public function getEdit($licenseId = null)
{
// Check if the license exists
if (is_null($license = License::find($licenseId))) {
if (is_null($item = License::find($licenseId))) {
// Redirect to the blogs management page
return redirect()->to('admin/licenses')->with('error', trans('admin/licenses/message.does_not_exist'));
} elseif (!Company::isCurrentUserHasAccess($license)) {
} elseif (!Company::isCurrentUserHasAccess($item)) {
return redirect()->to('admin/licenses')->with('error', trans('general.insufficient_permissions'));
}
if ($license->purchase_date == "0000-00-00") {
$license->purchase_date = null;
if ($item->purchase_date == "0000-00-00") {
$item->purchase_date = null;
}
if ($license->purchase_cost == "0.00") {
$license->purchase_cost = null;
if ($item->purchase_cost == "0.00") {
$item->purchase_cost = null;
}
// Show the page
$license_options = array('' => 'Top Level') + DB::table('assets')->where('id', '!=', $licenseId)->pluck('name', 'id');
$maintained_list = array('' => 'Maintained', '1' => 'Yes', '0' => 'No');
return View::make('licenses/edit', compact('license'))
return View::make('licenses/edit', compact('item'))
->with('license_options', $license_options)
->with('depreciation_list', Helper::depreciationList())
->with('supplier_list', Helper::suppliersList())
@@ -289,10 +286,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')) == '') {
@@ -334,11 +330,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 {
@@ -359,10 +355,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'));
@@ -399,7 +396,7 @@ class LicensesController extends Controller
return redirect()->to('admin/licenses')->with('error', trans('general.insufficient_permissions'));
}
if (($license->assignedcount()) && ($license->assignedcount() > 0)) {
if ($license->assigned_seats_count > 0) {
// Redirect to the license management page
return redirect()->to('admin/licenses')->with('error', trans('admin/licenses/message.assoc_users'));
@@ -543,14 +540,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();
@@ -558,11 +551,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/'.$user->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().'>.';
}
@@ -588,7 +579,7 @@ class LicensesController extends Controller
],
[
'title' => 'Note:',
'value' => e($logaction->note)
'value' => e(Input::get('note'))
],
@@ -602,9 +593,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'));
}
@@ -682,10 +670,10 @@ class LicensesController extends Controller
// Ooops.. something went wrong
return redirect()->back()->withInput()->withErrors($validator);
}
$return_to = $licenseseat->assigned_to;
$logaction = new Actionlog();
$logaction->checkedout_to = $licenseseat->assigned_to;
$return_to = User::find($licenseseat->assigned_to);
if (!$return_to) {
$return_to = Asset::find($licenseseat->asset_id);
}
// Update the asset data
$licenseseat->assigned_to = null;
$licenseseat->asset_id = null;
@@ -694,11 +682,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($return_to, e(Input::get('note')));
$settings = Setting::getSettings();
@@ -719,11 +703,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'))
],
]
@@ -736,12 +720,9 @@ 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'));
return redirect()->to("admin/users/".$return_to->id.'/view')->with('success', trans('admin/licenses/message.checkin.success'));
} else {
return redirect()->to("admin/licenses/".$licenseseat->license_id."/view")->with('success', trans('admin/licenses/message.checkin.success'));
}
@@ -764,6 +745,7 @@ class LicensesController extends Controller
{
$license = License::find($licenseId);
$license = $license->load('assignedusers', 'licenseSeats.user', 'licenseSeats.asset');
if (isset($license->id)) {
@@ -807,9 +789,10 @@ class LicensesController extends Controller
->with('license_options', $license_options)
->with('depreciation_list', $depreciation_list)
->with('supplier_list', $supplier_list)
->with('license', $license)
->with('item', $license)
->with('maintained_list', $maintained_list)
->with('company_list', $company_list);
->with('company_list', $company_list)
->with('manufacturer_list', Helper::manufacturerList());
}
@@ -842,7 +825,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,xml,lic|max:2000'
);
$validator = Validator::make(array('licensefile'=> $file), $rules);
@@ -853,16 +836,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'));
}
@@ -976,17 +951,28 @@ class LicensesController extends Controller
*/
public function getDatatable()
{
$licenses = Company::scopeCompanyables(License::with('company'));
$licenses = Company::scopeCompanyables(License::with('company', 'licenseSeatsRelation', 'manufacturer'));
if (Input::has('search')) {
$licenses = $licenses->TextSearch(Input::get('search'));
}
$allowed_columns = ['id','name','purchase_cost','expiration_date','purchase_order','order_number','notes','purchase_date','serial'];
$allowed_columns = ['id','name','purchase_cost','expiration_date','purchase_order','order_number','notes','purchase_date','serial','manufacturer','company'];
$order = Input::get('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array(Input::get('sort'), $allowed_columns) ? e(Input::get('sort')) : 'created_at';
$licenses = $licenses->orderBy($sort, $order);
switch ($sort) {
case 'manufacturer':
$licenses = $licenses->OrderManufacturer($order);
break;
case 'company':
$licenses = $licenses->OrderCompany($order);
break;
default:
$licenses = $licenses->orderBy($sort, $order);
break;
}
$licenseCount = $licenses->count();
$licenses = $licenses->skip(Input::get('offset'))->take(Input::get('limit'))->get();
@@ -1003,7 +989,7 @@ class LicensesController extends Controller
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>';
. '" 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)
@@ -1020,7 +1006,7 @@ class LicensesController extends Controller
'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),
@@ -1031,7 +1017,7 @@ class LicensesController extends Controller
'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),
'company' => 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

@@ -61,7 +61,7 @@ class LocationsController extends Controller
return View::make('locations/edit')
->with('location_options', $location_options)
->with('location', new Location);
->with('item', new Location);
}
@@ -159,7 +159,7 @@ class LocationsController extends Controller
public function getEdit($locationId = null)
{
// Check if the location exists
if (is_null($location = Location::find($locationId))) {
if (is_null($item = Location::find($locationId))) {
return redirect()->to('admin/settings/locations')->with('error', trans('admin/locations/message.does_not_exist'));
}
@@ -169,7 +169,7 @@ class LocationsController extends Controller
$location_options = Location::flattenLocationsArray($location_options_array);
$location_options = array('' => 'Top Level') + $location_options;
return View::make('locations/edit', compact('location'))->with('location_options', $location_options);
return View::make('locations/edit', compact('item'))->with('location_options', $location_options);
}
@@ -318,7 +318,7 @@ class LocationsController extends Controller
$locations = $locations->OrderParent($order);
break;
default:
$allowed_columns = ['id','name','address','city','state','country','currency'];
$allowed_columns = ['id','name','address','city','state','country','currency','zip'];
$sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at';
$locations = $locations->orderBy($sort, $order);
@@ -344,6 +344,7 @@ class LocationsController extends Controller
'address' => ($location->address) ? e($location->address): '',
'city' => e($location->city),
'state' => e($location->state),
'zip' => e($location->zip),
'country' => e($location->country),
'currency' => e($location->currency),
'actions' => $actions

View File

@@ -46,7 +46,7 @@ class ManufacturersController extends Controller
*/
public function getCreate()
{
return View::make('manufacturers/edit')->with('manufacturer', new Manufacturer);
return View::make('manufacturers/edit')->with('item', new Manufacturer);
}
@@ -84,13 +84,13 @@ class ManufacturersController extends Controller
public function getEdit($manufacturerId = null)
{
// Check if the manufacturer exists
if (is_null($manufacturer = Manufacturer::find($manufacturerId))) {
if (is_null($item = Manufacturer::find($manufacturerId))) {
// Redirect to the manufacturer page
return redirect()->to('admin/settings/manufacturers')->with('error', trans('admin/manufacturers/message.does_not_exist'));
}
// Show the page
return View::make('manufacturers/edit', compact('manufacturer'));
return View::make('manufacturers/edit', compact('item'));
}
@@ -257,7 +257,7 @@ class ManufacturersController extends Controller
*/
public function getDataView($manufacturerId, $itemtype = null)
{
$manufacturer = Manufacturer::with('assets.company')->find($manufacturerId);
$manufacturer = Manufacturer::find($manufacturerId);
switch ($itemtype) {
case "assets":
@@ -276,6 +276,7 @@ class ManufacturersController extends Controller
protected function getDataAssetsView(Manufacturer $manufacturer)
{
$manufacturer = $manufacturer->load('assets.model', 'assets.assigneduser', 'assets.assetstatus', 'assets.company');
$manufacturer_assets = $manufacturer->assets;
if (Input::has('search')) {
@@ -329,20 +330,22 @@ class ManufacturersController extends Controller
'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' => e(Company::getName($asset)),
'companyName' => is_null($asset->company) ? '' : $asset->company->name
);
if (isset($inout)) {
$row['change'] = $inout;
}
if (isset($inout)) {
$row['change'] = $inout;
}
}
$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')) {
@@ -380,7 +383,7 @@ class ManufacturersController extends Controller
'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->licenseSeatCount,
'remaining' => $license->remaincount(),
'license_name' => e($license->license_name),
'license_email' => e($license->license_email),
@@ -403,6 +406,13 @@ class ManufacturersController extends Controller
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')) {
@@ -461,6 +471,13 @@ class ManufacturersController extends Controller
public function getDataConsumablesView($manufacturer)
{
$manufacturer = $manufacturer->load(
'consumables.location',
'consumables.company',
'consumables.category',
'consumables.manufacturer',
'consumables.users'
);
$consumables = $manufacturer->consumables;
if (Input::has('search')) {
@@ -504,7 +521,7 @@ class ManufacturersController extends Controller
'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),
'model_number' => e($consumable->model_number),
'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),

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,6 +55,11 @@ 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 = str_slug($user->first_name."-".$user->last_name).".".$image->getClientOriginalExtension();

View File

@@ -21,6 +21,7 @@ use Illuminate\Support\Facades\View;
use Input;
use League\Csv\Reader;
use Redirect;
use Symfony\Component\HttpFoundation\StreamedResponse;
/**
* This controller handles all actions related to Reports for
@@ -32,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]
@@ -88,7 +89,7 @@ class ReportsController extends Controller
}
/**
* Display asset report.
* Display asset report view.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
@@ -97,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
*
@@ -123,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[] = '"' . Helper::formatCurrencyOutput($asset->purchase_cost) . '"';
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->model_number) ? $asset->model->model_number : '',
($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;
}
/**
@@ -330,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();
@@ -342,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')) {
$activitylogs = $activitylogs->TextSearch(e(Input::get('search')));
}
if (Input::has('offset')) {
$offset = e(Input::get('offset'));
} else {
$offset = 0;
}
if (Input::has('limit')) {
$limit = e(Input::get('limit'));
} else {
$limit = 50;
}
$allowed_columns = ['created_at'];
$order = Input::get('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array(Input::get('sort'), $allowed_columns) ? e(Input::get('sort')) : 'created_at';
$activityCount = $activitylogs->count();
$activitylogs = $activitylogs->offset($offset)->limit($limit)->get();
$rows = array();
foreach ($activitylogs as $activity) {
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 = "unknown (deleted)";
$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,8 +453,9 @@ class ReportsController extends Controller
trans('admin/licenses/form.seats'),
trans('admin/licenses/form.remaining_seats'),
trans('admin/licenses/form.expiration'),
trans('admin/licenses/form.date'),
trans('admin/licenses/form.cost')
trans('general.purchase_date'),
trans('general.depreciation'),
trans('general.purchase_cost')
];
$header = array_map('trim', $header);
@@ -393,6 +470,7 @@ class ReportsController extends Controller
$row[] = $license->remaincount();
$row[] = $license->expiration_date;
$row[] = $license->purchase_date;
$row[] = ($license->depreciation!='') ? '' : e($license->depreciation->name);
$row[] = '"' . Helper::formatCurrencyOutput($license->purchase_cost) . '"';
$rows[] = implode($row, ',');
@@ -421,21 +499,25 @@ class ReportsController extends Controller
}
/**
* 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';
}
@@ -461,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';
}
@@ -476,6 +561,9 @@ class ReportsController extends Controller
if (e(Input::get('username')) == '1') {
$header[] = 'Username';
}
if (e(Input::get('employee_num')) == '1') {
$header[] = 'Employee No.';
}
if (e(Input::get('status')) == '1') {
$header[] = 'Status';
}
@@ -488,6 +576,14 @@ class ReportsController extends Controller
$header[] = 'Value';
$header[] = 'Diff';
}
if (e(Input::get('expected_checkin')) == '1') {
$header[] = trans('admin/hardware/form.expected_checkin');
}
if (e(Input::get('notes')) == '1') {
$header[] = trans('general.notes');
}
foreach ($customfields as $customfield) {
if (e(Input::get($customfield->db_column_name())) == '1') {
@@ -501,6 +597,11 @@ class ReportsController extends Controller
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) . '"';
}
@@ -516,7 +617,7 @@ class ReportsController extends Controller
}
if (e(Input::get('model')) == '1') {
$row[] = '"' . e($asset->model->name) . '"';
$row[] = '"' . e($asset->model->modelno) . '"';
$row[] = '"' . e($asset->model->model_number) . '"';
}
if (e(Input::get('category')) == '1') {
$row[] = '"' .e($asset->model->category->name) . '"';
@@ -531,6 +632,9 @@ class ReportsController extends Controller
if (e(Input::get('purchase_cost')) == '1' && ( e(Input::get('depreciation')) != '1' )) {
$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) {
$row[] = e($asset->order_number);
@@ -539,21 +643,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) {
@@ -566,19 +668,27 @@ 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->assigned_to > 0) {
$user = User::find($asset->assigned_to);
$row[] = '"' .e($user->username). '"';
if ($asset->assigneduser) {
$row[] = '"' .e($asset->assigneduser->username). '"';
} else {
$row[] = ''; // Empty string if unassigned
}
}
if (e(Input::get('employee_num')) == '1') {
if ($asset->assigneduser) {
$row[] = '"' .e($asset->assigneduser->employee_num). '"';
} else {
$row[] = ''; // Empty string if unassigned
}
@@ -610,11 +720,26 @@ class ReportsController extends Controller
$row[] = '"' . Helper::formatCurrencyOutput($depreciation) . '"';
$row[] = '"' . Helper::formatCurrencyOutput($asset->purchase_cost) . '"';
}
if (e(Input::get('expected_checkin')) == '1') {
if ($asset->expected_checkin) {
$row[] = '"' .e($asset->expected_checkin). '"';
} else {
$row[] = ''; // Empty string if blankd
}
}
if (e(Input::get('notes')) == '1') {
if ($asset->notes) {
$row[] = '"' .$asset->notes . '"';
} else {
$row[] = '';
}
}
foreach ($customfields as $customfield) {
$column_name = $customfield->db_column_name();
if (e(Input::get($customfield->db_column_name())) == '1') {
$row[] = $asset->$column_name;
$row[] = str_replace(",", "\,", $asset->$column_name);
}
}
@@ -627,14 +752,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
@@ -671,8 +797,9 @@ 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('general.supplier'),
trans('admin/asset_maintenances/form.asset_maintenance_type'),
trans('admin/asset_maintenances/form.title'),
trans('admin/asset_maintenances/form.start_date'),
@@ -686,6 +813,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);

View File

@@ -15,6 +15,7 @@ use Response;
use Artisan;
use Crypt;
use Mail;
use Auth;
use App\Models\User;
use App\Http\Requests\SetupUserRequest;
@@ -52,29 +53,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 +137,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) {
@@ -194,16 +185,19 @@ class SettingsController extends Controller
return redirect()->back()->withInput()->withErrors($user->getErrors())->withErrors($settings->getErrors());
} else {
$user->save();
Auth::login($user, true);
$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'));
});
}
return redirect()->route('setup.done');
}
@@ -233,6 +227,7 @@ class SettingsController extends Controller
*/
public function getSetupDone()
{
return View::make('setup/done')
->with('step', 4)
->with('section', 'Done!');
@@ -269,10 +264,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 +315,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')!='') {
@@ -354,6 +353,7 @@ class SettingsController extends Controller
$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'));
@@ -369,6 +369,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 {
@@ -388,7 +389,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'));
@@ -419,10 +420,8 @@ class SettingsController extends Controller
$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());
}
@@ -482,7 +481,7 @@ class SettingsController extends Controller
}
closedir($handle);
$files = array_reverse($files);
rsort($files);
}

View File

@@ -87,11 +87,11 @@ class StatuslabelsController extends Controller
public function getCreate()
{
// Show the page
$statuslabel = new Statuslabel;
$use_statuslabel_type = $statuslabel->getStatuslabelType();
$item = new Statuslabel;
$use_statuslabel_type = $item->getStatuslabelType();
$statuslabel_types = Helper::statusTypeList();
return View::make('statuslabels/edit', compact('statuslabel_types', 'statuslabel'))->with('use_statuslabel_type', $use_statuslabel_type);
return View::make('statuslabels/edit', compact('statuslabel_types', 'item'))->with('use_statuslabel_type', $use_statuslabel_type);
}
@@ -169,16 +169,16 @@ class StatuslabelsController extends Controller
public function getEdit($statuslabelId = null)
{
// Check if the Statuslabel exists
if (is_null($statuslabel = Statuslabel::find($statuslabelId))) {
if (is_null($item = Statuslabel::find($statuslabelId))) {
// Redirect to the blogs management page
return redirect()->to('admin/settings/statuslabels')->with('error', trans('admin/statuslabels/message.does_not_exist'));
}
$use_statuslabel_type = $statuslabel->getStatuslabelType();
$use_statuslabel_type = $item->getStatuslabelType();
$statuslabel_types = array('' => trans('admin/hardware/form.select_statustype')) + array('undeployable' => trans('admin/hardware/general.undeployable')) + array('pending' => trans('admin/hardware/general.pending')) + array('archived' => trans('admin/hardware/general.archived')) + array('deployable' => trans('admin/hardware/general.deployable'));
return View::make('statuslabels/edit', compact('statuslabel', 'statuslabel_types'))->with('use_statuslabel_type', $use_statuslabel_type);
return View::make('statuslabels/edit', compact('item', 'statuslabel_types'))->with('use_statuslabel_type', $use_statuslabel_type);
}

View File

@@ -45,7 +45,7 @@ class SuppliersController extends Controller
*/
public function getCreate()
{
return View::make('suppliers/edit')->with('supplier', new Supplier);
return View::make('suppliers/edit')->with('item', new Supplier);
}
@@ -125,13 +125,13 @@ class SuppliersController extends Controller
public function getEdit($supplierId = null)
{
// Check if the supplier exists
if (is_null($supplier = Supplier::find($supplierId))) {
if (is_null($item = Supplier::find($supplierId))) {
// Redirect to the supplier page
return redirect()->to('admin/settings/suppliers')->with('error', trans('admin/suppliers/message.does_not_exist'));
}
// Show the page
return View::make('suppliers/edit', compact('supplier'));
return View::make('suppliers/edit', compact('item'));
}
@@ -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;
@@ -81,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();
@@ -123,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 == "") {
@@ -157,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'));
@@ -209,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]));
});
}
@@ -231,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 {
@@ -247,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();
@@ -280,33 +304,48 @@ 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.');
}
try {
// 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 (is_array($orig_permissions_array)) {
if (array_key_exists('superuser', $orig_permissions_array)) {
$orig_superuser = $orig_permissions_array['superuser'];
} else {
$orig_superuser = '0';
}
} else {
$orig_superuser = '0';
}
if (!Company::isCurrentUserHasAccess($user)) {
return redirect()->route('users')->with('error', trans('general.insufficient_permissions'));
}
} catch (UserNotFoundException $e) {
// Prepare the error message
$error = trans('admin/users/message.user_not_found', compact('id'));
// Redirect to the user management page
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'));
@@ -320,6 +359,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));
@@ -329,8 +369,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;
@@ -376,17 +425,12 @@ class UsersController extends Controller
// Check if we are not trying to delete ourselves
if ($user->id === Auth::user()->id) {
// Prepare the error message
$error = trans('admin/users/message.error.delete');
// Redirect to the user management page
return redirect()->route('users')->with('error', $error);
return redirect()->route('users')->with('error', trans('admin/users/message.error.delete'));
}
// Do we have permission to delete this user?
if ((!Auth::user()->isSuperUser()) || (config('app.lock_passwords'))) {
// Redirect to the user management page
if ((Gate::denies('users.delete') || (config('app.lock_passwords')))) {
return redirect()->route('users')->with('error', 'Insufficient permissions!');
}
@@ -410,18 +454,11 @@ class UsersController extends Controller
// Delete the user
$user->delete();
// Prepare the success message
$success = trans('admin/users/message.success.delete');
// Redirect to the user management page
return redirect()->route('users')->with('success', $success);
} catch (UserNotFoundException $e) {
// Prepare the error message
$error = trans('admin/users/message.user_not_found', compact('id'));
// Redirect to the user management page
return redirect()->route('users')->with('error', $error);
} catch (UserNotFoundException $e) {
return redirect()->route('users')->with('error', trans('admin/users/message.user_not_found', compact('id')));
}
}
@@ -473,10 +510,7 @@ class UsersController extends Controller
if (($key = array_search(Auth::user()->id, $user_raw_array)) !== false) {
unset($user_raw_array[$key]);
}
if (!Auth::user()->isSuperUser()) {
return redirect()->route('users')->with('error', trans('admin/users/message.insufficient_permissions'));
}
if (!config('app.lock_passwords')) {
@@ -495,9 +529,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');
@@ -514,9 +549,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');
@@ -528,9 +564,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');
@@ -598,7 +635,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)) {
@@ -809,11 +846,10 @@ 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'
);
//dd($newuser);
DB::table('users')->insert($newuser);
@@ -829,7 +865,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']]));
});
}
}
@@ -875,7 +912,7 @@ 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'))
$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);
@@ -901,8 +938,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';
@@ -952,7 +990,7 @@ class UsersController extends Controller
$actions .= ' <span class="btn delete-asset btn-danger btn-sm disabled"><i class="fa fa-trash icon-white"></i></span>';
}
} else {
$actions.='foo';
$actions.='';
}
}
@@ -961,14 +999,15 @@ class UsersController extends Controller
$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(),
@@ -976,8 +1015,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)
);
@@ -1017,12 +1058,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();
@@ -1050,7 +1091,6 @@ class UsersController extends Controller
$user = User::find($userId);
$destinationPath = config('app.private_uploads').'/users';
// the license is valid
if (isset($user->id)) {
if (!Company::isCurrentUserHasAccess($user)) {
@@ -1262,4 +1302,110 @@ class UsersController extends Controller
$assets = Asset::where('assigned_to', '=', $userId)->with('model')->get();
return response()->json($assets);
}
/**
* 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,35 @@ 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->target_type = User::class;
$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 (isset($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

@@ -22,6 +22,7 @@ class Kernel extends HttpKernel
\App\Http\Middleware\NosniffGuard::class,
\App\Http\Middleware\CheckForSetup::class,
\Fideloper\Proxy\TrustProxies::class,
\App\Http\Middleware\CheckForDebug::class,
];
/**
@@ -35,6 +36,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

@@ -0,0 +1,27 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Auth;
class CheckForDebug
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
view()->share('debug_in_production', false);
if (((Auth::check() && (Auth::user()->isSuperUser()))) && (app()->environment()=='production') && (config('app.warn_debug')===true) && (config('app.debug')===true)) {
view()->share('debug_in_production', true);
}
return $next($request);
}
}

View File

@@ -14,6 +14,11 @@ class CheckForSetup
public function handle($request, Closure $next, $guard = null)
{
// This is dumb
if ($request->is('_debugbar*')) {
return $next($request);
}
if (Setting::setupCompleted()) {
if ($request->is('setup*')) {
@@ -23,7 +28,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,52 @@
<?php
namespace App\Http\Middleware;
use App\Models\Setting;
use Auth;
use Closure;
use Illuminate\Support\Facades\Schema;
use Log;
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 or the setup pages
if (($request->route()->getName()=='two-factor') || ($request->route()->getName()=='two-factor-enroll') || ($request->route()->getPrefix()=='setup') || ($request->route()->getName()=='logout')) {
return $next($request);
}
// Two-factor is enabled (either optional or required)
if (Setting::getSettings()) {
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

@@ -21,7 +21,9 @@ class CheckLocale
public function handle($request, Closure $next, $guard = null)
{
if (Schema::hasTable('settings')) {
if (Setting::getSettings()) {
// User's preference
if (($request->user()) && ($request->user()->locale)) {
\App::setLocale($request->user()->locale);

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

@@ -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

@@ -1,6 +1,7 @@
<?php
use App\Models\Statuslabel;
use App\Models\CheckoutRequest;
use App\Models\Location;
use App\Models\Statuslabel;
/*
|--------------------------------------------------------------------------
@@ -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' ]);
@@ -353,19 +355,19 @@ Route::group(
]);
# Asset Model Management
Route::group([ 'prefix' => 'models', 'middleware' => 'auth' ], function () {
Route::group([ 'prefix' => 'models', 'middleware' => ['auth'] ], function () {
Route::get('/', [ 'as' => 'models', 'uses' => 'AssetModelsController@getIndex' ]);
Route::get('create', [ 'as' => 'create/model', 'uses' => 'AssetModelsController@getCreate' ]);
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('/', [
@@ -377,6 +379,30 @@ Route::group(
}
);
/*
|--------------------------------------------------------------------------
| 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
@@ -388,6 +414,14 @@ 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 () {
@@ -447,17 +481,30 @@ Route::group([ 'prefix' => 'admin','middleware' => ['web','auth']], function ()
# Asset Maintenances
Route::group([ 'prefix' => 'asset_maintenances', 'middleware'=>'authorize:assets.view' ], function () {
Route::get(
'create/{assetId?}',
[ 'as' => 'create/asset_maintenances', 'uses' => 'AssetMaintenancesController@getCreate' ]
);
Route::post('create/{assetId?}', 'AssetMaintenancesController@postCreate');
Route::get('/', [ 'as' => 'asset_maintenances', 'uses' => 'AssetMaintenancesController@getIndex' ]);
Route::get(
'{assetMaintenanceId}/edit',
[ 'as' => 'update/asset_maintenance', 'uses' => 'AssetMaintenancesController@getEdit' ]
);
Route::post('{assetMaintenanceId}/edit', 'AssetMaintenancesController@postEdit');
Route::get('create/{assetId?}',
[ 'as' => 'create/asset_maintenances',
'middleware' => 'authorize:assets.edit',
'uses' => 'AssetMaintenancesController@getCreate'
]);
Route::post('create/{assetId?}',
[ 'as' => 'create/asset_maintenances.save',
'middleware' => 'authorize:assets.edit',
'uses' => 'AssetMaintenancesController@postCreate'
]);
Route::get('{assetMaintenanceId}/edit',
[ 'as' => 'update/asset_maintenance',
'middleware' => 'authorize:assets.edit',
'uses' => 'AssetMaintenancesController@getEdit'
]);
Route::post('{assetMaintenanceId}/edit',
[ 'as' => 'update/asset_maintenance.save',
'middleware' => 'authorize:assets.edit',
'uses' => 'AssetMaintenancesController@postEdit'
]);
Route::get(
'{assetMaintenanceId}/delete',
[ 'as' => 'delete/asset_maintenance', 'uses' => 'AssetMaintenancesController@getDelete' ]
@@ -466,6 +513,8 @@ Route::group([ 'prefix' => 'admin','middleware' => ['web','auth']], function ()
'{assetMaintenanceId}/view',
[ 'as' => 'view/asset_maintenance', 'uses' => 'AssetMaintenancesController@getView' ]
);
Route::get('/', [ 'as' => 'asset_maintenances', 'uses' => 'AssetMaintenancesController@getIndex' ]);
});
# Accessories
@@ -721,7 +770,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' ]
@@ -765,11 +814,12 @@ Route::group([ 'prefix' => 'admin','middleware' => ['web','auth']], function ()
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}/delete', [ 'as' => 'delete/user', 'uses' => 'UsersController@getDelete', 'middleware' => ['authorize:users.delete'] ]);
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'] ]);
@@ -858,6 +908,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' ]);
@@ -910,6 +965,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' ]
@@ -976,6 +1037,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(
'/',
@@ -985,8 +1069,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,8 @@
<?php
namespace App\Models;
use App\Models\Loggable;
use App\Models\SnipeModel;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
@@ -10,10 +12,11 @@ use Watson\Validating\ValidatingTrait;
*
* @version v1.0
*/
class Accessory extends Model
class Accessory extends SnipeModel
{
use SoftDeletes;
use CompanyableTrait;
use Loggable;
use SoftDeletes;
protected $dates = ['deleted_at'];
protected $table = 'accessories';
@@ -26,7 +29,7 @@ class Accessory extends Model
'qty' => 'required|integer|min:1',
'category_id' => 'required|integer',
'company_id' => 'integer',
'min_amt' => 'integer|min:1',
'min_amt' => 'integer|min:0',
'purchase_cost' => 'numeric',
);
@@ -68,7 +71,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();
}
@@ -151,6 +154,7 @@ class Accessory extends Model
$query->where('locations.name', 'LIKE', '%'.$search.'%');
});
})->orWhere('accessories.name', 'LIKE', '%'.$search.'%')
->orWhere('accessories.model_number', 'LIKE', '%'.$search.'%')
->orWhere('accessories.order_number', 'LIKE', '%'.$search.'%')
->orWhere('accessories.purchase_cost', 'LIKE', '%'.$search.'%')
->orWhere('accessories.purchase_date', 'LIKE', '%'.$search.'%');

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,110 +12,96 @@ 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','user_id','asset_id','action_type','note','checkedout_to' ];
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 company() {
return $this->hasMany('\App\Models\Company', 'id','company_id');
}
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 userasassetlog()
public function target()
{
return $this->belongsTo('\App\Models\User', 'asset_id')
->withTrashed();
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
*/
@@ -141,44 +127,36 @@ 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()
* Query builder scope to search on text for complex Bootstrap Tables API
*
* @param Illuminate\Database\Query\Builder $query Query builder instance
* @param text $search Search term
*
* @return Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeTextSearch($query, $search)
{
$search = explode(' OR ', $search);
return DB::table('asset_logs')
->select(DB::raw('asset_id, MAX(created_at) as last_created'))
->where('action_type', '=', 'checkout')
->groupBy('asset_id')
->get();
}
return $query->where(function ($query) use ($search) {
/**
* scopeCheckoutWithoutAcceptance
*
* @param $query
*
* @return mixed
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
*/
public function scopeCheckoutWithoutAcceptance($query)
{
foreach ($search as $search) {
$query->where(function ($query) use ($search) {
$query->whereHas('company', function ($query) use ($search) {
$query->where('companies.name', 'LIKE', '%'.$search.'%');
});
})->orWhere('action_type', 'LIKE', '%'.$search.'%')
->orWhere('note', 'LIKE', '%'.$search.'%');
}
return $query->where('action_type', '=', 'checkout')
->where('accepted_id', '=', null);
});
}
}

View File

@@ -1,20 +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 App\Http\Traits\UniqueUndeletedTrait;
use DateTime;
use App\Models\Setting;
use App\Helpers\Helper;
use Auth;
/**
* Model for Assets.
@@ -23,7 +25,9 @@ use Auth;
*/
class Asset extends Depreciable
{
use Loggable;
use SoftDeletes;
use Requestable;
/**
* The database table used by the model.
@@ -148,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'));
});
}
@@ -209,10 +214,13 @@ 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;
// On Checkin, this is the user that previously had the asset.
$logaction->target_id = $user->id;
$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 {
@@ -225,15 +233,9 @@ 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->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;
@@ -270,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');
@@ -308,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();
}
@@ -327,8 +329,7 @@ class Asset extends Depreciable
{
return $this->hasMany('\App\Models\AssetMaintenance', 'asset_id')
->orderBy('created_at', 'desc')
->withTrashed();
->orderBy('created_at', 'desc');
}
/**
@@ -398,6 +399,11 @@ class Asset extends Depreciable
}
}
public function getDisplayNameAttribute()
{
return $this->showAssetName();
}
public function warrantee_expires()
{
$date = date_create($this->purchase_date);
@@ -479,9 +485,12 @@ class Asset extends Depreciable
$settings = \App\Models\Setting::getSettings();
if ($settings->auto_increment_assets == '1') {
$asset_tag = \DB::table('assets')
$temp_asset_tag = \DB::table('assets')
->where('physical', '=', '1')
->max('id');
->max('asset_tag');
$asset_tag_digits = preg_replace('/\D/', '', $temp_asset_tag);
$asset_tag = preg_replace('/^0*/', '', $asset_tag_digits);
if ($settings->zerofill_count > 0) {
return $settings->auto_increment_prefix.Asset::zerofill(($asset_tag + 1),$settings->zerofill_count);
@@ -576,12 +585,12 @@ public function checkin_email()
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');
});
@@ -786,7 +795,7 @@ public function checkin_email()
$query->where(function ($query) use ($search) {
$query->where('categories.name', 'LIKE', '%'.$search.'%')
->orWhere('models.name', 'LIKE', '%'.$search.'%')
->orWhere('models.modelno', 'LIKE', '%'.$search.'%');
->orWhere('models.model_number', 'LIKE', '%'.$search.'%');
});
});
})->orWhereHas('model', function ($query) use ($search) {
@@ -854,21 +863,21 @@ public function checkin_email()
*/
public function scopeOrderModelNumber($query, $order)
{
return $query->join('models', 'assets.model_id', '=', 'models.id')->orderBy('models.modelno', $order);
return $query->join('models', 'assets.model_id', '=', 'models.id')->orderBy('models.model_number', $order);
}
/**
* Query builder scope to order on assigned user
*
* @param Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return Illuminate\Database\Query\Builder Modified query builder
*/
/**
* Query builder scope to order on assigned user
*
* @param Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeOrderAssigned($query, $order)
{
return $query->join('users', 'assets.assigned_to', '=', 'users.id')->orderBy('users.first_name', $order)->orderBy('users.last_name', $order);
return $query->leftJoin('users', 'assets.assigned_to', '=', 'users.id')->select('assets.*')->orderBy('users.first_name', $order)->orderBy('users.last_name', $order);
}
/**

View File

@@ -1,6 +1,8 @@
<?php
namespace App\Models;
use App\Models\Requestable;
use App\Models\SnipeModel;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
@@ -11,16 +13,17 @@ use Watson\Validating\ValidatingTrait;
*
* @version v1.0
*/
class AssetModel extends Model
class AssetModel extends SnipeModel
{
use SoftDeletes;
use Requestable;
protected $dates = ['deleted_at'];
protected $table = 'models';
// Declare the rules for the model validation
protected $rules = array(
'name' => 'required|min:1|max:255',
'modelno' => 'min:1|max:255',
'model_number' => 'min:1|max:255',
'category_id' => 'required|integer',
'manufacturer_id' => 'required|integer',
'eol' => 'integer:min:0|max:240',
@@ -90,8 +93,8 @@ class AssetModel extends Model
public function displayModelName()
{
$name = $this->manufacturer->name.' '.$this->name;
if ($this->modelno) {
$name .=" / ".$this->modelno;
if ($this->model_number) {
$name .=" / ".$this->model_number;
}
return $name;
}
@@ -131,6 +134,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
*
@@ -143,7 +162,7 @@ class AssetModel extends Model
{
return $query->where('name', 'LIKE', "%$search%")
->orWhere('modelno', 'LIKE', "%$search%")
->orWhere('model_number', 'LIKE', "%$search%")
->orWhere(function ($query) use ($search) {
$query->whereHas('depreciation', function ($query) use ($search) {
$query->where('name', 'LIKE', '%'.$search.'%');

View File

@@ -1,10 +1,11 @@
<?php
namespace App\Models;
use App\Http\Traits\UniqueUndeletedTrait;
use App\Models\SnipeModel;
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
@@ -14,7 +15,7 @@ use App\Http\Traits\UniqueUndeletedTrait;
*
* @version v1.0
*/
class Category extends Model
class Category extends SnipeModel
{
use SoftDeletes;

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

@@ -1,17 +1,18 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Watson\Validating\ValidatingTrait;
use App\Models\SnipeModel;
use Auth;
use DB;
use Illuminate\Database\Eloquent\Model;
use Watson\Validating\ValidatingTrait;
/**
* Model for Companies.
*
* @version v1.8
*/
final class Company extends Model
final class Company extends SnipeModel
{
protected $table = 'companies';
@@ -136,7 +137,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);
@@ -176,4 +178,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,14 @@
<?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\SnipeModel;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
@@ -16,10 +18,11 @@ use Watson\Validating\ValidatingTrait;
*
* @version v1.0
*/
class Component extends Model
class Component extends SnipeModel
{
use SoftDeletes;
use CompanyableTrait;
use Loggable;
use SoftDeletes;
protected $dates = ['deleted_at'];
protected $table = 'components';
@@ -30,7 +33,7 @@ class Component extends Model
*/
public $rules = array(
'name' => 'required|min:3|max:255',
'total_qty' => 'required|integer|min:1',
'qty' => 'required|integer|min:1',
'category_id' => 'required|integer',
'company_id' => 'integer',
'purchase_date' => 'date',
@@ -85,7 +88,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();
}
@@ -98,7 +101,7 @@ class Component extends Model
}
$total = $this->total_qty;
$total = $this->qty;
$remaining = $total - $checkedout;
return $remaining;
}
@@ -139,6 +142,7 @@ class Component extends Model
});
})->orWhere('components.name', 'LIKE', '%'.$search.'%')
->orWhere('components.order_number', 'LIKE', '%'.$search.'%')
->orWhere('components.serial', 'LIKE', '%'.$search.'%')
->orWhere('components.purchase_cost', 'LIKE', '%'.$search.'%')
->orWhere('components.purchase_date', 'LIKE', '%'.$search.'%');
}

View File

@@ -1,20 +1,23 @@
<?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\SnipeModel;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
class Consumable extends Model
class Consumable extends SnipeModel
{
use SoftDeletes;
use CompanyableTrait;
use Loggable;
use SoftDeletes;
protected $dates = ['deleted_at'];
protected $table = 'consumables';
@@ -85,7 +88,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

@@ -2,6 +2,7 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Schema;
class CustomField extends Model
{
@@ -22,7 +23,7 @@ class CustomField extends Model
];
public $rules=[
"name" => "required|unique:custom_fields"
"name" => "required|unique:custom_fields"
];
public static $table_name="assets";
@@ -36,12 +37,12 @@ class CustomField extends Model
{
self::creating(function ($custom_field) {
if (in_array($custom_field->db_column_name(), \Schema::getColumnListing(\DB::getTablePrefix().CustomField::$table_name))) {
if (Schema::hasColumn(CustomField::$table_name,$custom_field->db_column_name())) {
//field already exists when making a new custom field; fail.
return false;
}
\Schema::table(\DB::getTablePrefix().\App\Models\CustomField::$table_name, function ($table) use ($custom_field) {
Schema::table(CustomField::$table_name, function ($table) use ($custom_field) {
$table->text($custom_field->db_column_name())->nullable();
});
@@ -49,17 +50,21 @@ class CustomField extends Model
self::updating(function ($custom_field) {
if ($custom_field->isDirty("name")) {
if (in_array($custom_field->db_column_name(), \Schema::getColumnListing(CustomField::$table_name))) {
if (Schema::hasColumn(CustomField::$table_name,$custom_field->db_column_name())) {
//field already exists when renaming a custom field
return false;
}
return \DB::statement("UPDATE ".CustomField::$table_name." RENAME ".self::name_to_db_name($custom_field->get_original("name"))." TO ".$custom_field->db_column_name());
return Schema::table(CustomField::$table_name, function ($table) use ($custom_field) {
$table->renameColumn(self::name_to_db_name($custom_field->getOriginal("name")),$custom_field->db_column_name());
});
}
return true;
});
self::deleting(function ($custom_field) {
return \DB::statement("ALTER TABLE ".CustomField::$table_name." DROP COLUMN ".$custom_field->db_column_name());
return Schema::table(CustomField::$table_name,function ($table) use ($custom_field) {
$table->dropColumn(self::name_to_db_name($custom_field->getOriginal("name")));
});
});
}

View File

@@ -1,10 +1,11 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use App\Models\Depreciation;
use App\Models\SnipeModel;
use Illuminate\Database\Eloquent\Model;
class Depreciable extends Model
class Depreciable extends SnipeModel
{
/**
* Depreciation Relation, and associated helper methods

View File

@@ -1,10 +1,11 @@
<?php
namespace App\Models;
use App\Models\SnipeModel;
use Illuminate\Database\Eloquent\Model;
use Watson\Validating\ValidatingTrait;
class Depreciation extends Model
class Depreciation extends SnipeModel
{
// Declare the rules for the form validation
protected $rules = array(

View File

@@ -1,11 +1,10 @@
<?php
namespace App\Models;
use App\Models\SnipeModel;
use Watson\Validating\ValidatingTrait;
use Illuminate\Database\Eloquent\Model;
class Group extends Model
class Group extends SnipeModel
{
protected $table = 'groups';

View File

@@ -219,10 +219,10 @@ class Ldap extends Model
$user->notes = 'Imported on first login from LDAP';
if ($user->save()) {
return true;
return $user;
} else {
LOG::debug('Could not create user.'.$user->getErrors());
exit;
throw new Exception("Could not create user: ".$user->getErrors());
}
}
@@ -277,7 +277,7 @@ class Ldap extends Model
$global_count += $results['count'];
$result_set = array_merge($result_set, $results);
ldap_control_paged_result_response($ldapconn, $search_results, $cookie);
@ldap_control_paged_result_response($ldapconn, $search_results, $cookie);
} while ($cookie !== null && $cookie != '');

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;
@@ -22,7 +23,6 @@ class License extends Depreciable
protected $table = 'licenses';
protected $rules = array(
'name' => 'required|string|min:3|max:255',
'serial' => 'required|min:5',
'seats' => 'required|min:1|max:10000|integer',
'license_email' => 'email|min:0|max:120',
'license_name' => 'string|min:0|max:100',
@@ -54,8 +54,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');
}
@@ -64,8 +64,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');
@@ -100,6 +100,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
@@ -115,37 +129,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_count;
$diff = ($total - $taken);
return $diff;
}
@@ -155,7 +179,7 @@ class License extends Depreciable
*/
public function totalcount()
{
$avail = $this->availcount();
$avail = $this->availSeatsCount;
$taken = $this->assignedcount();
$diff = ($avail + $taken);
return $diff;
@@ -209,12 +233,51 @@ class License extends Depreciable
return $query->where(function ($query) use ($search) {
$query->where('name', 'LIKE', '%'.$search.'%')
->orWhere('serial', 'LIKE', '%'.$search.'%')
->orWhere('notes', 'LIKE', '%'.$search.'%')
->orWhere('order_number', 'LIKE', '%'.$search.'%')
->orWhere('purchase_date', 'LIKE', '%'.$search.'%')
->orWhere('purchase_cost', 'LIKE', '%'.$search.'%');
$query->where('licenses.name', 'LIKE', '%'.$search.'%')
->orWhere('licenses.serial', 'LIKE', '%'.$search.'%')
->orWhere('licenses.notes', 'LIKE', '%'.$search.'%')
->orWhere('licenses.order_number', 'LIKE', '%'.$search.'%')
->orWhere('licenses.purchase_order', 'LIKE', '%'.$search.'%')
->orWhere('licenses.purchase_date', 'LIKE', '%'.$search.'%')
->orWhere('licenses.purchase_cost', 'LIKE', '%'.$search.'%')
->orWhereHas('manufacturer', function ($query) use ($search) {
$query->where(function ($query) use ($search) {
$query->where('manufacturers.name', 'LIKE', '%'.$search.'%');
});
})
->orWhereHas('company', function ($query) use ($search) {
$query->where(function ($query) use ($search) {
$query->where('companies.name', 'LIKE', '%'.$search.'%');
});
});
});
}
/**
* Query builder scope to order on manufacturer
*
* @param Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeOrderManufacturer($query, $order)
{
return $query->leftJoin('manufacturers', 'licenses.manufacturer_id', '=', 'manufacturers.id')->select('licenses.*')
->orderBy('manufacturers.name', $order);
}
/**
* Query builder scope to order on company
*
* @param Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeOrderCompany($query, $order)
{
return $query->leftJoin('companies as companies', 'licenses.company_id', '=', 'companies.id')->select('licenses.*')
->orderBy('companies.name', $order);
}
}

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

@@ -1,14 +1,15 @@
<?php
namespace App\Models;
use App\Http\Traits\UniqueUndeletedTrait;
use App\Models\Asset;
use App\Models\SnipeModel;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
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
class Location extends SnipeModel
{
use SoftDeletes;
protected $dates = ['deleted_at'];
@@ -16,8 +17,8 @@ class Location extends Model
protected $rules = array(
'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',
'state' => 'min:0|max:2',
'country' => 'min:2|max:2',
'address' => 'min:5|max:80',
'address2' => 'min:2|max:80',
'zip' => 'min:3|max:10',
@@ -49,7 +50,7 @@ class Location extends Model
public function assets()
{
return $this->hasManyThrough('\App\Models\Asset', '\App\Models\Actionlog', 'location_id', 'id');
return $this->hasManyThrough('\App\Models\Asset', '\App\Models\User', 'location_id', 'assigned_to', 'id');
}
public function assignedassets()

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

@@ -0,0 +1,137 @@
<?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($target, $note)
{
$log = new Actionlog;
$log->target_type = get_class($target);
$log->target_id = $target->id;
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

@@ -1,11 +1,12 @@
<?php
namespace App\Models;
use App\Models\SnipeModel;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
class Manufacturer extends Model
class Manufacturer extends SnipeModel
{
use SoftDeletes;
protected $dates = ['deleted_at'];
@@ -46,6 +47,11 @@ class Manufacturer extends Model
return $this->hasManyThrough('\App\Models\Asset', '\App\Models\AssetModel', 'manufacturer_id', 'model_id');
}
public function models()
{
return $this->hasMany('\App\Models\AssetModel', 'manufacturer_id');
}
public function licenses()
{
return $this->hasMany('\App\Models\License', 'manufacturer_id');

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

@@ -49,10 +49,14 @@ class Setting extends Model
{
static $static_cache = null;
if (!$static_cache) {
$static_cache = Setting::first();
}
return $static_cache;
if (!$static_cache) {
if (Schema::hasTable('settings')) {
$static_cache = Setting::first();
}
}
return $static_cache;
}
public static function setupCompleted()

14
app/Models/SnipeModel.php Normal file
View File

@@ -0,0 +1,14 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class SnipeModel extends Model
{
//
public function getDisplayNameAttribute()
{
return $this->name;
}
}

View File

@@ -1,12 +1,13 @@
<?php
namespace App\Models;
use App\Http\Traits\UniqueUndeletedTrait;
use App\Models\SnipeModel;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
use App\Http\Traits\UniqueUndeletedTrait;
class Statuslabel extends Model
class Statuslabel extends SnipeModel
{
use SoftDeletes;
use ValidatingTrait;

View File

@@ -1,12 +1,13 @@
<?php
namespace App\Models;
use App\Http\Traits\UniqueUndeletedTrait;
use App\Models\SnipeModel;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
use App\Http\Traits\UniqueUndeletedTrait;
class Supplier extends Model
class Supplier extends SnipeModel
{
use SoftDeletes;
protected $dates = ['deleted_at'];
@@ -14,14 +15,14 @@ class Supplier extends Model
protected $rules = array(
'name' => 'required|min:3|max:255|unique_undeleted',
'address' => 'min:3|max:255',
'address2' => 'min:2|max:255',
'address' => 'min:3|max:50',
'address2' => 'min:2|max:50',
'city' => 'min:3|max:255',
'state' => 'min:0|max:32',
'country' => 'min:0|max:2',
'fax' => 'min:7|max:20',
'phone' => 'min:7|max:20',
'contact' => 'min:0|max:255',
'contact' => 'min:0|max:100',
'notes' => 'min:0|max:255',
'email' => 'email|min:5|max:150',
'zip' => 'min:0|max:10',
@@ -47,6 +48,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');
@@ -59,7 +75,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()
@@ -69,7 +89,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

@@ -9,6 +9,7 @@ use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use Watson\Validating\ValidatingTrait;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Http\Traits\UniqueUndeletedTrait;
use App\Models\Setting;
class User extends Model implements AuthenticatableContract, CanResetPasswordContract
{
@@ -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();
}
/**
@@ -255,13 +254,21 @@ 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');
}
/**
* Fetch Items User has requested
*/
public function checkoutRequests()
{
return $this->belongsToMany(Asset::class, 'checkout_requests');
}
public function throttle()
{
return $this->hasOne('\App\Models\Throttle');
@@ -375,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

@@ -4,6 +4,7 @@ namespace App\Providers;
use Validator;
use Illuminate\Support\ServiceProvider;
use DB;
use Log;
/**
@@ -64,6 +65,11 @@ class AppServiceProvider extends ServiceProvider
}
});
// Share common variables with all views.
view()->composer('*', function ($view) {
$view->with('snipeSettings', \App\Models\Setting::getSettings());
});
}
/**
@@ -73,6 +79,20 @@ class AppServiceProvider extends ServiceProvider
*/
public function register()
{
//
$monolog = Log::getMonolog();
if (config('app.debug')) {
$log_level = 'debug';
} else {
if (config('log-level')) {
$log_level = config('log-level');
} else {
$log_level = 'error';
}
}
foreach($monolog->getHandlers() as $handler) {
$handler->setLevel($log_level);
}
}
}

View File

@@ -255,6 +255,18 @@ 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'))) {
@@ -316,5 +328,15 @@ class AuthServiceProvider extends ServiceProvider
});
# -----------------------------------------
# Self
# -----------------------------------------
$gate->define('self.two_factor', function ($user) {
if (($user->hasAccess('self.two_factor')) || ($user->hasAccess('admin'))) {
return true;
}
});
}
}

View File

@@ -12,13 +12,6 @@ settings:
extensions:
enabled:
- Codeception\Extension\RunFailed
modules:
config:
Db:
dsn: ''
user: ''
password: ''
dump: tests/_data/dump.sql
coverage:
enabled: true
include:

View File

@@ -23,7 +23,8 @@
"barryvdh/laravel-debugbar": "^2.1",
"spatie/laravel-backup": "3.8.1",
"misterphilip/maintenance-mode": "1.0.*",
"neitanod/forceutf8": "dev-master"
"neitanod/forceutf8": "dev-master",
"pragmarx/google2fa": "^1.0"
},
"require-dev": {
"fzaninotto/faker": "~1.4",

119
composer.lock generated
View File

@@ -4,8 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "ed9f8700f2dcd943ff662a82e4d8314f",
"content-hash": "9c0251ddc1a110d83a762483abeea079",
"hash": "a188b3cf19debb9f4ad80016cb02bacd",
"content-hash": "d05155478c07249acdb2fed3d47189e6",
"packages": [
{
"name": "aws/aws-sdk-php",
@@ -197,6 +197,60 @@
],
"time": "2016-07-29 15:00:36"
},
{
"name": "christian-riesen/base32",
"version": "1.3.1",
"source": {
"type": "git",
"url": "https://github.com/ChristianRiesen/base32.git",
"reference": "0a31e50c0fa9b1692d077c86ac188eecdcbaf7fa"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ChristianRiesen/base32/zipball/0a31e50c0fa9b1692d077c86ac188eecdcbaf7fa",
"reference": "0a31e50c0fa9b1692d077c86ac188eecdcbaf7fa",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "4.*",
"satooshi/php-coveralls": "0.*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.1.x-dev"
}
},
"autoload": {
"psr-4": {
"Base32\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Christian Riesen",
"email": "chris.riesen@gmail.com",
"homepage": "http://christianriesen.com",
"role": "Developer"
}
],
"description": "Base32 encoder/decoder according to RFC 4648",
"homepage": "https://github.com/ChristianRiesen/base32",
"keywords": [
"base32",
"decode",
"encode",
"rfc4648"
],
"time": "2016-05-05 11:49:03"
},
{
"name": "classpreloader/classpreloader",
"version": "3.0.0",
@@ -2056,6 +2110,67 @@
],
"time": "2016-03-18 20:34:03"
},
{
"name": "pragmarx/google2fa",
"version": "v1.0.1",
"source": {
"type": "git",
"url": "https://github.com/antonioribeiro/google2fa.git",
"reference": "b346dc138339b745c5831405d00cff7c1351aa0d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/antonioribeiro/google2fa/zipball/b346dc138339b745c5831405d00cff7c1351aa0d",
"reference": "b346dc138339b745c5831405d00cff7c1351aa0d",
"shasum": ""
},
"require": {
"christian-riesen/base32": "~1.3",
"paragonie/random_compat": "~1.4|~2.0",
"php": ">=5.4",
"symfony/polyfill-php56": "~1.2"
},
"require-dev": {
"phpspec/phpspec": "~2.1"
},
"suggest": {
"bacon/bacon-qr-code": "Required to generate inline QR Codes."
},
"type": "library",
"extra": {
"component": "package",
"frameworks": [
"Laravel"
],
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"psr-4": {
"PragmaRX\\Google2FA\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Antonio Carlos Ribeiro",
"email": "acr@antoniocarlosribeiro.com",
"role": "Creator & Designer"
}
],
"description": "A One Time Password Authentication package, compatible with Google Authenticator.",
"keywords": [
"Authentication",
"Two Factor Authentication",
"google2fa",
"laravel"
],
"time": "2016-07-18 20:25:04"
},
{
"name": "psr/http-message",
"version": "1.0.1",

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

@@ -27,6 +27,7 @@ return [
*/
'debug' => env('APP_DEBUG', false),
'warn_debug' => env('WARN_DEBUG', true),
/*
|--------------------------------------------------------------------------
@@ -109,6 +110,7 @@ return [
*/
'log' => env('APP_LOG', 'single'),
'log-level' => env('APP_LOG_LEVEL', 'error'),
/*
@@ -212,7 +214,7 @@ return [
Fideloper\Proxy\TrustedProxyServiceProvider::class,
MisterPhilip\MaintenanceMode\MaintenanceModeServiceProvider::class,
MisterPhilip\MaintenanceMode\MaintenanceCommandServiceProvider::class,
PragmaRX\Google2FA\Vendor\Laravel\ServiceProvider::class,
/*
* Custom service provider
*/
@@ -269,6 +271,7 @@ return [
'View' => Illuminate\Support\Facades\View::class,
'Form' => 'Collective\Html\FormFacade',
'Html' => 'Collective\Html\HtmlFacade',
'Google2FA' => PragmaRX\Google2FA\Vendor\Laravel\Facade::class,
],
];

View File

@@ -104,4 +104,21 @@ return [
],
],
/*
|--------------------------------------------------------------------------
| Login throttling
|--------------------------------------------------------------------------
|
| This handles the max failed login attempt throttling.
| You should not change the values here, but should change them in your
| application's .env file instead, as future changes to this file could
| overwrite your changes here.
|
*/
'throttle' => [
'max_attempts' => env('LOGIN_MAX_ATTEMPTS', 10),
'lockout_duration' => env('LOGIN_LOCKOUT_DURATION', 60),
],
];

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

@@ -73,6 +73,12 @@ return [
'dump_command_path' => env('DB_DUMP_PATH', '/usr/local/bin'), // only the path, so without 'mysqldump'
'dump_command_timeout' => 60 * 5, // 5 minute timeout
'dump_using_single_transaction' => true, // perform dump using a single transaction
'options' => (env('DB_SSL')) ? [
PDO::MYSQL_ATTR_SSL_KEY => env('DB_SSL_KEY'), // /path/to/key.pem
PDO::MYSQL_ATTR_SSL_CERT => env('DB_SSL_CERT'), // /path/to/cert.pem
PDO::MYSQL_ATTR_SSL_CA => env('DB_SSL_CA'), // /path/to/ca.pem
PDO::MYSQL_ATTR_SSL_CIPHER => env('DB_SSL_CIPHER')
] : []
],
'pgsql' => [

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

@@ -106,7 +106,7 @@ return array(
'display' => true,
),
array(
'permission' => 'accessory.create',
'permission' => 'accessories.create',
'label' => 'Create ',
'note' => '',
'display' => true,
@@ -279,6 +279,16 @@ return array(
),
'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,7 @@
<?php
return array (
'app_version' => 'v3.4.0',
'hash_version' => 'v3.4.0-9-g67315d8',
'app_version' => 'v3.6.4',
'build_version' => '12',
'hash_version' => 'gf7e4fca',
'full_hash' => 'v3.6.4-12-gf7e4fca',
);

3
crowdin.yml Normal file
View File

@@ -0,0 +1,3 @@
files:
- source: /resources/lang/en/**/*.php
translation: '**/%original_file_name%'

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

@@ -11,6 +11,11 @@
|
*/
use App\Models\Company;
use App\Models\Location;
use App\Models\Manufacturer;
use App\Models\Supplier;
$factory->defineAs(App\Models\Asset::class, 'asset', function (Faker\Generator $faker) {
return [
'name' => $faker->catchPhrase,
@@ -22,9 +27,12 @@ $factory->defineAs(App\Models\Asset::class, 'asset', function (Faker\Generator $
'asset_tag' => $faker->unixTime('now'),
'notes' => $faker->sentence,
'purchase_date' => $faker->dateTime(),
'purchase_cost' => $faker->randomFloat(2),
'order_number' => $faker->numberBetween(1000000,50000000),
'supplier_id' => $faker->numberBetween(1,5),
'requestable' => $faker->numberBetween(0,1),
'company_id' => Company::inRandomOrder()->first()->id,
'requestable' => $faker->boolean()
];
});
@@ -34,25 +42,33 @@ $factory->defineAs(App\Models\AssetModel::class, 'assetmodel', function (Faker\G
'name' => $faker->catchPhrase,
'manufacturer_id' => $faker->numberBetween(1,10),
'category_id' => $faker->numberBetween(1,9),
'modelno' => $faker->numberBetween(1000000,50000000),
'model_number' => $faker->numberBetween(1000000,50000000),
'eol' => 1,
'notes' => $faker->paragraph(),
'requestable' => $faker->boolean(),
];
});
$factory->defineAs(App\Models\Location::class, 'location', function (Faker\Generator $faker) {
return [
'name' => $faker->city,
'city' => $faker->city,
'state' => $faker->stateAbbr,
'country' => $faker->countryCode,
'currency' => $faker->currencyCode,
];
return [
'name' => $faker->catchPhrase,
'address' => $faker->streetAddress,
'address2' => $faker->secondaryAddress,
'city' => $faker->city,
'state' => $faker->stateAbbr,
'country' => $faker->countryCode,
'currency' => $faker->currencyCode,
'zip' => $faker->postcode
];
});
$factory->defineAs(App\Models\Category::class, 'asset-category', function (Faker\Generator $faker) {
return [
'name' => $faker->text(20),
'category_type' => $faker->randomElement($array = array ('asset')),
'eula_text' => $faker->paragraph(),
'require_acceptance' => $faker->boolean(),
'checkin_email' => $faker->boolean()
];
});
@@ -94,8 +110,14 @@ $factory->defineAs(App\Models\Component::class, 'component', function (Faker\Gen
return [
'name' => $faker->text(20),
'category_id' => $faker->numberBetween(21,25),
'total_qty' => $faker->numberBetween(3, 10),
'location_id' => Location::inRandomOrder()->first()->id,
'serial' => $faker->uuid,
'qty' => $faker->numberBetween(3, 10),
'order_number' => $faker->numberBetween(1000000,50000000),
'purchase_date' => $faker->dateTime(),
'purchase_cost' => $faker->randomFloat(2),
'min_amt' => $faker->numberBetween($min = 1, $max = 2),
'company_id' => Company::inRandomOrder()->first()->id
];
});
@@ -108,37 +130,52 @@ $factory->defineAs(App\Models\Depreciation::class, 'depreciation', function (Fak
$factory->defineAs(App\Models\Accessory::class, 'accessory', function (Faker\Generator $faker) {
return [
'company_id' => Company::inRandomOrder()->first()->id,
'name' => $faker->text(20),
'category_id' => $faker->numberBetween(11,15),
'qty' => $faker->numberBetween(5, 10),
'manufacturer_id' => Manufacturer::inRandomOrder()->first()->id,
'location_id' => $faker->numberBetween(1,5),
'order_number' => $faker->numberBetween(1000000,50000000),
'purchase_date' => $faker->dateTime(),
'purchase_cost' => $faker->randomFloat(2),
'qty' => $faker->numberBetween(5, 10),
'min_amt' => $faker->numberBetween($min = 1, $max = 2),
];
});
$factory->defineAs(App\Models\Supplier::class, 'supplier', function (Faker\Generator $faker) {
return [
'name' => $faker->company,
'address' => $faker->streetAddress,
'city' => $faker->city,
'state' => $faker->stateAbbr,
'country' => $faker->countryCode,
'contact' => $faker->name,
'phone' => $faker->phoneNumber,
'email' => $faker->safeEmail,
];
return [
'name' => $faker->company,
'address' => $faker->streetAddress,
'address2' => $faker->secondaryAddress,
'city' => $faker->city,
'state' => $faker->stateAbbr,
'zip' => $faker->postCode,
'country' => $faker->countryCode,
'contact' => $faker->name,
'phone' => $faker->phoneNumber,
'fax' => $faker->phoneNumber,
'email' => $faker->safeEmail,
'url' => $faker->url,
'notes' => $faker->paragraph
];
});
$factory->defineAs(App\Models\Consumable::class, 'consumable', function (Faker\Generator $faker) {
return [
'name' => $faker->text(20),
'company_id' => Company::inRandomOrder()->first()->id,
'category_id' => $faker->numberBetween(16, 20),
'company_id' => $faker->numberBetween(1, 10),
'model_number' => $faker->numberBetween(1000000,50000000),
'item_no' => $faker->numberBetween(1000000,50000000),
'order_number' => $faker->numberBetween(1000000,50000000),
'purchase_date' => $faker->dateTime(),
'purchase_cost' => $faker->randomFloat(2),
'qty' => $faker->numberBetween(5, 10),
'min_amt' => $faker->numberBetween($min = 1, $max = 2),
];
});
@@ -167,7 +204,7 @@ $factory->defineAs(App\Models\Statuslabel::class, 'pending', function (Faker\Gen
'deployable' => 0,
'pending' => 1,
'archived' => 0,
'notes' => ''
'notes' => $faker->sentence
];
});
@@ -242,16 +279,20 @@ $factory->defineAs(App\Models\Statuslabel::class, 'lost', function (Faker\Genera
});
$factory->defineAs(App\Models\License::class, 'license', function (Faker\Generator $faker) {
return [
'name' => $faker->catchPhrase,
'serial' => $faker->uuid,
'seats' => $faker->numberBetween(1, 10),
'license_email' => $faker->safeEmail,
'license_name' => $faker->name,
'purchase_date' => $faker->dateTime(),
'purchase_cost' => $faker->randomFloat(2),
'notes' => $faker->sentence,
];
return [
'name' => $faker->catchPhrase,
'serial' => $faker->uuid,
'seats' => $faker->numberBetween(1, 10),
'license_email' => $faker->safeEmail,
'license_name' => $faker->name,
'order_number' => $faker->numberBetween(1500, 13250),
'purchase_order' => $faker->numberBetween(1500, 13250),
'purchase_date' => $faker->dateTime(),
'purchase_cost' => $faker->randomFloat(2),
'notes' => $faker->sentence,
'supplier_id' => Supplier::inRandomOrder()->first()->id,
'company_id' => Company::inRandomOrder()->first()->id
];
});
$factory->defineAs(App\Models\LicenseSeat::class, 'license-seat', function (Faker\Generator $faker) {
@@ -265,18 +306,82 @@ $factory->defineAs(App\Models\LicenseSeat::class, 'license-seat', function (Fake
});
$factory->defineAs(App\Models\Actionlog::class, 'asset-checkout', function (Faker\Generator $faker) {
$company = 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 = 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 = 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 = 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 = 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 [
@@ -288,11 +393,17 @@ $factory->defineAs(App\Models\CustomField::class, 'customfield-ip', function (Fa
$factory->defineAs(App\Models\User::class, 'valid-user', function (Faker\Generator $faker) {
return [
'first_name' => $faker->firstName,
'last_name' => $faker->lastName,
'email' => $faker->safeEmail,
'password' => $faker->password,
'username' => $faker->username,
];
return [
'first_name' => $faker->firstName,
'last_name' => $faker->lastName,
'username' => $faker->username,
'password' => $faker->password,
'email' => $faker->safeEmail,
'company_id' => Company::inRandomOrder()->first()->id,
'locale' => $faker->locale,
'employee_num' => $faker->numberBetween(3500, 35050),
'jobtitle' => $faker->word,
'phone' => $faker->phoneNumber,
'notes' => $faker->sentence
];
});

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

@@ -12,6 +12,10 @@ class MakePurchaseCostNullable extends Migration
*/
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();
});

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');
});
}
}

View File

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

View File

@@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class RenameModelnoToModelNumber extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('models', function (Blueprint $table) {
//
$table->renameColumn('modelno', 'model_number');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('models', function (Blueprint $table) {
//
$table->renameColumn('model_number', 'modelno');
});
}
}

View File

@@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class RenameConsumableModelnoToModelNumber extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('consumables', function (Blueprint $table) {
//
$table->renameColumn('model_no', 'model_number');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('consumables', function (Blueprint $table) {
//
$table->renameColumn('model_number', 'model_no');
});
}
}

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