Compare commits

..

280 Commits

Author SHA1 Message Date
snipe
141b0b410b Change variable name to be clearer 2019-07-23 18:23:51 -07:00
snipe
d40f06373e DIsable CORS allowed origins by default to replicate existing behavior 2019-07-23 18:23:39 -07:00
snipe
56753fa4cd More clarification 2019-07-23 18:07:45 -07:00
snipe
8a7bafb575 Clarified header comments 2019-07-23 18:05:07 -07:00
snipe
82f91cb944 Fixed typo 2019-07-23 18:03:53 -07:00
snipe
41b226e5fc Added APP_CORS_ALLOWED_ORIGINS env option 2019-07-23 18:02:51 -07:00
snipe
ae6048a6ea Changed order so CORS will still work if throttle hit 2019-07-23 18:02:27 -07:00
snipe
ef41e0060a Added CORS support to API 2019-07-23 17:17:01 -07:00
snipe
a0f3fc6d76 Bumped hash 2019-07-18 14:37:54 -07:00
snipe
74e647fea7 Apply fix from PR #7273 to master 2019-07-18 14:37:48 -07:00
snipe
55ee90b25d Fixes #7252 form request changes (#7272)
* Fixes for #7252 - custom fields not validating / no validaton messages in API w/form requests

* Removed debug info

* More fixes for #7252

This is mostly working as intended, if not yet the way Laravel wants us to do it.

Right now, the API returns correctly, and the form UI will return highlighted errors, with the input filled in ~sometimes~. I’m not sure why it’s only sometimes yet, but this is potentially progress.

* Removed experimental method

* Check for digits_between:0,240 for warranty

* Removed debug code
2019-07-18 14:32:23 -07:00
snipe
eec445fcf5 Command to fix custom field unicode conversion differences between PHP versions (#7263) 2019-07-18 14:30:18 -07:00
snipe
cef22c3158 Caps asset warranty to 20 years 2019-07-18 09:49:58 -07:00
snipe
61fb38087e Bumped hash 2019-07-17 17:55:53 -07:00
snipe
0e93495ca2 Check that the user has assets and that the aset model is valid 2019-07-17 17:51:35 -07:00
snipe
444e250609 Fixed countable() strings on user destroy 2019-07-17 17:51:13 -07:00
snipe
77a6f6f400 Cap warranty months to 3 on the frontend blade 2019-07-17 12:15:15 -07:00
snipe
15bfd07f30 Cap warranty months to three characters
Filles rollbar 209
2019-07-17 12:13:15 -07:00
snipe
fecf8015a1 Added space between footer and custom message 2019-07-17 12:09:32 -07:00
snipe
79ab0d8dc2 Check for valid seat on hardware view 2019-07-17 12:09:18 -07:00
snipe
b4b6d6b571 Comment clarification on #7186 2019-07-15 15:31:09 -07:00
snipe
8c73a47afb Fixed #7186 - has vs filled in User’s API blanking out groups if no group_ids are passed 2019-07-15 15:27:02 -07:00
snipe
f82ffe378c Merge branch 'master' of https://github.com/snipe/snipe-it 2019-07-15 14:11:18 -07:00
snipe
984c2a8fd4 Better log message for bad LDAP connection 2019-07-15 14:10:57 -07:00
snipe
6736b1c4e7 Addresses #7238 - add PWA code to layout
Needs additional UX testing
2019-07-15 13:49:56 -07:00
Ivan Nieto
d409be6d43 Fix #6910: Add logic to manipulate the eloquent query. (#7006)
* Added company_id to consumables_users table

* Added logic to manage when a pivot table doesn't have the column company_id trough a join with users

* Remove a migration that tries to fix this problem, but is not longer necessary
2019-07-15 13:02:44 -07:00
Thomas Misilo
e1b33f3087 Spelling Correction (#7206)
Fixed Spelling for the word reqrite, to be rewrite.
2019-06-27 18:33:13 -07:00
snipe
740d5a6846 Downgrading rollbar for Laravel 5.5 2019-06-25 18:07:21 -07:00
snipe
d19df4ded8 Bumped version 2019-06-24 14:43:44 -07:00
Kasey
03a4512406 fixing previous commit's actual wiping of password (#7183)
replaced Input::fille('ldap_pword') with _filled_.   Should be good to go.  

https://github.com/snipe/snipe-it/issues/7179

https://github.com/snipe/snipe-it/issues/7169
2019-06-19 14:21:53 -07:00
snipe
de992e4df3 Fixed LDAP password blanking on save 2019-06-14 17:20:37 -07:00
snipe
a85251aa83 Fixed #7164 - change table name to permission_groups 2019-06-14 10:37:20 -07:00
snipe
26a1181765 Possible fix for reporting/admin migration back in time 2019-06-12 18:53:53 -07:00
snipe
cef030cf55 Fixed permission insert
//TODO

Handle this via model
2019-06-12 18:39:55 -07:00
snipe
2bfa05fd2d Back in time fix FOR #7145 for new installs on MySQL 8+ 2019-06-12 16:24:55 -07:00
snipe
30904dd019 Reduce minimum group name length to 2 (from 3)
eg: IT
2019-06-12 15:56:19 -07:00
snipe
1d0d25db37 Fixed #7145 - rename groups table to permissions_group for mysql 8 reserved word compatibility 2019-06-12 15:51:47 -07:00
snipe
cbff66c9db Improved error checking in locations importer 2019-06-10 18:50:41 -07:00
snipe
27231d49ea Small fixes for phpleague CSB reader v9 2019-06-03 22:05:16 -07:00
snipe
765417c0be Bumped point version 2019-05-31 14:17:26 -07:00
snipe
49a255c8fb Changed has to filled to fix bulk asset editing 2019-05-31 14:11:43 -07:00
snipe
925d3a23c6 Bumped hash 2019-05-31 13:11:07 -07:00
snipe
6966c132d0 Update language strings 2019-05-31 12:17:09 -07:00
snipe
c29ab90029 Added Filipino, corrected order for Spanish variations 2019-05-31 11:58:14 -07:00
snipe
d2bbc09892 Increased throttle to 120 requests per minute 2019-05-31 11:57:57 -07:00
snipe
74a2c29bc2 Fixed #7100 - Check if $user isset on checkin 2019-05-30 19:06:30 -07:00
snipe
2c64739e8f Removed old comments 2019-05-30 19:02:20 -07:00
snipe
37f950ab42 Fixed #7099 - set email to null by default for backup notifications 2019-05-29 19:09:37 -07:00
snipe
b07a254e60 Bumped version 2019-05-29 15:51:54 -07:00
snipe
087cdd859e Fixed #7092 - handle weird port forwarding/port numbers for baseUrl 2019-05-29 14:57:58 -07:00
snipe
829d44bd27 Fixed #7098 - updated backup config for deleteFile() method 2019-05-29 14:47:55 -07:00
snipe
db76090e10 Missed one 2019-05-28 19:12:53 -07:00
snipe
03cf3b5431 Bumped release again :( 2019-05-28 19:12:42 -07:00
snipe
40f101d471 Merge branch 'master' of https://github.com/snipe/snipe-it 2019-05-28 19:08:39 -07:00
snipe
7aa6ef5f6c Bumped version 2019-05-28 19:08:35 -07:00
Kasey
186b94751d Dockerfile update to bring us up to php v7.1 for Laravel 5.5 (#7084)
* bump up to php7.1

& change deprecated MAINTAINER to a LABEL so it is visible with `docker inspect`

* AND modapache ><

* 2 updates required to get software-properties+ppa
2019-05-28 16:58:32 -07:00
snipe
6f2717a876 Updated branch in version file 2019-05-28 13:22:59 -07:00
snipe
a014af4c47 Fixed #7083 - Removed user_exists constraint on department save
If the user has been deleted, this prevented the department from being successfully saved on edit
2019-05-28 13:18:31 -07:00
snipe
2dd31544fe Increased image size to 800px, added lightboxes 2019-05-24 19:11:08 -07:00
snipe
237acdcff0 Show accessory image on view page 2019-05-24 18:22:57 -07:00
snipe
5db7a7c196 More Atlassian clarifications 2019-05-24 18:10:19 -07:00
snipe
68acdff11b Added link to Atlassian plugin 2019-05-24 18:08:40 -07:00
snipe
58e72e5ee6 Derp - typo 2019-05-24 18:06:15 -07:00
snipe
6b43cd10ba Updated README 2019-05-24 18:05:28 -07:00
snipe
b2c9a38db8 Fixed casing in sync command 2019-05-24 16:12:43 -07:00
snipe
6dcdb5abae Only display the file if the log record can be found 2019-05-24 16:06:52 -07:00
snipe
56576d9e45 Fixed more camel-casing -> snake-casing 2019-05-24 16:01:12 -07:00
snipe
d5c3ee5ed0 Only try to get fieldset if model is valid 2019-05-24 15:44:54 -07:00
snipe
18db0a50f1 Only gtry to delete the file if a record is found in the log 2019-05-24 15:44:40 -07:00
snipe
d596ced0a0 Fixed free_seats_count variable name
(I forgot that Laravel switched camel case to snake case for their old 5.4 withCount variables)
2019-05-24 15:44:18 -07:00
snipe
78fb2b2239 Only build the log upload destination path if there is a matching record
Fixes [ch1232]
2019-05-24 15:28:53 -07:00
snipe
1472e9d5b5 Check for valid model before attempting to access fieldsets
Fixes [ch1249]
2019-05-24 15:03:15 -07:00
snipe
fcbc7e4540 Fixed Undefined variable user in $backto if checked out to a non-user
Fixes [ch9194]
2019-05-24 14:51:27 -07:00
snipe
93bf541ce7 Fixed missed consumables_count withCount() statement 2019-05-24 14:21:53 -07:00
snipe
0e48d7b080 Removed alert-danger from tests 2019-05-24 14:21:37 -07:00
snipe
1e6c85da41 Removed custom fields from AssignedSearch to prevent confusing data in selectlist
Fixes [ch9193]
2019-05-24 13:50:11 -07:00
snipe
c5a23e8f5e Fixed bug where sorting by company name in Users API did not work
Fixes [ch9200]
2019-05-24 13:37:20 -07:00
snipe
b6d2392303 Small fix for reordering fields
Fixes Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'order' cannot be null (SQL: insert into `custom_field_custom_fieldset` (`custom_field_id`, `custom_fieldset_id`, `order`, `required`) values (12, 7, , 0)) [ch1151]

This needs revisiting for a more solid fix, especially for data that was already entered bad.
2019-05-24 12:05:52 -07:00
snipe
9995f1a743 Fixed field mapping 2019-05-24 11:45:07 -07:00
snipe
d6f251e992 Updated importer to work with newer CSV Reader::getRecords() method 2019-05-24 11:44:57 -07:00
snipe
4be95eac4b Removed extra escaping on checkin 2019-05-24 11:44:39 -07:00
snipe
8914d14681 Tidied up license check 2019-05-24 05:26:52 -07:00
snipe
d4725b61be Check that a model exists before trying to fiddle with fieldsets 2019-05-24 04:48:04 -07:00
snipe
aa0b627fe7 Fixed missing asset validation 2019-05-24 04:47:35 -07:00
snipe
5be5e3271d Trying to fix ajax asset validation
This I think gets us closer, but still not handling the validation on the asset properly.

When I do a print_r of the validation in the other items, its looking for an error bag that looks something like this:

```
Illuminate\Support\MessageBag Object
(
    [messages:protected] => Array
        (
            [name] => Array
                (
                    [0] => The name field is required.
                )

            [seats] => Array
                (
                    [0] => The seats field is required.
                )

            [category_id] => Array
                (
                    [0] => The category id field is required.
                )

        )

    [format:protected] => :message
)
```

Currently the Assets ajax returns:

```
[2019-05-24 06:52:06] develop.ERROR: array (
  'messages' =>
  array (
    'model_id' =>
    array (
      0 => 'The model id field is required.',
    ),
    'status_id' =>
    array (
      0 => 'The status id field is required.',
    ),
    'asset_tag' =>
    array (
      0 => 'The asset tag field is required.',
    ),
  ),
)
```

So not sure why it’s not working.
2019-05-24 03:55:31 -07:00
snipe
dd5d5cc07c Handle JSON validation errors like 5.4 2019-05-24 01:12:38 -07:00
snipe
84c3709161 Handle JSON validation errors like 5.4 2019-05-24 01:12:21 -07:00
snipe
96e2d74ae3 Handle JSON validation errors like 5.4 2019-05-24 00:46:30 -07:00
snipe
bf93e8cc32 Use getReader instead of fetchAssoc for CSV parser
https://csv.thephpleague.com/9.0/upgrading/
2019-05-23 19:09:58 -07:00
snipe
d1a8955ef9 Bumped packages 2019-05-23 19:09:14 -07:00
snipe
149ac4bdf8 Removed cosole log 2019-05-23 17:52:53 -07:00
snipe
2d036c64e9 Change ->has() to ->filled() 2019-05-23 17:39:50 -07:00
snipe
8db2470ac4 Switch has() to filled() 2019-05-23 17:17:46 -07:00
snipe
79156ff8f4 Bumped version 2019-05-23 17:10:47 -07:00
snipe
8e86d780bf Fix for included files in backup 2019-05-23 17:08:51 -07:00
snipe
f6ef139111 Fixed baseUrl is undefined error
I literally cannot figure out how this ever worked before.
2019-05-23 16:56:22 -07:00
snipe
12ec2d1f7a Fixed custom field edit screen 2019-05-22 01:07:14 -07:00
snipe
0dfc28b0e8 Bumped laravel version in readme 2019-05-22 01:04:42 -07:00
snipe
b3132a4a8f Updated travis with new php versions 2019-05-22 01:03:11 -07:00
snipe
6cd25fbdeb Updated backup path in backup admin 2019-05-22 00:56:14 -07:00
snipe
4be8ba9f17 Updated withCount to use manual naming 2019-05-22 00:52:51 -07:00
snipe
df8008f1ed Renamed fire() to handle() 2019-05-22 00:52:32 -07:00
snipe
77547c528b Added the command loader to console kernel 2019-05-22 00:52:14 -07:00
snipe
bfb910f375 Set the serialization 2019-05-22 00:51:43 -07:00
snipe
57e80ee317 Removed old laravel backups config
This config file was renamed in a newer version of spatie laravel-backup
2019-05-22 00:51:33 -07:00
snipe
de1189295a Added spatie language files 2019-05-22 00:51:00 -07:00
snipe
20d0dce73e Use laravel v5.5 withCount manual aliases 2019-05-22 00:50:48 -07:00
snipe
144a32b1ca Removed debugbar service provider (autodiscovery) 2019-05-22 00:50:00 -07:00
snipe
8244a2ad23 New backups config for spatie 2019-05-22 00:49:38 -07:00
snipe
77c3b8f8c1 Updated packages 2019-05-22 00:07:49 -07:00
snipe
7b34cf1a31 Bumped version 2019-05-21 19:17:56 -07:00
snipe
21ec670531 Updated language strings 2019-05-21 19:17:00 -07:00
snipe
b2eacb147b Fixed #7046 - added user website url back into UI 2019-05-21 18:55:12 -07:00
snipe
729e3eb70d Updated email strings 2019-05-21 18:43:00 -07:00
snipe
978533b2f4 Fixed XSS vulnerability when creating a new categories, etc via modal on create
Same fix as before, because of the weird select2 post-parsing ajax behavior
2019-05-21 18:29:50 -07:00
snipe
0358d13ddb Fixed #7044 - API update deleted custom fields if they are not re-presented 2019-05-20 11:49:18 -07:00
snipe
c944304444 Updated packages
- Updating erusev/parsedown (v1.7.2 => 1.7.3): Downloading (100%)
  - Updating squizlabs/php_codesniffer (3.4.1 => 3.4.2): Downloading (100%)
  - Updating symfony/polyfill-mbstring (v1.10.0 => v1.11.0): Downloading (100%)
  - Updating symfony/var-dumper (v3.4.23 => v3.4.27): Downloading (100%)
  - Updating league/flysystem (1.0.50 => 1.0.51): Downloading (100%)
  - Updating symfony/translation (v3.4.23 => v3.4.27): Downloading (100%)
  - Updating nesbot/carbon (1.36.2 => 1.37.1): Downloading (100%)
  - Updating symfony/debug (v3.4.23 => v3.4.27): Downloading (100%)
  - Updating symfony/console (v3.4.23 => v3.4.27): Downloading (100%)
  - Updating symfony/finder (v3.4.23 => v3.4.27): Downloading (100%)
  - Updating symfony/polyfill-ctype (v1.10.0 => v1.11.0): Downloading (100%)
  - Updating symfony/polyfill-php70 (v1.10.0 => v1.11.0): Downloading (100%)
  - Updating symfony/http-foundation (v3.4.23 => v3.4.27): Downloading (100%)
  - Updating symfony/event-dispatcher (v3.4.23 => v3.4.27): Downloading (100%)
  - Updating symfony/http-kernel (v3.4.23 => v3.4.27): Downloading (100%)
  - Updating symfony/process (v3.4.23 => v3.4.27): Downloading (100%)
  - Updating symfony/routing (v3.4.23 => v3.4.27): Downloading (100%)
  - Updating symfony/polyfill-util (v1.10.0 => v1.11.0): Downloading (100%)
  - Updating symfony/polyfill-php56 (v1.10.0 => v1.11.0): Downloading (100%)
  - Updating symfony/psr-http-message-bridge (v1.1.1 => v1.1.2): Downloading (failed)
Downloading (100%)
  - Updating rollbar/rollbar (v1.7.5 => v1.8.1): Downloading (100%)
  - Updating symfony/yaml (v3.4.23 => v3.4.27): Downloading (100%)
  - Updating symfony/browser-kit (v3.4.23 => v3.4.27): Downloading (100%)
2019-05-20 10:10:46 -07:00
Bob Clough
096393389c Fixes #5054: LDAP users deactivated for none-ad (#7032)
When using none-AD ldap, users are automatically deactivated every LDAP
sync.  This commit changes the behaviour so that if the active flag isn't set,
the users are enabled.

Fixed #5054, at least for 4.X
2019-05-16 09:31:55 -07:00
snipe
9eb7b668d1 Fixed #6880 - correctly encrypt encrypted fields via the API 2019-05-15 19:33:30 -07:00
snipe
6728089106 Fixed #6883 - remove escaping of fields on LDAP import 2019-05-15 19:15:41 -07:00
snipe
33b59d7bed Bumped version 2019-05-15 16:45:07 -07:00
snipe
888bdbdb68 Added ability to update groups via API
Fixes [ch9139]
2019-05-15 16:39:34 -07:00
snipe
d67c931f6a Import locations from CSV via command line (#7021)
* Added import locations command

* Small fixes to location importer

* Added country, LDAP OU

* Cleaned up comments, added more clarification to what the script does
2019-05-13 02:27:19 -07:00
snipe
dbdc511eff Merge branch 'master' of https://github.com/snipe/snipe-it 2019-05-08 09:23:58 -04:00
snipe
f47b960566 Added API middleware to API routes to enable throttling
TODO: Figure out how to make this costumizable without touching the code
2019-05-08 09:23:54 -04:00
snipe
d016076806 Fixed #6956 - viewKeys policy inconsistent (#7009)
* Fixed #6956 - Added additional gates show showing/hiding license keys

* Modified gate to allow user to see licenses if they can create or edit the license as well
2019-05-08 08:14:49 -04:00
snipe
23fa5d0bf4 Fixed #7003 - crash when warranty months or purchase date is null 2019-05-07 15:33:57 -04:00
Joris van Eijden
486c708911 Leave the activated state for users alone in normal LDAP synchronisation. (#6988) 2019-05-06 09:40:53 -04:00
snipe
e5c2d77c7d Fixes #6204 - added email alerts and web/API access to assets due for audits (#6992)
* Added upcoming audit report

TODO: Fid diff/threshold math

* Added route to list overdue / upcoming assets via API

* Controller/API methods for due/overdue audits

We could probably skip this and just handle it via view in the routes…

* Added query scopes for due and overdue audits

* Added audit due console command to kernel

* Added ability to pass audit specs to main API asset search method

* Added audit presenter

* Added bootstrap-tables presenter formatter to display an audit button

* Added gated sidenav items to left nav

* Added audit due/overdue blades

* Cleanup on audit due/overdue console command

* Added language strings for audit views

* Fixed :threshold placeholder

* Removed unused setting variable

* Fixed next audit date math

* Added scope for both overdue and upcoming

* Derp. Wrong version

* Bumped version

(I will release this version officially tomorrow)
2019-05-05 22:32:52 -04:00
snipe
ce16eae508 Merge branch 'master' of https://github.com/snipe/snipe-it 2019-05-02 15:20:52 -07:00
snipe
dc73dbfbfd Fixed #6911 - note must be a string on license checkin 2019-05-02 15:20:47 -07:00
snipe
dae26e0378 Remove “Imported from LDAP” note override 2019-04-18 17:56:08 -04:00
snipe
1bb1f7342f Fixed #6922 - date_add crashing if EOL is null 2019-04-18 15:49:59 -04:00
snipe
420e8bc85a Allow phone number to be changed in Profile 2019-04-18 14:13:50 -04:00
snipe
a521523d45 Truncate imports table on seed 2019-04-18 14:13:33 -04:00
snipe
25884a893e Bumped version 2019-03-20 02:41:33 -07:00
snipe
d1e9fbfa24 Updated compoer 2019-03-20 02:37:44 -07:00
snipe
da015ec4a8 Fixed #6834 and #6402 - use inline QR code generation for 2FA (#6840)
* Fixed  #6834 and #6402 - use inline QR code generation for

* Update auth controllers to use translations

* Updated composer lock

* Added comments

* Moar comments

* Typo
2019-03-20 01:24:31 -07:00
snipe
1451b4f45d Merge branch 'master' of https://github.com/snipe/snipe-it 2019-03-18 20:51:11 -07:00
snipe
b6da68a69c Bumped version 2019-03-18 20:50:47 -07:00
snipe
dee92cfc6c Fixes XSS vulnerabilities (#6831)
* Properly escape log_meta values

* Vue syntax fix to allow npm run dev to work again

* Janky fix for Select2 bug

* Compiled production assets

* Escape user’s last name in API

* Removed duplicate alertClass

* Compiled production assets
2019-03-18 20:49:32 -07:00
snipe
dec77890bd Merge branch 'master' of https://github.com/snipe/snipe-it 2019-03-18 11:59:48 -07:00
snipe
0e1289f12f Fixes #6821 - fixed 2 fa active for users list (#6822)
* Fixed #6821 - confusing UI for 2FA when 2FA is universally enforced

I also updated the language in the user’s listing table to clarify what “activated” means

* Added login enabled info to user view

* Clarified comments

* Added info about 2FA on user profile

Because why not

* Added nowrap to table, and added 2FA reset for superadmins
2019-03-18 11:59:02 -07:00
snipe
7b33f95e83 Fixes/import permissions mask (#6826)
* Check for empty headers in import

* Added import permission

* Fixed model path in docblock

* Added import gate to default blade

* Check if the user is an admin OR idf they have import permissions

* Walked back that admin permission

Since admins are bound by full company support, it makes less sense to let admins have this permission by default, versus having them specifically designated to the import permission
2019-03-18 11:58:08 -07:00
snipe
ab6744dfba Merge branch 'master' of https://github.com/snipe/snipe-it 2019-03-14 15:38:20 -07:00
snipe
0fd940ffa4 Check for empty headers in import 2019-03-14 15:38:07 -07:00
Tim Farmer
5893e25b43 Label bugs in alerts settings (#6808)
* Label bugs in alerts settings

Found another label bug where the alert_email label should be alerts_enabled.

* Update alerts.blade.php
2019-03-14 10:53:05 -07:00
snipe
7c3bbe3097 Fixes #6776 hungary date format (#6823)
* Add @timothyfarmer as a contributor

* Fixed #6776 - added hungary time format
2019-03-13 19:39:38 -07:00
snipe
858d382e26 Changed logging to info level for LDAP 2019-03-13 15:14:03 -07:00
snipe
de16fee00a Change image unlink error log to info from error 2019-03-13 12:22:12 -07:00
Tim Farmer
7deab0f53b Label bugs in general settings (#6801)
* checkbox label bug

The checkbox label in general settings for require_accept_signature was set to full_multiple_companies_support instead so when you click the label for require accept signature it would check the wrong box.

* Update general.blade.php

* Update general.blade.php

Another label that is wrong in general settings
2019-03-08 12:24:24 -08:00
Jonathon Reinhart
e59ec8b27f Run Laravel schedule in docker image using supervisord (#6606)
* docker: Rename /entrypoint.sh to /startup.sh

This script is not configured as the docker image ENTRYPOINT, thus it is
misleading to name it so.

* docker: Terminate supervisord if a process enters the FATAL state

By terminating PID 1, this will also terminate the Docker container.

* docker: Use supervisord to start up apache and cron

Note that this uses `apache2ctl -DFOREGROUND` rather than manually
sourcing /etc/apache2/envvars and running apache2, as recommended at
https://advancedweb.hu/2018/07/03/supervisor_docker/.

* docker: Add artisan schedule:run to crontab

This also switches to executing /var/www/html/artisan directly.

* docker: Run artisan schedule:run directly from supervisor

This has the following benefits over using cron:
- Cron doesn't need to be installed
- Docker-provided environment variables are preserved
- It's easy and explicit to run as the docker user
2019-03-07 12:42:00 -08:00
snipe
6d98bd6846 Fixed error if item requested or request was deleted (#6786)
ch628
2019-03-05 23:47:36 -08:00
snipe
58768e5aee Added ability to search consumables by item number (#6785)
Fixes ch1086
2019-03-05 23:21:22 -08:00
snipe
28a450ea25 Added ability to do full name search in user dropdown selectlist (#6784) 2019-03-05 21:13:39 -08:00
snipe
1393f44070 Create FUNDING.yml 2019-03-04 23:57:17 -08:00
snipe
8016939f31 Merge branch 'master' of https://github.com/snipe/snipe-it 2019-03-01 17:39:55 -08:00
snipe
c1ad2f9376 Added link to Marksman - A Windows agent for Snipe-IT
Per https://github.com/Scope-IT/marksman/issues/9#issuecomment-468275142
2019-03-01 17:39:50 -08:00
snipe
9575cd2651 Add accessories endpoint to user API (#6775) 2019-03-01 17:21:03 -08:00
snipe
cf086b711e Merge branch 'master' of https://github.com/snipe/snipe-it 2019-02-22 13:24:58 -08:00
snipe
53db96edad Bumped minor version 2019-02-22 13:24:45 -08:00
snipe
3b62c4a83a Fixes/integrity constraint (#6754)
* Migration to fix nullables

This should fix an issue introduced in 90cddb7aee where we’re passing null instead of an empty string (necessary to nullify values via the API)

* Removed asset migration - serial was already fixed
2019-02-22 13:20:42 -08:00
snipe
5f3147cf36 Added support for enum that was added :( 2019-02-20 21:04:03 -08:00
snipe
738896bdc2 Make serial nullable
Guessing this is new due to later versions of mysql
2019-02-20 20:47:14 -08:00
snipe
e2834fab90 Bumped minor version 2019-02-16 11:48:20 -08:00
snipe
d687e1d762 Fixed #6725 - revert auro_increment_prefix to string
This was mis-migrated as boolean.

It’s essentially a duplicate migration, as it is fixed in-place on the existing migration, and then a new migratio was created to handle anyone who already upgraded.
2019-02-16 11:37:05 -08:00
snipe
6256abddf2 Bumped point release 2019-02-14 15:07:11 -08:00
snipe
b26fbf986f Fixed issue where offset could be greater than total items, resulting in “No results” confusion 2019-02-14 14:49:08 -08:00
snipe
5c9b1ed43a Fixed #6676 - consumables API not respecting category id 2019-02-14 14:48:43 -08:00
snipe
14eb6b387b Possible fix for #6710 - explicitly make auto_increment_prefix nullable (#6716)
* Possible fix for #6710 - explicitly make auto_increment_prefix nullable

* Added migration to make auto_increment_prefix explicitly nullable
2019-02-14 12:46:09 -08:00
snipe
35ebe33e4e Fixed #6703 - fixes password confirmation (#6711)
* Fixed #6703 - fixes password confirmation

* Removed debugging

* Fixed tests

* I guess we use 10 as the settings for password min in tests

* One more try to fix tests - confirmation won’t validate until password validates
2019-02-13 23:01:19 -08:00
snipe
9035707bd6 Bumped point version 2019-02-13 07:40:52 -08:00
snipe
aa1e06f021 One more time…. Fixed #6704 - don’t apply gate to $arrays collection, just check that they can view assets 2019-02-13 04:46:19 -08:00
snipe
30b1cfabf5 Fixed dumb formatting 2019-02-13 04:45:21 -08:00
snipe
e75d22ab73 Revert "Fixed #6704 - don’t apply gate to $arrays collection, just check that they can view assets"
This reverts commit b1e17743b8.
2019-02-13 04:44:19 -08:00
snipe
b1e17743b8 Fixed #6704 - don’t apply gate to $arrays collection, just check that they can view assets 2019-02-13 04:35:55 -08:00
snipe
e2c0f01a10 Fixed #6367 - pass table name and column_id to scopeCompanyables
Solves error: Integrity constraint violation: 1052 Column 'company_id' in where clause is ambiguous
2019-02-13 01:26:11 -08:00
snipe
f88fee0f21 Make user notes field editable via API 2019-02-12 23:58:30 -08:00
snipe
c0669150fb Bumped point version 2019-02-12 23:48:31 -08:00
snipe
f3c12f38b6 Fixed #6061 - Assigned user group cannot be removed
This bug was a result of attempting to check if the groups field had a value, and only THEN trying to sync the groups. This meant that uf you were removing ALL groups, the  sync wouldn’t be triggered.

This still needs to be updated in the API.
2019-02-12 23:43:38 -08:00
snipe
5e19178a30 Do not count deleted locations in managedLocation check on user delete 2019-02-12 23:32:10 -08:00
snipe
90cddb7aee Fixed #6113 - use $asset->fill vs filled() to allow blanking values via API (#6693)
Need to confirm that re-enabling `\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,` won’t mangle anything. I know we ran into some issues when testing a long time ago, but not sure those issues apply anymore, and I can’t remember what they were.
2019-02-12 22:08:38 -08:00
snipe
6d828964be Merge branch 'master' of https://github.com/snipe/snipe-it 2019-02-04 18:58:32 -08:00
snipe
971fcf5800 Fixed #6633 - return 200 status code 2019-02-04 18:58:28 -08:00
Daniel Ruf
2ad270cf33 ci: fix indentation (#6669) 2019-01-30 15:14:17 -08:00
Daniel Ruf
8ce78c6b31 tests: allow to fail on PHP 7.3 and use the latest PHP 7.1 release (#6666) 2019-01-30 14:32:33 -08:00
Daniel Ruf
af3c8195af tests: fix expected string (#6665) 2019-01-30 14:12:20 -08:00
snipe
117b4c59cc Bumped minor version 2019-01-25 21:06:08 -08:00
snipe
194d0733d4 Fixed #6644 - asset name not linked in Reports > Asset Maintenance Report
This report will likely be deprecated.
2019-01-25 20:57:14 -08:00
snipe
a371e8d53f Added calibration as a maintenance type
Should just make these custmizable options
2019-01-24 15:17:33 -08:00
snipe
8f09cca043 Fixed incorrect group route 2019-01-24 15:17:11 -08:00
snipe
39bca49e8f Specify table name in deleted user display 2019-01-24 14:38:18 -08:00
snipe
b8269020ae Specify table name in deleted user display 2019-01-24 14:37:39 -08:00
snipe
601c129bbf Embed images in emails 2019-01-17 20:45:24 -08:00
snipe
b293d00699 Switch LDAP error to debug, to avoid crapping up the logs 2019-01-17 20:18:03 -08:00
snipe
75a0cf97e2 Return an error if asset maintenance is associated with a non-existant asset 2019-01-16 02:19:57 -08:00
snipe
c055e3af21 Only try to return the asset tag link if a valid asset id has been passed 2019-01-16 02:19:35 -08:00
snipe
a1f93e733c Fixed undefined error when maintenance is associated with a deleted asset 2019-01-16 01:45:51 -08:00
fanta8897
49073742b5 Updating LDAP such that each user is not required to be bindable to LDAP (#6571)
* Update Ldap.php

* Update Ldap.php

* Update Ldap.php

* Update Ldap.php

* Update Ldap.php

Updating LDAP.php such that the admin bind will ONLY occur if the user attempting auth cannot bind. If that is the case, it will attempt to bind as admin and search for that user, prior to failing.
2019-01-15 14:04:21 -08:00
Sxderp
187206cb88 Fix saving of REMOTE_USER setting broken by 1a64879b6 (#6565)
The previous commit made it such that remote user login could only
be enabled if two factor authentication was also enabled. Unnest
the configuration so that the setting can be applied without.
2019-01-15 13:59:36 -08:00
Hubert
8420cb7ec1 Fixed problem with import when using snipeit:import command (#6550) 2019-01-15 13:58:23 -08:00
Andrey Bolonin
75252bce05 add php 7.3 (#6556) 2019-01-10 13:21:04 -08:00
snipe
794824713e Bumped minor version 2019-01-03 11:22:06 -08:00
snipe
8f6ea84fca Fixed #4568 - escaping values in custom report 2018-12-12 19:38:24 -08:00
snipe
ea1b792a93 Fixed #6491 - cleaner return methods for PHP 7.3 compact() 2018-12-12 18:23:39 -08:00
Ben RUBSON
4ffb8f14b8 Improve Memcached settings (#6485)
* Improved memcached settings

* Improved memcached settings
2018-12-06 14:39:14 -08:00
Wes Hulette
d023f61bc4 Fixed missing importer (#6413)
Fixed missing manager_id
Fixed missing department_id
2018-12-04 13:06:12 -08:00
snipe
dd5ca73602 Set support footer and version footer to on when resetting the demo 2018-11-08 12:52:37 -08:00
snipe
2632f730d1 Sets activated to 0 in UserImporter if the activated column isn’t set 2018-11-07 22:36:58 -08:00
snipe
24c158bfe6 Added missing use statement for departments in importer 2018-11-07 18:33:43 -08:00
snipe
3d4a5a8066 More importer tweaks for dept and manager 2018-11-07 18:05:53 -08:00
snipe
db7e0b56f2 Fixed department id on asset import with users 2018-11-07 17:36:34 -08:00
snipe
f2478d813c Fix manager id if no manager is given in importer 2018-11-07 17:33:27 -08:00
snipe
192aa9eb71 Fixed #6386 - licenses not searching on category name 2018-11-02 17:14:08 -07:00
Tim Bishop
0eef0fc1dd Sync with develop branch. (#6377)
Without this change argv[1] is ignored.
2018-10-31 11:11:41 -07:00
snipe
81f8fe34cd Removed debugging line 2018-10-30 18:11:27 -07:00
snipe
f744696043 Fixed #6375 - lowercase keys on findAndBindUser to address LDAP syncing issue 2018-10-30 13:12:10 -07:00
snipe
29b0780c6c Added company info to asset maintenances transforrmer 2018-10-30 00:20:16 -07:00
Wes Hulette
6b3b673daa Changed NULL coalesce from ?? (#6353)
PHP 5 does not have the double question mark null coalesce support.
2018-10-26 15:53:18 -07:00
snipe
a4876e9f3e Updated language files 2018-10-26 15:51:38 -07:00
snipe
925258bfb4 Bumped version 2018-10-26 15:29:10 -07:00
snipe
1a10aa0dda Fixed #6349 - add view permission for print all assigned 2018-10-19 16:43:28 -07:00
snipe
d6f8d1b464 Updated composer lock 2018-10-19 16:40:54 -07:00
snipe
09a102fea8 Only try to return a department if there is a matching field 2018-10-19 01:44:45 -07:00
snipe
304fce73fc Null if blank on user import 2018-10-19 01:38:14 -07:00
snipe
295a68bb7a Try false instead of null 2018-10-19 01:36:15 -07:00
snipe
3aeb521782 Patch PR #6335 to master 2018-10-19 01:30:05 -07:00
snipe
f587d2248b WIP: Better handle activation column in importer (#6290)
* Better handle activation column

* Added comments for clarity on importer methods
2018-10-19 00:23:12 -07:00
snipe
8579c5a68a Allow 0 as a consumable min amt 2018-10-15 17:04:51 -07:00
snipe
835b461d7d Fixed #6323 - typo in link for low inventory 2018-10-11 15:31:10 -07:00
Wes Hulette
b8a37a0c73 Fixed Expiring Assets Email (#6321) 2018-10-11 14:03:00 -07:00
snipe
41b5b1dfd0 Bumped hash 2018-10-09 17:32:46 -07:00
snipe
c7596e7741 Fixed image not uploading on asset create 2018-10-09 17:31:52 -07:00
snipe
d4fa81301d Check if user can see assets in statuslabels gate 2018-10-09 16:34:12 -07:00
snipe
ec7245965f Bumped to rollbar 2.4.1
https://github.com/rollbar/rollbar-php-laravel/issues/65
2018-10-04 17:09:12 -07:00
snipe
de76e8db5f Re-enable rollbar 2018-10-04 12:11:36 -07:00
snipe
a52575c7bf Lock rollbar to v2.3.0
https://github.com/rollbar/rollbar-php-laravel/issues/65
https://github.com/rollbar/rollbar-php-laravel/issues/67
2018-10-04 12:11:36 -07:00
Nenad Ticaric
bf6703c2e8 fixing double word typo (#6292)
Thanks!
2018-10-04 09:41:50 -07:00
snipe
4db1dd8afc Fixed #6291 - send-welcome argument in cli importer 2018-10-04 04:43:06 -07:00
snipe
c39e3acb59 Bumped hash 2018-10-04 02:24:41 -07:00
snipe
7a44da85a0 Fixed issue where admin users could disable activation when editing their own profile 2018-10-04 02:18:20 -07:00
snipe
890b613f71 Temporarily suppress rollbar 2018-10-03 15:47:56 -07:00
snipe
1014bd74e0 Updated rollbar 2018-10-03 14:58:14 -07:00
snipe
db385e024b Possible proxy issue fix 2018-10-03 13:04:25 -07:00
snipe
c8bff3ef38 Features/add manager and dept to importer (#6277)
* Ignore the simlink for public storage

* Added manager and department to user import

* More UI importer tweaks

* Fisxed typos
2018-10-02 15:43:54 -07:00
snipe
10bc35d604 Fixed PHP warning Undefined offset: 1 in upgrade.php 2018-09-28 12:13:35 -07:00
snipe
eea65a3f26 Fixed manufacturers item count 2018-09-28 12:03:27 -07:00
snipe
3b21a19491 Updated language strings 2018-09-28 11:54:52 -07:00
snipe
7a52477294 Added Icelandic and Serbian to locale list 2018-09-28 11:47:59 -07:00
snipe
ef0bd72076 Bumped version 2018-09-28 11:21:39 -07:00
snipe
ff824ec4db Fixes #6252 - activated flag not checked when editing active user 2018-09-28 11:18:33 -07:00
snipe
75032def9e Fixed #4151 - Undefined index: samaccountname on LDAP import 2018-09-27 16:11:09 -07:00
snipe
3a0f738fb0 Added some hepful comments 2018-09-26 19:20:50 -07:00
snipe
55846cc717 Changed LOG:: to Log:: 2018-09-26 19:06:31 -07:00
snipe
1784278a59 Fixed importer email test 2018-09-26 19:06:09 -07:00
snipe
afac0bc441 Removed old isActive model (unused) 2018-09-26 19:05:42 -07:00
snipe
ffbee77f6f Patch for 5965 - multiple email recipients no longer working (#6238) 2018-09-26 15:47:53 -07:00
snipe
b69b5fdf84 Added counts to location show() API method 2018-09-21 15:50:14 -07:00
Brady Wetherington
89e06054bf Merge pull request #6205 from dasjoe/patch-1
Fixes #5630
2018-09-17 21:45:48 -07:00
Hajo Möller
3159e7713a Fixes #5630 2018-09-11 13:07:45 +02:00
snipe
adf6e7d1cd Added group support for user API 2018-09-07 18:25:58 -07:00
snipe
ba3662a9ed Bumped hash 2018-09-07 18:12:29 -07:00
snipe
05ea61421f Added manager_id to fillable for locations API 2018-09-07 18:11:38 -07:00
snipe
22ef2ce0b6 Bumped hash 2018-09-07 03:20:31 -07:00
snipe
51d3d130e4 Fixed Not unique table/alias: 'models' on custom report triggered when category is selected 2018-09-07 03:19:54 -07:00
snipe
d8a8e1cc09 Bumped version 2018-08-28 11:43:56 -07:00
snipe
522dc1db2a Fixed #6124 2018-08-23 21:05:10 -07:00
snipe
db907815ff Removed check for active in password reset form 2018-08-21 18:40:27 -07:00
snipe
ae6abdddad Check the user is active before displaying password reset
This would only come into play if an inactive user already received a password reset email and then the system was upgraded to prevent those emails from being sent to inactive users
2018-08-14 19:04:47 -07:00
snipe
63c9fbe10c Temporarily disbable notifying users on import 2018-08-14 18:27:46 -07:00
snipe
101dfd01f2 Bumped hash 2018-08-14 18:22:53 -07:00
snipe
5db5134ae0 Set activated to default on when new user is created 2018-08-14 18:14:41 -07:00
snipe
5294489b0e Fixed HTML typo 2018-08-14 18:14:29 -07:00
snipe
05b2b8fb59 Tweaked code/language for password reset 2018-08-14 18:09:33 -07:00
snipe
0100c56046 Only allow password reset if user is active 2018-08-14 17:46:29 -07:00
Jordi Boggiano
e81b221fd1 Fix license identifier (#6043) 2018-08-08 20:36:45 -07:00
snipe
f374ac1bf7 Removed duplicate BACKUP_ENV in example env 2018-08-01 15:31:43 -07:00
snipe
524c6c502e Features/restore deleted cmd (#5982)
* Delete content from login attempts table

* Script to restore deleted users and put their asset assignments back

* Uncomment backup
2018-07-27 02:42:55 -07:00
snipe
614e858e44 Restrict users asset listing to just assets checked out to users 2018-07-25 21:38:14 -07:00
snipe
708b1a962c Split out custom_css from custom_header
This makes it so that the custom_css will still be respected even if there is no custom header
2018-07-25 19:01:47 -07:00
731 changed files with 21254 additions and 4290 deletions

View File

@@ -1650,6 +1650,15 @@
"contributions": [
"code"
]
},
{
"login": "timothyfarmer",
"name": "Tim Farmer",
"avatar_url": "https://avatars1.githubusercontent.com/u/7632599?v=4",
"profile": "https://github.com/timothyfarmer",
"contributions": [
"code"
]
}
]
}

View File

@@ -7,7 +7,6 @@ APP_KEY=ChangeMe
APP_URL=null
APP_TIMEZONE='UTC'
APP_LOCALE=en
BACKUP_ENV=false
# --------------------------------------------
# REQUIRED: DATABASE SETTINGS
@@ -44,6 +43,7 @@ MAIL_FROM_ADDR=you@example.com
MAIL_FROM_NAME='Snipe-IT'
MAIL_REPLYTO_ADDR=you@example.com
MAIL_REPLYTO_NAME='Snipe-IT'
MAIL_BACKUP_NOTIFICATION_ADDRESS=you@example.com
# --------------------------------------------
# REQUIRED: IMAGE LIBRARY
@@ -66,6 +66,7 @@ SECURE_COOKIES=false
# --------------------------------------------
REFERRER_POLICY=same-origin
ENABLE_CSP=false
CORS_ALLOWED_ORIGINS=null
# --------------------------------------------
# OPTIONAL: CACHE SETTINGS
@@ -73,13 +74,20 @@ ENABLE_CSP=false
CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync
CACHE_PREFIX=snipeit
# --------------------------------------------
# OPTIONAL: REDIS SETTINGS
# --------------------------------------------
REDIS_HOST=null
REDIS_PASSWORD=null
REDIS_PORT-null
REDIS_PORT=null
# --------------------------------------------
# OPTIONAL: MEMCACHED SETTINGS
# --------------------------------------------
MEMCACHED_HOST=null
MEMCACHED_PORT=null
# --------------------------------------------
# OPTIONAL: AWS S3 SETTINGS

5
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,5 @@
# You can add one username per supported platform and one custom link
# patreon: # Replace with your Patreon username
# open_collective: # Replace with your Open Collective username
# ko_fi: # Replace with your Ko-fi username
custom: https://snipeitapp.com/donate

1
.gitignore vendored
View File

@@ -50,3 +50,4 @@ tests/_support/_generated/*
/storage/oauth-public.key
*.cache
/public/storage

View File

@@ -14,10 +14,13 @@ services:
# list any PHP version you want to test against
php:
- 5.6
- 7.0
- 7.2
- 7.1.4
- 7.1.2
- 7.2
- 7.3
matrix:
allow_failures:
- php: 7.3
# execute any number of scripts before the test run, custom env's are available as variables
before_script:

View File

@@ -1,26 +1,27 @@
FROM ubuntu:xenial
MAINTAINER Brady Wetherington <uberbrady@gmail.com>
LABEL maintainer="uberbrady, hinchk"
RUN apt-get update && apt-get install -y software-properties-common
RUN LC_ALL=C.UTF-8 add-apt-repository -y ppa:ondrej/php
RUN apt-get update && apt-get install -y \
apache2 \
apache2-bin \
libapache2-mod-php7.0 \
php7.0-curl \
php7.0-ldap \
php7.0-mysql \
php7.0-mcrypt \
php7.0-gd \
php7.0-xml \
php7.0-mbstring \
php7.0-zip \
php7.0-bcmath \
libapache2-mod-php7.1 \
php7.1-curl \
php7.1-ldap \
php7.1-mysql \
php7.1-mcrypt \
php7.1-gd \
php7.1-xml \
php7.1-mbstring \
php7.1-zip \
php7.1-bcmath \
patch \
curl \
vim \
git \
cron \
mysql-client \
cron \
supervisor \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
@@ -28,8 +29,8 @@ RUN phpenmod mcrypt
RUN phpenmod gd
RUN phpenmod bcmath
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php/7.0/apache2/php.ini
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php/7.0/cli/php.ini
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php/7.1/apache2/php.ini
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php/7.1/cli/php.ini
RUN useradd -m --uid 1000 --gid 50 docker
@@ -69,7 +70,9 @@ RUN \
&& rm -r "/var/www/html/storage/app/backups" && ln -fs "/var/lib/snipeit/dumps" "/var/www/html/storage/app/backups" \
&& mkdir "/var/lib/snipeit/keys" && ln -fs "/var/lib/snipeit/keys/oauth-private.key" "/var/www/html/storage/oauth-private.key" \
&& ln -fs "/var/lib/snipeit/keys/oauth-public.key" "/var/www/html/storage/oauth-public.key" \
&& chown docker "/var/lib/snipeit/keys/"
&& chown docker "/var/lib/snipeit/keys/" \
&& chmod +x /var/www/html/artisan \
&& echo "Finished setting up application in /var/www/html"
############## DEPENDENCIES via COMPOSER ###################
@@ -96,16 +99,11 @@ VOLUME ["/var/lib/snipeit"]
##### START SERVER
COPY docker/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
COPY docker/startup.sh docker/supervisord.conf /
COPY docker/supervisor-exit-event-listener /usr/bin/supervisor-exit-event-listener
RUN chmod +x /startup.sh /usr/bin/supervisor-exit-event-listener
# Add Tini
ENV TINI_VERSION v0.14.0
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
RUN chmod +x /tini
ENTRYPOINT ["/tini", "--"]
CMD ["/entrypoint.sh"]
CMD ["/startup.sh"]
EXPOSE 80
EXPOSE 443

View File

@@ -1,16 +1,16 @@
[![Build Status](https://travis-ci.org/snipe/snipe-it.svg?branch=master)](https://travis-ci.org/snipe/snipe-it) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/snipe-it/localized.svg)](https://crowdin.com/project/snipe-it) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/snipe/snipe-it?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Docker Pulls](https://img.shields.io/docker/pulls/snipe/snipe-it.svg)](https://hub.docker.com/r/snipe/snipe-it/) [![Twitter Follow](https://img.shields.io/twitter/follow/snipeitapp.svg?style=social)](https://twitter.com/snipeitapp) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/553ce52037fc43ea99149785afcfe641)](https://www.codacy.com/app/snipe/snipe-it?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=snipe/snipe-it&amp;utm_campaign=Badge_Grade)
[![All Contributors](https://img.shields.io/badge/all_contributors-180-orange.svg?style=flat-square)](#contributors) [![Open Source Helpers](https://www.codetriage.com/snipe/snipe-it/badges/users.svg)](https://www.codetriage.com/snipe/snipe-it)
[![All Contributors](https://img.shields.io/badge/all_contributors-181-orange.svg?style=flat-square)](#contributors) [![Open Source Helpers](https://www.codetriage.com/snipe/snipe-it/badges/users.svg)](https://www.codetriage.com/snipe/snipe-it)
## Snipe-IT - Open Source Asset Management System
This is a FOSS project for asset management in IT Operations. Knowing who has which laptop, when it was purchased in order to depreciate it correctly, handling software licenses, etc.
It is built on [Laravel 5.4](http://laravel.com).
It is built on [Laravel 5.5](http://laravel.com).
Snipe-IT is actively developed and we're [releasing quite frequently](https://github.com/snipe/snipe-it/releases). ([Check out the live demo here](https://snipeitapp.com/demo/).)
Snipe-IT is actively developed and we [release quite frequently](https://github.com/snipe/snipe-it/releases). ([Check out the live demo here](https://snipeitapp.com/demo/).)
__This is web-based software__. This means there there is no executable file (aka no .exe files), and it must be run on a web server and accessed through a web browser. It runs on any Mac OSX, flavor of Linux, as well as Windows, and we have a [Docker image](https://snipe-it.readme.io/docs/docker) available if that's what you're into.
__This is web-based software__. This means there is no executable file (aka no .exe files), and it must be run on a web server and accessed through a web browser. It runs on any Mac OSX, flavor of Linux, as well as Windows, and we have a [Docker image](https://snipe-it.readme.io/docs/docker) available if that's what you're into.
-----
@@ -58,12 +58,20 @@ Since the release of the JSON REST API, several third-party developers have been
- [SnipeSharp - .NET module in C#](https://github.com/barrycarey/SnipeSharp) by [@barrycarey](https://github.com/barrycarey)
- [InQRy](https://github.com/Microsoft/InQRy) by [@Microsoft](https://github.com/Microsoft)
- [SnipeitPS](https://github.com/snazy2000/SnipeitPS) by [@snazy2000](https://github.com/snazy2000) - Powershell API Wrapper for Snipe-it
- [jamf2snipe](https://github.com/ParadoxGuitarist/jamf2snipe) by [@ParadoxGuitarist](https://github.com/ParadoxGuitarist) - Python script to sync assets between a JAMFPro instance and a Snipe-II instance
- [jamf2snipe](https://github.com/ParadoxGuitarist/jamf2snipe) by [@ParadoxGuitarist](https://github.com/ParadoxGuitarist) - Python script to sync assets between a JAMFPro instance and a Snipe-IT instance
- [Marksman](https://github.com/Scope-IT/marksman) - A Windows agent for Snipe-IT
- [Snipe-IT plugin for Jira Service Desk (beta)](https://marketplace.atlassian.com/apps/1220379/snipe-it-for-jira-service-desk-beta?hosting=cloud&tab=overview) - for the upcoming Snipe-IT v5 only
As these were created by third-parties, Snipe-IT cannot provide support for these project, and you should contact the developers directly if you need assistance. Additionally, Snipe-IT makes no guarantees as to the reliability, accuracy or maintainability of these libraries. Use at your own risk. :)
-----
### Security
To report a security vulnerability, please email security@snipeitapp.com instead of using the issue tracker.
-----
### Contributors
Thanks goes to all of these wonderful people ([emoji key](https://github.com/kentcdodds/all-contributors#emoji-key)) who have helped Snipe-IT get this far:
@@ -95,7 +103,7 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
| [<img src="https://avatars2.githubusercontent.com/u/982885?v=4" width="110px;"/><br /><sub>Martin Stub</sub>](http://martinstub.dk)<br />[🌍](#translation-stubben "Translation") | [<img src="https://avatars2.githubusercontent.com/u/28959963?v=4" width="110px;"/><br /><sub>Meyer Flavio</sub>](https://github.com/meyerf99)<br />[🌍](#translation-meyerf99 "Translation") | [<img src="https://avatars3.githubusercontent.com/u/796443?v=4" width="110px;"/><br /><sub>Micael Rodrigues</sub>](https://github.com/MicaelRodrigues)<br />[🌍](#translation-MicaelRodrigues "Translation") | [<img src="https://avatars0.githubusercontent.com/u/10481331?v=4" width="110px;"/><br /><sub>Mikael Rasmussen</sub>](http://rubixy.com/)<br />[🌍](#translation-mikaelssen "Translation") | [<img src="https://avatars1.githubusercontent.com/u/1544552?v=4" width="110px;"/><br /><sub>IxFail</sub>](https://github.com/IxFail)<br />[🌍](#translation-IxFail "Translation") | [<img src="https://avatars3.githubusercontent.com/u/18483118?v=4" width="110px;"/><br /><sub>Mohammed Fota</sub>](http://www.mohammedfota.com)<br />[🌍](#translation-MohammedFota "Translation") | [<img src="https://avatars0.githubusercontent.com/u/227080?v=4" width="110px;"/><br /><sub>Moayad Alserihi</sub>](https://github.com/omego)<br />[🌍](#translation-omego "Translation") |
| [<img src="https://avatars0.githubusercontent.com/u/1680266?v=4" width="110px;"/><br /><sub>saymd</sub>](https://github.com/saymd)<br />[🌍](#translation-saymd "Translation") | [<img src="https://avatars0.githubusercontent.com/u/1826808?v=4" width="110px;"/><br /><sub>Patrik Larsson</sub>](https://nordsken.se)<br />[🌍](#translation-pooot "Translation") | [<img src="https://avatars1.githubusercontent.com/u/20584746?v=4" width="110px;"/><br /><sub>drcryo</sub>](https://github.com/drcryo)<br />[🌍](#translation-drcryo "Translation") | [<img src="https://avatars1.githubusercontent.com/u/19408004?v=4" width="110px;"/><br /><sub>pawel1615</sub>](https://github.com/pawel1615)<br />[🌍](#translation-pawel1615 "Translation") | [<img src="https://avatars2.githubusercontent.com/u/23340468?v=4" width="110px;"/><br /><sub>bodrovics</sub>](https://github.com/bodrovics)<br />[🌍](#translation-bodrovics "Translation") | [<img src="https://avatars0.githubusercontent.com/u/3257654?v=4" width="110px;"/><br /><sub>priatna</sub>](https://github.com/priatna)<br />[🌍](#translation-priatna "Translation") | [<img src="https://avatars1.githubusercontent.com/u/5358374?v=4" width="110px;"/><br /><sub>Fan Jiang</sub>](https://amayume.net)<br />[🌍](#translation-ProfFan "Translation") |
| [<img src="https://avatars1.githubusercontent.com/u/22555451?v=4" width="110px;"/><br /><sub>ragnarcx</sub>](https://github.com/ragnarcx)<br />[🌍](#translation-ragnarcx "Translation") | [<img src="https://avatars2.githubusercontent.com/u/18654582?v=4" width="110px;"/><br /><sub>Rein van Haaren</sub>](http://www.reinvanhaaren.nl/)<br />[🌍](#translation-reinvanhaaren "Translation") | [<img src="https://avatars1.githubusercontent.com/u/386672?v=4" width="110px;"/><br /><sub>Teguh Dwicaksana</sub>](http://dheche.songolimo.net)<br />[🌍](#translation-dheche "Translation") | [<img src="https://avatars2.githubusercontent.com/u/2572552?v=4" width="110px;"/><br /><sub>fraccie</sub>](https://github.com/FRaccie)<br />[🌍](#translation-FRaccie "Translation") | [<img src="https://avatars0.githubusercontent.com/u/35182720?v=4" width="110px;"/><br /><sub>vinzruzell</sub>](https://github.com/vinzruzell)<br />[🌍](#translation-vinzruzell "Translation") | [<img src="https://avatars1.githubusercontent.com/u/7883603?v=4" width="110px;"/><br /><sub>Kevin Austin</sub>](http://kevinaustin.com)<br />[🌍](#translation-vipsystem "Translation") | [<img src="https://avatars3.githubusercontent.com/u/3861828?v=4" width="110px;"/><br /><sub>Wira Sandy</sub>](http://azuraweb.xyz)<br />[🌍](#translation-wira-sandy "Translation") |
| [<img src="https://avatars2.githubusercontent.com/u/8663789?v=4" width="110px;"/><br /><sub>Илья</sub>](https://github.com/GrayHoax)<br />[🌍](#translation-GrayHoax "Translation") | [<img src="https://avatars3.githubusercontent.com/u/30119111?v=4" width="110px;"/><br /><sub>GodUseVPN</sub>](https://github.com/godusevpn)<br />[🌍](#translation-godusevpn "Translation") | [<img src="https://avatars1.githubusercontent.com/u/745576?v=4" width="110px;"/><br /><sub>周周</sub>](https://github.com/EngrZhou)<br />[🌍](#translation-EngrZhou "Translation") | [<img src="https://avatars3.githubusercontent.com/u/1631095?v=4" width="110px;"/><br /><sub>Sam</sub>](https://github.com/takuy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=takuy "Code") | [<img src="https://avatars1.githubusercontent.com/u/264022?v=4" width="110px;"/><br /><sub>Azerothian</sub>](https://www.illisian.com.au)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Azerothian "Code") |
| [<img src="https://avatars2.githubusercontent.com/u/8663789?v=4" width="110px;"/><br /><sub>Илья</sub>](https://github.com/GrayHoax)<br />[🌍](#translation-GrayHoax "Translation") | [<img src="https://avatars3.githubusercontent.com/u/30119111?v=4" width="110px;"/><br /><sub>GodUseVPN</sub>](https://github.com/godusevpn)<br />[🌍](#translation-godusevpn "Translation") | [<img src="https://avatars1.githubusercontent.com/u/745576?v=4" width="110px;"/><br /><sub>周周</sub>](https://github.com/EngrZhou)<br />[🌍](#translation-EngrZhou "Translation") | [<img src="https://avatars3.githubusercontent.com/u/1631095?v=4" width="110px;"/><br /><sub>Sam</sub>](https://github.com/takuy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=takuy "Code") | [<img src="https://avatars1.githubusercontent.com/u/264022?v=4" width="110px;"/><br /><sub>Azerothian</sub>](https://www.illisian.com.au)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Azerothian "Code") | [<img src="https://avatars1.githubusercontent.com/u/7632599?v=4" width="110px;"/><br /><sub>Tim Farmer</sub>](https://github.com/timothyfarmer)<br />[💻](https://github.com/snipe/snipe-it/commits?author=timothyfarmer "Code") |
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
@@ -108,9 +116,3 @@ 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,160 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use League\Csv\Reader;
use App\Models\Location;
class ImportLocations extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'snipeit:import-locations {filename}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Import locations and their parents';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
if (!ini_get("auto_detect_line_endings")) {
ini_set("auto_detect_line_endings", '1');
}
$filename = $this->argument('filename');
$csv = Reader::createFromPath(storage_path('private_uploads/imports/').$filename, 'r');
$this->info('Attempting to process: '.storage_path('private_uploads/imports/').$filename);
$csv->setHeaderOffset(0); //because we don't want to insert the header
$results = $csv->getRecords();
// Import parent location names first if they don't exist
foreach ($results as $parent_index => $parent_row) {
if (array_key_exists('Parent Name', $parent_row)) {
$parent_name = trim($parent_row['Parent Name']);
if (array_key_exists('Name', $parent_row)) {
$this->info('- Parent: ' . $parent_name . ' in row as: ' . trim($parent_row['Parent Name']));
}
// Save parent location name
// This creates a sort of name-stub that we'll update later on in this script
$parent_location = Location::firstOrCreate(array('name' => $parent_name));
if (array_key_exists('Name', $parent_row)) {
$this->info('Parent for ' . $parent_row['Name'] . ' is ' . $parent_name . '. Attempting to save ' . $parent_name . '.');
}
// Check if the record was updated or created.
// This is mostly for clearer debugging.
if ($parent_location->exists) {
$this->info('- Parent location '.$parent_name.' already exists.');
} else {
$this->info('- Parent location '.$parent_name.' was created.');
}
} else {
$this->info('- No Parent Name provided, so no parent location will be created.');
}
}
$this->info('----- Parents Created.... backfilling additional details... --------');
// Loop through ALL records and add/update them if there are additional fields
// besides name
foreach ($results as $index => $row) {
if (array_key_exists('Parent Name', $row)) {
$parent_name = trim($row['Parent Name']);
}
// Set the location attributes to save
if (array_key_exists('Name', $row)) {
$location = Location::firstOrNew(array('name' => trim($row['Name'])));
$location->name = trim($row['Name']);
$this->info('Checking location: '.$location->name);
} else {
$this->error('Location name is required and is missing from at least one row in this dataset. Check your CSV for extra trailing rows and try again.');
return false;
}
if (array_key_exists('Currency', $row)) {
$location->currency = trim($row['Currency']);
}
if (array_key_exists('Address 1', $row)) {
$location->address = trim($row['Address 1']);
}
if (array_key_exists('Address 2', $row)) {
$location->address2 = trim($row['Address 2']);
}
if (array_key_exists('City', $row)) {
$location->city = trim($row['City']);
}
if (array_key_exists('State', $row)) {
$location->state = trim($row['State']);
}
if (array_key_exists('Zip', $row)) {
$location->zip = trim($row['Zip']);
}
if (array_key_exists('Country', $row)) {
$location->country = trim($row['Country']);
}
if (array_key_exists('Country', $row)) {
$location->ldap_ou = trim($row['OU']);
}
// If a parent name is provided, we created it earlier in the script,
// so let's grab that ID
if ($parent_name) {
$this->info('-- Searching for Parent Name: '.$parent_name);
$parent = Location::where('name', '=', $parent_name)->first();
$location->parent_id = $parent->id;
$this->info('Parent: '.$parent_name.' - ID: '.$parent->id);
}
// Make sure the more advanced (non-name) fields pass validation
if (($location->isValid()) && ($location->save())) {
// Check if the record was updated or created.
// This is mostly for clearer debugging.
if ($location->exists) {
$this->info('Location ' . $location->name . ' already exists. Updating...');
} else {
$this->info('- Location '.$location->name.' was created. ');
}
// If there's a validation error, display that
} else {
$this->error('- Non-parent Location '.$location->name.' could not be created: '.$location->getErrors() );
}
}
}
}

View File

@@ -61,16 +61,16 @@ class LdapSync extends Command
$json_summary = [ "error" => true, "error_message" => $e->getMessage(), "summary" => [] ];
$this->info(json_encode($json_summary));
}
LOG::error($e);
LOG::info($e);
return [];
}
$summary = array();
try {
try {
if ($this->option('base_dn') != '') {
$search_base = $this->option('base_dn');
LOG::debug('Importing users from specified base DN: \"'.$search_base.'\".');
LOG::debug('Importing users from specified base DN: \"'.$search_base.'\".');
} else {
$search_base = null;
}
@@ -80,7 +80,7 @@ class LdapSync extends Command
$json_summary = [ "error" => true, "error_message" => $e->getMessage(), "summary" => [] ];
$this->info(json_encode($json_summary));
}
LOG::error($e);
LOG::info($e);
return [];
}
@@ -106,7 +106,7 @@ class LdapSync extends Command
// Retrieve locations with a mapped OU, and sort them from the shallowest to deepest OU (see #3993)
$ldap_ou_locations = Location::where('ldap_ou', '!=', '')->get()->toArray();
$ldap_ou_lengths = array();
foreach ($ldap_ou_locations as $location) {
$ldap_ou_lengths[] = strlen($location["ldap_ou"]);
}
@@ -128,15 +128,21 @@ class LdapSync extends Command
$location_users = Ldap::findLdapUsers($ldap_loc["ldap_ou"]);
$usernames = array();
for ($i = 0; $i < $location_users["count"]; $i++) {
$location_users[$i]["ldap_location_override"] = true;
$location_users[$i]["location_id"] = $ldap_loc["id"];
$usernames[] = $location_users[$i][$ldap_result_username][0];
if (array_key_exists($ldap_result_username, $location_users[$i])) {
$location_users[$i]["ldap_location_override"] = true;
$location_users[$i]["location_id"] = $ldap_loc["id"];
$usernames[] = $location_users[$i][$ldap_result_username][0];
}
}
// Delete located users from the general group.
foreach ($results as $key => $generic_entry) {
if (in_array($generic_entry[$ldap_result_username][0], $usernames)) {
unset($results[$key]);
if ((is_array($generic_entry)) && (array_key_exists($ldap_result_username, $generic_entry))) {
if (in_array($generic_entry[$ldap_result_username][0], $usernames)) {
unset($results[$key]);
}
}
}
@@ -162,30 +168,36 @@ class LdapSync extends Command
$item["ldap_location_override"] = isset($results[$i]["ldap_location_override"]) ? $results[$i]["ldap_location_override"]:"";
$item["location_id"] = isset($results[$i]["location_id"]) ? $results[$i]["location_id"]:"";
if ( array_key_exists('useraccountcontrol', $results[$i]) ) {
$enabled_accounts = [
'512', '544', '66048', '66080', '262656', '262688', '328192', '328224'
];
$item['activated'] = ( in_array($results[$i]['useraccountcontrol'][0], $enabled_accounts) ) ? 1 : 0;
$user = User::where('username', $item["username"])->first();
if ($user) {
// Updating an existing user.
$item["createorupdate"] = 'updated';
} else {
$item['activated'] = 0;
}
// User exists
$item["createorupdate"] = 'updated';
if (!$user = User::where('username', $item["username"])->first()) {
// Creating a new user.
$user = new User;
$user->password = $pass;
$user->activated = 0;
$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->first_name = $item["firstname"];
$user->last_name = $item["lastname"];
$user->username = $item["username"];
$user->email = $item["email"];
$user->employee_num = e($item["employee_number"]);
$user->activated = $item['activated'];
// Sync activated state for Active Directory.
if ( array_key_exists('useraccountcontrol', $results[$i]) ) {
$enabled_accounts = [
'512', '544', '66048', '66080', '262656', '262688', '328192', '328224'
];
$user->activated = ( in_array($results[$i]['useraccountcontrol'][0], $enabled_accounts) ) ? 1 : 0;
}
// If we're not using AD, and there isn't an activated flag set, activate all users
elseif (empty($ldap_result_active_flag)) {
$user->activated = 1;
}
if ($item['ldap_location_override'] == true) {
$user->location_id = $item['location_id'];
@@ -199,7 +211,6 @@ class LdapSync extends Command
}
$user->notes = 'Imported from LDAP';
$user->ldap_import = 1;
$errors = '';

View File

@@ -65,7 +65,7 @@ class ObjectImportCommand extends Command
*
* @return mixed
*/
public function fire()
public function handle()
{
$filename = $this->argument('filename');
$class = title_case($this->option('item-type'));
@@ -74,6 +74,7 @@ class ObjectImportCommand extends Command
$importer->setCallbacks([$this, 'log'], [$this, 'progress'], [$this, 'errorCallback'])
->setUserId($this->option('user_id'))
->setUpdating($this->option('update'))
->setShouldNotify($this->option('send-welcome'))
->setUsernameFormat($this->option('username_format'));
$logFile = $this->option('logfile');
@@ -172,6 +173,7 @@ class ObjectImportCommand extends Command
array('web-importer', null, InputOption::VALUE_NONE, 'Internal: packages output for use with the web importer'),
array('user_id', null, InputOption::VALUE_REQUIRED, 'ID of user creating items', 1),
array('update', null, InputOption::VALUE_NONE, 'If a matching item is found, update item information'),
array('send-welcome', null, InputOption::VALUE_NONE, 'Whether to send a welcome email to any new users that are created.'),
);
}

View File

@@ -79,6 +79,7 @@ class PaveIt extends Command
DB::statement('delete from accessories_users');
DB::statement('delete from asset_logs');
DB::statement('delete from asset_maintenances');
DB::statement('delete from login_attempts');
DB::statement('delete from asset_uploads');
DB::statement('delete from action_logs');
DB::statement('delete from checkout_requests');

View File

@@ -33,7 +33,7 @@ class Purge extends Command
*
* @var string
*/
protected $description = 'Purge all soft-deleted deleted records in the database. This will rewrite history for items that have been edited, or checked in or out. It will also reqrite history for users associated with deleted items.';
protected $description = 'Purge all soft-deleted deleted records in the database. This will rewrite history for items that have been edited, or checked in or out. It will also rewrite history for users associated with deleted items.';
/**
* Create a new command instance.

View File

@@ -0,0 +1,126 @@
<?php
namespace App\Console\Commands;
use App\Models\CustomField;
use Illuminate\Console\Command;
class ReEncodeCustomFieldNames extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'snipeit:regenerate-fieldnames';
/**
* The console command description.
*
* @var string
*/
protected $description = 'This utility will regenerate the column names for custom fields. It should typically only be needed when a PHP upgrade changed the behavior of the unicode conversion between versions.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* All three of these things must match for the custom fields system to work as expected:
*
* - what the system thinks the output of $field->convertUnicodeDbSlug() is
* - the actual db_column name in the customfields table
* - the physical column name that was created on the assets table
*
* For some people who upgraded their version of PHP, the unicode converter now behaves
* differently in than it did when their custom fields were first created, specifically as it
* relates to handling slashes, ampersands, etc. This can result in the field names no longer
* matching up, as an older version of the PHP extension simply dropped slashes, etc, while the
* newer version of the PHP extension will convert them to underscores.
*
* @return mixed
*/
public function handle()
{
if ($this->confirm('This will regenerate all of the custom field database fieldnames in your database. THIS WILL CHANGE YOUR SCHEMA AND SHOULD NOT BE DONE WITHOUT MAKING A BACKUP FIRST. Do you wish to continue?'))
{
/** Get all of the custom fields */
$fields = CustomField::get();
$asset_columns = \DB::getSchemaBuilder()->getColumnListing('assets');
$custom_field_columns = array();
/** Loop through the columns on the assets table */
foreach ($asset_columns as $asset_column) {
/** Add ones that start with _snipeit_ to an array for handling */
if (strpos($asset_column, '_snipeit_') === 0) {
/**
* Get the ID of the custom field based on the fieldname.
* For example, in _snipeit_mac_address_1, we grab the 1 because we know
* that's the ID of the custom field that created the column.
* Then use that ID as the array key for use comparing the actual assets field name
* and the db_column value from the custom fields table.
*/
$last_part = substr(strrchr($asset_column, "_snipeit_"), 1);
$custom_field_columns[$last_part] = $asset_column;
}
}
foreach ($fields as $field) {
$this->info($field->name .' ('.$field->id.') column should be '. $field->convertUnicodeDbSlug().'');
/** The assets table has the column it should have, all is well */
if (\Schema::hasColumn('assets', $field->convertUnicodeDbSlug()))
{
$this->info('-- ✓ This field exists - all good');
/**
* There is a mismatch between the fieldname on the assets table and
* what $field->convertUnicodeDbSlug() is *now* expecting.
*/
} else {
$this->warn('-- X Field mismatch: updating... ');
/** Make sure the custom_field_columns array has the ID */
if (array_key_exists($field->id, $custom_field_columns)) {
/**
* Update the asset schema to the corrected fieldname that will be recognized by the
* system elsewhere that we use $field->convertUnicodeDbSlug()
*/
\Schema::table('assets', function($table) use ($custom_field_columns, $field) {
$table->renameColumn($custom_field_columns[$field->id], $field->convertUnicodeDbSlug());
});
$this->warn('-- ✓ Field updated from '.$custom_field_columns[$field->id].' to '.$field->convertUnicodeDbSlug());
} else {
$this->warn('-- X WARNING: There is no field on the assets table ending in '.$field->id.'. This may require more in-depth investigation and may mean the schema was altered manually.');
}
}
/** Update the db_column property in the custom fields table, just in case it doesn't match the other
* things.
*/
$field->db_column = $field->convertUnicodeDbSlug();
$field->save();
}
}
}
}

View File

@@ -63,6 +63,8 @@ class ResetDemoSettings extends Command
$settings->time_display_format = 'g:iA';
$settings->thumbnail_max_h = '30';
$settings->locale = 'en';
$settings->version_footer = 'on';
$settings->support_footer = 'on';
$settings->save();
if ($user = User::where('username', '=', 'admin')->first()) {

View File

@@ -0,0 +1,120 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\User;
use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\Consumable;
use App\Models\Accessory;
use App\Models\LicenseSeat;
use App\Models\License;
use DB;
use Artisan;
class RestoreDeletedUsers extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'snipeit:restore-users {--start_date=} {--end_date=}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Restore users, and any associated assets and license checkouts.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$start_date = $this->option('start_date');
$end_date = $this->option('end_date');
$asset_totals = 0;
$license_totals = 0;
$user_count = 0;
if (($start_date=='') || ($end_date=='')) {
$this->info('ERROR: All fields are required.');
return false;
}
$users = User::whereBetween('deleted_at', [$start_date, $end_date])->withTrashed()->get();
$this->info('There are '.$users->count().' users deleted between '.$start_date.' and '.$end_date);
$this->warn('Making a backup!');
Artisan::call('backup:run');
foreach ($users as $user) {
$user_count++;
$user_logs = Actionlog::where('target_id', $user->id)->where('target_type',User::class)
->where('action_type','checkout')->with('item')->get();
$this->info($user_count.'. '.$user->username.' ('.$user->id.') was deleted at '.$user->deleted_at. ' and has '.$user_logs->count().' checkouts associated.');
foreach ($user_logs as $user_log) {
$this->info(' * '.$user_log->item_type.': '.$user_log->item->name.' - item_id: '.$user_log->item_id);
if ($user_log->item_type==Asset::class) {
$asset_totals++;
DB::table('assets')
->where('id', $user_log->item_id)
->update(['assigned_to' => $user->id, 'assigned_type'=> User::class]);
$this->info(' ** Asset '.$user_log->item->id.' ('.$user_log->item->asset_tag.') restored to user '.$user->id.'');
} elseif ($user_log->item_type==License::class) {
$license_totals++;
$avail_seat = DB::table('license_seats')->where('license_id','=',$user_log->item->id)
->whereNull('assigned_to')->whereNull('asset_id')->whereBetween('updated_at', [$start_date, $end_date])->first();
if ($avail_seat) {
$this->info(' ** Allocating seat '.$avail_seat->id.' for this License');
DB::table('license_seats')
->where('id', $avail_seat->id)
->update(['assigned_to' => $user->id]);
} else {
$this->warn('ERROR: No available seats for '.$user_log->item->name);
}
}
}
$this->warn('Restoring user '.$user->username.'!');
$user->restore();
}
$this->info($asset_totals.' assets affected');
$this->info($license_totals.' licenses affected');
}
}

View File

@@ -42,7 +42,7 @@ class SendExpectedCheckinAlerts extends Command
*
* @return mixed
*/
public function fire()
public function handle()
{
$settings = Setting::getSettings();
$whenNotify = Carbon::now()->addDays(7);
@@ -57,12 +57,12 @@ class SendExpectedCheckinAlerts extends Command
}
}
// Send a rollup to the admin, if settings dictate
$recipient = new \App\Models\Recipients\AlertRecipient();
if (($assets) && ($assets->count() > 0) && ($settings->alert_email!='')) {
$recipient->notify(new ExpectedCheckinAdminNotification($assets));
if (($assets) && ($assets->count() > 0) && ($settings->alert_email != '')) {
// Send a rollup to the admin, if settings dictate
$recipients = collect(explode(',', $settings->alert_email))->map(function ($item, $key) {
return new \App\Models\Recipients\AlertRecipient($item);
});
\Notification::send($recipients, new ExpectedCheckinAdminNotification($assets));
}

View File

@@ -43,33 +43,35 @@ class SendExpirationAlerts extends Command
*
* @return mixed
*/
public function fire()
public function handle()
{
$settings = Setting::getSettings();
$threshold = $settings->alert_interval;
// Expiring Assets
$assets = Asset::getExpiringWarrantee(Setting::getSettings()->alert_interval);
$this->info(trans_choice('mail.assets_warrantee_alert', $assets->count(), ['count'=>$assets->count(), 'threshold' => $threshold]));
if (($settings->alert_email != '') && ($settings->alerts_enabled == 1)) {
// Expiring licenses
$licenses = License::getExpiringLicenses($threshold);
$this->info(trans_choice('mail.license_expiring_alert', $licenses->count(), ['count'=>$licenses->count(), 'threshold' => $threshold]));
$recipient = new \App\Models\Recipients\AlertRecipient();
if ((Setting::getSettings()->alert_email!='') && ($settings->alerts_enabled==1)) {
// Send a rollup to the admin, if settings dictate
$recipients = collect(explode(',', $settings->alert_email))->map(function ($item, $key) {
return new \App\Models\Recipients\AlertRecipient($item);
});
// Expiring Assets
$assets = Asset::getExpiringWarrantee(Setting::getSettings()->alert_interval);
if ($assets->count() > 0) {
// Send a rollup to the admin, if settings dictate
$recipient->notify(new ExpiringAssetsNotification($assets, $threshold));
$this->info(trans_choice('mail.assets_warrantee_alert', $assets->count(),
['count' => $assets->count(), 'threshold' => $threshold]));
\Notification::send($recipients, new ExpiringAssetsNotification($assets, $threshold));
}
// Expiring licenses
$licenses = License::getExpiringLicenses($threshold);
if ($licenses->count() > 0) {
$recipient->notify(new ExpiringLicenseNotification($licenses, $threshold));
$this->info(trans_choice('mail.license_expiring_alert', $licenses->count(), ['count' => $licenses->count(), 'threshold' => $threshold]));
\Notification::send($recipients, new ExpiringLicenseNotification($licenses, $threshold));
}

View File

@@ -50,13 +50,14 @@ class SendInventoryAlerts extends Command
$items = Helper::checkLowInventory();
// Send a rollup to the admin, if settings dictate
$recipient = new \App\Models\Recipients\AlertRecipient();
if (($items) && (count($items) > 0) && ($settings->alert_email!='')) {
$this->info( trans_choice('mail.low_inventory_alert',count($items)) );
$recipient->notify(new InventoryAlert($items, $settings->alert_threshold));
if (($items) && (count($items) > 0)) {
$this->info(trans_choice('mail.low_inventory_alert', count($items)));
// Send a rollup to the admin, if settings dictate
$recipients = collect(explode(',', $settings->alert_email))->map(function ($item, $key) {
return new \App\Models\Recipients\AlertRecipient($item);
});
\Notification::send($recipients, new InventoryAlert($items, $settings->alert_threshold));
}
} else {

View File

@@ -0,0 +1,91 @@
<?php
namespace App\Console\Commands;
use App\Models\Asset;
use App\Models\License;
use App\Models\Setting;
use App\Notifications\ExpiringAssetsNotification;
use App\Models\Recipients;
use DB;
use Illuminate\Console\Command;
use App\Notifications\SendUpcomingAuditNotification;
use Carbon\Carbon;
class SendUpcomingAuditReport extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'snipeit:upcoming-audits';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Send email/slack notifications for upcoming asset audits.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$settings = Setting::getSettings();
if (($settings->alert_email != '') && ($settings->audit_warning_days) && ($settings->alerts_enabled == 1)) {
// Send a rollup to the admin, if settings dictate
$recipients = collect(explode(',', $settings->alert_email))->map(function ($item, $key) {
return new \App\Models\Recipients\AlertRecipient($item);
});
// Assets due for auditing
$assets = Asset::whereNotNull('next_audit_date')
->DueOrOverdueForAudit($settings)
->orderBy('last_audit_date', 'asc')->get();
if ($assets->count() > 0) {
$this->info(trans_choice('mail.upcoming-audits', $assets->count(),
['count' => $assets->count(), 'threshold' => $settings->audit_warning_days]));
\Notification::send($recipients, new SendUpcomingAuditNotification($assets, $settings->audit_warning_days));
$this->info('Audit report sent to '.$settings->alert_email);
} else {
$this->info('No assets to be audited. No report sent.');
}
} elseif ($settings->alert_email=='') {
$this->error('Could not send email. No alert email configured in settings');
} elseif (!$settings->audit_warning_days) {
$this->error('No audit warning days set in Admin Notifications. No mail will be sent.');
} elseif ($settings->alerts_enabled!=1) {
$this->info('Alerts are disabled in the settings. No mail will be sent');
} else {
$this->error('Something went wrong. :( ');
$this->error('Admin Notifications Email Setting: '.$settings->alert_email);
$this->error('Admin Audit Warning Setting: '.$settings->audit_warning_days);
$this->error('Admin Alerts Emnabled: '.$settings->alerts_enabled);
}
}
}

View File

@@ -39,7 +39,7 @@ class SyncAssetCounters extends Command
public function handle()
{
$start = microtime(true);
$assets = Asset::withCount('checkins', 'checkouts', 'userRequests')
$assets = Asset::withCount('checkins as checkins_count', 'checkouts as checkouts_count', 'userRequests as user_requests_count')
->withTrashed()->get();
if ($assets) {

View File

@@ -64,7 +64,7 @@ class SyncAssetLocations extends Command
$output['info'][] = 'There are '.$assigned_user_assets->count().' assets checked out to users.';
foreach ($assigned_user_assets as $assigned_user_asset) {
if (($assigned_user_asset->assignedTo) && ($assigned_user_asset->assignedTo->userLoc)) {
$new_location=$assigned_user_asset->assignedTo->userloc->id;
$new_location = $assigned_user_asset->assignedTo->userLoc->id;
$output['info'][] ='Setting User Asset ' . $assigned_user_asset->id . ' ('.$assigned_user_asset->asset_tag.') to ' . $assigned_user_asset->assignedTo->userLoc->name . ' which is id: ' . $new_location;
} else {
$output['warn'][] ='Asset ' . $assigned_user_asset->id . ' ('.$assigned_user_asset->asset_tag.') still has no location! ';

View File

@@ -36,7 +36,7 @@ class SystemBackup extends Command
*
* @return mixed
*/
public function fire()
public function handle()
{
//
$this->call('backup:run');

View File

@@ -2,6 +2,8 @@
namespace App\Console;
use App\Console\Commands\ImportLocations;
use App\Console\Commands\RestoreDeletedUsers;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
@@ -30,6 +32,10 @@ class Kernel extends ConsoleKernel
Commands\SyncAssetLocations::class,
Commands\RegenerateAssetTags::class,
Commands\SyncAssetCounters::class,
Commands\RestoreDeletedUsers::class,
Commands\SendUpcomingAuditReport::class,
Commands\ImportLocations::class,
Commands\ReEncodeCustomFieldNames::class,
];
/**
@@ -46,10 +52,12 @@ class Kernel extends ConsoleKernel
$schedule->command('snipeit:expected-checkin')->daily();
$schedule->command('snipeit:backup')->weekly();
$schedule->command('backup:clean')->daily();
$schedule->command('snipeit:upcoming-audits')->daily();
}
protected function commands()
{
require base_path('routes/console.php');
$this->load(__DIR__.'/Commands');
}
}

View File

@@ -23,6 +23,7 @@ class Handler extends ExceptionHandler
\Illuminate\Database\Eloquent\ModelNotFoundException::class,
\Illuminate\Session\TokenMismatchException::class,
\Illuminate\Validation\ValidationException::class,
\Intervention\Image\Exception\NotSupportedException::class,
];
/**
@@ -66,10 +67,6 @@ class Handler extends ExceptionHandler
return response()->json(Helper::formatStandardApiResponse('error', null, $className . ' not found'), 200);
}
if ($e instanceof \Illuminate\Validation\ValidationException) {
return response()->json(Helper::formatStandardApiResponse('error', null, $e->response['messages'], 400));
}
if ($this->isHttpException($e)) {
$statusCode = $e->getStatusCode();
@@ -84,11 +81,6 @@ class Handler extends ExceptionHandler
}
}
// Try to parse 500 Errors in a bit nicer way when debug is enabled.
if (config('app.debug')) {
return response()->json(Helper::formatStandardApiResponse('error', null, "An Error has occured! " . $e->getMessage()), 500);
}
}
@@ -117,4 +109,16 @@ class Handler extends ExceptionHandler
return redirect()->guest('login');
}
/**
* Convert a validation exception into a JSON response.
*
* @param \Illuminate\Http\Request $request
* @param \Illuminate\Validation\ValidationException $exception
* @return \Illuminate\Http\JsonResponse
*/
protected function invalidJson($request, ValidationException $exception)
{
return response()->json(Helper::formatStandardApiResponse('error', null, $exception->errors(), 400));
}
}

View File

@@ -281,9 +281,9 @@ class Helper
*/
public static function checkLowInventory()
{
$consumables = Consumable::withCount('consumableAssignments')->whereNotNull('min_amt')->get();
$accessories = Accessory::withCount('users')->whereNotNull('min_amt')->get();
$components = Component::withCount('assets')->whereNotNull('min_amt')->get();
$consumables = Consumable::withCount('consumableAssignments as consumable_assignments_count')->whereNotNull('min_amt')->get();
$accessories = Accessory::withCount('users as users_count')->whereNotNull('min_amt')->get();
$components = Component::withCount('assets as assets_count')->whereNotNull('min_amt')->get();
$avail_consumables = 0;
$items_array = array();

View File

@@ -94,7 +94,7 @@ class AccessoriesController extends Controller
$file_name = "accessory-".str_random(18).'.'.$ext;
$path = public_path('/uploads/accessories');
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(null, 250, function ($constraint) {
Image::make($image->getRealPath())->resize(null, 800, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path.'/'.$file_name);
@@ -173,7 +173,7 @@ class AccessoriesController extends Controller
$file_name = "accessory-".str_random(18).'.'.$ext;
$path = public_path('/uploads/accessories');
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(null, 250, function ($constraint) {
Image::make($image->getRealPath())->resize(null, 800, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path.'/'.$file_name);

View File

@@ -26,27 +26,27 @@ class AccessoriesController extends Controller
$accessories = Accessory::with('category', 'company', 'manufacturer', 'users', 'location');
if ($request->has('search')) {
if ($request->filled('search')) {
$accessories = $accessories->TextSearch($request->input('search'));
}
if ($request->has('company_id')) {
if ($request->filled('company_id')) {
$accessories->where('company_id','=',$request->input('company_id'));
}
if ($request->has('category_id')) {
if ($request->filled('category_id')) {
$accessories->where('category_id','=',$request->input('category_id'));
}
if ($request->has('manufacturer_id')) {
if ($request->filled('manufacturer_id')) {
$accessories->where('manufacturer_id','=',$request->input('manufacturer_id'));
}
if ($request->has('supplier_id')) {
if ($request->filled('supplier_id')) {
$accessories->where('supplier_id','=',$request->input('supplier_id'));
}
$offset = $request->input('offset', 0);
$offset = (($accessories) && (request('offset') > $accessories->count())) ? 0 : request('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';

View File

@@ -40,11 +40,11 @@ class AssetMaintenancesController extends Controller
$maintenances = $maintenances->TextSearch(e($request->input('search')));
}
if ($request->has('asset_id')) {
if ($request->filled('asset_id')) {
$maintenances->where('asset_id', '=', $request->input('asset_id'));
}
$offset = request('offset', 0);
$offset = (($maintenances) && (request('offset') > $maintenances->count())) ? 0 : request('offset', 0);
$limit = request('limit', 50);
$allowed_columns = [

View File

@@ -48,19 +48,19 @@ class AssetModelsController extends Controller
'models.updated_at',
])
->with('category','depreciation', 'manufacturer','fieldset')
->withCount('assets');
->withCount('assets as assets_count');
if ($request->has('status')) {
if ($request->filled('status')) {
$assetmodels->onlyTrashed();
}
if ($request->has('search')) {
if ($request->filled('search')) {
$assetmodels->TextSearch($request->input('search'));
}
$offset = $request->input('offset', 0);
$offset = (($assetmodels) && (request('offset') > $assetmodels->count())) ? 0 : request('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'models.created_at';
@@ -114,7 +114,7 @@ class AssetModelsController extends Controller
public function show($id)
{
$this->authorize('view', AssetModel::class);
$assetmodel = AssetModel::withCount('assets')->findOrFail($id);
$assetmodel = AssetModel::withCount('assets as assets_count')->findOrFail($id);
return (new AssetModelsTransformer)->transformAssetModel($assetmodel);
}
@@ -179,7 +179,7 @@ class AssetModelsController extends Controller
try {
unlink(public_path().'/uploads/models/'.$assetmodel->image);
} catch (\Exception $e) {
\Log::error($e);
\Log::info($e);
}
}
@@ -210,7 +210,7 @@ class AssetModelsController extends Controller
$settings = \App\Models\Setting::getSettings();
if ($request->has('search')) {
if ($request->filled('search')) {
$assetmodels = $assetmodels->SearchByManufacturerOrCat($request->input('search'));
}

View File

@@ -52,7 +52,7 @@ class AssetsController extends Controller
* @since [v4.0]
* @return JsonResponse
*/
public function index(Request $request)
public function index(Request $request, $audit = null)
{
$this->authorize('index', Asset::class);
@@ -84,7 +84,7 @@ class AssetsController extends Controller
$filter = array();
if ($request->has('filter')) {
if ($request->filled('filter')) {
$filter = json_decode($request->input('filter'), true);
}
@@ -95,13 +95,13 @@ class AssetsController extends Controller
$assets = Company::scopeCompanyables(Asset::select('assets.*'),"company_id","assets")
->with('location', 'assetstatus', 'assetlog', 'company', 'defaultLoc','assignedTo',
'model.category', 'model.manufacturer', 'model.fieldset','supplier');
'model.category', 'model.manufacturer', 'model.fieldset','supplier');
// These are used by the API to query against specific ID numbers.
// They are also used by the individual searches on detail pages like
// locations, etc.
if ($request->has('status_id')) {
if ($request->filled('status_id')) {
$assets->where('assets.status_id', '=', $request->input('status_id'));
}
@@ -109,45 +109,60 @@ class AssetsController extends Controller
$assets->where('assets.requestable', '=', '1');
}
if ($request->has('model_id')) {
if ($request->filled('model_id')) {
$assets->InModelList([$request->input('model_id')]);
}
if ($request->has('category_id')) {
if ($request->filled('category_id')) {
$assets->InCategory($request->input('category_id'));
}
if ($request->has('location_id')) {
if ($request->filled('location_id')) {
$assets->where('assets.location_id', '=', $request->input('location_id'));
}
if ($request->has('supplier_id')) {
if ($request->filled('supplier_id')) {
$assets->where('assets.supplier_id', '=', $request->input('supplier_id'));
}
if (($request->has('assigned_to')) && ($request->has('assigned_type'))) {
if (($request->filled('assigned_to')) && ($request->filled('assigned_type'))) {
$assets->where('assets.assigned_to', '=', $request->input('assigned_to'))
->where('assets.assigned_type', '=', $request->input('assigned_type'));
->where('assets.assigned_type', '=', $request->input('assigned_type'));
}
if ($request->has('company_id')) {
if ($request->filled('company_id')) {
$assets->where('assets.company_id', '=', $request->input('company_id'));
}
if ($request->has('manufacturer_id')) {
if ($request->filled('manufacturer_id')) {
$assets->ByManufacturer($request->input('manufacturer_id'));
}
if ($request->has('depreciation_id')) {
if ($request->filled('depreciation_id')) {
$assets->ByDepreciationId($request->input('depreciation_id'));
}
$request->has('order_number') ? $assets = $assets->where('assets.order_number', '=', e($request->get('order_number'))) : '';
$request->filled('order_number') ? $assets = $assets->where('assets.order_number', '=', e($request->get('order_number'))) : '';
$offset = request('offset', 0);
$offset = (($assets) && (request('offset') > $assets->count())) ? 0 : request('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
// This is used by the audit reporting routes
if (Gate::allows('audit', Asset::class)) {
switch ($audit) {
case 'due':
$assets->DueOrOverdueForAudit($settings);
break;
case 'overdue':
$assets->overdueForAudit($settings);
break;
}
}
// This is used by the sidenav, mostly
// We switched from using query scopes here because of a Laravel bug
@@ -167,12 +182,12 @@ class AssetsController extends Controller
break;
case 'RTD':
$assets->whereNull('assets.assigned_to')
->join('status_labels AS status_alias',function ($join) {
$join->on('status_alias.id', "=", "assets.status_id")
->where('status_alias.deployable','=',1)
->where('status_alias.pending','=',0)
->where('status_alias.archived', '=', 0);
});
->join('status_labels AS status_alias',function ($join) {
$join->on('status_alias.id', "=", "assets.status_id")
->where('status_alias.deployable','=',1)
->where('status_alias.pending','=',0)
->where('status_alias.archived', '=', 0);
});
break;
case 'Undeployable':
$assets->Undeployable();
@@ -188,11 +203,11 @@ class AssetsController extends Controller
case 'Requestable':
$assets->where('assets.requestable', '=', 1)
->join('status_labels AS status_alias',function ($join) {
$join->on('status_alias.id', "=", "assets.status_id")
->where('status_alias.deployable','=',1)
->where('status_alias.pending','=',0)
->where('status_alias.archived', '=', 0);
});
$join->on('status_alias.id', "=", "assets.status_id")
->where('status_alias.deployable','=',1)
->where('status_alias.pending','=',0)
->where('status_alias.archived', '=', 0);
});
break;
case 'Deployed':
@@ -201,14 +216,14 @@ class AssetsController extends Controller
break;
default:
if ((!$request->has('status_id')) && ($settings->show_archived_in_list!='1')) {
if ((!$request->filled('status_id')) && ($settings->show_archived_in_list!='1')) {
// terrible workaround for complex-query Laravel bug in fulltext
$assets->join('status_labels AS status_alias',function ($join) {
$join->on('status_alias.id', "=", "assets.status_id")
->where('status_alias.archived', '=', 0);
});
// If there is a status ID, don't take show_archived_in_list into consideration
// If there is a status ID, don't take show_archived_in_list into consideration
} else {
$assets->join('status_labels AS status_alias',function ($join) {
$join->on('status_alias.id', "=", "assets.status_id");
@@ -220,7 +235,7 @@ class AssetsController extends Controller
if ((!is_null($filter)) && (count($filter)) > 0) {
$assets->ByFilter($filter);
} elseif ($request->has('search')) {
} elseif ($request->filled('search')) {
$assets->TextSearch($request->input('search'));
}
@@ -233,8 +248,8 @@ class AssetsController extends Controller
// This handles all of the pivot sorting (versus the assets.* fields
// in the allowed_columns array)
$column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'assets.created_at';
switch ($sort_override) {
case 'model':
$assets->OrderModels($order);
@@ -291,7 +306,7 @@ class AssetsController extends Controller
$this->authorize('view', $asset);
return (new AssetsTransformer)->transformAsset($asset);
}
return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 404);
return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 200);
}
@@ -305,17 +320,18 @@ class AssetsController extends Controller
*/
public function showBySerial($serial)
{
$this->authorize('index', Asset::class);
if ($assets = Asset::with('assetstatus')->with('assignedTo')
->withTrashed()->where('serial',$serial)->get()) {
$this->authorize('view', $assets);
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
}
return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 404);
return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 200);
}
/**
/**
* Returns JSON with information about an asset for detail view.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
@@ -325,7 +341,7 @@ class AssetsController extends Controller
*/
public function show($id)
{
if ($asset = Asset::with('assetstatus')->with('assignedTo')->withTrashed()->withCount('checkins', 'checkouts', 'userRequests')->findOrFail($id)) {
if ($asset = Asset::with('assetstatus')->with('assignedTo')->withTrashed()->withCount('checkins as checkins_count', 'checkouts as checkouts_count', 'userRequests as userRequests_count')->findOrFail($id)) {
$this->authorize('view', $asset);
return (new AssetsTransformer)->transformAsset($asset);
}
@@ -353,13 +369,13 @@ class AssetsController extends Controller
'assets.assigned_to',
'assets.assigned_type',
'assets.status_id'
])->with('model', 'assetstatus', 'assignedTo')->NotArchived());
])->with('model', 'assetstatus', 'assignedTo')->NotArchived(),'company_id', 'assets');
if ($request->has('assetStatusType') && $request->input('assetStatusType') === 'RTD') {
if ($request->filled('assetStatusType') && $request->input('assetStatusType') === 'RTD') {
$assets = $assets->RTD();
}
if ($request->has('search')) {
if ($request->filled('search')) {
$assets = $assets->AssignedSearch($request->input('search'));
}
@@ -378,7 +394,7 @@ class AssetsController extends Controller
$asset->use_text .= ' → '.$asset->assigned->getFullNameAttribute();
}
if ($asset->assetstatus->getStatuslabelType()=='pending') {
$asset->use_text .= '('.$asset->assetstatus->getStatuslabelType().')';
}
@@ -430,9 +446,15 @@ class AssetsController extends Controller
// Update custom fields in the database.
// Validation for these fields is handled through the AssetRequest form request
$model = AssetModel::find($request->get('model_id'));
if ($model->fieldset) {
if (($model) && ($model->fieldset)) {
foreach ($model->fieldset->fields as $field) {
$asset->{$field->convertUnicodeDbSlug()} = e($request->input($field->convertUnicodeDbSlug(), null));
if ($field->field_encrypted=='1') {
if (Gate::allows('admin')) {
$asset->{$field->convertUnicodeDbSlug()} = \Crypt::encrypt($request->input($field->convertUnicodeDbSlug()));
}
} else {
$asset->{$field->convertUnicodeDbSlug()} = $request->input($field->convertUnicodeDbSlug());
}
}
}
@@ -468,49 +490,27 @@ class AssetsController extends Controller
$this->authorize('update', Asset::class);
if ($asset = Asset::find($id)) {
($request->has('model_id')) ?
$asset->model()->associate(AssetModel::find($request->get('model_id'))) : '';
($request->has('name')) ?
$asset->name = $request->get('name') : '';
($request->has('serial')) ?
$asset->serial = $request->get('serial') : '';
($request->has('model_id')) ?
$asset->model_id = $request->get('model_id') : '';
($request->has('order_number')) ?
$asset->order_number = $request->get('order_number') : '';
($request->has('notes')) ?
$asset->notes = $request->get('notes') : '';
($request->has('asset_tag')) ?
$asset->asset_tag = $request->get('asset_tag') : '';
($request->has('archived')) ?
$asset->archived = $request->get('archived') : '';
($request->has('status_id')) ?
$asset->status_id = $request->get('status_id') : '';
($request->has('warranty_months')) ?
$asset->warranty_months = $request->get('warranty_months') : '';
($request->has('purchase_cost')) ?
$asset->purchase_cost = Helper::ParseFloat($request->get('purchase_cost')) : '';
($request->has('purchase_date')) ?
$asset->purchase_date = $request->get('purchase_date') : '';
($request->has('assigned_to')) ?
$asset->assigned_to = $request->get('assigned_to') : '';
($request->has('supplier_id')) ?
$asset->supplier_id = $request->get('supplier_id') : '';
($request->has('requestable')) ?
$asset->requestable = $request->get('requestable') : '';
($request->has('rtd_location_id')) ?
$asset->rtd_location_id = $request->get('rtd_location_id') : '';
($request->has('rtd_location_id')) ?
$asset->location_id = $request->get('rtd_location_id') : '';
($request->has('company_id')) ?
$asset->company_id = Company::getIdForCurrentUser($request->get('company_id')) : '';
$asset->fill($request->all());
($request->filled('model_id')) ?
$asset->model()->associate(AssetModel::find($request->get('model_id'))) : null;
($request->filled('company_id')) ?
$asset->company_id = Company::getIdForCurrentUser($request->get('company_id')) : null;
($request->filled('rtd_location_id')) ?
$asset->location_id = $request->get('rtd_location_id') : null;
// Update custom fields
if (($model = AssetModel::find($asset->model_id)) && (isset($model->fieldset))) {
foreach ($model->fieldset->fields as $field) {
if ($request->has($field->convertUnicodeDbSlug())) {
$asset->{$field->convertUnicodeDbSlug()} = e($request->input($field->convertUnicodeDbSlug()));
if ($field->field_encrypted=='1') {
if (Gate::allows('admin')) {
$asset->{$field->convertUnicodeDbSlug()} = \Crypt::encrypt($request->input($field->convertUnicodeDbSlug()));
}
} else {
$asset->{$field->convertUnicodeDbSlug()} = $request->input($field->convertUnicodeDbSlug());
}
}
}
}
@@ -518,11 +518,11 @@ class AssetsController extends Controller
if ($asset->save()) {
if (($request->has('assigned_user')) && ($target = User::find($request->get('assigned_user')))) {
$location = $target->location_id;
} elseif (($request->has('assigned_asset')) && ($target = Asset::find($request->get('assigned_asset')))) {
$location = $target->location_id;
} elseif (($request->has('assigned_location')) && ($target = Location::find($request->get('assigned_location')))) {
if (($request->filled('assigned_user')) && ($target = User::find($request->get('assigned_user')))) {
$location = $target->location_id;
} elseif (($request->filled('assigned_asset')) && ($target = Asset::find($request->get('assigned_asset')))) {
$location = $target->location_id;
} elseif (($request->filled('assigned_location')) && ($target = Location::find($request->get('assigned_location')))) {
$location = $target->id;
}
@@ -631,7 +631,7 @@ class AssetsController extends Controller
$expected_checkin = request('expected_checkin', null);
$note = request('note', null);
$asset_name = request('name', null);
// Set the location ID to the RTD location id if there is one
if ($asset->rtd_location_id!='') {
$asset->location_id = $target->rtd_location_id;
@@ -639,7 +639,7 @@ class AssetsController extends Controller
if ($asset->checkOut($target, Auth::user(), $checkout_at, $expected_checkin, $note, $asset_name, $asset->location_id)) {
return response()->json(Helper::formatStandardApiResponse('success', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkout.success')));
@@ -677,7 +677,7 @@ class AssetsController extends Controller
$asset->name = Input::get('name');
$asset->location_id = $asset->rtd_location_id;
if ($request->has('location_id')) {
if ($request->filled('location_id')) {
$asset->location_id = $request->input('location_id');
}

View File

@@ -24,13 +24,13 @@ class CategoriesController extends Controller
$allowed_columns = ['id', 'name','category_type', 'category_type','use_default_eula','eula_text', 'require_acceptance','checkin_email', 'assets_count', 'accessories_count', 'consumables_count', 'components_count','licenses_count', 'image'];
$categories = Category::select(['id', 'created_at', 'updated_at', 'name','category_type','use_default_eula','eula_text', 'require_acceptance','checkin_email','image'])
->withCount('assets', 'accessories', 'consumables', 'components','licenses');
->withCount('assets as assets_count', 'accessories as accessories_count', 'consumables as consumables_count', 'components as components_count','licenses as licenses_count');
if ($request->has('search')) {
if ($request->filled('search')) {
$categories = $categories->TextSearch($request->input('search'));
}
$offset = $request->input('offset', 0);
$offset = (($categories) && (request('offset') > $categories->count())) ? 0 : request('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'assets_count';
@@ -148,7 +148,7 @@ class CategoriesController extends Controller
'image',
]);
if ($request->has('search')) {
if ($request->filled('search')) {
$categories = $categories->where('name', 'LIKE', '%'.$request->get('search').'%');
}

View File

@@ -35,13 +35,13 @@ class CompaniesController extends Controller
'components_count',
];
$companies = Company::withCount('assets','licenses','accessories','consumables','components','users');
$companies = Company::withCount('assets as assets_count','licenses as licenses_count','accessories as accessories_count','consumables as consumables_count','components as components_count','users as users_count');
if ($request->has('search')) {
if ($request->filled('search')) {
$companies->TextSearch($request->input('search'));
}
$offset = $request->input('offset', 0);
$offset = (($companies) && (request('offset') > $companies->count())) ? 0 : request('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
@@ -168,7 +168,7 @@ class CompaniesController extends Controller
'companies.image',
]);
if ($request->has('search')) {
if ($request->filled('search')) {
$companies = $companies->where('companies.name', 'LIKE', '%'.$request->get('search').'%');
}

View File

@@ -27,23 +27,23 @@ class ComponentsController extends Controller
$components = Company::scopeCompanyables(Component::select('components.*')
->with('company', 'location', 'category'));
if ($request->has('search')) {
if ($request->filled('search')) {
$components = $components->TextSearch($request->input('search'));
}
if ($request->has('company_id')) {
if ($request->filled('company_id')) {
$components->where('company_id','=',$request->input('company_id'));
}
if ($request->has('category_id')) {
if ($request->filled('category_id')) {
$components->where('category_id','=',$request->input('category_id'));
}
if ($request->has('location_id')) {
if ($request->filled('location_id')) {
$components->where('location_id','=',$request->input('location_id'));
}
$offset = request('offset', 0);
$offset = (($components) && (request('offset') > $components->count())) ? 0 : request('offset', 0);
$limit = request('limit', 50);
$allowed_columns = ['id','name','min_amt','order_number','serial','purchase_date','purchase_cost','company','category','qty','location','image'];

View File

@@ -27,20 +27,24 @@ class ConsumablesController extends Controller
->with('company', 'location', 'category', 'users', 'manufacturer')
);
if ($request->has('search')) {
if ($request->filled('search')) {
$consumables = $consumables->TextSearch(e($request->input('search')));
}
if ($request->has('company_id')) {
if ($request->filled('company_id')) {
$consumables->where('company_id','=',$request->input('company_id'));
}
if ($request->has('manufacturer_id')) {
if ($request->filled('category_id')) {
$consumables->where('category_id','=',$request->input('category_id'));
}
if ($request->filled('manufacturer_id')) {
$consumables->where('manufacturer_id','=',$request->input('manufacturer_id'));
}
$offset = request('offset', 0);
$offset = (($consumables) && (request('offset') > $consumables->count())) ? 0 : request('offset', 0);
$limit = request('limit', 50);
$allowed_columns = ['id','name','order_number','min_amt','purchase_date','purchase_cost','company','category','model_number', 'item_no', 'manufacturer','location','qty','image'];
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
@@ -161,7 +165,7 @@ class ConsumablesController extends Controller
{
$consumable = Consumable::with(array('consumableAssignments'=>
function ($query) {
$query->orderBy('created_at', 'DESC');
$query->orderBy($query->getModel()->getTable().'.created_at', 'DESC');
},
'consumableAssignments.admin'=> function ($query) {
},

View File

@@ -43,7 +43,7 @@ class CustomFieldsetsController extends Controller
public function index()
{
$this->authorize('index', CustomFieldset::class);
$fieldsets = CustomFieldset::withCount(['fields', 'models'])->get();
$fieldsets = CustomFieldset::withCount('fields as fields_count', 'models as models_count')->get();
return (new CustomFieldsetsTransformer)->transformCustomFieldsets($fieldsets, $fieldsets->count());
}

View File

@@ -33,13 +33,13 @@ class DepartmentsController extends Controller
'departments.created_at',
'departments.updated_at',
'departments.image'
])->with('users')->with('location')->with('manager')->with('company')->withCount('users');
])->with('users')->with('location')->with('manager')->with('company')->withCount('users as users_count');
if ($request->has('search')) {
if ($request->filled('search')) {
$departments = $departments->TextSearch($request->input('search'));
}
$offset = $request->input('offset', 0);
$offset = (($departments) && (request('offset') > $departments->count())) ? 0 : request('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
@@ -76,7 +76,7 @@ class DepartmentsController extends Controller
$department = new Department;
$department->fill($request->all());
$department->user_id = Auth::user()->id;
$department->manager_id = ($request->has('manager_id' ) ? $request->input('manager_id') : null);
$department->manager_id = ($request->filled('manager_id' ) ? $request->input('manager_id') : null);
if ($department->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $department, trans('admin/departments/message.create.success')));
@@ -142,7 +142,7 @@ class DepartmentsController extends Controller
'image',
]);
if ($request->has('search')) {
if ($request->filled('search')) {
$departments = $departments->where('name', 'LIKE', '%'.$request->get('search').'%');
}

View File

@@ -24,11 +24,11 @@ class DepreciationsController extends Controller
$depreciations = Depreciation::select('id','name','months','user_id','created_at','updated_at');
if ($request->has('search')) {
if ($request->filled('search')) {
$depreciations = $depreciations->TextSearch($request->input('search'));
}
$offset = $request->input('offset', 0);
$offset = (($depreciations) && (request('offset') > $depreciations->count())) ? 0 : request('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';

View File

@@ -22,13 +22,13 @@ class GroupsController extends Controller
$this->authorize('view', Group::class);
$allowed_columns = ['id','name','created_at', 'users_count'];
$groups = Group::select('id','name','permissions','created_at','updated_at')->withCount('users');
$groups = Group::select('id','name','permissions','created_at','updated_at')->withCount('users as users_count');
if ($request->has('search')) {
if ($request->filled('search')) {
$groups = $groups->TextSearch($request->input('search'));
}
$offset = $request->input('offset', 0);
$offset = (($groups) && (request('offset') > $groups->count())) ? 0 : request('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';

View File

@@ -25,7 +25,7 @@ class ImportController extends Controller
*/
public function index()
{
//
$this->authorize('import');
$imports = Import::latest()->get();
return (new ImportsTransformer)->transformImports($imports);
@@ -39,10 +39,8 @@ class ImportController extends Controller
*/
public function store()
{
//
if (!Company::isCurrentUserAuthorized()) {
return redirect()->route('hardware.index')->with('error', trans('general.insufficient_permissions'));
} elseif (!config('app.lock_passwords')) {
$this->authorize('import');
if (!config('app.lock_passwords')) {
$files = Input::file('files');
$path = config('app.private_uploads').'/imports';
$results = [];
@@ -119,7 +117,7 @@ class ImportController extends Controller
*/
public function process(ItemImportRequest $request, $import_id)
{
$this->authorize('create', Asset::class);
$this->authorize('import');
// Run a backup immediately before processing
Artisan::call('backup:run');
$errors = $request->import(Import::find($import_id));
@@ -162,7 +160,7 @@ class ImportController extends Controller
*/
public function destroy($import_id)
{
$this->authorize('create', Asset::class);
$this->authorize('import');
$import = Import::find($import_id);
try {
unlink(config('app.private_uploads').'/imports/'.$import->file_path);

View File

@@ -25,64 +25,64 @@ class LicensesController extends Controller
public function index(Request $request)
{
$this->authorize('view', License::class);
$licenses = Company::scopeCompanyables(License::with('company', 'manufacturer', 'freeSeats', 'supplier','category')->withCount('freeSeats'));
$licenses = Company::scopeCompanyables(License::with('company', 'manufacturer', 'freeSeats', 'supplier','category')->withCount('freeSeats as free_seats_count'));
if ($request->has('company_id')) {
if ($request->filled('company_id')) {
$licenses->where('company_id','=',$request->input('company_id'));
}
if ($request->has('name')) {
if ($request->filled('name')) {
$licenses->where('licenses.name','=',$request->input('name'));
}
if ($request->has('product_key')) {
if ($request->filled('product_key')) {
$licenses->where('licenses.serial','=',$request->input('product_key'));
}
if ($request->has('order_number')) {
if ($request->filled('order_number')) {
$licenses->where('order_number','=',$request->input('order_number'));
}
if ($request->has('purchase_order')) {
if ($request->filled('purchase_order')) {
$licenses->where('purchase_order','=',$request->input('purchase_order'));
}
if ($request->has('license_name')) {
if ($request->filled('license_name')) {
$licenses->where('license_name','=',$request->input('license_name'));
}
if ($request->has('license_email')) {
if ($request->filled('license_email')) {
$licenses->where('license_email','=',$request->input('license_email'));
}
if ($request->has('manufacturer_id')) {
if ($request->filled('manufacturer_id')) {
$licenses->where('manufacturer_id','=',$request->input('manufacturer_id'));
}
if ($request->has('supplier_id')) {
if ($request->filled('supplier_id')) {
$licenses->where('supplier_id','=',$request->input('supplier_id'));
}
if ($request->has('category_id')) {
if ($request->filled('category_id')) {
$licenses->where('category_id','=',$request->input('category_id'));
}
if ($request->has('depreciation_id')) {
if ($request->filled('depreciation_id')) {
$licenses->where('depreciation_id','=',$request->input('depreciation_id'));
}
if ($request->has('supplier_id')) {
if ($request->filled('supplier_id')) {
$licenses->where('supplier_id','=',$request->input('supplier_id'));
}
if ($request->has('search')) {
if ($request->filled('search')) {
$licenses = $licenses->TextSearch($request->input('search'));
}
$offset = request('offset', 0);
$offset = (($licenses) && (request('offset') > $licenses->count())) ? 0 : request('offset', 0);
$limit = request('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
@@ -227,7 +227,8 @@ class LicensesController extends Controller
$seats = LicenseSeat::where('license_id', $licenseId)->with('license', 'user', 'asset');
$offset = request('offset', 0);
$offset = (($seats) && (request('offset') > $seats->count())) ? 0 : request('offset', 0);
$limit = request('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';

View File

@@ -41,17 +41,17 @@ class LocationsController extends Controller
'locations.updated_at',
'locations.image',
'locations.currency'
])->withCount('assignedAssets')
->withCount('assets')
->withCount('users');
])->withCount('assignedAssets as assigned_assets_count')
->withCount('assets as assets_count')
->withCount('users as users_count');
if ($request->has('search')) {
if ($request->filled('search')) {
$locations = $locations->TextSearch($request->input('search'));
}
$offset = $request->input('offset', 0);
$offset = (($locations) && (request('offset') > $locations->count())) ? 0 : request('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
@@ -106,7 +106,26 @@ class LocationsController extends Controller
public function show($id)
{
$this->authorize('view', Location::class);
$location = Location::findOrFail($id);
$location = Location::with('parent', 'manager', 'childLocations')
->select([
'locations.id',
'locations.name',
'locations.address',
'locations.address2',
'locations.city',
'locations.state',
'locations.zip',
'locations.country',
'locations.parent_id',
'locations.manager_id',
'locations.created_at',
'locations.updated_at',
'locations.image',
'locations.currency'
])
->withCount('assignedAssets as assigned_assets_count')
->withCount('assets as assets_count')
->withCount('users as users_count')->findOrFail($id);
return (new LocationsTransformer)->transformLocation($location);
}
@@ -173,7 +192,7 @@ class LocationsController extends Controller
'locations.image',
]);
if ($request->has('search')) {
if ($request->filled('search')) {
$locations = $locations->where('locations.name', 'LIKE', '%'.$request->get('search').'%');
}

View File

@@ -26,20 +26,20 @@ class ManufacturersController extends Controller
$manufacturers = Manufacturer::select(
array('id','name','url','support_url','support_email','support_phone','created_at','updated_at','image', 'deleted_at')
)->withCount('assets')->withCount('licenses')->withCount('consumables')->withCount('accessories');
)->withCount('assets as assets_count')->withCount('licenses as licenses_count')->withCount('consumables as consumables_count')->withCount('accessories as accessories_count');
if ($request->input('deleted')=='true') {
$manufacturers->onlyTrashed();
}
if ($request->has('search')) {
if ($request->filled('search')) {
$manufacturers = $manufacturers->TextSearch($request->input('search'));
}
$offset = request('offset', 0);
$offset = (($manufacturers) && (request('offset') > $manufacturers->count())) ? 0 : request('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
@@ -83,7 +83,7 @@ class ManufacturersController extends Controller
public function show($id)
{
$this->authorize('view', Manufacturer::class);
$manufacturer = Manufacturer::findOrFail($id);
$manufacturer = Manufacturer::withCount('assets as assets_count')->withCount('licenses as licenses_count')->withCount('consumables as consumables_count')->withCount('accessories as accessories_count')->findOrFail($id);
return (new ManufacturersTransformer)->transformManufacturer($manufacturer);
}
@@ -145,7 +145,7 @@ class ManufacturersController extends Controller
'image',
]);
if ($request->has('search')) {
if ($request->filled('search')) {
$manufacturers = $manufacturers->where('name', 'LIKE', '%'.$request->get('search').'%');
}

View File

@@ -27,15 +27,20 @@ class ProfileController extends Controller
foreach ($checkoutRequests as $checkoutRequest) {
$results['rows'][] = [
'image' => $checkoutRequest->itemRequested()->present()->getImageUrl(),
'name' => $checkoutRequest->itemRequested()->present()->name(),
'type' => $checkoutRequest->itemType(),
'qty' => $checkoutRequest->quantity,
'location' => ($checkoutRequest->location()) ? $checkoutRequest->location()->name : null,
'expected_checkin' => Helper::getFormattedDateObject($checkoutRequest->itemRequested()->expected_checkin, 'datetime'),
'request_date' => Helper::getFormattedDateObject($checkoutRequest->created_at, 'datetime'),
];
// Make sure the asset and request still exist
if ($checkoutRequest && $checkoutRequest->itemRequested()) {
$results['rows'][] = [
'image' => $checkoutRequest->itemRequested()->present()->getImageUrl(),
'name' => $checkoutRequest->itemRequested()->present()->name(),
'type' => $checkoutRequest->itemType(),
'qty' => $checkoutRequest->quantity,
'location' => ($checkoutRequest->location()) ? $checkoutRequest->location()->name : null,
'expected_checkin' => Helper::getFormattedDateObject($checkoutRequest->itemRequested()->expected_checkin, 'datetime'),
'request_date' => Helper::getFormattedDateObject($checkoutRequest->created_at, 'datetime'),
];
}
}
return $results;
}

View File

@@ -22,25 +22,25 @@ class ReportsController extends Controller
$actionlogs = Actionlog::with('item', 'user', 'target','location');
if ($request->has('search')) {
if ($request->filled('search')) {
$actionlogs = $actionlogs->TextSearch(e($request->input('search')));
}
if (($request->has('target_type')) && ($request->has('target_id'))) {
if (($request->filled('target_type')) && ($request->filled('target_id'))) {
$actionlogs = $actionlogs->where('target_id','=',$request->input('target_id'))
->where('target_type','=',"App\\Models\\".ucwords($request->input('target_type')));
}
if (($request->has('item_type')) && ($request->has('item_id'))) {
if (($request->filled('item_type')) && ($request->filled('item_id'))) {
$actionlogs = $actionlogs->where('item_id','=',$request->input('item_id'))
->where('item_type','=',"App\\Models\\".ucwords($request->input('item_type')));
}
if ($request->has('action_type')) {
if ($request->filled('action_type')) {
$actionlogs = $actionlogs->where('action_type','=',$request->input('action_type'))->orderBy('created_at', 'desc');
}
if ($request->has('uploads')) {
if ($request->filled('uploads')) {
$actionlogs = $actionlogs->whereNotNull('filename')->orderBy('created_at', 'desc');
}

View File

@@ -38,7 +38,7 @@ class SettingsController extends Controller
//return response()->json(['message' => $e->getMessage()], 500);
}
} catch (\Exception $e) {
\Log::debug('Connection failed');
\Log::debug('Connection failed but we cannot debug it any further on our end.');
return response()->json(['message' => $e->getMessage()], 600);
}

View File

@@ -24,13 +24,13 @@ class StatuslabelsController extends Controller
$this->authorize('view', Statuslabel::class);
$allowed_columns = ['id','name','created_at', 'assets_count','color','default_label'];
$statuslabels = Statuslabel::withCount('assets');
$statuslabels = Statuslabel::withCount('assets as assets_count');
if ($request->has('search')) {
if ($request->filled('search')) {
$statuslabels = $statuslabels->TextSearch($request->input('search'));
}
$offset = $request->input('offset', 0);
$offset = (($statuslabels) && (request('offset') > $statuslabels->count())) ? 0 : request('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
@@ -55,7 +55,7 @@ class StatuslabelsController extends Controller
$this->authorize('create', Statuslabel::class);
$request->except('deployable', 'pending','archived');
if (!$request->has('type')) {
if (!$request->filled('type')) {
return response()->json(Helper::formatStandardApiResponse('error', null, ["type" => ["Status label type is required."]]),500);
}
@@ -106,7 +106,7 @@ class StatuslabelsController extends Controller
$request->except('deployable', 'pending','archived');
if (!$request->has('type')) {
if (!$request->filled('type')) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'Status label type is required.'));
}
@@ -162,7 +162,7 @@ class StatuslabelsController extends Controller
{
$this->authorize('view', Statuslabel::class);
$statuslabels = Statuslabel::with('assets')->groupBy('id')->withCount('assets')->get();
$statuslabels = Statuslabel::with('assets')->groupBy('id')->withCount('assets as assets_count')->get();
$labels=[];
$points=[];
@@ -238,8 +238,7 @@ class StatuslabelsController extends Controller
*/
public function checkIfDeployable($id) {
$statuslabel = Statuslabel::findOrFail($id);
$this->authorize('view', $statuslabel);
$this->authorize('view', Asset::class);
if ($statuslabel->getStatuslabelType()=='deployable') {
return '1';

View File

@@ -26,14 +26,14 @@ class SuppliersController extends Controller
$suppliers = Supplier::select(
array('id','name','address','address2','city','state','country','fax', 'phone','email','contact','created_at','updated_at','deleted_at','image','notes')
)->withCount('assets')->withCount('licenses')->withCount('accessories');
)->withCount('assets as assets_count')->withCount('licenses as licenses_count')->withCount('accessories as accessories_count');
if ($request->has('search')) {
if ($request->filled('search')) {
$suppliers = $suppliers->TextSearch($request->input('search'));
}
$offset = request('offset', 0);
$offset = (($suppliers) && (request('offset') > $suppliers->count())) ? 0 : request('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
@@ -115,7 +115,7 @@ class SuppliersController extends Controller
public function destroy($id)
{
$this->authorize('delete', Supplier::class);
$supplier = Supplier::with('asset_maintenances', 'assets', 'licenses')->withCount('asset_maintenances','assets', 'licenses')->findOrFail($id);
$supplier = Supplier::with('asset_maintenances', 'assets', 'licenses')->withCount('asset_maintenances as asset_maintenances_count','assets as assets_count', 'licenses as licenses_count')->findOrFail($id);
$this->authorize('delete', $supplier);
@@ -153,7 +153,7 @@ class SuppliersController extends Controller
'image',
]);
if ($request->has('search')) {
if ($request->filled('search')) {
$suppliers = $suppliers->where('suppliers.name', 'LIKE', '%'.$request->get('search').'%');
}

View File

@@ -12,6 +12,7 @@ use App\Http\Requests\SaveUserRequest;
use App\Models\Asset;
use App\Http\Transformers\AssetsTransformer;
use App\Http\Transformers\SelectlistTransformer;
use App\Http\Transformers\AccessoriesTransformer;
class UsersController extends Controller
{
@@ -51,41 +52,42 @@ class UsersController extends Controller
'users.phone',
'users.state',
'users.two_factor_enrolled',
'users.two_factor_optin',
'users.updated_at',
'users.username',
'users.zip',
])->with('manager', 'groups', 'userloc', 'company', 'department','assets','licenses','accessories','consumables')
->withCount('assets','licenses','accessories','consumables');
->withCount('assets as assets_count','licenses as licenses_count','accessories as accessories_count','consumables as consumables_count');
$users = Company::scopeCompanyables($users);
if (($request->has('deleted')) && ($request->input('deleted')=='true')) {
if (($request->filled('deleted')) && ($request->input('deleted')=='true')) {
$users = $users->GetDeleted();
}
if ($request->has('company_id')) {
if ($request->filled('company_id')) {
$users = $users->where('users.company_id', '=', $request->input('company_id'));
}
if ($request->has('location_id')) {
if ($request->filled('location_id')) {
$users = $users->where('users.location_id', '=', $request->input('location_id'));
}
if ($request->has('group_id')) {
if ($request->filled('group_id')) {
$users = $users->ByGroup($request->get('group_id'));
}
if ($request->has('department_id')) {
if ($request->filled('department_id')) {
$users = $users->where('users.department_id','=',$request->input('department_id'));
}
if ($request->has('search')) {
if ($request->filled('search')) {
$users = $users->TextSearch($request->input('search'));
}
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$offset = request('offset', 0);
$offset = (($users) && (request('offset') > $users->count())) ? 0 : request('offset', 0);
$limit = request('limit', 20);
switch ($request->input('sort')) {
@@ -98,6 +100,9 @@ class UsersController extends Controller
case 'department':
$users = $users->OrderDepartment($order);
break;
case 'company':
$users = $users->OrderCompany($order);
break;
default:
$allowed_columns =
[
@@ -146,9 +151,8 @@ class UsersController extends Controller
$users = Company::scopeCompanyables($users);
if ($request->has('search')) {
$users = $users->where('first_name', 'LIKE', '%'.$request->get('search').'%')
->orWhere('last_name', 'LIKE', '%'.$request->get('search').'%')
if ($request->filled('search')) {
$users = $users->SimpleNameSearch($request->get('search'))
->orWhere('username', 'LIKE', '%'.$request->get('search').'%')
->orWhere('employee_num', 'LIKE', '%'.$request->get('search').'%');
}
@@ -200,6 +204,12 @@ class UsersController extends Controller
$user->password = bcrypt($request->get('password', $tmp_pass));
if ($user->save()) {
if ($request->filled('groups')) {
$user->groups()->sync($request->input('groups'));
} else {
$user->groups()->sync(array());
}
return response()->json(Helper::formatStandardApiResponse('success', (new UsersTransformer)->transformUser($user), trans('admin/users/message.success.create')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $user->getErrors()));
@@ -240,7 +250,7 @@ class UsersController extends Controller
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot be your own manager'));
}
if ($request->has('password')) {
if ($request->filled('password')) {
$user->password = bcrypt($request->input('password'));
}
@@ -249,6 +259,22 @@ class UsersController extends Controller
->where('assigned_to', $user->id)->update(['location_id' => $request->input('location_id', null)]);
if ($user->save()) {
// Sync group memberships:
// This was changed in Snipe-IT v4.6.x to 4.7, since we upgraded to Laravel 5.5
// which changes the behavior of has vs filled.
// The $request->has method will now return true even if the input value is an empty string or null.
// A new $request->filled method has was added that provides the previous behavior of the has method.
// Check if the request has groups passed and has a value
if ($request->filled('groups')) {
$user->groups()->sync($request->input('groups'));
// The groups field has been passed but it is null, so we should blank it out
} elseif ($request->has('groups')) {
$user->groups()->sync(array());
}
return response()->json(Helper::formatStandardApiResponse('success', (new UsersTransformer)->transformUser($user), trans('admin/users/message.success.update')));
}
@@ -270,10 +296,23 @@ class UsersController extends Controller
$this->authorize('delete', $user);
if ($user->assets()->count() > 0) {
if (($user->assets) && ($user->assets->count() > 0)) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.error.delete_has_assets')));
}
if (($user->licenses) && ($user->licenses->count() > 0)) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'This user still has ' . $user->licenses->count() . ' license(s) associated with them and cannot be deleted.'));
}
if (($user->accessories) && ($user->accessories->count() > 0)) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'This user still has ' . $user->accessories->count() . ' accessories associated with them.'));
}
if (($user->managedLocations()) && ($user->managedLocations()->count() > 0)) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'This user still has ' . $user->managedLocations()->count() . ' locations that they manage.'));
}
if ($user->delete()) {
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.success.delete')));
}
@@ -292,10 +331,27 @@ class UsersController extends Controller
{
$this->authorize('view', User::class);
$this->authorize('view', Asset::class);
$assets = Asset::where('assigned_to', '=', $id)->with('model')->get();
$assets = Asset::where('assigned_to', '=', $id)->where('assigned_type', '=', User::class)->with('model')->get();
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
}
/**
* Return JSON containing a list of accessories assigned to a user.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.6.14]
* @param $userId
* @return string JSON
*/
public function accessories($id)
{
$this->authorize('view', User::class);
$user = User::findOrFail($id);
$this->authorize('view', Accessory::class);
$accessories = $user->accessories;
return (new AccessoriesTransformer)->transformAccessories($accessories, $accessories->count());
}
/**
* Reset the user's two-factor status
*
@@ -309,7 +365,7 @@ class UsersController extends Controller
$this->authorize('update', User::class);
if ($request->has('id')) {
if ($request->filled('id')) {
try {
$user = User::find($request->get('id'));
$user->two_factor_secret = null;

View File

@@ -65,15 +65,15 @@ class AssetCheckinController extends Controller
$asset->assignedTo()->disassociate($asset);
$asset->assigned_type = null;
$asset->accepted = null;
$asset->name = e($request->get('name'));
$asset->name = $request->get('name');
if ($request->has('status_id')) {
if ($request->filled('status_id')) {
$asset->status_id = e($request->get('status_id'));
}
$asset->location_id = $asset->rtd_location_id;
if ($request->has('location_id')) {
if ($request->filled('location_id')) {
$asset->location_id = e($request->get('location_id'));
}
@@ -93,7 +93,7 @@ class AssetCheckinController extends Controller
$data['model_name'] = $asset->model->name;
$data['model_number'] = $asset->model->model_number;
if ($backto=='user') {
if ((isset($user)) && ($backto =='user')) {
return redirect()->route("users.show", $user->id)->with('success', trans('admin/hardware/message.checkin.success'));
}
return redirect()->route("hardware.index")->with('success', trans('admin/hardware/message.checkin.success'));

View File

@@ -28,7 +28,6 @@ class AssetCheckoutController extends Controller
{
// Check if the asset exists
if (is_null($asset = Asset::find(e($assetId)))) {
// Redirect to the asset management page with error
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
}
@@ -39,7 +38,6 @@ class AssetCheckoutController extends Controller
}
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkout.not_available'));
// Get the dropdown of users and then pass it to the checkout view
}
@@ -71,12 +69,12 @@ class AssetCheckoutController extends Controller
$asset = $this->updateAssetLocation($asset, $target);
$checkout_at = date("Y-m-d H:i:s");
if (($request->has('checkout_at')) && ($request->get('checkout_at')!= date("Y-m-d"))) {
if (($request->filled('checkout_at')) && ($request->get('checkout_at')!= date("Y-m-d"))) {
$checkout_at = $request->get('checkout_at');
}
$expected_checkin = '';
if ($request->has('expected_checkin')) {
if ($request->filled('expected_checkin')) {
$expected_checkin = $request->get('expected_checkin');
}

View File

@@ -111,12 +111,16 @@ class AssetFilesController extends Controller
$this->authorize('update', $asset);
$log = Actionlog::find($fileId);
$full_filename = $destinationPath.'/'.$log->filename;
if (file_exists($full_filename)) {
unlink($destinationPath.'/'.$log->filename);
if ($log) {
$full_filename = $destinationPath.'/'.$log->filename;
if (file_exists($full_filename)) {
unlink($destinationPath.'/'.$log->filename);
}
$log->delete();
return redirect()->back()->with('success', trans('admin/hardware/message.deletefile.success'));
}
$log->delete();
return redirect()->back()->with('success', trans('admin/hardware/message.deletefile.success'));
return redirect()->back()->with('error', 'Could not find matching upload log.');
}
// Redirect to the hardware management page

View File

@@ -162,6 +162,9 @@ class AssetMaintenancesController extends Controller
// Redirect to the improvement management page
return redirect()->route('maintenances.index')
->with('error', trans('admin/asset_maintenances/message.not_found'));
} elseif (!$assetMaintenance->asset) {
return redirect()->route('maintenances.index')
->with('error', 'The asset associated with this maintenance does not exist.');
} elseif (!Company::isCurrentUserHasAccess($assetMaintenance->asset)) {
return static::getInsufficientPermissionsRedirect();
}

View File

@@ -97,7 +97,7 @@ class AssetModelsController extends Controller
$path = app('models_upload_path');
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(500, null, function ($constraint) {
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path.'/'.$file_name);
@@ -194,7 +194,7 @@ class AssetModelsController extends Controller
$file_name = $model->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(500, null, function ($constraint) {
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save(app('models_upload_path').$file_name);
@@ -209,7 +209,7 @@ class AssetModelsController extends Controller
try {
unlink(app('models_upload_path').$old_image);
} catch (\Exception $e) {
\Log::error($e);
\Log::info($e);
}
}
@@ -246,7 +246,7 @@ class AssetModelsController extends Controller
try {
unlink(public_path().'/uploads/models/'.$model->image);
} catch (\Exception $e) {
\Log::error($e);
\Log::info($e);
}
}
@@ -373,7 +373,7 @@ class AssetModelsController extends Controller
if ((is_array($models_raw_array)) && (count($models_raw_array) > 0)) {
$models = AssetModel::whereIn('id', $models_raw_array)->withCount('assets')->orderBy('assets_count', 'ASC')->get();
$models = AssetModel::whereIn('id', $models_raw_array)->withCount('assets as assets_count')->orderBy('assets_count', 'ASC')->get();
// If deleting....
if ($request->input('bulk_actions')=='delete') {
@@ -420,10 +420,10 @@ class AssetModelsController extends Controller
$update_array = array();
if (($request->has('manufacturer_id') && ($request->input('manufacturer_id')!='NC'))) {
if (($request->filled('manufacturer_id') && ($request->input('manufacturer_id')!='NC'))) {
$update_array['manufacturer_id'] = $request->input('manufacturer_id');
}
if (($request->has('category_id') && ($request->input('category_id')!='NC'))) {
if (($request->filled('category_id') && ($request->input('category_id')!='NC'))) {
$update_array['category_id'] = $request->input('category_id');
}
if ($request->input('fieldset_id')!='NC') {
@@ -461,7 +461,7 @@ class AssetModelsController extends Controller
if ((is_array($models_raw_array)) && (count($models_raw_array) > 0)) {
$models = AssetModel::whereIn('id', $models_raw_array)->withCount('assets')->get();
$models = AssetModel::whereIn('id', $models_raw_array)->withCount('assets as assets_count')->get();
$del_error_count = 0;
$del_count = 0;

View File

@@ -71,7 +71,7 @@ class AssetsController extends Controller
public function index(Request $request)
{
$this->authorize('index', Asset::class);
if ($request->has('company_id')) {
if ($request->filled('company_id')) {
$company = Company::find($request->input('company_id'));
} else {
$company = null;
@@ -96,7 +96,7 @@ class AssetsController extends Controller
->with('item', new Asset)
->with('statuslabel_types', Helper::statusTypeList());
if ($request->has('model_id')) {
if ($request->filled('model_id')) {
$selected_model = AssetModel::find($request->input('model_id'));
$view->with('selected_model', $selected_model);
}
@@ -143,7 +143,7 @@ class AssetsController extends Controller
}
// Create the image (if one was chosen.)
if ($request->hasFile('image')) {
if ($request->filled('image')) {
$image = $request->input('image');
// After modification, the image is prefixed by mime info like the following:
@@ -163,7 +163,7 @@ class AssetsController extends Controller
}
$path = public_path('uploads/assets/'.$file_name);
try {
Image::make($image)->resize(500, 500, function ($constraint) {
Image::make($image)->resize(800, 800, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
@@ -183,7 +183,7 @@ class AssetsController extends Controller
// Validation for these fields is handled through the AssetRequest form request
$model = AssetModel::find($request->get('model_id'));
if ($model->fieldset) {
if (($model) && ($model->fieldset)) {
foreach ($model->fieldset->fields as $field) {
if ($field->field_encrypted=='1') {
if (Gate::allows('admin')) {
@@ -313,7 +313,7 @@ class AssetsController extends Controller
$asset->supplier_id = $request->input('supplier_id', null);
// If the box isn't checked, it's not in the request at all.
$asset->requestable = $request->has('requestable');
$asset->requestable = $request->filled('requestable');
$asset->rtd_location_id = $request->input('rtd_location_id', null);
if ($asset->assigned_to=='') {
@@ -321,12 +321,12 @@ class AssetsController extends Controller
}
if ($request->has('image_delete')) {
if ($request->filled('image_delete')) {
try {
unlink(public_path().'/uploads/assets/'.$asset->image);
$asset->image = '';
} catch (\Exception $e) {
\Log::error($e);
\Log::info($e);
}
}
@@ -343,7 +343,7 @@ class AssetsController extends Controller
$asset->physical = '1';
// Update the image
if ($request->has('image')) {
if ($request->filled('image')) {
$image = $request->input('image');
// See postCreate for more explaination of the following.
$header = explode(';', $image, 2)[0];
@@ -359,7 +359,7 @@ class AssetsController extends Controller
$file_name = str_random(25).".".$extension;
$path = public_path('uploads/assets/'.$file_name);
try {
Image::make($image)->resize(500, 500, function ($constraint) {
Image::make($image)->resize(800, 800, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
@@ -380,7 +380,7 @@ class AssetsController extends Controller
// FIXME: No idea why this is returning a Builder error on db_column_name.
// Need to investigate and fix. Using static method for now.
$model = AssetModel::find($request->get('model_id'));
if ($model->fieldset) {
if (($model) && ($model->fieldset)) {
foreach ($model->fieldset->fields as $field) {
if ($field->field_encrypted=='1') {
if (Gate::allows('admin')) {
@@ -579,7 +579,7 @@ class AssetsController extends Controller
//get the first row, usually the CSV header
//$headers = $csv->fetchOne();
$results = $csv->fetchAssoc();
$results = $csv->getRecords();
$item = array();
$status = array();
$status['error'] = array();
@@ -744,6 +744,18 @@ class AssetsController extends Controller
return view('hardware/audit')->with('asset', $asset)->with('next_audit_date', $dt)->with('locations_list');
}
public function dueForAudit()
{
$this->authorize('audit', Asset::class);
return view('hardware/audit-due');
}
public function overdueForAudit()
{
$this->authorize('audit', Asset::class);
return view('hardware/audit-overdue');
}
public function auditStore(AssetFileRequest $request, $id)
{
@@ -781,7 +793,7 @@ class AssetsController extends Controller
$filename = 'audit-'.$asset->id.'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
$file->move($destinationPath, $filename);
} catch (\Exception $e) {
\Log::error($e);
\Log::info($e);
}
}

View File

@@ -55,7 +55,10 @@ class ForgotPasswordController extends Controller
// to send the link, we will examine the response then see the message we
// need to show to the user. Finally, we'll send out a proper response.
$response = $this->broker()->sendResetLink(
$request->only('email')
array_merge(
$request->only('email'),
['activated' => '1']
)
);
if ($response === \Password::RESET_LINK_SENT) {

View File

@@ -68,7 +68,7 @@ class LoginController extends Controller
{
$remote_user = $request->server('REMOTE_USER');
if (Setting::getSettings()->login_remote_user_enabled == "1" && isset($remote_user) && !empty($remote_user)) {
LOG::debug("Authenticatiing via REMOTE_USER.");
Log::debug("Authenticatiing via REMOTE_USER.");
$pos = strpos($remote_user, '\\');
if ($pos > 0) {
@@ -77,45 +77,45 @@ class LoginController extends Controller
try {
$user = User::where('username', '=', $remote_user)->whereNull('deleted_at')->where('activated', '=', '1')->first();
LOG::debug("Remote user auth lookup complete");
Log::debug("Remote user auth lookup complete");
if(!is_null($user)) Auth::login($user, true);
} catch(Exception $e) {
LOG::error("There was an error authenticating the Remote user: " . $e->getMessage());
Log::debug("There was an error authenticating the Remote user: " . $e->getMessage());
}
}
}
private function loginViaLdap(Request $request)
{
LOG::debug("Binding user to LDAP.");
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");
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");
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)->where('activated', '=', '1')->first();
LOG::debug("Local auth lookup complete");
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'));
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.");
Log::debug("Local user created.");
} else {
LOG::debug("Could not create local user.");
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.");
Log::debug("Local user ".$request->input('username')." exists in database. Updating existing user against LDAP.");
$ldap_attr = Ldap::parseAndMapLdapAttributes($ldap_user);
@@ -161,7 +161,7 @@ class LoginController extends Controller
// Should we even check for LDAP users?
if (Setting::getSettings()->ldap_enabled=='1') {
LOG::debug("LDAP is enabled.");
Log::debug("LDAP is enabled.");
try {
$user = $this->loginViaLdap($request);
Auth::login($user, true);
@@ -169,13 +169,13 @@ class LoginController extends Controller
// If the user was unable to login via LDAP, log the error and let them fall through to
// local authentication.
} catch (\Exception $e) {
LOG::error("There was an error authenticating the LDAP user: ".$e->getMessage());
Log::debug("There was an error authenticating the LDAP user: ".$e->getMessage());
}
}
// If the user wasn't authenticated via LDAP, skip to local auth
if (!$user) {
LOG::debug("Authenticating user against database.");
Log::debug("Authenticating user against database.");
// Try to log the user in
if (!Auth::attempt(['username' => $request->input('username'), 'password' => $request->input('password'), 'activated' => 1], $request->input('remember'))) {
@@ -183,7 +183,7 @@ class LoginController extends Controller
$this->incrementLoginAttempts($request);
}
LOG::debug("Local authentication failed.");
Log::debug("Local authentication failed.");
return redirect()->back()->withInput()->with('error', trans('auth/message.account_not_found'));
} else {
@@ -193,7 +193,6 @@ class LoginController extends Controller
if ($user = Auth::user()) {
$user->last_login = \Carbon::now();
\Log::debug('Last login:'.$user->last_login);
$user->save();
}
// Redirect to the users page
@@ -209,26 +208,33 @@ class LoginController extends Controller
public function getTwoFactorEnroll()
{
// Make sure the user is logged in
if (!Auth::check()) {
return redirect()->route('login')->with('error', 'You must be logged in.');
return redirect()->route('login')->with('error', trans('auth/general.login_prompt'));
}
$settings = Setting::getSettings();
$user = Auth::user();
$google2fa = app()->make('PragmaRX\Google2FA\Contracts\Google2FA');
if ($user->two_factor_secret=='') {
$user->two_factor_secret = $google2fa->generateSecretKey(32);
$user->save();
// We wouldn't normally see this page if 2FA isn't enforced via the
// \App\Http\Middleware\CheckForTwoFactor middleware AND if a device isn't enrolled,
// but let's check check anyway in case there's a browser history or back button thing.
// While you can access this page directly, enrolling a device when 2FA isn't enforced
// won't cause any harm.
if (($user->two_factor_secret!='') && ($user->two_factor_enrolled==1)) {
return redirect()->route('two-factor')->with('error', trans('auth/message.two_factor.already_enrolled'));
}
$google2fa = new Google2FA();
$secret = $google2fa->generateSecretKey();
$user->two_factor_secret = $secret;
$user->save();
$google2fa_url = $google2fa->getQRCodeGoogleUrl(
urlencode(Setting::getSettings()->site_name),
urlencode($user->username),
$user->two_factor_secret
);
return view('auth.two_factor_enroll')->with('google2fa_url', $google2fa_url);
$barcode = new \Com\Tecnick\Barcode\Barcode();
$barcode_obj = $barcode->getBarcodeObj('QRCODE', 'otpauth://totp/'.urlencode($settings->site_name).':'.urlencode($user->username).'?secret='.urlencode($secret).'&issuer=Snipe-IT&period=30', 300, 300, 'black', array(-2, -2, -2, -2));
return view('auth.two_factor_enroll')->with('barcode_obj', $barcode_obj);
}
@@ -240,6 +246,20 @@ class LoginController extends Controller
*/
public function getTwoFactorAuth()
{
// Check that the user is logged in
if (!Auth::check()) {
return redirect()->route('login')->with('error', trans('auth/general.login_prompt'));
}
$user = Auth::user();
// Check whether there is a device enrolled.
// This *should* be handled via the \App\Http\Middleware\CheckForTwoFactor middleware
// but we're just making sure (in case someone edited the database directly, etc)
if (($user->two_factor_secret=='') || ($user->two_factor_enrolled!=1)) {
return redirect()->route('two-factor-enroll');
}
return view('auth.two_factor');
}
@@ -252,22 +272,25 @@ class LoginController extends Controller
{
if (!Auth::check()) {
return redirect()->route('login')->with('error', 'You must be logged in.');
return redirect()->route('login')->with('error', trans('auth/general.login_prompt'));
}
if (!$request->filled('two_factor_secret')) {
return redirect()->route('two-factor')->with('error', trans('auth/message.two_factor.code_required'));
}
$user = Auth::user();
$secret = $request->get('two_factor_secret');
$google2fa = app()->make('PragmaRX\Google2FA\Contracts\Google2FA');
$valid = $google2fa->verifyKey($user->two_factor_secret, $secret);
$google2fa = new Google2FA();
$secret = $request->input('two_factor_secret');
if ($valid) {
if ($google2fa->verifyKey($user->two_factor_secret, $secret)) {
$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');
return redirect()->route('two-factor')->with('error', trans('auth/message.two_factor.invalid_code'));
}
@@ -290,7 +313,7 @@ class LoginController extends Controller
return redirect()->away($customLogoutUrl);
}
return redirect()->route('login')->with('success', 'You have successfully logged out!');
return redirect()->route('login')->with('success', trans('auth/message.logout.success'));
}
@@ -315,11 +338,11 @@ class LoginController extends Controller
}
/**
* Redirect the user after determining they are locked out.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse
*/
* Redirect the user after determining they are locked out.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse
*/
protected function sendLockoutResponse(Request $request)
{
$seconds = $this->limiter()->availableIn(
@@ -330,18 +353,18 @@ class LoginController extends Controller
$message = \Lang::get('auth/message.throttle', ['minutes' => $minutes]);
return redirect()->back()
return redirect()->back()
->withInput($request->only($this->username(), 'remember'))
->withErrors([$this->username() => $message]);
}
/**
* Override the lockout time and duration
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse
*/
* Override the lockout time and duration
*
* @param \Illuminate\Http\Request $request
* @return bool
*/
protected function hasTooManyLoginAttempts(Request $request)
{
$lockoutTime = config('auth.throttle.lockout_duration');

View File

@@ -4,6 +4,8 @@ namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ResetsPasswords;
use App\Models\User;
use Illuminate\Http\Request;
class ResetPasswordController extends Controller
{
@@ -36,4 +38,8 @@ class ResetPasswordController extends Controller
{
$this->middleware('guest');
}
}

View File

@@ -26,13 +26,13 @@ class BulkAssetsController extends Controller
{
$this->authorize('update', Asset::class);
if (!$request->has('ids')) {
if (!$request->filled('ids')) {
return redirect()->back()->with('error', 'No assets selected');
}
$asset_ids = array_keys($request->input('ids'));
if ($request->has('bulk_actions')) {
if ($request->filled('bulk_actions')) {
switch($request->input('bulk_actions')) {
case 'labels':
return view('hardware/labels')
@@ -68,22 +68,22 @@ class BulkAssetsController extends Controller
\Log::debug($request->input('ids'));
if(!$request->has('ids') || count($request->input('ids')) <= 0) {
if(!$request->filled('ids') || count($request->input('ids')) <= 0) {
return redirect()->route("hardware.index")->with('warning', trans('No assets selected, so nothing was updated.'));
}
$assets = array_keys($request->input('ids'));
if (($request->has('purchase_date'))
|| ($request->has('purchase_cost'))
|| ($request->has('supplier_id'))
|| ($request->has('order_number'))
|| ($request->has('warranty_months'))
|| ($request->has('rtd_location_id'))
|| ($request->has('requestable'))
|| ($request->has('company_id'))
|| ($request->has('status_id'))
|| ($request->has('model_id'))
if (($request->filled('purchase_date'))
|| ($request->filled('purchase_cost'))
|| ($request->filled('supplier_id'))
|| ($request->filled('order_number'))
|| ($request->filled('warranty_months'))
|| ($request->filled('rtd_location_id'))
|| ($request->filled('requestable'))
|| ($request->filled('company_id'))
|| ($request->filled('status_id'))
|| ($request->filled('model_id'))
) {
foreach ($assets as $assetId) {
$this->update_array = [];
@@ -96,20 +96,20 @@ class BulkAssetsController extends Controller
->conditionallyAddItem('supplier_id')
->conditionallyAddItem('warranty_months');
if ($request->has('purchase_cost')) {
if ($request->filled('purchase_cost')) {
$this->update_array['purchase_cost'] = Helper::ParseFloat($request->input('purchase_cost'));
}
if ($request->has('company_id')) {
if ($request->filled('company_id')) {
$this->update_array['company_id'] = $request->input('company_id');
if ($request->input('company_id')=="clear") {
$this->update_array['company_id'] = null;
}
}
if ($request->has('rtd_location_id')) {
if ($request->filled('rtd_location_id')) {
$this->update_array['rtd_location_id'] = $request->input('rtd_location_id');
if (($request->has('update_real_loc')) && (($request->input('update_real_loc')) == '1')) {
if (($request->filled('update_real_loc')) && (($request->input('update_real_loc')) == '1')) {
$this->update_array['location_id'] = $request->input('rtd_location_id');
}
}
@@ -137,7 +137,7 @@ class BulkAssetsController extends Controller
*/
protected function conditionallyAddItem($field)
{
if(request()->has($field)) {
if(request()->filled($field)) {
$this->update_array[$field] = request()->input($field);
}
return $this;
@@ -155,7 +155,7 @@ class BulkAssetsController extends Controller
{
$this->authorize('delete', Asset::class);
if ($request->has('ids')) {
if ($request->filled('ids')) {
$assets = Asset::find($request->get('ids'));
foreach ($assets as $asset) {
$update_array['deleted_at'] = date('Y-m-d H:i:s');
@@ -206,13 +206,13 @@ class BulkAssetsController extends Controller
}
}
$checkout_at = date("Y-m-d H:i:s");
if (($request->has('checkout_at')) && ($request->get('checkout_at')!= date("Y-m-d"))) {
if (($request->filled('checkout_at')) && ($request->get('checkout_at')!= date("Y-m-d"))) {
$checkout_at = e($request->get('checkout_at'));
}
$expected_checkin = '';
if ($request->has('expected_checkin')) {
if ($request->filled('expected_checkin')) {
$expected_checkin = e($request->get('expected_checkin'));
}

View File

@@ -87,7 +87,7 @@ class CategoriesController extends Controller
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/categories/'.$file_name);
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
@@ -164,7 +164,7 @@ class CategoriesController extends Controller
$file_name = $category->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(500, null, function ($constraint) {
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save(app('categories_upload_path').$file_name);
@@ -179,7 +179,7 @@ class CategoriesController extends Controller
try {
unlink(app('categories_upload_path').$old_image);
} catch (\Exception $e) {
\Log::error($e);
\Log::info($e);
}
}

View File

@@ -31,7 +31,7 @@ final class CompaniesController extends Controller
{
$this->authorize('view', Company::class);
return view('companies/index')->with('companies', Company::all());
return view('companies/index');
}
/**
@@ -67,7 +67,7 @@ final class CompaniesController extends Controller
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/companies/'.$file_name);
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
@@ -133,7 +133,7 @@ final class CompaniesController extends Controller
$file_name = $company->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(500, null, function ($constraint) {
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save(app('companies_upload_path').$file_name);
@@ -148,7 +148,7 @@ final class CompaniesController extends Controller
try {
unlink(app('companies_upload_path').$old_image);
} catch (\Exception $e) {
\Log::error($e);
\Log::info($e);
}
}

View File

@@ -95,7 +95,7 @@ class ComponentsController extends Controller
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/components/'.$file_name);
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
@@ -168,7 +168,7 @@ class ComponentsController extends Controller
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/components/'.$file_name);
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);

View File

@@ -91,7 +91,7 @@ class ConsumablesController extends Controller
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/consumables/'.$file_name);
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
@@ -162,7 +162,7 @@ class ConsumablesController extends Controller
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/consumables/'.$file_name);
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);

View File

@@ -44,7 +44,7 @@ class CustomFieldsetsController extends Controller
$custom_fields_list = ["" => "Add New Field to Fieldset"] + CustomField::pluck("name", "id")->toArray();
$maxid = 0;
foreach ($cfset->fields() as $field) {
foreach ($cfset->fields as $field) {
if ($field->pivot->order > $maxid) {
$maxid=$field->pivot->order;
}
@@ -172,7 +172,7 @@ class CustomFieldsetsController extends Controller
* @since [v1.8]
* @return View
*/
public function associate($id)
public function associate(Request $request, $id)
{
$set = CustomFieldset::find($id);
@@ -180,12 +180,12 @@ class CustomFieldsetsController extends Controller
$this->authorize('update', $set);
foreach ($set->fields as $field) {
if ($field->id == Input::get('field_id')) {
if ($field->id == $request->input('field_id')) {
return redirect()->route("fieldsets.show", [$id])->withInput()->withErrors(['field_id' => trans('admin/custom_fields/message.field.already_added')]);
}
}
$results=$set->fields()->attach(Input::get('field_id'), ["required" => (Input::get('required') == "on"),"order" => Input::get('order')]);
$results = $set->fields()->attach(Input::get('field_id'), ["required" => ($request->input('required') == "on"),"order" => $request->input('order', 1)]);
return redirect()->route("fieldsets.show", [$id])->with("success", trans('admin/custom_fields/message.field.create.assoc_success'));
}

View File

@@ -30,7 +30,7 @@ class DepartmentsController extends Controller
{
$this->authorize('index', Department::class);
$company = null;
if ($request->has('company_id')) {
if ($request->filled('company_id')) {
$company = Company::find($request->input('company_id'));
}
return view('departments/index')->with('company', $company);
@@ -51,13 +51,13 @@ class DepartmentsController extends Controller
$department = new Department;
$department->fill($request->all());
$department->user_id = Auth::user()->id;
$department->manager_id = ($request->has('manager_id' ) ? $request->input('manager_id') : null);
$department->manager_id = ($request->filled('manager_id' ) ? $request->input('manager_id') : null);
if ($request->file('image')) {
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/departments/'.$file_name);
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
@@ -162,7 +162,7 @@ class DepartmentsController extends Controller
$this->authorize('update', $department);
$department->fill($request->all());
$department->manager_id = ($request->has('manager_id' ) ? $request->input('manager_id') : null);
$department->manager_id = ($request->filled('manager_id' ) ? $request->input('manager_id') : null);
$old_image = $department->image;
@@ -176,7 +176,7 @@ class DepartmentsController extends Controller
$file_name = $department->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(500, null, function ($constraint) {
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save(app('departments_upload_path').$file_name);
@@ -191,7 +191,7 @@ class DepartmentsController extends Controller
try {
unlink(app('departments_upload_path').$old_image);
} catch (\Exception $e) {
\Log::error($e);
\Log::info($e);
}
}

View File

@@ -34,7 +34,7 @@ class DepreciationsController extends Controller
$this->authorize('view', Depreciation::class);
// Show the page
return view('depreciations/index', compact('depreciations'));
return view('depreciations/index');
}

View File

@@ -31,7 +31,7 @@ class GroupsController extends Controller
public function index()
{
// Show the page
return view('groups/index', compact('groups'));
return view('groups/index');
}
/**
@@ -72,7 +72,7 @@ class GroupsController extends Controller
if ($group->save()) {
return redirect()->route("groups.index")->with('success', trans('admin/groups/message.success.create'));
}
return redirect(route('groups.create'))->withInput()->withErrors($group->getErrors());
return redirect()->back()->withInput()->withErrors($group->getErrors());
}
/**
@@ -111,7 +111,7 @@ class GroupsController extends Controller
{
$permissions = config('permissions');
if (!$group = Group::find($id)) {
return redirect()->route('groups')->with('error', trans('admin/groups/message.group_not_found', compact('id')));
return redirect()->route('groups.index')->with('error', trans('admin/groups/message.group_not_found', compact('id')));
}
$group->name = e(Input::get('name'));
$group->permissions = json_encode(Input::get('permission'));
@@ -138,7 +138,7 @@ class GroupsController extends Controller
{
if (!config('app.lock_passwords')) {
if (!$group = Group::find($id)) {
return redirect()->route('groups')->with('error', trans('admin/groups/message.group_not_found', compact('id')));
return redirect()->route('groups.index')->with('error', trans('admin/groups/message.group_not_found', compact('id')));
}
$group->delete();
// Redirect to the group management page

View File

@@ -12,7 +12,7 @@ class ImportsController extends Controller
{
public function index()
{
$this->authorize('create', Asset::class);
$this->authorize('import');
$imports = Import::latest()->get();
$imports = (new ImportsTransformer)->transformImports($imports);
return view('importer/import')->with('imports', $imports);

View File

@@ -179,7 +179,9 @@ class LicensesController extends Controller
$license->purchase_date = $request->input('purchase_date');
$license->purchase_order = $request->input('purchase_order');
$license->reassignable = $request->input('reassignable', 0);
$license->serial = $request->input('serial');
if (Gate::allows('viewKeys', $license)) {
$license->serial = $request->input('serial');
}
$license->termination_date = $request->input('termination_date');
$license->seats = e($request->input('seats'));
$license->manufacturer_id = $request->input('manufacturer_id');
@@ -413,20 +415,7 @@ class LicensesController extends Controller
return redirect()->back()->withInput();
}
// Declare the rules for the form validation
$rules = array(
'note' => 'string',
'notes' => 'string',
);
// Create a new validator instance from our validation rules
$validator = Validator::make(Input::all(), $rules);
// If validation fails, we'll exit the operation now.
if ($validator->fails()) {
// Ooops.. something went wrong
return redirect()->back()->withInput()->withErrors($validator);
}
$return_to = User::find($licenseSeat->assigned_to);
if (!$return_to) {
$return_to = Asset::find($licenseSeat->asset_id);
@@ -438,7 +427,7 @@ class LicensesController extends Controller
// Was the asset updated?
if ($licenseSeat->save()) {
$licenseSeat->logCheckin($return_to, e(request('note')));
$licenseSeat->logCheckin($license, e(request('note')));
if ($backTo=='user') {
return redirect()->route("users.show", $return_to->id)->with('success', trans('admin/licenses/message.checkin.success'));
}
@@ -556,21 +545,24 @@ class LicensesController extends Controller
$destinationPath = config('app.private_uploads').'/licenses';
// the license is valid
if (isset($license->id)) {
if ($license) {
$this->authorize('edit', $license);
$log = Actionlog::find($fileId);
$full_filename = $destinationPath.'/'.$log->filename;
if (file_exists($full_filename)) {
unlink($destinationPath.'/'.$log->filename);
if ($log) {
$full_filename = $destinationPath.'/'.$log->filename;
if (file_exists($full_filename)) {
unlink($destinationPath.'/'.$log->filename);
}
$log->delete();
return redirect()->back()->with('success', trans('admin/licenses/message.deletefile.success'));
}
$log->delete();
return redirect()->back()->with('success', trans('admin/licenses/message.deletefile.success'));
return redirect()->back()->with('error', 'Could not locate that file.');
}
// Prepare the error message
$error = trans('admin/licenses/message.does_not_exist', compact('id'));
// Redirect to the licence management page
return redirect()->route('licenses.index')->with('error', $error);
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist', compact('id')));
}
@@ -593,29 +585,31 @@ class LicensesController extends Controller
if (isset($license->id)) {
$this->authorize('view', $license);
$log = Actionlog::find($fileId);
$file = $log->get_src('licenses');
if ($log) {
if ($file =='') {
return response('File not found on server', 404)
->header('Content-Type', 'text/plain');
}
$mimetype = \File::mimeType($file);
if (!file_exists($file)) {
return response('File '.$file.' not found on server', 404)
->header('Content-Type', 'text/plain');
}
if ($download != 'true') {
if ($contents = file_get_contents($file)) {
return Response::make($contents)->header('Content-Type', $mimetype);
$file = $log->get_src('licenses');
if ($file =='') {
return response('File not found on server', 404)
->header('Content-Type', 'text/plain');
}
return JsonResponse::create(["error" => "Failed validation: "], 500);
$mimetype = \File::mimeType($file);
if (!file_exists($file)) {
return response('File '.$file.' not found on server', 404)
->header('Content-Type', 'text/plain');
}
if ($download != 'true') {
if ($contents = file_get_contents($file)) {
return Response::make($contents)->header('Content-Type', $mimetype);
}
return JsonResponse::create(["error" => "Failed validation: "], 500);
}
return Response::download($file);
}
return Response::download($file);
}

View File

@@ -44,7 +44,7 @@ class LocationsController extends Controller
$locations = Location::orderBy('created_at', 'DESC')->with('parent', 'assets', 'assignedassets')->get();
// Show the page
return view('locations/index', compact('locations'));
return view('locations/index');
}
@@ -101,7 +101,7 @@ class LocationsController extends Controller
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/locations/'.$file_name);
Image::make($image->getRealPath())->resize(600, null, function ($constraint) {
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
@@ -185,7 +185,7 @@ class LocationsController extends Controller
$file_name = $location->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(600, null, function ($constraint) {
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save(app('locations_upload_path').$file_name);
@@ -200,7 +200,7 @@ class LocationsController extends Controller
try {
unlink(app('locations_upload_path').$old_image);
} catch (\Exception $e) {
\Log::error($e);
\Log::info($e);
}
}

View File

@@ -36,7 +36,7 @@ class ManufacturersController extends Controller
public function index()
{
$this->authorize('index', Manufacturer::class);
return view('manufacturers/index', compact('manufacturers'));
return view('manufacturers/index');
}
@@ -81,7 +81,7 @@ class ManufacturersController extends Controller
$image = $request->file('image');
$file_name = str_slug($image->getClientOriginalName()).".".$image->getClientOriginalExtension();
$path = public_path('uploads/manufacturers/'.$file_name);
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
@@ -155,7 +155,7 @@ class ManufacturersController extends Controller
$file_name = $manufacturer->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(500, null, function ($constraint) {
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save(app('manufacturers_upload_path').$file_name);
@@ -170,7 +170,7 @@ class ManufacturersController extends Controller
try {
unlink(app('manufacturers_upload_path').$old_image);
} catch (\Exception $e) {
\Log::error($e);
\Log::info($e);
}
}
@@ -207,7 +207,7 @@ class ManufacturersController extends Controller
try {
unlink(public_path().'/uploads/manufacturers/'.$manufacturer->image);
} catch (\Exception $e) {
\Log::error($e);
\Log::info($e);
}
}

View File

@@ -49,6 +49,9 @@ class ProfileController extends Controller
$user->last_name = $request->input('last_name');
$user->website = $request->input('website');
$user->gravatar = $request->input('gravatar');
$user->phone = $request->input('phone');
if (!config('app.lock_passwords')) {
$user->locale = $request->input('locale', 'en');
@@ -125,8 +128,7 @@ class ProfileController extends Controller
$rules = array(
'current_password' => 'required',
'password' => Setting::passwordComplexityRulesSaving('store'),
'password_confirm' => 'required|same:password',
'password' => Setting::passwordComplexityRulesSaving('store').'|confirmed',
);
$validator = \Validator::make($request->all(), $rules);

View File

@@ -314,65 +314,65 @@ class ReportsController extends Controller
// Open output stream
$handle = fopen('php://output', 'w');
if ($request->has('use_bom')) {
if ($request->filled('use_bom')) {
fprintf($handle, chr(0xEF) . chr(0xBB) . chr(0xBF));
}
$header = [];
if ($request->has('company')) {
if ($request->filled('company')) {
$header[] = trans('general.company');
}
if ($request->has('asset_name')) {
if ($request->filled('asset_name')) {
$header[] = trans('admin/hardware/form.name');
}
if ($request->has('asset_tag')) {
if ($request->filled('asset_tag')) {
$header[] = trans('admin/hardware/table.asset_tag');
}
if ($request->has('model')) {
if ($request->filled('model')) {
$header[] = trans('admin/hardware/form.model');
$header[] = trans('general.model_no');
}
if ($request->has('category')) {
if ($request->filled('category')) {
$header[] = trans('general.category');
}
if ($request->has('manufacturer')) {
if ($request->filled('manufacturer')) {
$header[] = trans('admin/hardware/form.manufacturer');
}
if ($request->has('serial')) {
if ($request->filled('serial')) {
$header[] = trans('admin/hardware/table.serial');
}
if ($request->has('purchase_date')) {
if ($request->filled('purchase_date')) {
$header[] = trans('admin/hardware/table.purchase_date');
}
if (($request->has('purchase_cost')) || ($request->has('depreciation'))) {
if (($request->filled('purchase_cost')) || ($request->filled('depreciation'))) {
$header[] = trans('admin/hardware/table.purchase_cost');
}
if ($request->has('eol')) {
if ($request->filled('eol')) {
$header[] = trans('admin/hardware/table.eol');
}
if ($request->has('order')) {
if ($request->filled('order')) {
$header[] = trans('admin/hardware/form.order');
}
if ($request->has('supplier')) {
if ($request->filled('supplier')) {
$header[] = trans('general.supplier');
}
if ($request->has('location')) {
if ($request->filled('location')) {
$header[] = trans('admin/hardware/table.location');
}
if ($request->has('location_address')) {
if ($request->filled('location_address')) {
$header[] = trans('general.address');
$header[] = trans('general.address');
$header[] = trans('general.city');
@@ -381,11 +381,11 @@ class ReportsController extends Controller
$header[] = trans('general.zip');
}
if ($request->has('rtd_location')) {
if ($request->filled('rtd_location')) {
$header[] = trans('admin/hardware/form.default_location');
}
if ($request->has('rtd_location_address')) {
if ($request->filled('rtd_location_address')) {
$header[] = trans('general.address');
$header[] = trans('general.address');
$header[] = trans('general.city');
@@ -395,65 +395,65 @@ class ReportsController extends Controller
}
if ($request->has('assigned_to')) {
if ($request->filled('assigned_to')) {
$header[] = trans('admin/hardware/table.checkoutto');
$header[] = trans('general.type');
}
if ($request->has('username')) {
if ($request->filled('username')) {
$header[] = 'Username';
}
if ($request->has('employee_num')) {
if ($request->filled('employee_num')) {
$header[] = 'Employee No.';
}
if ($request->has('manager')) {
if ($request->filled('manager')) {
$header[] = trans('admin/users/table.manager');
}
if ($request->has('department')) {
if ($request->filled('department')) {
$header[] = trans('general.department');
}
if ($request->has('status')) {
if ($request->filled('status')) {
$header[] = trans('general.status');
}
if ($request->has('warranty')) {
if ($request->filled('warranty')) {
$header[] = 'Warranty';
$header[] = 'Warranty Expires';
}
if ($request->has('depreciation')) {
if ($request->filled('depreciation')) {
$header[] = 'Value';
$header[] = 'Diff';
}
if ($request->has('checkout_date')) {
if ($request->filled('checkout_date')) {
$header[] = trans('admin/hardware/table.checkout_date');
}
if ($request->has('expected_checkin')) {
if ($request->filled('expected_checkin')) {
$header[] = trans('admin/hardware/form.expected_checkin');
}
if ($request->has('created_at')) {
if ($request->filled('created_at')) {
$header[] = trans('general.created_at');
}
if ($request->has('updated_at')) {
if ($request->filled('updated_at')) {
$header[] = trans('general.updated_at');
}
if ($request->has('last_audit_date')) {
if ($request->filled('last_audit_date')) {
$header[] = trans('general.last_audit');
}
if ($request->has('next_audit_date')) {
if ($request->filled('next_audit_date')) {
$header[] = trans('general.next_audit_date');
}
if ($request->has('notes')) {
if ($request->filled('notes')) {
$header[] = trans('general.notes');
}
@@ -471,52 +471,52 @@ class ReportsController extends Controller
'location', 'assetstatus', 'assetlog', 'company', 'defaultLoc','assignedTo',
'model.category', 'model.manufacturer','supplier');
if ($request->has('by_location_id')) {
if ($request->filled('by_location_id')) {
$assets->where('assets.location_id', $request->input('by_location_id'));
}
if ($request->has('by_rtd_location_id')) {
if ($request->filled('by_rtd_location_id')) {
\Log::debug('RTD location should match: '.$request->input('by_rtd_location_id'));
$assets->where('assets.rtd_location_id', $request->input('by_rtd_location_id'));
}
if ($request->has('by_supplier_id')) {
if ($request->filled('by_supplier_id')) {
$assets->where('assets.supplier_id', $request->input('by_supplier_id'));
}
if ($request->has('by_company_id')) {
if ($request->filled('by_company_id')) {
$assets->where('assets.company_id', $request->input('by_company_id'));
}
if ($request->has('by_model_id')) {
if ($request->filled('by_model_id')) {
$assets->where('assets.model_id', $request->input('by_model_id'));
}
if ($request->has('by_category_id')) {
if ($request->filled('by_category_id')) {
$assets->InCategory($request->input('by_category_id'));
}
if ($request->has('by_manufacturer_id')) {
if ($request->filled('by_manufacturer_id')) {
$assets->ByManufacturer($request->input('by_manufacturer_id'));
}
if ($request->has('by_order_number')) {
if ($request->filled('by_order_number')) {
$assets->where('assets.order_number', $request->input('by_order_number'));
}
if ($request->has('by_status_id')) {
if ($request->filled('by_status_id')) {
$assets->where('assets.status_id', $request->input('by_status_id'));
}
if (($request->has('purchase_start')) && ($request->has('purchase_end'))) {
if (($request->filled('purchase_start')) && ($request->filled('purchase_end'))) {
$assets->whereBetween('assets.purchase_date', [$request->input('purchase_start'), $request->input('purchase_end')]);
}
if (($request->has('created_start')) && ($request->has('created_end'))) {
if (($request->filled('created_start')) && ($request->filled('created_end'))) {
$assets->whereBetween('assets.created_at', [$request->input('created_start'), $request->input('created_end')]);
}
if (($request->has('expected_checkin_start')) && ($request->has('expected_checkin_end'))) {
if (($request->filled('expected_checkin_start')) && ($request->filled('expected_checkin_end'))) {
$assets->whereBetween('assets.expected_checkin', [$request->input('expected_checkin_start'), $request->input('expected_checkin_end')]);
}
@@ -525,61 +525,61 @@ class ReportsController extends Controller
foreach ($assets as $asset) {
$row = [];
if ($request->has('company')) {
if ($request->filled('company')) {
$row[] = ($asset->company) ? $asset->company->name : '';
}
if ($request->has('asset_name')) {
if ($request->filled('asset_name')) {
$row[] = ($asset->name) ? $asset->name : '';
}
if ($request->has('asset_tag')) {
if ($request->filled('asset_tag')) {
$row[] = ($asset->asset_tag) ? $asset->asset_tag : '';
}
if ($request->has('model')) {
if ($request->filled('model')) {
$row[] = ($asset->model) ? $asset->model->name : '';
$row[] = ($asset->model) ? $asset->model->model_number : '';
}
if ($request->has('category')) {
if ($request->filled('category')) {
$row[] = (($asset->model) && ($asset->model->category)) ? $asset->model->category->name : '';
}
if ($request->has('manufacturer')) {
if ($request->filled('manufacturer')) {
$row[] = ($asset->model && $asset->model->manufacturer) ? $asset->model->manufacturer->name : '';
}
if ($request->has('serial')) {
if ($request->filled('serial')) {
$row[] = ($asset->serial) ? $asset->serial : '';
}
if ($request->has('purchase_date')) {
if ($request->filled('purchase_date')) {
$row[] = ($asset->purchase_date) ? $asset->purchase_date : '';
}
if ($request->has('purchase_cost')) {
if ($request->filled('purchase_cost')) {
$row[] = ($asset->purchase_cost) ? Helper::formatCurrencyOutput($asset->purchase_cost) : '';
}
if ($request->has('eol')) {
if ($request->filled('eol')) {
$row[] = ($asset->purchase_date!='') ? $asset->present()->eol_date() : '';
}
if ($request->has('order')) {
if ($request->filled('order')) {
$row[] = ($asset->order_number) ? $asset->order_number : '';
}
if ($request->has('supplier')) {
if ($request->filled('supplier')) {
$row[] = ($asset->supplier) ? $asset->supplier->name : '';
}
if ($request->has('location')) {
if ($request->filled('location')) {
$row[] = ($asset->location) ? $asset->location->present()->name() : '';
}
if ($request->has('location_address')) {
if ($request->filled('location_address')) {
$row[] = ($asset->location) ? $asset->location->address : '';
$row[] = ($asset->location) ? $asset->location->address2 : '';
$row[] = ($asset->location) ? $asset->location->city : '';
@@ -588,11 +588,11 @@ class ReportsController extends Controller
$row[] = ($asset->location) ? $asset->location->zip : '';
}
if ($request->has('rtd_location')) {
if ($request->filled('rtd_location')) {
$row[] = ($asset->defaultLoc) ? $asset->defaultLoc->present()->name() : '';
}
if ($request->has('rtd_location_address')) {
if ($request->filled('rtd_location_address')) {
$row[] = ($asset->defaultLoc) ? $asset->defaultLoc->address : '';
$row[] = ($asset->defaultLoc) ? $asset->defaultLoc->address2 : '';
$row[] = ($asset->defaultLoc) ? $asset->defaultLoc->city : '';
@@ -602,12 +602,12 @@ class ReportsController extends Controller
}
if ($request->has('assigned_to')) {
$row[] = ($asset->checkedOutToUser() && $asset->assigned) ? e($asset->assigned->getFullNameAttribute()) : ($asset->assigned ? e($asset->assigned->display_name) : '');
$row[] = ($asset->checkedOutToUser() && $asset->assigned) ? 'user' : e($asset->assignedType());
if ($request->filled('assigned_to')) {
$row[] = ($asset->checkedOutToUser() && $asset->assigned) ? $asset->assigned->getFullNameAttribute() : ($asset->assigned ? $asset->assigned->display_name : '');
$row[] = ($asset->checkedOutToUser() && $asset->assigned) ? 'user' : $asset->assignedType();
}
if ($request->has('username')) {
if ($request->filled('username')) {
// Only works if we're checked out to a user, not anything else.
if ($asset->checkedOutToUser()) {
$row[] = ($asset->assignedto) ? $asset->assignedto->username : '';
@@ -616,7 +616,7 @@ class ReportsController extends Controller
}
}
if ($request->has('employee_num')) {
if ($request->filled('employee_num')) {
// Only works if we're checked out to a user, not anything else.
if ($asset->checkedOutToUser()) {
$row[] = ($asset->assignedto) ? $asset->assignedto->employee_num : '';
@@ -625,7 +625,7 @@ class ReportsController extends Controller
}
}
if ($request->has('manager')) {
if ($request->filled('manager')) {
if ($asset->checkedOutToUser()) {
$row[] = (($asset->assignedto) && ($asset->assignedto->manager)) ? $asset->assignedto->manager->present()->fullName : '';
} else {
@@ -634,7 +634,7 @@ class ReportsController extends Controller
}
if ($request->has('department')) {
if ($request->filled('department')) {
if ($asset->checkedOutToUser()) {
$row[] = (($asset->assignedto) && ($asset->assignedto->department)) ? $asset->assignedto->department->name : '';
} else {
@@ -642,55 +642,55 @@ class ReportsController extends Controller
}
}
if ($request->has('status')) {
if ($request->filled('status')) {
$row[] = ($asset->assetstatus) ? $asset->assetstatus->name.' ('.$asset->present()->statusMeta.')' : '';
}
if ($request->has('warranty')) {
if ($request->filled('warranty')) {
$row[] = ($asset->warranty_months) ? $asset->warranty_months : '';
$row[] = $asset->present()->warrantee_expires();
}
if ($request->has('depreciation')) {
if ($request->filled('depreciation')) {
$depreciation = $asset->getDepreciatedValue();
$diff = ($asset->purchase_cost - $depreciation);
$row[] = Helper::formatCurrencyOutput($depreciation);
$row[] = Helper::formatCurrencyOutput($diff);
}
if ($request->has('checkout_date')) {
if ($request->filled('checkout_date')) {
$row[] = ($asset->last_checkout) ? $asset->last_checkout : '';
}
if ($request->has('expected_checkin')) {
if ($request->filled('expected_checkin')) {
$row[] = ($asset->expected_checkin) ? $asset->expected_checkin : '';
}
if ($request->has('created_at')) {
if ($request->filled('created_at')) {
$row[] = ($asset->created_at) ? $asset->created_at : '';
}
if ($request->has('updated_at')) {
if ($request->filled('updated_at')) {
$row[] = ($asset->updated_at) ? $asset->updated_at : '';
}
if ($request->has('last_audit_date')) {
if ($request->filled('last_audit_date')) {
$row[] = ($asset->last_audit_date) ? $asset->last_audit_date : '';
}
if ($request->has('next_audit_date')) {
if ($request->filled('next_audit_date')) {
$row[] = ($asset->next_audit_date) ? $asset->next_audit_date : '';
}
if ($request->has('notes')) {
if ($request->filled('notes')) {
$row[] = ($asset->notes) ? $asset->notes : '';
}
foreach ($customfields as $customfield) {
$column_name = $customfield->db_column_name();
if ($request->has($customfield->db_column_name())) {
if ($request->filled($customfield->db_column_name())) {
$row[] = $asset->$column_name;
}
}

View File

@@ -326,7 +326,7 @@ class SettingsController extends Controller
$setting->modellist_displays = '';
if (($request->has('show_in_model_list')) && (count($request->input('show_in_model_list')) > 0))
if (($request->filled('show_in_model_list')) && (count($request->input('show_in_model_list')) > 0))
{
$setting->modellist_displays = implode(',', $request->input('show_in_model_list'));
}
@@ -482,13 +482,12 @@ class SettingsController extends Controller
$setting->two_factor_enabled = null;
} else {
$setting->two_factor_enabled = $request->input('two_factor_enabled');
# remote user login
$setting->login_remote_user_enabled = (int)$request->input('login_remote_user_enabled');
$setting->login_common_disabled= (int)$request->input('login_common_disabled');
$setting->login_remote_user_custom_logout_url = $request->input('login_remote_user_custom_logout_url');
}
# remote user login
$setting->login_remote_user_enabled = (int)$request->input('login_remote_user_enabled');
$setting->login_common_disabled = (int)$request->input('login_common_disabled');
$setting->login_remote_user_custom_logout_url = $request->input('login_remote_user_custom_logout_url');
}
$setting->pwd_secure_uncommon = (int) $request->input('pwd_secure_uncommon');
@@ -496,7 +495,7 @@ class SettingsController extends Controller
$setting->pwd_secure_complexity = '';
if ($request->has('pwd_secure_complexity')) {
if ($request->filled('pwd_secure_complexity')) {
$setting->pwd_secure_complexity = implode('|', $request->input('pwd_secure_complexity'));
}
@@ -795,31 +794,31 @@ class SettingsController extends Controller
if ($request->has('labels_display_name')) {
if ($request->filled('labels_display_name')) {
$setting->labels_display_name = 1;
} else {
$setting->labels_display_name = 0;
}
if ($request->has('labels_display_serial')) {
if ($request->filled('labels_display_serial')) {
$setting->labels_display_serial = 1;
} else {
$setting->labels_display_serial = 0;
}
if ($request->has('labels_display_tag')) {
if ($request->filled('labels_display_tag')) {
$setting->labels_display_tag = 1;
} else {
$setting->labels_display_tag = 0;
}
if ($request->has('labels_display_tag')) {
if ($request->filled('labels_display_tag')) {
$setting->labels_display_tag = 1;
} else {
$setting->labels_display_tag = 0;
}
if ($request->has('labels_display_model')) {
if ($request->filled('labels_display_model')) {
$setting->labels_display_model = 1;
} else {
$setting->labels_display_model = 0;
@@ -866,7 +865,7 @@ class SettingsController extends Controller
$setting->ldap_server = $request->input('ldap_server');
$setting->ldap_server_cert_ignore = $request->input('ldap_server_cert_ignore', false);
$setting->ldap_uname = $request->input('ldap_uname');
if (Input::has('ldap_pword')) {
if (Input::filled('ldap_pword')) {
$setting->ldap_pword = Crypt::encrypt($request->input('ldap_pword'));
}
$setting->ldap_basedn = $request->input('ldap_basedn');
@@ -908,7 +907,7 @@ class SettingsController extends Controller
public function getBackups()
{
$path = storage_path().'/app/'.config('laravel-backup.backup.name');
$path = storage_path().'/app/'.config('backup.backup.name');
$files = array();
@@ -984,7 +983,7 @@ class SettingsController extends Controller
public function downloadFile($filename = null)
{
if (!config('app.lock_passwords')) {
$path = storage_path().'/app/'.config('laravel-backup.backup.name');
$path = storage_path().'/app/'.config('backup.backup.name');
$file = $path.'/'.$filename;
if (file_exists($file)) {
return Response::download($file);
@@ -1013,7 +1012,7 @@ class SettingsController extends Controller
if (!config('app.lock_passwords')) {
$path = storage_path().'/app/'.config('laravel-backup.backup.name');
$path = storage_path().'/app/'.config('backup.backup.name');
$file = $path.'/'.$filename;
if (file_exists($file)) {
unlink($file);

View File

@@ -33,7 +33,7 @@ class StatuslabelsController extends Controller
public function index()
{
$this->authorize('view', Statuslabel::class);
return view('statuslabels.index', compact('statuslabels'));
return view('statuslabels.index');
}
public function show($id)
@@ -78,7 +78,7 @@ class StatuslabelsController extends Controller
// create a new model instance
$statusLabel = new Statuslabel();
if (!$request->has('statuslabel_types')) {
if (!$request->filled('statuslabel_types')) {
return redirect()->back()->withInput()->withErrors(['statuslabel_types' => trans('validation.statuslabel_type')]);
}
@@ -141,7 +141,7 @@ class StatuslabelsController extends Controller
return redirect()->route('statuslabels.index')->with('error', trans('admin/statuslabels/message.does_not_exist'));
}
if (!$request->has('statuslabel_types')) {
if (!$request->filled('statuslabel_types')) {
return redirect()->back()->withInput()->withErrors(['statuslabel_types' => trans('validation.statuslabel_type')]);
}

View File

@@ -34,10 +34,9 @@ class SuppliersController extends Controller
{
// Grab all the suppliers
$this->authorize('view', Supplier::class);
$suppliers = Supplier::orderBy('created_at', 'DESC')->get();
// Show the page
return view('suppliers/index', compact('suppliers'));
return view('suppliers/index');
}
@@ -84,7 +83,7 @@ class SuppliersController extends Controller
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/suppliers/'.$file_name);
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
@@ -160,7 +159,7 @@ class SuppliersController extends Controller
$file_name = $supplier->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(500, null, function ($constraint) {
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save(app('suppliers_upload_path').$file_name);
@@ -175,7 +174,7 @@ class SuppliersController extends Controller
try {
unlink(app('suppliers_upload_path').$old_image);
} catch (\Exception $e) {
\Log::error($e);
\Log::info($e);
}
}
@@ -197,7 +196,7 @@ class SuppliersController extends Controller
public function destroy($supplierId)
{
$this->authorize('delete', Supplier::class);
if (is_null($supplier = Supplier::with('asset_maintenances', 'assets', 'licenses')->withCount('asset_maintenances','assets','licenses')->find($supplierId))) {
if (is_null($supplier = Supplier::with('asset_maintenances', 'assets', 'licenses')->withCount('asset_maintenances as asset_maintenances_count','assets as assets_count','licenses as licenses_count')->find($supplierId))) {
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.not_found'));
}

View File

@@ -86,8 +86,11 @@ class UsersController extends Controller
$userPermissions = Helper::selectedPermissionsArray($permissions, Input::old('permissions', array()));
$permissions = $this->filterDisplayable($permissions);
$user = new User;
$user->activated = 1;
return view('users/edit', compact('groups', 'userGroups', 'permissions', 'userPermissions'))
->with('user', new User);
->with('user', $user);
}
/**
@@ -104,7 +107,7 @@ class UsersController extends Controller
//Username, email, and password need to be handled specially because the need to respect config values on an edit.
$user->email = $data['email'] = e($request->input('email'));
$user->username = $data['username'] = e($request->input('username'));
if ($request->has('password')) {
if ($request->filled('password')) {
$user->password = bcrypt($request->input('password'));
$data['password'] = $request->input('password');
}
@@ -136,13 +139,13 @@ class UsersController extends Controller
if ($user->save()) {
if ($request->has('groups')) {
if ($request->filled('groups')) {
$user->groups()->sync($request->input('groups'));
} else {
$user->groups()->sync(array());
}
if (($request->input('email_user') == 1) && ($request->has('email'))) {
if (($request->input('email_user') == 1) && ($request->filled('email'))) {
// Send the credentials through email
$data = array();
$data['email'] = e($request->input('email'));
@@ -256,13 +259,11 @@ class UsersController extends Controller
// Only save groups if the user is a super user
if (Auth::user()->isSuperUser()) {
if ($request->has('groups')) {
$user->groups()->sync($request->input('groups'));
}
$user->groups()->sync($request->input('groups'));
}
if ($request->has('username')) {
if ($request->filled('username')) {
$user->username = $request->input('username');
}
$user->email = $request->input('email');
@@ -277,6 +278,7 @@ class UsersController extends Controller
$user->activated = $request->input('activated', 0);
$user->jobtitle = $request->input('jobtitle', null);
$user->phone = $request->input('phone');
$user->website = $request->input('website', null);
$user->location_id = $request->input('location_id', null);
$user->company_id = Company::getIdForUser($request->input('company_id', null));
$user->manager_id = $request->input('manager_id', null);
@@ -295,7 +297,7 @@ class UsersController extends Controller
->where('assigned_to', $user->id)->update(['location_id' => $request->input('location_id', null)]);
// Do we want to update the user password?
if ($request->has('password')) {
if ($request->filled('password')) {
$user->password = bcrypt($request->input('password'));
}
@@ -338,25 +340,25 @@ class UsersController extends Controller
// Check if we are not trying to delete ourselves
if ($user->id === Auth::user()->id) {
// Redirect to the user management page
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->assets()->count() . ' assets associated with them.');
return redirect()->route('users.index')->with('error', 'You cannot delete yourself.');
}
if ($user->assets->count() > 0) {
if (($user->assets) && ($user->assets->count() > 0)) {
// Redirect to the user management page
return redirect()->route('users.index')->with('error', 'This user still has ' . count($user->assets->count()) . ' assets associated with them.');
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->assets->count() . ' assets associated with them. Use the Checkin and Delete button on the user profile to check these items back in and delete this user.');
}
if ($user->licenses()->count() > 0) {
if (($user->licenses) && ($user->licenses->count() > 0)) {
// Redirect to the user management page
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->assets()->count() . ' assets associated with them.');
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->licenses->count() . ' license(s associated with them. Use the Checkin and Delete button on the user profile to check these items back in and delete this user.');
}
if ($user->accessories()->count() > 0) {
if (($user->accessories) && ($user->accessories->count() > 0)) {
// Redirect to the user management page
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->accessories()->count() . ' accessories associated with them.');
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->accessories->count() . ' accessories associated with them. Use the Checkin and Delete button on the user profile to check these items back in and delete this user.');
}
if ($user->managedLocations()->count() > 0) {
if (($user->managedLocations()) && ($user->managedLocations()->count() > 0)) {
// Redirect to the user management page
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->managedLocations()->count() . ' locations that they manage.');
}
@@ -388,7 +390,7 @@ class UsersController extends Controller
{
$this->authorize('update', User::class);
if (($request->has('ids')) && (count($request->input('ids')) > 0)) {
if (($request->filled('ids')) && (count($request->input('ids')) > 0)) {
$statuslabel_list = Helper::statusLabelList();
$user_raw_array = array_keys(Input::get('ids'));
$users = User::whereIn('id', $user_raw_array)->with('groups', 'assets', 'licenses', 'accessories')->get();
@@ -414,28 +416,28 @@ class UsersController extends Controller
{
$this->authorize('update', User::class);
if (($request->has('ids')) && (count($request->input('ids')) > 0)) {
if (($request->filled('ids')) && (count($request->input('ids')) > 0)) {
$user_raw_array = $request->input('ids');
$update_array = array();
$manager_conflict = false;
$users = User::whereIn('id', $user_raw_array)->where('id', '!=', Auth::user()->id)->get();
if ($request->has('location_id')) {
if ($request->filled('location_id')) {
$update_array['location_id'] = $request->input('location_id');
}
if ($request->has('department_id')) {
if ($request->filled('department_id')) {
$update_array['department_id'] = $request->input('department_id');
}
if ($request->has('company_id')) {
if ($request->filled('company_id')) {
$update_array['company_id'] = $request->input('company_id');
}
if ($request->has('locale')) {
if ($request->filled('locale')) {
$update_array['locale'] = $request->input('locale');
}
if ($request->has('manager_id')) {
if ($request->filled('manager_id')) {
// Do not allow a manager update if the selected manager is one of the users being
// edited.
@@ -446,7 +448,7 @@ class UsersController extends Controller
}
}
if ($request->has('activated')) {
if ($request->filled('activated')) {
$update_array['activated'] = $request->input('activated');
}
@@ -456,7 +458,7 @@ class UsersController extends Controller
}
// Only sync groups if groups were selected
if ($request->has('groups')) {
if ($request->filled('groups')) {
foreach ($users as $user) {
$user->groups()->sync($request->input('groups'));
}
@@ -488,9 +490,9 @@ class UsersController extends Controller
{
$this->authorize('update', User::class);
if ((!$request->has('ids')) || (count($request->input('ids')) == 0)) {
if ((!$request->filled('ids')) || (count($request->input('ids')) == 0)) {
return redirect()->back()->with('error', 'No users selected');
} elseif ((!$request->has('status_id')) || ($request->input('status_id')=='')) {
} elseif ((!$request->filled('status_id')) || ($request->input('status_id')=='')) {
return redirect()->route('users.index')->with('error', 'No status selected');
} else {
@@ -981,7 +983,7 @@ class UsersController extends Controller
*/
public function printInventory($id)
{
$this->authorize('view', User::class);
$show_user = User::where('id',$id)->withTrashed()->first();
$assets = Asset::where('assigned_to', $id)->where('assigned_type', User::class)->with('model', 'model.category')->get();
$licenses = $show_user->licenses()->get();

View File

@@ -73,7 +73,7 @@ class ViewAssetsController extends Controller
$assets = Asset::with('model', 'defaultLoc', 'location', 'assignedTo', 'requests')->Hardware()->RequestableAssets()->get();
$models = AssetModel::with('category', 'requests', 'assets')->RequestableModels()->get();
return view('account/requestable-assets', compact('user', 'assets', 'models'));
return view('account/requestable-assets', compact('assets', 'models'));
}
@@ -269,7 +269,7 @@ class ViewAssetsController extends Controller
return redirect()->to('account/view-assets')->with('error', trans('admin/users/message.error.incorrect_user_accepted'));
}
if ($request->has('signature_output')) {
if ($request->filled('signature_output')) {
$path = config('app.private_uploads').'/signatures';
$sig_filename = "siglog-".$findlog->id.'-'.date('Y-m-d-his').".png";
$data_uri = e($request->get('signature_output'));

View File

@@ -25,7 +25,7 @@ class Kernel extends HttpKernel
\Fideloper\Proxy\TrustProxies::class,
\App\Http\Middleware\CheckForSetup::class,
\App\Http\Middleware\CheckForDebug::class,
// \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
/**
@@ -44,7 +44,8 @@ class Kernel extends HttpKernel
],
'api' => [
'throttle:60,1',
\Barryvdh\Cors\HandleCors::class,
'throttle:120,1',
'auth:api',
],
];

View File

@@ -6,6 +6,8 @@ use Illuminate\Cookie\Middleware\EncryptCookies as BaseEncrypter;
class EncryptCookies extends BaseEncrypter
{
/**
* The names of the cookies that should not be encrypted.
*
@@ -14,4 +16,13 @@ class EncryptCookies extends BaseEncrypter
protected $except = [
//
];
/**
* Indicates if cookies should be serialized.
*
* @var bool
*/
protected static $serialize = true;
}

View File

@@ -2,9 +2,11 @@
namespace App\Http\Requests;
use App\Http\Requests\Request;
use App\Models\AssetModel;
use Session;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Contracts\Validation\Validator;
class AssetRequest extends Request
{
@@ -30,7 +32,7 @@ class AssetRequest extends Request
'model_id' => 'required|integer|exists:models,id',
'status_id' => 'required|integer|exists:status_labels,id',
'company_id' => 'integer|nullable',
'warranty_months' => 'numeric|nullable',
'warranty_months' => 'numeric|nullable|digits_between:0,240',
'physical' => 'integer|nullable',
'checkout_date' => 'date',
'checkin_date' => 'date',
@@ -46,7 +48,7 @@ class AssetRequest extends Request
$rules['asset_tag'] = ($settings->auto_increment_assets == '1') ? 'max:255' : 'required';
if($this->request->get('model_id') != '') {
if ($this->request->get('model_id') != '') {
$model = AssetModel::find($this->request->get('model_id'));
if (($model) && ($model->fieldset)) {
@@ -58,11 +60,26 @@ class AssetRequest extends Request
}
public function response(array $errors)
/**
* Handle a failed validation attempt.
*
* public function json($data = [], $status = 200, array $headers = [], $options = 0)
*
* @param \Illuminate\Contracts\Validation\Validator $validator
* @return void
*
* @throws \Illuminate\Http\Exceptions\HttpResponseException
*/
protected function failedValidation(Validator $validator)
{
$this->session()->flash('errors', Session::get('errors', new \Illuminate\Support\ViewErrorBag)
->put('default', new \Illuminate\Support\MessageBag($errors)));
->put('default', new \Illuminate\Support\MessageBag($validator->errors()->toArray())));
\Input::flash();
return parent::response($errors);
throw new HttpResponseException(response()->json([
'status' => 'error',
'messages' => $validator->errors(),
'payload' => null
], 422));
}
}

View File

@@ -43,6 +43,20 @@ class ItemImportRequest extends FormRequest
$import->save();
$fieldMappings=[];
if ($import->field_map) {
// This checks to make sure the field header has been mapped.
// If it hasn't been, it will throw an array_flip error
foreach ($import->field_map as $field => $fieldValue) {
$errorMessage = null;
if(is_null($fieldValue)){
$errorMessage = 'All import fields must be mapped.';
$this->errorCallback($import, $field, $errorMessage);
return $this->errors;
}
}
// We submit as csv field: column, but the importer is happier if we flip it here.
$fieldMappings = array_change_key_case(array_flip($import->field_map), CASE_LOWER);
// dd($fieldMappings);
@@ -50,6 +64,7 @@ class ItemImportRequest extends FormRequest
$importer->setCallbacks([$this, 'log'], [$this, 'progress'], [$this, 'errorCallback'])
->setUserId(Auth::id())
->setUpdating($this->has('import-update'))
->setShouldNotify($this->has('send-welcome'))
->setUsernameFormat('firstname.lastname')
->setFieldMappings($fieldMappings);
// $logFile = storage_path('logs/importer.log');
@@ -60,7 +75,7 @@ class ItemImportRequest extends FormRequest
public function log($string)
{
// \Log::Info($string);
\Log::Info($string);
}
public function progress($count)

View File

@@ -2,10 +2,12 @@
namespace App\Http\Requests;
use App\Http\Requests\Request;
use App\Models\Setting;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
class SaveUserRequest extends Request
class SaveUserRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
@@ -37,7 +39,7 @@ class SaveUserRequest extends Request
$rules['username'] = 'required_unless:ldap_import,1|string|min:1';
if ($this->request->get('ldap_import') == false)
{
$rules['password'] = Setting::passwordComplexityRulesSaving('store');
$rules['password'] = Setting::passwordComplexityRulesSaving('store').'|confirmed';
}
break;
}
@@ -46,7 +48,7 @@ class SaveUserRequest extends Request
case 'PUT':
$rules['first_name'] = 'required|string|min:1';
$rules['username'] = 'required_unless:ldap_import,1|string|min:1';
$rules['password'] = Setting::passwordComplexityRulesSaving('update');
$rules['password'] = Setting::passwordComplexityRulesSaving('update').'|confirmed';
break;
// Save only what's passed
@@ -58,10 +60,9 @@ class SaveUserRequest extends Request
default:break;
}
$rules['password_confirm'] = 'sometimes|required_with:password';
return $rules;
}
}

View File

@@ -29,8 +29,7 @@ class SetupUserRequest extends Request
'last_name' => 'required|string|min:1',
'username' => 'required|string|min:2|unique:users,username,NULL,deleted_at',
'email' => 'email|unique:users,email',
'password' => 'required|min:6',
'password_confirm' => 'required|min:6|same:password',
'password' => 'required|min:6|confirmed',
'email_domain' => 'required|min:4',
];
}

View File

@@ -26,6 +26,18 @@ class ActionlogsTransformer
if ($actionlog->filename!='') {
$icon = e(\App\Helpers\Helper::filetype_icon($actionlog->filename));
}
// This is necessary since we can't escape special characters within a JSON object
if (($actionlog->log_meta) && ($actionlog->log_meta!='')) {
$meta_array = json_decode($actionlog->log_meta);
foreach ($meta_array as $key => $value) {
foreach ($value as $meta_key => $meta_value) {
$clean_meta[$key][$meta_key] = e($meta_value);
}
}
}
$array = [
'id' => (int) $actionlog->id,
'icon' => $icon,
@@ -64,7 +76,7 @@ class ActionlogsTransformer
'note' => ($actionlog->note) ? e($actionlog->note): null,
'signature_file' => ($actionlog->accept_signature) ? route('log.signature.view', ['filename' => $actionlog->accept_signature ]) : null,
'log_meta' => ($actionlog->log_meta) ? json_decode($actionlog->log_meta): null,
'log_meta' => ((isset($clean_meta)) && (is_array($clean_meta))) ? $clean_meta: null,
];

View File

@@ -27,6 +27,11 @@ class AssetMaintenancesTransformer
'name'=> ($assetmaintenance->asset->name) ? e($assetmaintenance->asset->name) : null,
'asset_tag'=> e($assetmaintenance->asset->asset_tag)
] : null,
'company' => (($assetmaintenance->asset) && ($assetmaintenance->asset->company)) ? [
'id' => (int) $assetmaintenance->asset->company->id,
'name'=> ($assetmaintenance->asset->company->name) ? e($assetmaintenance->asset->company->name) : null,
] : null,
'title' => ($assetmaintenance->title) ? e($assetmaintenance->title) : null,
'location' => (($assetmaintenance->asset) && ($assetmaintenance->asset->location)) ? [

View File

@@ -24,7 +24,7 @@ class UsersTransformer
$array = [
'id' => (int) $user->id,
'avatar' => e($user->present()->gravatar),
'name' => e($user->first_name).' '.($user->last_name),
'name' => e($user->first_name).' '.e($user->last_name),
'first_name' => e($user->first_name),
'last_name' => e($user->last_name),
'username' => e($user->username),
@@ -35,6 +35,7 @@ class UsersTransformer
] : null,
'jobtitle' => ($user->jobtitle) ? e($user->jobtitle) : null,
'phone' => ($user->phone) ? e($user->phone) : null,
'website' => ($user->website) ? e($user->website) : null,
'address' => ($user->address) ? e($user->address) : null,
'city' => ($user->city) ? e($user->city) : null,
'state' => ($user->state) ? e($user->state) : null,
@@ -53,6 +54,8 @@ class UsersTransformer
'permissions' => $user->decodePermissions(),
'activated' => ($user->activated =='1') ? true : false,
'two_factor_activated' => ($user->two_factor_active()) ? true : false,
'two_factor_enrolled' => ($user->two_factor_active_and_enrolled()) ? true : false,
'assets_count' => (int) $user->assets_count,
'licenses_count' => (int) $user->licenses_count,
'accessories_count' => (int) $user->accessories_count,

View File

@@ -4,6 +4,7 @@ namespace App\Importer;
use App\Models\CustomField;
use App\Models\Setting;
use App\Models\User;
use App\Models\Department;
use ForceUTF8\Encoding;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Auth;
@@ -29,6 +30,7 @@ abstract class Importer
*/
private $defaultFieldMap = [
'asset_tag' => 'asset tag',
'activated' => 'activated',
'category' => 'category',
'checkout_class' => 'checkout type', // Supports Location or User for assets. Using checkout_class instead of checkout_type because type exists on asset already.
'checkout_location' => 'checkout location',
@@ -66,6 +68,9 @@ abstract class Importer
'phone_number' => 'phone number',
'first_name' => 'first name',
'last_name' => 'last name',
'department' => 'department',
'manager_first_name' => 'manager first name',
'manager_last_name' => 'manager last name',
];
/**
* Map of item fields->csv names
@@ -115,7 +120,8 @@ abstract class Importer
public function import()
{
$headerRow = $this->csv->fetchOne();
$results = $this->normalizeInputArray($this->csv->fetchAssoc());
$this->csv->setHeaderOffset(0); //explicitly sets the CSV document header record
$results = $this->normalizeInputArray($this->csv->getRecords($headerRow));
$this->populateCustomFields($headerRow);
@@ -176,10 +182,9 @@ abstract class Importer
{
$val = $default;
$key = $this->lookupCustomKey($key);
$this->log("Custom Key: ${key}");
// $this->log("Custom Key: ${key}");
if (array_key_exists($key, $array)) {
$val = Encoding::toUTF8(trim($array[ $key ]));
}
@@ -198,7 +203,6 @@ abstract class Importer
public function lookupCustomKey($key)
{
if (array_key_exists($key, $this->fieldMap)) {
// $this->log("Found a match in our custom map: {$key} is " . $this->fieldMap[$key]);
return $this->fieldMap[$key];
}
// Otherwise no custom key, return original.
@@ -248,7 +252,10 @@ abstract class Importer
}
/**
* Finds the user matching given data, or creates a new one if there is no match
* Finds the user matching given data, or creates a new one if there is no match.
* This is NOT used by the User Import, only for Asset/Accessory/etc where
* there are users listed and we have to create them and associate them at
* the same time. [ALG]
*
* @author Daniel Melzter
* @since 3.0
@@ -261,8 +268,13 @@ abstract class Importer
$user_array = [
'full_name' => $this->findCsvMatch($row, "full_name"),
'email' => $this->findCsvMatch($row, "email"),
'username' => $this->findCsvMatch($row, "username")
'manager_id'=> '',
'department_id' => '',
'username' => $this->findCsvMatch($row, "username"),
'activated' => $this->fetchHumanBoolean($this->findCsvMatch($row, 'activated')),
];
\Log::debug('Importer.php Activated: '.$this->findCsvMatch($row, 'activated'));
// If the full name is empty, bail out--we need this to extract first name (at the very least)
if(empty($user_array['full_name'])) {
$this->log('Insufficient user data provided (Full name is required)- skipping user creation, just adding asset');
@@ -283,6 +295,7 @@ abstract class Importer
$user_formatted_array = User::generateFormattedNameFromFullName(Setting::getSettings()->username_format, $user_array['full_name']);
$user_array['first_name'] = $user_formatted_array['first_name'];
$user_array['last_name'] = $user_formatted_array['last_name'];
if (empty($user_array['username'])) {
$user_array['username'] = $user_formatted_array['username'];
if ($this->usernameFormat =='email') {
@@ -290,8 +303,9 @@ abstract class Importer
}
}
// Does this ever actually fire??
// Check for a matching user after trying to guess username.
if($user = User::where('username', $user_array['username'])->first()) {
if ($user = User::where('username', $user_array['username'])->first()) {
$this->log('User '.$user_array['username'].' already exists');
return $user;
}
@@ -307,10 +321,15 @@ abstract class Importer
$user->last_name = $user_array['last_name'];
$user->username = $user_array['username'];
$user->email = $user_array['email'];
$user->activated = 1;
$user->manager_id = (isset($user_array['manager_id']) ? $user_array['manager_id'] : null);
$user->department_id = (isset($user_array['department_id']) ? $user_array['department_id']: null);
$user->activated = $user_array['activated'];
$user->password = $this->tempPassword;
\Log::debug('Creating a user with the following attributes: '.print_r($user_array, true));
if ($user->save()) {
\Log::debug('Importer.php Name: '.$user->first_name.' '.$user->last_name.' ('.$user->username.')');
$this->log('User '.$user_array['username'].' created');
return $user;
}
@@ -360,6 +379,20 @@ abstract class Importer
return $this;
}
/**
* Sets the Are we updating items in the import.
*
* @param bool $updating the updating
*
* @return self
*/
public function setShouldNotify($send_welcome)
{
$this->send_welcome = $send_welcome;
return $this;
}
/**
* Defines mappings of csv fields
*
@@ -407,4 +440,64 @@ abstract class Importer
return $this;
}
public function fetchHumanBoolean($value)
{
if (($value =='1') || (strtolower($value) =='true') || (strtolower($value) =='yes'))
{
return '1';
}
return '0';
}
/**
* Fetch an existing department, or create new if it doesn't exist
*
* @author A. Gianotto
* @since 4.6.5
* @param $user_department string
* @return int id of company created/found
*/
public function createOrFetchDepartment($user_department_name)
{
if ($user_department_name!='') {
$department = Department::where('name', '=', $user_department_name)->first();
if ($department) {
$this->log('A matching Department ' . $user_department_name . ' already exists');
return $department->id;
}
$department = new Department();
$department->name = $user_department_name;
if ($department->save()) {
$this->log('Department ' . $user_department_name . ' was created');
return $department->id;
}
$this->logError($department, 'Department');
}
return null;
}
/**
* Fetch an existing manager
*
* @author A. Gianotto
* @since 4.6.5
* @param $user_manager string
* @return int id of company created/found
*/
public function fetchManager($user_manager_first_name, $user_manager_last_name)
{
$manager = User::where('first_name', '=', $user_manager_first_name)
->where('last_name', '=', $user_manager_last_name)->first();
if ($manager) {
$this->log('A matching Manager ' . $user_manager_first_name . ' '. $user_manager_last_name . ' already exists');
return $manager->id;
}
$this->log('No matching Manager ' . $user_manager_first_name . ' '. $user_manager_last_name . ' found. If their user account is being created through this import, you should re-process this file again. ');
return null;
}
}

View File

@@ -10,6 +10,7 @@ use App\Models\Location;
use App\Models\Manufacturer;
use App\Models\Statuslabel;
use App\Models\Supplier;
use App\Models\Department;
use App\Models\User;
class ItemImporter extends Importer
@@ -54,6 +55,18 @@ class ItemImporter extends Importer
if ($this->shouldUpdateField($item_supplier)) {
$this->item['supplier_id'] = $this->createOrFetchSupplier($item_supplier);
}
$item_department = $this->findCsvMatch($row, "department");
if ($this->shouldUpdateField($item_department)) {
$this->item['department_id'] = $this->createOrFetchDepartment($item_department);
}
$item_manager_first_name = $this->findCsvMatch($row, "manager_first_name");
$item_manager_last_name = $this->findCsvMatch($row, "manager_last_name");
if ($this->shouldUpdateField($item_manager_first_name)) {
$this->item['manager_id'] = $this->fetchManager($item_manager_first_name, $item_manager_last_name);
}
$this->item["name"] = $this->findCsvMatch($row, "item_name");
$this->item["notes"] = $this->findCsvMatch($row, "notes");
$this->item["order_number"] = $this->findCsvMatch($row, "order_number");
@@ -84,7 +97,7 @@ class ItemImporter extends Importer
*/
protected function determineCheckout($row)
{
// We only support checkout-to-location for asset, so short circuit otherw.
// We only support checkout-to-location for asset, so short circuit otherwise.
if(get_class($this) != AssetImporter::class) {
return $this->createOrFetchUser($row);
}
@@ -161,7 +174,7 @@ class ItemImporter extends Importer
* @since 3.0
* @param array
* @param $category Category
* @param $manufacturer Manufacturer
* @param $row Manufacturer
* @return int Id of asset model created/found
* @internal param $asset_modelno string
*/
@@ -279,6 +292,8 @@ class ItemImporter extends Importer
return null;
}
/**
* Fetch the existing status label or create new if it doesn't exist.
*

View File

@@ -6,13 +6,21 @@ use App\Helpers\Helper;
use App\Models\User;
use App\Notifications\WelcomeNotification;
/**
* This is ONLY used for the User Import. When we are importing users
* via an Asset/etc import, we use createOrFetchUser() in
* App\Importer.php. [ALG]
*
* Class UserImporter
* @package App\Importer
*
*/
class UserImporter extends ItemImporter
{
protected $users;
public function __construct($filename)
{
parent::__construct($filename);
// $this->users = User::all();
}
protected function handle($row)
@@ -31,25 +39,40 @@ class UserImporter extends ItemImporter
*/
public function createUserIfNotExists(array $row)
{
// User Specific Bits
// Pull the records from the CSV to determine their values
$this->item['username'] = $this->findCsvMatch($row, 'username');
$this->item['first_name'] = $this->findCsvMatch($row, 'first_name');
$this->item['last_name'] = $this->findCsvMatch($row, 'last_name');
\Log::debug('UserImporter.php Name: '.$this->item['first_name'].' '.$this->item['last_name'].' ('.$this->item['username'].')');
$this->item['email'] = $this->findCsvMatch($row, 'email');
$this->item['phone'] = $this->findCsvMatch($row, 'phone_number');
$this->item['jobtitle'] = $this->findCsvMatch($row, 'jobtitle');
$this->item['activated'] = ($this->fetchHumanBoolean($this->findCsvMatch($row, 'activated')) == 1) ? '1' : 0;
\Log::debug('UserImporter.php Activated: '.$this->findCsvMatch($row, 'activated'));
\Log::debug('UserImporter.php Activated fetchHumanBoolean: '. $this->fetchHumanBoolean($this->findCsvMatch($row, 'activated')));
$this->item['employee_num'] = $this->findCsvMatch($row, 'employee_num');
$this->item['department_id'] = $this->createOrFetchDepartment($this->findCsvMatch($row, 'department')) ? $this->createOrFetchDepartment($this->findCsvMatch($row, 'department')) : null;
$this->item['manager_id'] = $this->fetchManager($this->findCsvMatch($row, 'manager_first_name'), $this->findCsvMatch($row, 'manager_last_name')) ? $this->fetchManager($this->findCsvMatch($row, 'manager_first_name'), $this->findCsvMatch($row, 'manager_last_name')) : null;
$user = User::where('username', $this->item['username'])->first();
if ($user) {
if (!$this->updating) {
$this->log('A matching User ' . $this->item["name"] . ' already exists. ');
\Log::debug('A matching User ' . $this->item["name"] . ' already exists. ');
return;
}
$this->log('Updating User');
$user->update($this->sanitizeItemForUpdating($user));
$user->save();
// \Log::debug('UserImporter.php Updated User ' . print_r($user, true));
return;
}
// This needs to be applied after the update logic, otherwise we'll overwrite user passwords
// Issue #5408
$this->item['password'] = $this->tempPassword;
@@ -57,10 +80,11 @@ class UserImporter extends ItemImporter
$this->log("No matching user, creating one");
$user = new User();
$user->fill($this->sanitizeItemForStoring($user));
if ($user->save()) {
// $user->logCreate('Imported using CSV Importer');
$this->log("User " . $this->item["name"] . ' was created');
if($user->email) {
if(($user->email) && ($user->activated=='1')) {
$data = [
'email' => $user->email,
'username' => $user->username,
@@ -68,7 +92,11 @@ class UserImporter extends ItemImporter
'last_name' => $user->last_name,
'password' => $this->tempPassword,
];
$user->notify(new WelcomeNotification($data));
if ($this->send_welcome) {
$user->notify(new WelcomeNotification($data));
}
}
$user = null;
$this->item = null;

View File

@@ -1,16 +1,20 @@
| CSV | Item | Applicable Types |
|---------------------|------------------|-------------------------------------------|
| activated | | User |
| asset tag | asset_tag | Asset |
| category | category | All |
| company | company | All |
| department_id | | User ? All |
| item name | item_name | All |
| image | image | asset |
| image | image | Asset |
| email | | |
| expiration date | expiration_date | License |
| location | location | All |
| notes | notes | All |
| licensed to email | license_email | License |
| licensed to name | license_name | License |
| maintained | maintained | License |
| manager_id | | User |
| manufacturer | manufacturer | All |
| model name | asset_model | Asset |
| model number | model_number | Asset |
@@ -22,12 +26,12 @@
| reassignable | reassignable | License |
| requestable | requestable | Asset, Accessory? |
| seats | seats | License |
| serial number | serial | asset, license |
| status | status | asset ? All |
| serial number | serial | Asset, license |
| status | status | Asset ? All |
| supplier | supplier | Asset ? All |
| termination date | termination_date | License |
| warranty months | warranty_months | asset |
| warranty months | warranty_months | Asset |
| User Related Fields | assigned_to | Asset |
| name | | |
| email | | |
| username | | |
| username | | |

View File

@@ -75,7 +75,7 @@ class Asset extends Depreciable
'model_id' => 'required|integer|exists:models,id',
'status_id' => 'required|integer|exists:status_labels,id',
'company_id' => 'integer|nullable',
'warranty_months' => 'numeric|nullable',
'warranty_months' => 'numeric|nullable|digits_between:0,240',
'physical' => 'numeric|max:1|nullable',
'checkout_date' => 'date|max:10|min:10|nullable',
'checkin_date' => 'date|max:10|min:10|nullable',
@@ -796,6 +796,85 @@ class Asset extends Depreciable
});
}
/**
* Query builder scope for Assets that are due for auditing, based on the assets.next_audit_date
* and settings.audit_warning_days.
*
* This is/will be used in the artisan command snipeit:upcoming-audits and also
* for an upcoming API call for retrieving a report on assets that will need to be audited.
*
* Due for audit soon:
* next_audit_date greater than or equal to now (must be in the future)
* and (next_audit_date - threshold days) <= now ()
*
* Example:
* next_audit_date = May 4, 2025
* threshold for alerts = 30 days
* now = May 4, 2019
*
* @author A. Gianotto <snipe@snipe.net>
* @since v4.6.16
* @param Setting $settings
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeDueForAudit($query, $settings)
{
return $query->whereNotNull('assets.next_audit_date')
->where('assets.next_audit_date', '>=', Carbon::now())
->whereRaw("DATE_SUB(assets.next_audit_date, INTERVAL $settings->audit_warning_days DAY) <= '".Carbon::now()."'")
->where('assets.archived', '=', 0)
->NotArchived();
}
/**
* Query builder scope for Assets that are OVERDUE for auditing, based on the assets.next_audit_date
* and settings.audit_warning_days. It checks to see if assets.next audit_date is before now
*
* This is/will be used in the artisan command snipeit:upcoming-audits and also
* for an upcoming API call for retrieving a report on overdue assets.
*
* @author A. Gianotto <snipe@snipe.net>
* @since v4.6.16
* @param Setting $settings
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeOverdueForAudit($query)
{
return $query->whereNotNull('assets.next_audit_date')
->where('assets.next_audit_date', '<', Carbon::now())
->where('assets.archived', '=', 0)
->NotArchived();
}
/**
* Query builder scope for Assets that are due for auditing OR overdue, based on the assets.next_audit_date
* and settings.audit_warning_days.
*
* This is/will be used in the artisan command snipeit:upcoming-audits and also
* for an upcoming API call for retrieving a report on assets that will need to be audited.
*
* @author A. Gianotto <snipe@snipe.net>
* @since v4.6.16
* @param Setting $settings
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeDueOrOverdueForAudit($query, $settings)
{
$interval = $settings->audit_warning_days ?? 0;
return $query->whereNotNull('assets.next_audit_date')
->whereRaw("DATE_SUB(assets.next_audit_date, INTERVAL $interval DAY) <= '".Carbon::now()."'")
->where('assets.archived', '=', 0)
->NotArchived();
}
/**
* Query builder scope for Archived assets
*
@@ -961,9 +1040,7 @@ class Asset extends Depreciable
->orWhere('assets.order_number', 'LIKE', '%'.$search.'%')
->orWhere('assets.notes', 'LIKE', '%'.$search.'%');
}
foreach (CustomField::all() as $field) {
$query->orWhere('assets.'.$field->db_column_name(), 'LIKE', "%$search%");
}
})->withTrashed()->whereNull("assets.deleted_at"); //workaround for laravel bug
}
@@ -1180,8 +1257,8 @@ class Asset extends Depreciable
*/
public function scopeInCategory($query, $category_id)
{
return $query->join('models', 'assets.model_id', '=', 'models.id')
->join('categories', 'models.category_id', '=', 'categories.id')->where('models.category_id', '=', $category_id);
return $query->join('models as category_models', 'assets.model_id', '=', 'category_models.id')
->join('categories', 'category_models.category_id', '=', 'categories.id')->where('category_models.category_id', '=', $category_id);
}
/**

View File

@@ -72,6 +72,8 @@ class AssetMaintenance extends Model implements ICompanyableChild
trans('admin/asset_maintenances/general.repair') => trans('admin/asset_maintenances/general.repair'),
trans('admin/asset_maintenances/general.upgrade') => trans('admin/asset_maintenances/general.upgrade'),
'PAT test' => 'PAT test',
trans('admin/asset_maintenances/general.calibration') => trans('admin/asset_maintenances/general.calibration'),
'PAT test' => 'PAT test',
];
}

View File

@@ -80,7 +80,13 @@ final class Company extends SnipeModel
}
$table = ($table_name) ? DB::getTablePrefix().$table_name."." : '';
return $query->where($table.$column, '=', $company_id);
if(\Schema::hasColumn($query->getModel()->getTable(), $column)){
return $query->where($table.$column, '=', $company_id);
} else {
return $query->join('users as users_comp', 'users_comp.id', 'user_id')->where('users_comp.company_id', '=', $company_id);
}
}
public static function getIdFromInput($unescaped_input)

View File

@@ -35,7 +35,7 @@ class Consumable extends SnipeModel
'qty' => 'required|integer|min:0',
'category_id' => 'required|integer',
'company_id' => 'integer|nullable',
'min_amt' => 'integer|min:1|nullable',
'min_amt' => 'integer|min:0|nullable',
'purchase_cost' => 'numeric|nullable',
);
@@ -76,7 +76,7 @@ class Consumable extends SnipeModel
*
* @var array
*/
protected $searchableAttributes = ['name', 'order_number', 'purchase_cost', 'purchase_date'];
protected $searchableAttributes = ['name', 'order_number', 'purchase_cost', 'purchase_date', 'item_no'];
/**
* The relations and their attributes that should be included when searching the model.

View File

@@ -25,11 +25,10 @@ class Department extends SnipeModel
use ValidatingTrait, UniqueUndeletedTrait;
protected $rules = [
'name' => 'required|max:255',
'user_id' => 'required',
'location_id' => 'numeric|nullable',
'company_id' => 'numeric|nullable',
'manager_id' => 'numeric|nullable',
'name' => 'required|max:255',
'location_id' => 'numeric|nullable',
'company_id' => 'numeric|nullable',
'manager_id' => 'numeric|nullable',
];
/**

View File

@@ -7,10 +7,10 @@ use Watson\Validating\ValidatingTrait;
class Group extends SnipeModel
{
protected $table = 'groups';
protected $table = 'permission_groups';
public $rules = array(
'name' => 'required|min:3|max:255',
'name' => 'required|min:2|max:255',
);
/**

View File

@@ -96,8 +96,11 @@ class Ldap extends Model
$filterQuery = $settings->ldap_auth_filter_query . $username;
if (!$ldapbind = @ldap_bind($connection, $userDn, $password)) {
return false;
if(!$ldapbind = Ldap::bindAdminToLdap($connection)){
return false;
}
}
if (!$results = ldap_search($connection, $baseDn, $filterQuery)) {
@@ -112,7 +115,7 @@ class Ldap extends Model
return false;
}
return $user;
return array_change_key_case($user);
}

View File

@@ -110,6 +110,7 @@ class License extends Depreciable
protected $searchableRelations = [
'manufacturer' => ['name'],
'company' => ['name'],
'category' => ['name'],
];
public static function boot()

View File

@@ -26,7 +26,7 @@ class Location extends SnipeModel
'address' => 'max:80|nullable',
'address2' => 'max:80|nullable',
'zip' => 'min:3|max:10|nullable',
// 'manager_id' => 'exists:users'
'manager_id' => 'exists:users,id|nullable'
);
/**
@@ -57,6 +57,7 @@ class Location extends SnipeModel
'zip',
'ldap_ou',
'currency',
'manager_id',
'image',
];
protected $hidden = ['user_id'];

View File

@@ -41,7 +41,8 @@ trait Loggable
$settings = Setting::getSettings();
$log = new Actionlog;
$log = $this->determineLogItemType($log);
$log->user_id = Auth::user()->id;
if(Auth::user())
$log->user_id = Auth::user()->id;
if (!isset($target)) {
throw new Exception('All checkout logs require a target');

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