Compare commits
250 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 70a9b7bf05 | |||
| d9824a0454 | |||
| e759a249bd | |||
| 42c2a66946 | |||
| 4d32f2b337 | |||
| 0e29744ec2 | |||
| 51236a2ad9 | |||
| 9b6726a630 | |||
| cbdd05144a | |||
| 507f1f196c | |||
| b60febeea2 | |||
| b3e0d8f675 | |||
| 9b84a0d516 | |||
| adac5ac544 | |||
| 1775995f26 | |||
| df4700b411 | |||
| 26a7701cda | |||
| a34085f1d9 | |||
| 8e682c715e | |||
| 915c19ebda | |||
| 7fded367c4 | |||
| 0a4743210c | |||
| af19e5d976 | |||
| 3d7277398c | |||
| a7ad48a02a | |||
| 469a3fc608 | |||
| 0fb4ff77f4 | |||
| ac83dba2bb | |||
| 979ecf961d | |||
| 13dcdf41b8 | |||
| fc96fa756e | |||
| ea9a502152 | |||
| d844734b6c | |||
| ec8a3d2e56 | |||
| 5410dc4255 | |||
| d1112bbc99 | |||
| ecf041fa10 | |||
| 0ab9bc1db8 | |||
| 73e788b94b | |||
| e91a537552 | |||
| ef8c1abf28 | |||
| bd0498aa69 | |||
| ea45033588 | |||
| 5e1df7049c | |||
| e27e1a78c3 | |||
| d585a34a26 | |||
| 4edaba648e | |||
| 9dca7396f3 | |||
| 4324242475 | |||
| eca5a05335 | |||
| aa4d3c3ffb | |||
| d442feb687 | |||
| 0a88141b18 | |||
| d5e6d82ca1 | |||
| f2a62857cb | |||
| b354ca817d | |||
| 4b9bfc178d | |||
| abc2f7e789 | |||
| 29cc9a0815 | |||
| f2ee7dcabb | |||
| 26203801f6 | |||
| fbe9539130 | |||
| 43ec959385 | |||
| 9b6276f281 | |||
| 0715791229 | |||
| 0a0661bf41 | |||
| 6ee939d29b | |||
| c3afbc0e53 | |||
| 38326314ca | |||
| 865950e766 | |||
| d49b67d033 | |||
| 6b63808e34 | |||
| 34dfcb5add | |||
| 30019a144a | |||
| 3e222b674a | |||
| e316444c63 | |||
| b29d7beb3a | |||
| f0a49fefd7 | |||
| 998c4a5fe5 | |||
| 626a6408d0 | |||
| 126a5671fe | |||
| aff104fa5d | |||
| a5764351f7 | |||
| 348becbbec | |||
| 922d6937ae | |||
| c53dae4b72 | |||
| 17ad7f7800 | |||
| 6232a077b5 | |||
| e7d72beb88 | |||
| 01e3f4a4db | |||
| 1b76880b0e | |||
| ed4ea7f1f4 | |||
| 81e358a01d | |||
| 6c283de60a | |||
| 4e7a6c0ccf | |||
| eba145503b | |||
| ae8c9d6afc | |||
| faeca4139d | |||
| 47909b93f7 | |||
| 472658b2fe | |||
| 42a03a0436 | |||
| ae0573b3da | |||
| 34f816097e | |||
| c651c9f1ed | |||
| 7c390cee2c | |||
| 987536930c | |||
| 10f322198f | |||
| 761371509d | |||
| 3518ea7e7d | |||
| c92eed2b3e | |||
| 0054ce3071 | |||
| b0f74466bb | |||
| b4a0484295 | |||
| bb874012d9 | |||
| bb8583eb14 | |||
| 8d2c229bc3 | |||
| 48e6208214 | |||
| 22233e3ba6 | |||
| fd515654ff | |||
| e439f15a64 | |||
| 42175782a5 | |||
| c7a21e0e4d | |||
| d98ffd94f9 | |||
| 6ad5da44f3 | |||
| 479f422e68 | |||
| e10cdd57a5 | |||
| bf157773c8 | |||
| fba3949530 | |||
| abc3dea8ac | |||
| 51d74ac06d | |||
| af835d6efc | |||
| a7a10455ae | |||
| bd02b9ed62 | |||
| 16f57e16cb | |||
| af6f208c43 | |||
| 52270fa4db | |||
| bf3731d65c | |||
| 233ebf06ee | |||
| e27f6a483d | |||
| 19670f9dd8 | |||
| 1448229cd2 | |||
| 4721cab928 | |||
| 08f3e78d26 | |||
| 62227ec27d | |||
| 10711245ba | |||
| 29a7c8577d | |||
| dfb1ff81e6 | |||
| 021e723acf | |||
| 14c0c314aa | |||
| d23ea70b08 | |||
| 1b047c768b | |||
| e6323e0a1b | |||
| 73ce5f98bb | |||
| a37cb616eb | |||
| 659d953f3f | |||
| c1dcc22217 | |||
| 6a67426140 | |||
| 4ba474cf73 | |||
| fb6caa35ff | |||
| a5870c888e | |||
| f35f8477d3 | |||
| d0637d38f3 | |||
| 7141968d64 | |||
| 0f7b7d8e6a | |||
| ca78b3ed7c | |||
| 2d2cae10b9 | |||
| 5347b19910 | |||
| 5e9331f5ae | |||
| 6e30fa6922 | |||
| 58b3f0519d | |||
| f119c69698 | |||
| 57f4c986af | |||
| 2958630923 | |||
| 72dacda4f9 | |||
| 9c2b986bb0 | |||
| 06c5bce3c7 | |||
| a0cbca85bf | |||
| 9bda62d295 | |||
| 1d7e243d0a | |||
| 63bc2ec09f | |||
| d5cadeab1a | |||
| 31516abef9 | |||
| d2535582f3 | |||
| eaaea303f4 | |||
| 8c5312b931 | |||
| 4ef6e292d1 | |||
| 6310670835 | |||
| 15bb30acd6 | |||
| 148d41d8dc | |||
| 71c1c74164 | |||
| 9c02526a37 | |||
| 25dc26aac3 | |||
| afc763ebac | |||
| 6a73ec6537 | |||
| 481143b891 | |||
| cef67695cd | |||
| 4576cb6f56 | |||
| 56f88d2c22 | |||
| c1d1cb8122 | |||
| 29f1cf2b48 | |||
| f56862c684 | |||
| 1052be670d | |||
| 54279f22a3 | |||
| dfea47a272 | |||
| f0d78091d2 | |||
| 30a9704625 | |||
| 9a9b6ae228 | |||
| 7c8dc9fe2d | |||
| b81dd18576 | |||
| dac4b58892 | |||
| 71fd430f8e | |||
| 5265821bcc | |||
| cb494a74ca | |||
| c526ffbf68 | |||
| 6f5fe83a91 | |||
| 5a3816c907 | |||
| c8796cf045 | |||
| f4095c6dd0 | |||
| ee2c67a65f | |||
| 5614578710 | |||
| 08ef78356d | |||
| 47ac59abef | |||
| 265a896211 | |||
| f7e4fca70d | |||
| bb4c443cd9 | |||
| 7b1d2ee050 | |||
| b3f70a046f | |||
| 734e87f85f | |||
| f371c5fd62 | |||
| 4b3edbd2f5 | |||
| 1f3106b9da | |||
| 9fd3a9a82d | |||
| a6e6991a2d | |||
| 93ba0717d8 | |||
| a8839e0ef4 | |||
| 3e4152c966 | |||
| 1bf34d73f5 | |||
| d1e360d64d | |||
| 3b5b19848c | |||
| 93ba90e837 | |||
| fc70d79a17 | |||
| 65016a2383 | |||
| dbcb2ccb46 | |||
| 2afcfcc87c | |||
| 1afef9416a | |||
| 4049143ebf | |||
| 4df53bdf8d | |||
| d49a1ea304 | |||
| 521f4facd5 | |||
| b4653dfc15 |
@@ -719,6 +719,42 @@
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "zwerch",
|
||||
"name": "Robin Temme",
|
||||
"avatar_url": "https://avatars2.githubusercontent.com/u/2809241?v=4",
|
||||
"profile": "https://github.com/zwerch",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "imanghafoori1",
|
||||
"name": "Iman",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/6961695?v=4",
|
||||
"profile": "https://github.com/imanghafoori1",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "richardhofman6",
|
||||
"name": "Richard Hofman",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/6551003?v=4",
|
||||
"profile": "https://github.com/richardhofman6",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "gizzmojr",
|
||||
"name": "gizzmojr",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/3697569?v=4",
|
||||
"profile": "https://github.com/gizzmojr",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ DB_USERNAME=null
|
||||
DB_PASSWORD=null
|
||||
DB_PREFIX=null
|
||||
DB_DUMP_PATH='/usr/bin'
|
||||
DB_CHARSET=utf8mb4
|
||||
DB_COLLATION=utf8mb4_unicode_ci
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: SSL DATABASE SETTINGS
|
||||
@@ -61,6 +63,7 @@ ENCRYPT=false
|
||||
COOKIE_NAME=snipeit_session
|
||||
COOKIE_DOMAIN=null
|
||||
SECURE_COOKIES=false
|
||||
REFERRER_POLICY=strict-origin
|
||||
|
||||
|
||||
# --------------------------------------------
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ FILESYSTEM_DISK=local
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=localhost
|
||||
DB_DATABASE=snipeit_unit
|
||||
DB_USERNAME=travis
|
||||
DB_USERNAME=root
|
||||
DB_PASSWORD=null
|
||||
|
||||
# --------------------------------------------
|
||||
|
||||
+7
-1
@@ -6,6 +6,9 @@ sudo: false
|
||||
# see http://about.travis-ci.org/docs/user/languages/php/ for more hints
|
||||
language: php
|
||||
|
||||
services:
|
||||
- mysql
|
||||
|
||||
# list any PHP version you want to test against
|
||||
php:
|
||||
- 5.6
|
||||
@@ -15,7 +18,10 @@ php:
|
||||
before_script:
|
||||
- phantomjs --webdriver=4444 &
|
||||
- sleep 4
|
||||
- mysql -e "create database IF NOT EXISTS snipeit_unit;" -utravis
|
||||
- mysql -e 'CREATE DATABASE snipeit_unit;'
|
||||
- mysql -e 'CREATE USER "travis'@'localhost";'
|
||||
- mysql -e 'GRANT ALL PRIVILEGES ON * . * TO "travis'@'localhost";'
|
||||
- mysql -e 'FLUSH PRIVILEGES;'
|
||||
- composer self-update
|
||||
- composer install -n --prefer-source
|
||||
- chmod -R 777 storage
|
||||
|
||||
@@ -13,6 +13,7 @@ php7.0-gd \
|
||||
php7.0-xml \
|
||||
php7.0-mbstring \
|
||||
php7.0-zip \
|
||||
php7.0-bcmath \
|
||||
patch \
|
||||
curl \
|
||||
vim \
|
||||
@@ -23,6 +24,7 @@ mysql-client \
|
||||
|
||||
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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[](https://travis-ci.org/snipe/snipe-it) [](http://waffle.io/snipe/snipe-it) []() [](https://crowdin.com/project/snipe-it) [](https://gitter.im/snipe/snipe-it?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [](https://hub.docker.com/r/snipe/snipe-it/) [](https://twitter.com/snipeyhead) [](https://zenhub.io) [](https://www.codacy.com/app/snipe/snipe-it?utm_source=github.com&utm_medium=referral&utm_content=snipe/snipe-it&utm_campaign=Badge_Grade)
|
||||
[](#contributors)
|
||||
[](https://travis-ci.org/snipe/snipe-it) [](http://waffle.io/snipe/snipe-it) []() [](https://crowdin.com/project/snipe-it) [](https://gitter.im/snipe/snipe-it?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [](https://hub.docker.com/r/snipe/snipe-it/) [](https://twitter.com/snipeyhead) [](https://zenhub.io) [](https://www.codacy.com/app/snipe/snipe-it?utm_source=github.com&utm_medium=referral&utm_content=snipe/snipe-it&utm_campaign=Badge_Grade)
|
||||
[](#contributors)
|
||||
|
||||
|
||||
## Snipe-IT - Open Source Asset Management System
|
||||
@@ -67,6 +67,7 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
|
||||
| [<img src="https://avatars0.githubusercontent.com/u/8341172?v=3" width="110px;"/><br /><sub>Jay Richards</sub>](http://www.cordeos.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=technogenus "Code") | [<img src="https://avatars2.githubusercontent.com/u/7295127?v=3" width="110px;"/><br /><sub>Alexander Innes</sub>](https://necurity.co.uk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=leostat "Code") | [<img src="https://avatars2.githubusercontent.com/u/334485?v=3" width="110px;"/><br /><sub>Danny Garcia</sub>](https://buzzedword.codes)<br />[💻](https://github.com/snipe/snipe-it/commits?author=buzzedword "Code") | [<img src="https://avatars2.githubusercontent.com/u/366855?v=3" width="110px;"/><br /><sub>archpoint</sub>](https://github.com/archpoint)<br />[💻](https://github.com/snipe/snipe-it/commits?author=archpoint "Code") | [<img src="https://avatars1.githubusercontent.com/u/67991?v=3" width="110px;"/><br /><sub>Jake McGraw</sub>](http://www.jakemcgraw.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jakemcgraw "Code") | [<img src="https://avatars1.githubusercontent.com/u/1714374?v=3" width="110px;"/><br /><sub>FleischKarussel</sub>](https://github.com/FleischKarussel)<br />[📖](https://github.com/snipe/snipe-it/commits?author=FleischKarussel "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/319644?v=3" width="110px;"/><br /><sub>Dylan Yi</sub>](https://github.com/feeva)<br />[💻](https://github.com/snipe/snipe-it/commits?author=feeva "Code") |
|
||||
| [<img src="https://avatars2.githubusercontent.com/u/857740?v=3" width="110px;"/><br /><sub>Gil Rutkowski</sub>](http://FlashingCursor.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=flashingcursor "Code") | [<img src="https://avatars3.githubusercontent.com/u/129360?v=3" width="110px;"/><br /><sub>Desmond Morris</sub>](http://www.desmondmorris.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=desmondmorris "Code") | [<img src="https://avatars2.githubusercontent.com/u/52936?v=3" width="110px;"/><br /><sub>Nick Peelman</sub>](http://peelman.us)<br />[💻](https://github.com/snipe/snipe-it/commits?author=peelman "Code") | [<img src="https://avatars0.githubusercontent.com/u/53161?v=3" width="110px;"/><br /><sub>Abraham Vegh</sub>](https://abrahamvegh.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=abrahamvegh "Code") | [<img src="https://avatars0.githubusercontent.com/u/2818680?v=3" width="110px;"/><br /><sub>Mohamed Rashid</sub>](https://github.com/rashivkp)<br />[📖](https://github.com/snipe/snipe-it/commits?author=rashivkp "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/1509456?v=3" width="110px;"/><br /><sub>Kasey</sub>](http://hinchk.github.io)<br />[💻](https://github.com/snipe/snipe-it/commits?author=HinchK "Code") | [<img src="https://avatars2.githubusercontent.com/u/10522541?v=3" width="110px;"/><br /><sub>Brett</sub>](https://github.com/BrettFagerlund)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=BrettFagerlund "Tests") |
|
||||
| [<img src="https://avatars2.githubusercontent.com/u/16108587?v=3" width="110px;"/><br /><sub>Jason Spriggs</sub>](http://jasonspriggs.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jasonspriggs "Code") | [<img src="https://avatars2.githubusercontent.com/u/1134568?v=3" width="110px;"/><br /><sub>Nate Felton</sub>](http://n8felton.wordpress.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=n8felton "Code") | [<img src="https://avatars2.githubusercontent.com/u/14036694?v=3" width="110px;"/><br /><sub>Manasses Ferreira</sub>](http://homepages.dcc.ufmg.br/~manassesferreira)<br />[💻](https://github.com/snipe/snipe-it/commits?author=manassesferreira "Code") | [<img src="https://avatars0.githubusercontent.com/u/15913949?v=3" width="110px;"/><br /><sub>Steve</sub>](https://github.com/steveelwood)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=steveelwood "Tests") | [<img src="https://avatars1.githubusercontent.com/u/3361683?v=3" width="110px;"/><br /><sub>matc</sub>](http://twitter.com/matc)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=matc "Tests") | [<img src="https://avatars3.githubusercontent.com/u/7405702?v=3" width="110px;"/><br /><sub>Cole R. Davis</sub>](http://www.davisracingteam.com)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=VanillaNinjaD "Tests") | [<img src="https://avatars2.githubusercontent.com/u/10167681?v=3" width="110px;"/><br /><sub>gibsonjoshua55</sub>](https://github.com/gibsonjoshua55)<br />[💻](https://github.com/snipe/snipe-it/commits?author=gibsonjoshua55 "Code") |
|
||||
| [<img src="https://avatars2.githubusercontent.com/u/2809241?v=4" width="110px;"/><br /><sub>Robin Temme</sub>](https://github.com/zwerch)<br />[💻](https://github.com/snipe/snipe-it/commits?author=zwerch "Code") | [<img src="https://avatars0.githubusercontent.com/u/6961695?v=4" width="110px;"/><br /><sub>Iman</sub>](https://github.com/imanghafoori1)<br />[💻](https://github.com/snipe/snipe-it/commits?author=imanghafoori1 "Code") | [<img src="https://avatars1.githubusercontent.com/u/6551003?v=4" width="110px;"/><br /><sub>Richard Hofman</sub>](https://github.com/richardhofman6)<br />[💻](https://github.com/snipe/snipe-it/commits?author=richardhofman6 "Code") | [<img src="https://avatars0.githubusercontent.com/u/3697569?v=4" width="110px;"/><br /><sub>gizzmojr</sub>](https://github.com/gizzmojr)<br />[💻](https://github.com/snipe/snipe-it/commits?author=gizzmojr "Code") |
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
|
||||
@@ -75,7 +76,7 @@ This project follows the [all-contributors](https://github.com/kentcdodds/all-co
|
||||
|
||||
### Contributing
|
||||
|
||||
Please see the documentation on [contributing and developing for Snipe-IT](https://snipe-it.readme.io/docs/contributing).
|
||||
Please see the documentation on [contributing and developing for Snipe-IT](https://snipe-it.readme.io/docs/contributing-overview).
|
||||
|
||||
|
||||
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.
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\CustomField;
|
||||
use Illuminate\Console\Command;
|
||||
use App\LegacyEncrypter\McryptEncrypter;
|
||||
use App\Models\Setting;
|
||||
use App\Models\Asset;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class RecryptFromMcrypt extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'snipeit:legacy-recrypt';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'This command allows upgrading users to de-encrypt their deprecated mcrypt encrypted fields and re-encrypt them using the current OpenSSL encryption.';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
|
||||
// Check and see if they have a legacy app key listed in their .env
|
||||
// If not, we can try to use the current APP_KEY if looks like it's old
|
||||
$legacy_key = env('LEGACY_APP_KEY');
|
||||
$key_parts = explode(':', $legacy_key);
|
||||
$errors = array();
|
||||
|
||||
if (!$legacy_key) {
|
||||
$this->error('ERROR: You do not have a LEGACY_APP_KEY set in your .env file. Please locate your old APP_KEY and ADD a line to your .env file like: LEGACY_APP_KEY=YOUR_OLD_APP_KEY');
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Do some basic legacy app key length checks
|
||||
if (strlen($legacy_key) == 32) {
|
||||
$legacy_length_check = true;
|
||||
} elseif (array_key_exists('1', $key_parts) && (strlen($key_parts[1])==44)) {
|
||||
$legacy_length_check = true;
|
||||
} else {
|
||||
$legacy_length_check = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Check that the app key is 32 characters
|
||||
if ($legacy_length_check === true) {
|
||||
$this->comment('INFO: Your LEGACY_APP_KEY looks correct. Okay to continue.');
|
||||
} else {
|
||||
$this->error('ERROR: Your LEGACY_APP_KEY is not the correct length (32 characters or base64 followed by 44 characters for later versions). Please locate your old APP_KEY and use that as your LEGACY_APP_KEY in your .env file to continue.');
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->error('================================!!!! WARNING !!!!================================');
|
||||
$this->error('================================!!!! WARNING !!!!================================');
|
||||
$this->comment("This tool will attempt to decrypt your old Snipe-IT (mcrypt, now deprecated) encrypted data and re-encrypt it using OpenSSL. \n\nYou should only continue if you have backed up any and all old APP_KEYs and have backed up your data.");
|
||||
|
||||
if ($this->confirm("Are you SURE you wish to continue?")) {
|
||||
|
||||
$backup_file = 'backups/env-backups/'.'app_key-'.date('Y-m-d-gis');
|
||||
|
||||
try {
|
||||
Storage::disk('local')->put($backup_file, 'APP_KEY: '.config('app.key'));
|
||||
Storage::disk('local')->append($backup_file, 'LEGACY_APP_KEY: '.$legacy_key);
|
||||
} catch (\Exception $e) {
|
||||
$this->info('WARNING: Could not backup app keys');
|
||||
}
|
||||
|
||||
|
||||
$mcrypter = new McryptEncrypter($legacy_key);
|
||||
$settings = Setting::getSettings();
|
||||
|
||||
if ($settings->ldap_password=='') {
|
||||
$this->comment('INFO: No LDAP password found. Skipping... ');
|
||||
}
|
||||
|
||||
$custom_fields = CustomField::where('field_encrypted','=', 1)->get();
|
||||
$this->comment('INFO: Retrieving encrypted custom fields...');
|
||||
|
||||
$query = Asset::withTrashed();
|
||||
|
||||
foreach ($custom_fields as $custom_field) {
|
||||
$this->comment('FIELD TO RECRYPT: '.$custom_field->name .' ('.$custom_field->db_column.')');
|
||||
$query->orWhereNotNull($custom_field->db_column);
|
||||
}
|
||||
|
||||
|
||||
// Get all assets with a value in any of the fields that were encrypted
|
||||
$assets = $query->get();
|
||||
|
||||
$bar = $this->output->createProgressBar(count($assets));
|
||||
|
||||
foreach ($custom_fields as $encrypted_field) {
|
||||
|
||||
// Try to decrypt the payload using the legacy app key
|
||||
try {
|
||||
$decrypted_field = $mcrypter->decrypt($encrypted_field);
|
||||
$this->comment($decrypted_field);
|
||||
} catch (\Exception $e) {
|
||||
$errors[] = ' - ERROR: Could not decrypt field ['.$encrypted_field->name.']: '.$e->getMessage();
|
||||
}
|
||||
$bar->advance();
|
||||
}
|
||||
|
||||
|
||||
foreach ($assets as $asset) {
|
||||
foreach ($custom_fields as $encrypted_field) {
|
||||
|
||||
// Make sure the value isn't null
|
||||
if ($asset->{$encrypted_field}!='') {
|
||||
// Try to decrypt the payload using the legacy app key
|
||||
try {
|
||||
$decrypted_field = $mcrypter->decrypt($asset->{$encrypted_field});
|
||||
$asset->{$encrypted_field} = \Crypt::encrypt($decrypted_field);
|
||||
$this->comment($decrypted_field);
|
||||
} catch (\Exception $e) {
|
||||
$errors[] = ' - ERROR: Could not decrypt field ['.$encrypted_field->name.']: '.$e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
$asset->save();
|
||||
$bar->advance();
|
||||
}
|
||||
|
||||
|
||||
|
||||
$bar->finish();
|
||||
|
||||
if (count($errors) > 0) {
|
||||
$this->comment("\n\n");
|
||||
$this->error("The decrypter encountered some errors: \n");
|
||||
foreach ($errors as $error) {
|
||||
$this->error($error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
|
||||
use App\Models\Asset;
|
||||
use Illuminate\Console\Command;
|
||||
use App\Notifications\ExpectedCheckinNotification;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class SendExpectedCheckinAlerts extends Command
|
||||
{
|
||||
|
||||
/**
|
||||
* The console command name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'snipeit:expected-checkin';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Check for overdue or upcoming expected checkins.';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fire()
|
||||
{
|
||||
|
||||
$whenNotify = Carbon::now()->addDays(7);
|
||||
$assets = Asset::with('assignedTo')->whereNotNull('expected_checkin')->where('expected_checkin', '<=', $whenNotify)->get();
|
||||
|
||||
$this->info($whenNotify.' is deadline');
|
||||
$this->info($assets->count().' assets');
|
||||
|
||||
foreach ($assets as $asset) {
|
||||
if ($asset->assignedTo && $asset->checkoutOutToUser()) {
|
||||
$asset->assignedTo->notify((new ExpectedCheckinNotification($asset)));
|
||||
//$this->info($asset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -17,13 +17,15 @@ class Kernel extends ConsoleKernel
|
||||
Commands\CreateAdmin::class,
|
||||
Commands\SendExpirationAlerts::class,
|
||||
Commands\SendInventoryAlerts::class,
|
||||
Commands\SendExpectedCheckinAlerts::class,
|
||||
Commands\ObjectImportCommand::class,
|
||||
Commands\Versioning::class,
|
||||
Commands\SystemBackup::class,
|
||||
Commands\DisableLDAP::class,
|
||||
Commands\Purge::class,
|
||||
Commands\LdapSync::class,
|
||||
Commands\FixDoubleEscape::class
|
||||
Commands\FixDoubleEscape::class,
|
||||
Commands\RecryptFromMcrypt::class
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -37,6 +39,7 @@ class Kernel extends ConsoleKernel
|
||||
|
||||
$schedule->command('snipeit:inventory-alerts')->daily();
|
||||
$schedule->command('snipeit:expiring-alerts')->daily();
|
||||
$schedule->command('snipeit:expected-checkins')->daily();
|
||||
$schedule->command('snipeit:backup')->weekly();
|
||||
$schedule->command('backup:clean')->daily();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exceptions;
|
||||
|
||||
use Exception;
|
||||
class CheckoutNotAllowed extends Exception
|
||||
{
|
||||
public function __toString()
|
||||
{
|
||||
"A checkout is not allowed under these circumstances";
|
||||
}
|
||||
}
|
||||
@@ -80,7 +80,7 @@ class Handler extends ExceptionHandler
|
||||
|
||||
}
|
||||
}
|
||||
// Try to parse 500 Errors ina bit nicer way when debug is enabled.
|
||||
// Try to parse 500 Errors in a bit nicer way when debug is enabled.
|
||||
if (config('app.debug')) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, "An Error has occured! " . $e->getMessage()), 500);
|
||||
}
|
||||
|
||||
@@ -683,12 +683,11 @@ class Helper
|
||||
public static function formatStandardApiResponse($status, $payload = null, $messages = null) {
|
||||
|
||||
$array['status'] = $status;
|
||||
($payload) ? $array['payload'] = $payload : '';
|
||||
|
||||
$array['messages'] = $messages;
|
||||
if (($messages) && (count($messages) > 0)) {
|
||||
$array['messages'] = $messages;
|
||||
}
|
||||
|
||||
($payload) ? $array['payload'] = $payload : $array['payload'] = null;
|
||||
return $array;
|
||||
}
|
||||
|
||||
|
||||
@@ -260,7 +260,7 @@ class AccessoriesController extends Controller
|
||||
'assigned_to' => $request->get('assigned_to')
|
||||
]);
|
||||
|
||||
$logaction = $accessory->logCheckout(e(Input::get('note')));
|
||||
$logaction = $accessory->logCheckout(e(Input::get('note')), $user);
|
||||
|
||||
DB::table('accessories_users')->where('assigned_to', '=', $accessory->assigned_to)->where('accessory_id', '=', $accessory->id)->first();
|
||||
|
||||
@@ -274,7 +274,7 @@ class AccessoriesController extends Controller
|
||||
$data['note'] = $logaction->note;
|
||||
$data['require_acceptance'] = $accessory->requireAcceptance();
|
||||
// TODO: Port this to new mail notifications
|
||||
if (($accessory->requireAcceptance()=='1') || ($accessory->getEula())) {
|
||||
if ((($accessory->requireAcceptance()=='1') || ($accessory->getEula())) && ($user->email!='')) {
|
||||
|
||||
Mail::send('emails.accept-accessory', $data, function ($m) use ($user) {
|
||||
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
|
||||
@@ -351,7 +351,7 @@ class AccessoriesController extends Controller
|
||||
$data['item_tag'] = '';
|
||||
$data['note'] = e($logaction->note);
|
||||
|
||||
if (($accessory->checkin_email()=='1')) {
|
||||
if ((($accessory->checkin_email()=='1')) && ($user->email!='')) {
|
||||
|
||||
Mail::send('emails.checkin-asset', $data, function ($m) use ($user) {
|
||||
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
|
||||
|
||||
@@ -129,9 +129,8 @@ class AccessoriesController extends Controller
|
||||
{
|
||||
$this->authorize('view', Accessory::class);
|
||||
$accessory = Accessory::findOrFail($id)->with('users')->first();
|
||||
$accessories_users = $accessory->users;
|
||||
$total = $accessories_users->count();
|
||||
return (new AccessoriesTransformer)->transformCheckedoutAccessories($accessories_users, $total);
|
||||
$total = $accessory->users->count();
|
||||
return (new AccessoriesTransformer)->transformCheckedoutAccessory($accessory, $total);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
<?php
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Transformers\AssetMaintenancesTransformer;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetMaintenance;
|
||||
use App\Models\Company;
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use Gate;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to Asset Maintenance for
|
||||
* the Snipe-IT Asset Management application.
|
||||
*
|
||||
* @version v2.0
|
||||
*/
|
||||
class AssetMaintenancesController extends Controller
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Generates the JSON response for asset maintenances listing view.
|
||||
*
|
||||
* @see AssetMaintenancesController::getIndex() method that generates view
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @version v1.0
|
||||
* @since [v1.8]
|
||||
* @return String JSON
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$maintenances = AssetMaintenance::with('asset', 'supplier', 'asset.company', 'admin');
|
||||
|
||||
if (Input::has('search')) {
|
||||
$maintenances = $maintenances->TextSearch(e($request->input('search')));
|
||||
}
|
||||
|
||||
$offset = request('offset', 0);
|
||||
$limit = request('limit', 50);
|
||||
|
||||
$allowed_columns = ['id','title','asset_maintenance_time','asset_maintenance_type','cost','start_date','completion_date','notes','user_id'];
|
||||
$order = Input::get('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array(Input::get('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
|
||||
|
||||
switch ($sort) {
|
||||
case 'user_id':
|
||||
$maintenances = $maintenances->OrderAdmin($order);
|
||||
break;
|
||||
default:
|
||||
$maintenances = $maintenances->orderBy($sort, $order);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
$maintenances = $maintenances->skip($offset)->take($limit)->get();
|
||||
|
||||
|
||||
return (new AssetMaintenancesTransformer())->transformAssetMaintenances($maintenances, $maintenances->count());
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates and stores the new asset maintenance
|
||||
*
|
||||
* @see AssetMaintenancesController::getCreate() method for the form
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @version v1.0
|
||||
* @since [v1.8]
|
||||
* @return String JSON
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
// create a new model instance
|
||||
$assetMaintenance = new AssetMaintenance();
|
||||
$assetMaintenance->supplier_id = $request->input('supplier_id');
|
||||
$assetMaintenance->is_warranty = $request->input('is_warranty');
|
||||
$assetMaintenance->cost = e($request->input('cost'));
|
||||
$assetMaintenance->notes = e($request->input('notes'));
|
||||
$asset = Asset::find(e($request->input('asset_id')));
|
||||
|
||||
if (!Company::isCurrentUserHasAccess($asset)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot add a maintenance for that asset'));
|
||||
}
|
||||
|
||||
// Save the asset maintenance data
|
||||
$assetMaintenance->asset_id = $request->input('asset_id');
|
||||
$assetMaintenance->asset_maintenance_type = $request->input('asset_maintenance_type');
|
||||
$assetMaintenance->title = $request->input('title');
|
||||
$assetMaintenance->start_date = $request->input('start_date');
|
||||
$assetMaintenance->completion_date = $request->input('completion_date');
|
||||
$assetMaintenance->user_id = Auth::id();
|
||||
|
||||
if (( $assetMaintenance->completion_date !== null )
|
||||
&& ( $assetMaintenance->start_date !== "" )
|
||||
&& ( $assetMaintenance->start_date !== "0000-00-00" )
|
||||
) {
|
||||
$startDate = Carbon::parse($assetMaintenance->start_date);
|
||||
$completionDate = Carbon::parse($assetMaintenance->completion_date);
|
||||
$assetMaintenance->asset_maintenance_time = $completionDate->diffInDays($startDate);
|
||||
}
|
||||
|
||||
// Was the asset maintenance created?
|
||||
if ($assetMaintenance->save()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $assetMaintenance, trans('admin/asset_maintenances/message.create.success')));
|
||||
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $assetMaintenance->getErrors()));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates and stores an update to an asset maintenance
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @param int $assetMaintenanceId
|
||||
* @param int $request
|
||||
* @version v1.0
|
||||
* @since [v4.0]
|
||||
* @return String JSON
|
||||
*/
|
||||
public function update(Request $request, $assetMaintenanceId = null)
|
||||
{
|
||||
// Check if the asset maintenance exists
|
||||
$assetMaintenance = AssetMaintenance::findOrFail($assetMaintenanceId);
|
||||
|
||||
if (!Company::isCurrentUserHasAccess($assetMaintenance->asset)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot edit a maintenance for that asset'));
|
||||
}
|
||||
|
||||
$assetMaintenance->supplier_id = e($request->input('supplier_id'));
|
||||
$assetMaintenance->is_warranty = e($request->input('is_warranty'));
|
||||
$assetMaintenance->cost = Helper::ParseFloat(e($request->input('cost')));
|
||||
$assetMaintenance->notes = e($request->input('notes'));
|
||||
|
||||
$asset = Asset::find(request('asset_id'));
|
||||
|
||||
if (!Company::isCurrentUserHasAccess($asset)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot edit a maintenance for that asset'));
|
||||
}
|
||||
|
||||
// Save the asset maintenance data
|
||||
$assetMaintenance->asset_id = $request->input('asset_id');
|
||||
$assetMaintenance->asset_maintenance_type = $request->input('asset_maintenance_type');
|
||||
$assetMaintenance->title = $request->input('title');
|
||||
$assetMaintenance->start_date = $request->input('start_date');
|
||||
$assetMaintenance->completion_date = $request->input('completion_date');
|
||||
|
||||
if (( $assetMaintenance->completion_date == null )
|
||||
) {
|
||||
if (( $assetMaintenance->asset_maintenance_time !== 0 )
|
||||
|| ( !is_null($assetMaintenance->asset_maintenance_time) )
|
||||
) {
|
||||
$assetMaintenance->asset_maintenance_time = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (( $assetMaintenance->completion_date !== null )
|
||||
&& ( $assetMaintenance->start_date !== "" )
|
||||
&& ( $assetMaintenance->start_date !== "0000-00-00" )
|
||||
) {
|
||||
$startDate = Carbon::parse($assetMaintenance->start_date);
|
||||
$completionDate = Carbon::parse($assetMaintenance->completion_date);
|
||||
$assetMaintenance->asset_maintenance_time = $completionDate->diffInDays($startDate);
|
||||
}
|
||||
|
||||
// Was the asset maintenance created?
|
||||
if ($assetMaintenance->save()) {
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $assetMaintenance, trans('admin/asset_maintenances/message.edit.success')));
|
||||
|
||||
}
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $assetMaintenance->getErrors()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an asset maintenance
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @param int $assetMaintenanceId
|
||||
* @version v1.0
|
||||
* @since [v4.0]
|
||||
* @return String JSON
|
||||
*/
|
||||
public function destroy($assetMaintenanceId)
|
||||
{
|
||||
// Check if the asset maintenance exists
|
||||
$assetMaintenance = AssetMaintenance::findOrFail($assetMaintenanceId);
|
||||
|
||||
if (!Company::isCurrentUserHasAccess($assetMaintenance->asset)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot delete a maintenance for that asset'));
|
||||
}
|
||||
|
||||
$assetMaintenance->delete();
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $assetMaintenance, trans('admin/asset_maintenances/message.delete.success')));
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* View an asset maintenance
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @param int $assetMaintenanceId
|
||||
* @version v1.0
|
||||
* @since [v4.0]
|
||||
* @return String JSON
|
||||
*/
|
||||
public function show($assetMaintenanceId)
|
||||
{
|
||||
$assetMaintenance = AssetMaintenance::findOrFail($assetMaintenanceId);
|
||||
if (!Company::isCurrentUserHasAccess($assetMaintenance->asset)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot view a maintenance for that asset'));
|
||||
}
|
||||
return (new AssetMaintenancesTransformer())->transformAssetMaintenance($assetMaintenance);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -76,7 +76,7 @@ class AssetModelsController extends Controller
|
||||
$assetmodel->fill($request->all());
|
||||
|
||||
if ($assetmodel->save()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $assetmodel, trans('admin/assetmodels/message.create.success')));
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $assetmodel, trans('admin/models/message.create.success')));
|
||||
}
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $assetmodel->getErrors()));
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ use TCPDF;
|
||||
use Validator;
|
||||
use View;
|
||||
|
||||
|
||||
/**
|
||||
* This class controls all actions related to assets for
|
||||
* the Snipe-IT Asset Management application.
|
||||
@@ -83,9 +84,8 @@ class AssetsController extends Controller
|
||||
}
|
||||
|
||||
$assets = Company::scopeCompanyables(Asset::select('assets.*'))->with(
|
||||
'assetLoc', 'assetstatus', 'defaultLoc', 'assetlog', 'company',
|
||||
'model.category', 'model.manufacturer', 'model.fieldset', 'assigneduser','supplier');
|
||||
|
||||
'assetloc', 'assetstatus', 'defaultLoc', 'assetlog', 'company',
|
||||
'model.category', 'model.manufacturer', 'model.fieldset','supplier');
|
||||
// If we should search on everything
|
||||
if (($request->has('search')) && (count($filter) == 0)) {
|
||||
$assets->TextSearch($request->input('search'));
|
||||
@@ -96,7 +96,6 @@ class AssetsController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// These are used by the API to query against specific ID numbers
|
||||
if ($request->has('status_id')) {
|
||||
$assets->where('status_id', '=', $request->input('status_id'));
|
||||
@@ -231,7 +230,8 @@ class AssetsController extends Controller
|
||||
*/
|
||||
public function store(AssetRequest $request)
|
||||
{
|
||||
// $this->authorize('create', Asset::class);
|
||||
|
||||
$this->authorize('create', Asset::class);
|
||||
|
||||
$asset = new Asset();
|
||||
$asset->model()->associate(AssetModel::find((int) $request->get('model_id')));
|
||||
@@ -279,6 +279,7 @@ class AssetsController extends Controller
|
||||
}
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.create.success')));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $asset->getErrors()), 200);
|
||||
}
|
||||
|
||||
@@ -493,5 +494,52 @@ class AssetsController extends Controller
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkin.error')));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mark an asset as audited
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $id
|
||||
* @since [v4.0]
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function audit(Request $request) {
|
||||
|
||||
|
||||
$this->authorize('audit', Asset::class);
|
||||
$rules = array(
|
||||
'asset_tag' => 'required',
|
||||
'location_id' => 'exists:locations,id|nullable|numeric',
|
||||
'next_audit_date' => 'date|nullable'
|
||||
);
|
||||
|
||||
$validator = Validator::make($request->all(), $rules);
|
||||
if ($validator->fails()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $validator->errors()->all()));
|
||||
}
|
||||
|
||||
$asset = Asset::where('asset_tag','=', $request->input('asset_tag'))->first();
|
||||
|
||||
|
||||
if ($asset) {
|
||||
$asset->next_audit_date = $request->input('next_audit_date');
|
||||
if ($asset->save()) {
|
||||
$log = $asset->logAudit(request('note'),request('location_id'));
|
||||
return response()->json(Helper::formatStandardApiResponse('success', [
|
||||
'asset_tag'=> e($asset->asset_tag),
|
||||
'note'=> e($request->input('note')),
|
||||
'next_audit_date' => Helper::getFormattedDateObject($log->calcNextAuditDate())
|
||||
], trans('admin/hardware/message.audit.success')));
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', ['asset_tag'=> e($request->input('asset_tag'))], 'Asset with tag '.$request->input('asset_tag').' not found'));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ class CategoriesController extends Controller
|
||||
$this->authorize('view', Category::class);
|
||||
$allowed_columns = ['id', 'name','category_type','use_default_eula','require_acceptance','checkin_email'];
|
||||
|
||||
$categories = Category::select(['id', 'name','category_type','use_default_eula','require_acceptance','checkin_email'])
|
||||
$categories = Category::select(['id', 'created_at', 'updated_at', 'name','category_type','use_default_eula','require_acceptance','checkin_email'])
|
||||
->withCount('assets', 'accessories', 'consumables', 'components');
|
||||
|
||||
if ($request->has('search')) {
|
||||
@@ -75,7 +75,8 @@ class CategoriesController extends Controller
|
||||
{
|
||||
$this->authorize('view', Category::class);
|
||||
$category = Category::findOrFail($id);
|
||||
return $category;
|
||||
return (new CategoriesTransformer)->transformCategory($category);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -148,4 +148,47 @@ class ConsumablesController extends Controller
|
||||
$consumable->delete();
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/consumables/message.delete.success')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a JSON response containing details on the users associated with this consumable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ConsumablesController::getView() method that returns the form.
|
||||
* @since [v1.0]
|
||||
* @param int $consumableId
|
||||
* @return array
|
||||
*/
|
||||
public function getDataView($consumableId)
|
||||
{
|
||||
//$consumable = Consumable::find($consumableID);
|
||||
$consumable = Consumable::with(array('consumableAssignments'=>
|
||||
function ($query) {
|
||||
$query->orderBy('created_at', 'DESC');
|
||||
},
|
||||
'consumableAssignments.admin'=> function ($query) {
|
||||
},
|
||||
'consumableAssignments.user'=> function ($query) {
|
||||
},
|
||||
))->find($consumableId);
|
||||
|
||||
// $consumable->load('consumableAssignments.admin','consumableAssignments.user');
|
||||
|
||||
if (!Company::isCurrentUserHasAccess($consumable)) {
|
||||
return ['total' => 0, 'rows' => []];
|
||||
}
|
||||
$this->authorize('view', Component::class);
|
||||
$rows = array();
|
||||
|
||||
foreach ($consumable->consumableAssignments as $consumable_assignment) {
|
||||
$rows[] = [
|
||||
'name' => $consumable_assignment->user->present()->nameUrl(),
|
||||
'created_at' => ($consumable_assignment->created_at->format('Y-m-d H:i:s')=='-0001-11-30 00:00:00') ? '' : $consumable_assignment->created_at->format('Y-m-d H:i:s'),
|
||||
'admin' => ($consumable_assignment->admin) ? $consumable_assignment->admin->present()->nameUrl() : '',
|
||||
];
|
||||
}
|
||||
|
||||
$consumableCount = $consumable->users->count();
|
||||
$data = array('total' => $consumableCount, 'rows' => $rows);
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Transformers\CustomFieldsTransformer;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\CustomFieldset;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class CustomFieldsController extends Controller
|
||||
{
|
||||
@@ -16,6 +18,15 @@ class CustomFieldsController extends Controller
|
||||
* @since [v3.0]
|
||||
* @return Array
|
||||
*/
|
||||
|
||||
public function index()
|
||||
{
|
||||
$this->authorize('index', CustomFields::class);
|
||||
$fields = CustomField::get();
|
||||
|
||||
$total = count($fields);
|
||||
return (new CustomFieldsTransformer)->transformCustomFields($fields, $total);
|
||||
}
|
||||
public function postReorder(Request $request, $id)
|
||||
{
|
||||
$fieldset = CustomFieldset::find($id);
|
||||
|
||||
@@ -99,16 +99,14 @@ class DepartmentsController extends Controller
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
if (is_null($department = Department::find($id))) {
|
||||
return redirect()->to(route('departments.index'))->with('error', trans('admin/departments/message.not_found'));
|
||||
}
|
||||
$department = Department::findOrFail($id);
|
||||
|
||||
if ($department->users->count() > 0) {
|
||||
return redirect()->to(route('departments.index'))->with('error', trans('admin/departments/message.assoc_users'));
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/departments/message.assoc_users')));
|
||||
}
|
||||
|
||||
$department->delete();
|
||||
return redirect()->to(route('departments.index'))->with('success', trans('admin/departments/message.delete.success'));
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/departments/message.delete.success')));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ class GroupsController extends Controller
|
||||
{
|
||||
$this->authorize('view', Group::class);
|
||||
$group = Group::findOrFail($id);
|
||||
return $group;
|
||||
return (new GroupsTransformer)->transformGroup($group);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ use Illuminate\Support\Facades\Input;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use League\Csv\Reader;
|
||||
use Symfony\Component\HttpFoundation\File\Exception\FileException;
|
||||
use Artisan;
|
||||
|
||||
class ImportController extends Controller
|
||||
{
|
||||
@@ -94,6 +95,8 @@ class ImportController extends Controller
|
||||
public function process(ItemImportRequest $request, $import_id)
|
||||
{
|
||||
$this->authorize('create', Asset::class);
|
||||
// Run a backup immediately before processing
|
||||
Artisan::call('backup:run');
|
||||
$errors = $request->import(Import::find($import_id));
|
||||
$redirectTo = "hardware.index";
|
||||
switch ($request->get('import-type')) {
|
||||
|
||||
@@ -21,7 +21,7 @@ class LicensesController extends Controller
|
||||
public function index(Request $request)
|
||||
{
|
||||
$this->authorize('view', License::class);
|
||||
$licenses = Company::scopeCompanyables(License::with('company', 'licenseSeatsRelation', 'manufacturer'));
|
||||
$licenses = Company::scopeCompanyables(License::with('company', 'licenseSeatsRelation', 'manufacturer', 'supplier'));
|
||||
|
||||
if ($request->has('search')) {
|
||||
$licenses = $licenses->TextSearch($request->input('search'));
|
||||
@@ -59,6 +59,10 @@ class LicensesController extends Controller
|
||||
$licenses->where('manufacturer_id','=',$request->input('manufacturer_id'));
|
||||
}
|
||||
|
||||
if ($request->has('supplier_id')) {
|
||||
$licenses->where('supplier_id','=',$request->input('supplier_id'));
|
||||
}
|
||||
|
||||
if ($request->has('depreciation_id')) {
|
||||
$licenses->where('depreciation_id','=',$request->input('depreciation_id'));
|
||||
}
|
||||
@@ -69,22 +73,26 @@ class LicensesController extends Controller
|
||||
|
||||
$offset = request('offset', 0);
|
||||
$limit = request('limit', 50);
|
||||
|
||||
$allowed_columns = ['id','name','purchase_cost','expiration_date','purchase_order','order_number','notes','purchase_date','serial','manufacturer','company','license_name','license_email'];
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
|
||||
|
||||
switch ($sort) {
|
||||
|
||||
switch ($request->input('sort')) {
|
||||
case 'manufacturer':
|
||||
$licenses = $licenses->OrderManufacturer($order);
|
||||
break;
|
||||
case 'supplier':
|
||||
$licenses = $licenses->OrderSupplier($order);
|
||||
break;
|
||||
case 'company':
|
||||
$licenses = $licenses->OrderCompany($order);
|
||||
break;
|
||||
default:
|
||||
$allowed_columns = ['id','name','purchase_cost','expiration_date','purchase_order','order_number','notes','purchase_date','serial','company','license_name','license_email'];
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
|
||||
$licenses = $licenses->orderBy($sort, $order);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
$total = $licenses->count();
|
||||
$licenses = $licenses->skip($offset)->take($limit)->get();
|
||||
|
||||
@@ -21,7 +21,7 @@ class LocationsController extends Controller
|
||||
{
|
||||
$this->authorize('view', Location::class);
|
||||
$allowed_columns = ['id','name','address','address2','city','state','country','zip','created_at',
|
||||
'updated_at','parent_id'];
|
||||
'updated_at','parent_id', 'manager_id'];
|
||||
|
||||
$locations = Location::select([
|
||||
'locations.id',
|
||||
@@ -33,6 +33,7 @@ class LocationsController extends Controller
|
||||
'locations.zip',
|
||||
'locations.country',
|
||||
'locations.parent_id',
|
||||
'locations.manager_id',
|
||||
'locations.created_at',
|
||||
'locations.updated_at',
|
||||
'locations.currency'
|
||||
|
||||
@@ -19,7 +19,7 @@ class ReportsController extends Controller
|
||||
public function index(Request $request)
|
||||
{
|
||||
|
||||
$actionlogs = Actionlog::with('item', 'user', 'target');
|
||||
$actionlogs = Actionlog::with('item', 'user', 'target','location');
|
||||
|
||||
if ($request->has('search')) {
|
||||
$actionlogs = $actionlogs->TextSearch(e($request->input('search')));
|
||||
@@ -36,6 +36,10 @@ class ReportsController extends Controller
|
||||
->where('item_type','=',"App\\Models\\".ucwords($request->input('item_type')));
|
||||
}
|
||||
|
||||
if ($request->has('action_type')) {
|
||||
$actionlogs = $actionlogs->where('action_type','=',$request->input('action_type'))->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
$allowed_columns = [
|
||||
'id',
|
||||
'created_at'
|
||||
|
||||
@@ -53,9 +53,20 @@ class StatuslabelsController extends Controller
|
||||
public function store(Request $request)
|
||||
{
|
||||
$this->authorize('create', Statuslabel::class);
|
||||
$request->except('deployable', 'pending','archived');
|
||||
|
||||
if (!$request->has('type')) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, ["type" => ["Status label type is required."]]));
|
||||
}
|
||||
|
||||
$statuslabel = new Statuslabel;
|
||||
$statuslabel->fill($request->all());
|
||||
|
||||
$statusType = Statuslabel::getStatuslabelTypesForDB($request->input('type'));
|
||||
$statuslabel->deployable = $statusType['deployable'];
|
||||
$statuslabel->pending = $statusType['pending'];
|
||||
$statuslabel->archived = $statusType['archived'];
|
||||
|
||||
if ($statuslabel->save()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $statuslabel, trans('admin/statuslabels/message.create.success')));
|
||||
}
|
||||
@@ -75,7 +86,7 @@ class StatuslabelsController extends Controller
|
||||
{
|
||||
$this->authorize('view', Statuslabel::class);
|
||||
$statuslabel = Statuslabel::findOrFail($id);
|
||||
return $statuslabel;
|
||||
return (new StatuslabelsTransformer)->transformStatuslabel($statuslabel);
|
||||
}
|
||||
|
||||
|
||||
@@ -92,8 +103,20 @@ class StatuslabelsController extends Controller
|
||||
{
|
||||
$this->authorize('edit', Statuslabel::class);
|
||||
$statuslabel = Statuslabel::findOrFail($id);
|
||||
|
||||
$request->except('deployable', 'pending','archived');
|
||||
|
||||
if (!$request->has('type')) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Status label type is required.'));
|
||||
}
|
||||
|
||||
$statuslabel->fill($request->all());
|
||||
|
||||
$statusType = Statuslabel::getStatuslabelTypesForDB($request->input('type'));
|
||||
$statuslabel->deployable = $statusType['deployable'];
|
||||
$statuslabel->pending = $statusType['pending'];
|
||||
$statuslabel->archived = $statusType['archived'];
|
||||
|
||||
if ($statuslabel->save()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $statuslabel, trans('admin/statuslabels/message.update.success')));
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ use App\Http\Transformers\UsersTransformer;
|
||||
use App\Models\Company;
|
||||
use App\Models\User;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Requests\SaveUserRequest;
|
||||
use App\Models\Asset;
|
||||
|
||||
class UsersController extends Controller
|
||||
{
|
||||
@@ -50,6 +52,12 @@ class UsersController extends Controller
|
||||
$users = $users->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
|
||||
if (($request->has('deleted')) && ($request->input('deleted')=='true')) {
|
||||
$users = $users->GetDeleted();
|
||||
}
|
||||
|
||||
|
||||
if ($request->has('company_id')) {
|
||||
$users = $users->where('company_id', '=', $request->input('company_id'));
|
||||
}
|
||||
@@ -102,7 +110,7 @@ class UsersController extends Controller
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
public function store(SaveUserRequest $request)
|
||||
{
|
||||
$this->authorize('view', User::class);
|
||||
$user = new User;
|
||||
@@ -139,7 +147,7 @@ class UsersController extends Controller
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(Request $request, $id)
|
||||
public function update(SaveUserRequest $request, $id)
|
||||
{
|
||||
$this->authorize('edit', User::class);
|
||||
$user = User::findOrFail($id);
|
||||
@@ -181,4 +189,19 @@ class UsersController extends Controller
|
||||
}
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.error.delete')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return JSON containing a list of assets assigned to a user.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v3.0]
|
||||
* @param $userId
|
||||
* @return string JSON
|
||||
*/
|
||||
public function assets($id)
|
||||
{
|
||||
$this->authorize('view', User::class);
|
||||
$assets = Asset::where('assigned_to', '=', $id)->with('model')->get();
|
||||
return response()->json($assets);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ class AssetModelsController extends Controller
|
||||
$model->manufacturer_id = $request->input('manufacturer_id');
|
||||
$model->category_id = $request->input('category_id');
|
||||
$model->notes = $request->input('notes');
|
||||
$model->user_id = Auth::guard('api')->user();
|
||||
$model->user_id = Auth::id();
|
||||
$model->requestable = Input::has('requestable');
|
||||
|
||||
if ($request->input('custom_fieldset')!='') {
|
||||
@@ -414,7 +414,7 @@ class AssetModelsController extends Controller
|
||||
$manufacturer_list = $nochange + Helper::manufacturerList();
|
||||
|
||||
|
||||
return view('models/bulk-edit', compact('models'))
|
||||
return view('models/bulk-edit', compact('models'))
|
||||
->with('manufacturer_list', $manufacturer_list)
|
||||
->with('category_list', $category_list)
|
||||
->with('fieldset_list', $fieldset_list)
|
||||
|
||||
@@ -116,9 +116,9 @@ class AssetsController extends Controller
|
||||
->with('statuslabel_list', Helper::statusLabelList())
|
||||
->with('location_list', Helper::locationsList())
|
||||
->with('item', new Asset)
|
||||
->with('manufacturer', Helper::manufacturerList())
|
||||
->with('category', Helper::categoryList('asset'))
|
||||
->with('statuslabel_types', Helper::statusTypeList())
|
||||
->with('manufacturer', Helper::manufacturerList()) //handled in modal now?
|
||||
->with('category', Helper::categoryList('asset')) //handled in modal now?
|
||||
->with('statuslabel_types', Helper::statusTypeList()) //handled in modal now?
|
||||
->with('users_list', Helper::usersList())
|
||||
->with('assets_list', Helper::assetsList())
|
||||
->with('locations_list', Helper::locationsList());
|
||||
@@ -412,6 +412,13 @@ class AssetsController extends Controller
|
||||
|
||||
$asset->delete();
|
||||
|
||||
$logaction = new Actionlog();
|
||||
$logaction->item_type = Asset::class;
|
||||
$logaction->item_id = $asset->id;
|
||||
$logaction->created_at = date("Y-m-d H:i:s");
|
||||
$logaction->user_id = Auth::user()->id;
|
||||
$log = $logaction->logaction('deleted');
|
||||
|
||||
// Redirect to the asset management page
|
||||
return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.delete.success'));
|
||||
}
|
||||
@@ -537,17 +544,18 @@ class AssetsController extends Controller
|
||||
$this->authorize('checkin', $asset);
|
||||
|
||||
$admin = Auth::user();
|
||||
$user = $asset->assignedUser;
|
||||
if($asset->assignedType() == Asset::USER) {
|
||||
$user = $asset->assignedTo;
|
||||
}
|
||||
if (is_null($target = $asset->assignedTo)) {
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkin.already_checked_in'));
|
||||
}
|
||||
|
||||
// This is just used for the redirect
|
||||
$return_to = $asset->assigned_to;
|
||||
$asset->expected_checkin = null;
|
||||
$asset->last_checkout = null;
|
||||
$asset->assigned_to = null;
|
||||
$asset->assignedTo()->disassociate($asset);
|
||||
$asset->assigned_type = null;
|
||||
$asset->accepted = null;
|
||||
$asset->name = e(Input::get('name'));
|
||||
|
||||
@@ -566,7 +574,7 @@ class AssetsController extends Controller
|
||||
$data['item_serial'] = $asset->serial;
|
||||
$data['note'] = $logaction->note;
|
||||
|
||||
if ((($asset->checkin_email()=='1')) && (isset($user)) && (!config('app.lock_passwords'))) {
|
||||
if ((($asset->checkin_email()=='1')) && (isset($user)) && (!empty($user->email)) && (!config('app.lock_passwords'))) {
|
||||
Mail::send('emails.checkin-asset', $data, function ($m) use ($user) {
|
||||
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
|
||||
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
|
||||
@@ -575,7 +583,7 @@ class AssetsController extends Controller
|
||||
}
|
||||
|
||||
if ($backto=='user') {
|
||||
return redirect()->to("admin/users/".$return_to.'/view')->with('success', trans('admin/hardware/message.checkin.success'));
|
||||
return redirect()->to("admin/users/".$user->id.'/view')->with('success', trans('admin/hardware/message.checkin.success'));
|
||||
}
|
||||
return redirect()->route("hardware.index")->with('success', trans('admin/hardware/message.checkin.success'));
|
||||
}
|
||||
@@ -595,9 +603,12 @@ class AssetsController extends Controller
|
||||
*/
|
||||
public function show($assetId = null)
|
||||
{
|
||||
|
||||
$asset = Asset::withTrashed()->find($assetId);
|
||||
$settings = Setting::getSettings();
|
||||
$this->authorize('view', $asset);
|
||||
$settings = Setting::getSettings();
|
||||
$audit_log = Actionlog::where('action_type','=','audit')->where('item_id','=',$assetId)->where('item_type','=',Asset::class)->orderBy('created_at','DESC')->first();
|
||||
|
||||
|
||||
if (isset($asset)) {
|
||||
|
||||
@@ -617,7 +628,8 @@ class AssetsController extends Controller
|
||||
'url' => route('qr_code/hardware', $asset->id)
|
||||
);
|
||||
|
||||
return view('hardware/view', compact('asset', 'qr_code', 'settings'))->with('use_currency', $use_currency);
|
||||
return view('hardware/view', compact('asset', 'qr_code', 'settings'))
|
||||
->with('use_currency', $use_currency)->with('audit_log',$audit_log);
|
||||
}
|
||||
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist', compact('id')));
|
||||
@@ -638,7 +650,7 @@ class AssetsController extends Controller
|
||||
if ($settings->qr_code == '1') {
|
||||
$asset = Asset::find($assetId);
|
||||
$size = Helper::barcodeDimensions($settings->barcode_type);
|
||||
$qr_file = public_path().'/uploads/barcodes/qr-'.str_slug($asset->asset_tag).'.png';
|
||||
$qr_file = public_path().'/uploads/barcodes/qr-'.str_slug($asset->asset_tag).'-'.str_slug($asset->id).'.png';
|
||||
|
||||
if (isset($asset->id,$asset->asset_tag)) {
|
||||
|
||||
@@ -953,7 +965,7 @@ class AssetsController extends Controller
|
||||
* @since [v1.0]
|
||||
* @return View
|
||||
*/
|
||||
public function getDeleteFile($assetId = null, $fileId = null)
|
||||
public function deleteFile($assetId = null, $fileId = null)
|
||||
{
|
||||
$asset = Asset::find($assetId);
|
||||
$this->authorize('update', $asset);
|
||||
@@ -1233,4 +1245,47 @@ class AssetsController extends Controller
|
||||
// Redirect to the asset management page with error
|
||||
return redirect()->to("hardware/bulk-checkout")->with('error', trans('admin/hardware/message.checkout.error'))->withErrors($errors);
|
||||
}
|
||||
|
||||
|
||||
public function quickScan(Request $request)
|
||||
{
|
||||
$this->authorize('audit', Asset::class);
|
||||
$dt = Carbon::now()->addMonths(12)->toDateString();
|
||||
return view('hardware/quickscan')->with('next_audit_date', $dt)->with('locations_list', Helper::locationsList());
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function audit(Request $request, $id)
|
||||
{
|
||||
$this->authorize('audit', Asset::class);
|
||||
$dt = Carbon::now()->addMonths(12)->toDateString();
|
||||
$asset = Asset::findOrFail($id);
|
||||
return view('hardware/audit')->with('asset', $asset)->with('next_audit_date', $dt)->with('locations_list', Helper::locationsList());
|
||||
}
|
||||
|
||||
public function auditStore(Request $request, $id)
|
||||
{
|
||||
$this->authorize('audit', Asset::class);
|
||||
|
||||
$rules = array(
|
||||
'location_id' => 'exists:locations,id|nullable|numeric',
|
||||
'next_audit_date' => 'date|nullable'
|
||||
);
|
||||
|
||||
$validator = \Validator::make($request->all(), $rules);
|
||||
if ($validator->fails()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $validator->errors()->all()));
|
||||
}
|
||||
|
||||
$asset = Asset::findOrFail($id);
|
||||
$asset->next_audit_date = $request->input('next_audit_date');
|
||||
|
||||
if ($asset->save()) {
|
||||
$asset->logAudit(request('note'),request('location_id'));
|
||||
return redirect()->to("hardware")->with('success', trans('admin/hardware/message.audit.success'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Foundation\Auth\ResetsPasswords;
|
||||
|
||||
class RegisterController extends Controller
|
||||
{
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('guest');
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ class ResetPasswordController extends Controller
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $redirectTo = '/home';
|
||||
protected $redirectTo = '/';
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
|
||||
@@ -74,20 +74,20 @@ class ComponentsController extends Controller
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store()
|
||||
public function store(Request $request)
|
||||
{
|
||||
$this->authorize('create', Component::class);
|
||||
$component = new Component();
|
||||
$component->name = Input::get('name');
|
||||
$component->category_id = Input::get('category_id');
|
||||
$component->location_id = Input::get('location_id');
|
||||
$component->company_id = Company::getIdForCurrentUser(Input::get('company_id'));
|
||||
$component->order_number = Input::get('order_number');
|
||||
$component->min_amt = Input::get('min_amt');
|
||||
$component->serial = Input::get('serial');
|
||||
$component->purchase_date = Input::get('purchase_date');
|
||||
$component->purchase_cost = request('purchase_cost');
|
||||
$component->qty = Input::get('qty');
|
||||
$component->name = $request->input('name');
|
||||
$component->category_id = $request->input('category_id');
|
||||
$component->location_id = $request->input('location_id');
|
||||
$component->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$component->order_number = $request->input('order_number', null);
|
||||
$component->min_amt = $request->input('min_amt', null);
|
||||
$component->serial = $request->input('serial', null);
|
||||
$component->purchase_date = $request->input('purchase_date', null);
|
||||
$component->purchase_cost = $request->input('purchase_cost', null);
|
||||
$component->qty = $request->input('qty');
|
||||
$component->user_id = Auth::id();
|
||||
|
||||
if ($component->save()) {
|
||||
@@ -283,7 +283,7 @@ class ComponentsController extends Controller
|
||||
'asset_id' => $asset_id
|
||||
]);
|
||||
|
||||
$component->logCheckout(e(Input::get('note')), $asset_id);
|
||||
$component->logCheckout(e(Input::get('note')), $asset);
|
||||
return redirect()->route('components.index')->with('success', trans('admin/components/message.checkout.success'));
|
||||
}
|
||||
|
||||
|
||||
@@ -250,7 +250,7 @@ class ConsumablesController extends Controller
|
||||
'assigned_to' => e(Input::get('assigned_to'))
|
||||
]);
|
||||
|
||||
$logaction = $consumable->logCheckout(e(Input::get('note')));
|
||||
$logaction = $consumable->logCheckout(e(Input::get('note')), $user);
|
||||
$data['log_id'] = $logaction->id;
|
||||
$data['eula'] = $consumable->getEula();
|
||||
$data['first_name'] = $user->first_name;
|
||||
@@ -273,47 +273,4 @@ class ConsumablesController extends Controller
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a JSON response containing details on the users associated with this consumable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ConsumablesController::getView() method that returns the form.
|
||||
* @since [v1.0]
|
||||
* @param int $consumableId
|
||||
* @return array
|
||||
*/
|
||||
public function getDataView($consumableId)
|
||||
{
|
||||
//$consumable = Consumable::find($consumableID);
|
||||
$consumable = Consumable::with(array('consumableAssigments'=>
|
||||
function ($query) {
|
||||
$query->orderBy('created_at', 'DESC');
|
||||
},
|
||||
'consumableAssigments.admin'=> function ($query) {
|
||||
},
|
||||
'consumableAssigments.user'=> function ($query) {
|
||||
},
|
||||
))->find($consumableId);
|
||||
|
||||
// $consumable->load('consumableAssigments.admin','consumableAssigments.user');
|
||||
|
||||
if (!Company::isCurrentUserHasAccess($consumable)) {
|
||||
return ['total' => 0, 'rows' => []];
|
||||
}
|
||||
$this->authorize('view', Component::class);
|
||||
$rows = array();
|
||||
|
||||
foreach ($consumable->consumableAssigments as $consumable_assignment) {
|
||||
$rows[] = [
|
||||
'name' => $consumable_assignment->user->present()->nameUrl(),
|
||||
'created_at' => ($consumable_assignment->created_at->format('Y-m-d H:i:s')=='-0001-11-30 00:00:00') ? '' : $consumable_assignment->created_at->format('Y-m-d H:i:s'),
|
||||
'admin' => ($consumable_assignment->admin) ? $consumable_assignment->admin->present()->nameUrl() : '',
|
||||
];
|
||||
}
|
||||
|
||||
$consumableCount = $consumable->users->count();
|
||||
$data = array('total' => $consumableCount, 'rows' => $rows);
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,19 +37,25 @@ class CustomFieldsetsController extends Controller
|
||||
public function show($id)
|
||||
{
|
||||
$cfset = CustomFieldset::with('fields')->where('id', '=', $id)->orderBy('id', 'ASC')->first();
|
||||
$custom_fields_list = ["" => "Add New Field to Fieldset"] + CustomField::pluck("name", "id")->toArray();
|
||||
|
||||
$maxid = 0;
|
||||
foreach ($cfset->fields() as $field) {
|
||||
if ($field->pivot->order > $maxid) {
|
||||
$maxid=$field->pivot->order;
|
||||
}
|
||||
if (isset($custom_fields_list[$field->id])) {
|
||||
unset($custom_fields_list[$field->id]);
|
||||
if ($cfset) {
|
||||
$custom_fields_list = ["" => "Add New Field to Fieldset"] + CustomField::pluck("name", "id")->toArray();
|
||||
|
||||
$maxid = 0;
|
||||
foreach ($cfset->fields() as $field) {
|
||||
if ($field->pivot->order > $maxid) {
|
||||
$maxid=$field->pivot->order;
|
||||
}
|
||||
if (isset($custom_fields_list[$field->id])) {
|
||||
unset($custom_fields_list[$field->id]);
|
||||
}
|
||||
}
|
||||
|
||||
return view("custom_fields.fieldsets.view")->with("custom_fieldset", $cfset)->with("maxid", $maxid+1)->with("custom_fields_list", $custom_fields_list);
|
||||
}
|
||||
|
||||
return view("custom_fields.fieldsets.view")->with("custom_fieldset", $cfset)->with("maxid", $maxid+1)->with("custom_fields_list", $custom_fields_list);
|
||||
return redirect()->route("fields.index")->with("error", trans('admin/custom_fields/message.fieldset.does_not_exist'));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -133,16 +139,21 @@ class CustomFieldsetsController extends Controller
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
//
|
||||
$fieldset = CustomFieldset::find($id);
|
||||
|
||||
$models = AssetModel::where("fieldset_id", "=", $id);
|
||||
if ($models->count() == 0) {
|
||||
$fieldset->delete();
|
||||
return redirect()->route("fields.show")->with("success", trans('admin/custom_fields/message.fieldset.delete.success'));
|
||||
} else {
|
||||
return redirect()->route("fields.show")->with("error", trans('admin/custom_fields/message.fieldset.delete.in_use'));
|
||||
if ($fieldset) {
|
||||
$models = AssetModel::where("fieldset_id", "=", $id);
|
||||
if ($models->count() == 0) {
|
||||
$fieldset->delete();
|
||||
return redirect()->route("fields.index")->with("success", trans('admin/custom_fields/message.fieldset.delete.success'));
|
||||
} else {
|
||||
return redirect()->route("fields.index")->with("error", trans('admin/custom_fields/message.fieldset.delete.in_use'));
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->route("fields.index")->with("error", trans('admin/custom_fields/message.fieldset.does_not_exist'));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -291,23 +291,23 @@ class LicensesController extends Controller
|
||||
// Ooops.. something went wrong
|
||||
return redirect()->back()->withInput()->withErrors($validator);
|
||||
}
|
||||
|
||||
$target = null;
|
||||
if ($assigned_to!='') {
|
||||
// Check if the user exists
|
||||
if (is_null($is_assigned_to = User::find($assigned_to))) {
|
||||
if (is_null($target = User::find($assigned_to))) {
|
||||
// Redirect to the asset management page with error
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.user_does_not_exist'));
|
||||
}
|
||||
}
|
||||
|
||||
if ($asset_id!='') {
|
||||
if (is_null($asset = Asset::find($asset_id))) {
|
||||
if (is_null($target = Asset::find($asset_id))) {
|
||||
// Redirect to the asset management page with error
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.asset_does_not_exist'));
|
||||
}
|
||||
|
||||
if (($asset->assigned_to!='') && (($asset->assigned_to!=$assigned_to)) && ($assigned_to!='')) {
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.owner_doesnt_match_asset'));
|
||||
if (($request->has('assigned_to')) && ($request->has('asset_id'))) {
|
||||
return redirect()->back()->withInput()->with('error', trans('admin/licenses/message.select_asset_or_person'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,7 +332,7 @@ class LicensesController extends Controller
|
||||
|
||||
// Was the asset updated?
|
||||
if ($licenseSeat->save()) {
|
||||
$licenseSeat->logCheckout($request->input('note'));
|
||||
$licenseSeat->logCheckout($request->input('note'), $target);
|
||||
|
||||
$data['license_id'] =$licenseSeat->license_id;
|
||||
$data['note'] = $request->input('note');
|
||||
@@ -440,7 +440,10 @@ class LicensesController extends Controller
|
||||
*/
|
||||
public function show($licenseId = null)
|
||||
{
|
||||
|
||||
$license = License::find($licenseId);
|
||||
$license = $license->load('assignedusers', 'licenseSeats.user', 'licenseSeats.asset');
|
||||
|
||||
if (isset($license->id)) {
|
||||
$license = $license->load('assignedusers', 'licenseSeats.user', 'licenseSeats.asset');
|
||||
$this->authorize('view', $license);
|
||||
|
||||
@@ -63,7 +63,8 @@ class LocationsController extends Controller
|
||||
|
||||
return view('locations/edit')
|
||||
->with('location_options', $location_options)
|
||||
->with('item', new Location);
|
||||
->with('item', new Location)
|
||||
->with('manager_list', Helper::managerList());
|
||||
}
|
||||
|
||||
|
||||
@@ -88,6 +89,7 @@ class LocationsController extends Controller
|
||||
$location->state = Input::get('state');
|
||||
$location->country = Input::get('country');
|
||||
$location->zip = Input::get('zip');
|
||||
$location->manager_id = Input::get('manager_id');
|
||||
$location->user_id = Auth::id();
|
||||
|
||||
if ($location->save()) {
|
||||
@@ -154,7 +156,10 @@ class LocationsController extends Controller
|
||||
$location_options = Location::flattenLocationsArray($location_options_array);
|
||||
$location_options = array('' => 'Top Level') + $location_options;
|
||||
|
||||
return view('locations/edit', compact('item'))->with('location_options', $location_options);
|
||||
|
||||
return view('locations/edit', compact('item'))
|
||||
->with('location_options', $location_options)
|
||||
->with('manager_list', Helper::managerList());
|
||||
}
|
||||
|
||||
|
||||
@@ -185,6 +190,7 @@ class LocationsController extends Controller
|
||||
$location->country = Input::get('country');
|
||||
$location->zip = Input::get('zip');
|
||||
$location->ldap_ou = Input::get('ldap_ou');
|
||||
$location->manager_id = Input::get('manager_id');
|
||||
|
||||
// Was the location updated?
|
||||
if ($location->save()) {
|
||||
@@ -232,8 +238,6 @@ class LocationsController extends Controller
|
||||
* the content for the locations detail page.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see LocationsController::getDataViewUsers() method that returns JSON for location users
|
||||
* @see LocationsController::getDataViewAssets() method that returns JSON for location assets
|
||||
* @param int $locationId
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
@@ -252,78 +256,4 @@ class LocationsController extends Controller
|
||||
return redirect()->route('locations.index')->with('error', $error);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a JSON response that contains the users association with the
|
||||
* selected location, to be used by the location detail view.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see LocationsController::getView() method that creates the display view
|
||||
* @param $locationID
|
||||
* @return array
|
||||
* @internal param int $locationId
|
||||
* @since [v1.8]
|
||||
*/
|
||||
public function getDataViewUsers($locationID)
|
||||
{
|
||||
$location = Location::find($locationID);
|
||||
$users = User::where('location_id', '=', $location->id);
|
||||
|
||||
if (Input::has('search')) {
|
||||
$users = $users->TextSearch(e(Input::get('search')));
|
||||
}
|
||||
|
||||
$users = $users->get();
|
||||
$rows = array();
|
||||
|
||||
foreach ($users as $user) {
|
||||
$rows[] = array(
|
||||
'name' => (string)link_to_route('users.show', e($user->present()->fullName()), ['user'=>$user->id])
|
||||
);
|
||||
}
|
||||
|
||||
$data = array('total' => $users->count(), 'rows' => $rows);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a JSON response that contains the assets association with the
|
||||
* selected location, to be used by the location detail view.
|
||||
*
|
||||
* @todo This is broken for accessories and consumables.
|
||||
* @todo This is a very naive implementation. Should clean this up with query scopes.
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see LocationsController::getView() method that creates the display view
|
||||
* @param int $locationID
|
||||
* @since [v1.8]
|
||||
* @return array
|
||||
*/
|
||||
public function getDataViewAssets($locationID)
|
||||
{
|
||||
$location = Location::find($locationID)->load('assignedassets.model');
|
||||
$assets = Asset::AssetsByLocation($location);
|
||||
|
||||
if (Input::has('search')) {
|
||||
$assets = $assets->TextSearch(e(Input::get('search')));
|
||||
}
|
||||
|
||||
$assets = $assets->get();
|
||||
|
||||
$rows = array();
|
||||
|
||||
foreach ($assets as $asset) {
|
||||
$rows[] = [
|
||||
'name' => (string)link_to_route('hardware.show', e($asset->present()->name()), ['hardware' => $asset->id]),
|
||||
'asset_tag' => e($asset->asset_tag),
|
||||
'serial' => e($asset->serial),
|
||||
'model' => e($asset->model->name),
|
||||
];
|
||||
}
|
||||
|
||||
$data = array('total' => $assets->count(), 'rows' => $rows);
|
||||
return $data;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
|
||||
class ModalController extends Controller
|
||||
{
|
||||
function location() {
|
||||
return view('modals.location');
|
||||
}
|
||||
|
||||
function model() {
|
||||
return view('modals.model')
|
||||
->with('manufacturer', Helper::manufacturerList())
|
||||
->with('category', Helper::categoryList('asset'));
|
||||
}
|
||||
|
||||
function statuslabel() {
|
||||
return view('modals.statuslabel')->with('statuslabel_types', Helper::statusTypeList());
|
||||
}
|
||||
|
||||
function supplier() {
|
||||
return view('modals.supplier');
|
||||
}
|
||||
|
||||
function user() {
|
||||
return view('modals.user');
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,13 @@ namespace App\Http\Controllers;
|
||||
use Image;
|
||||
use Input;
|
||||
use Redirect;
|
||||
use App\Models\Location;
|
||||
use View;
|
||||
use Auth;
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Setting;
|
||||
use Gate;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to User Profiles for
|
||||
@@ -87,4 +88,60 @@ class ProfileController extends Controller
|
||||
public function api() {
|
||||
return view('account/api');
|
||||
}
|
||||
|
||||
/**
|
||||
* User change email page.
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function password()
|
||||
{
|
||||
$user = Auth::user();
|
||||
return view('account/change-password', compact('user'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Users change password form processing page.
|
||||
*
|
||||
* @return Redirect
|
||||
*/
|
||||
public function passwordSave(Request $request)
|
||||
{
|
||||
|
||||
if (config('app.lock_passwords')) {
|
||||
return redirect()->route('account.password.index')->with('error', Lang::get('admin/users/table.lock_passwords'));
|
||||
}
|
||||
|
||||
$user = Auth::user();
|
||||
if ($user->ldap_import=='1') {
|
||||
return redirect()->route('account.password.index')->with('error', Lang::get('admin/users/message.error.password_ldap'));
|
||||
}
|
||||
|
||||
$rules = array(
|
||||
'current_password' => 'required',
|
||||
'password' => Setting::passwordComplexityRulesSaving('store'),
|
||||
'password_confirm' => 'required|same:password',
|
||||
);
|
||||
|
||||
$validator = \Validator::make($request->all(), $rules);
|
||||
$validator->after(function($validator) use ($request, $user) {
|
||||
|
||||
if (!Hash::check($request->input('current_password'), $user->password)) {
|
||||
$validator->errors()->add('current_password', trans('validation.hashed_pass'));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
if (!$validator->fails()) {
|
||||
$user->password = Hash::make($request->input('password'));
|
||||
$user->save();
|
||||
return redirect()->route('account.password.index')->with('success', 'Password updated!');
|
||||
|
||||
}
|
||||
return redirect()->back()->withInput()->withErrors($validator);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ class ReportsController extends Controller
|
||||
{
|
||||
|
||||
// Grab all the assets
|
||||
$assets = Asset::with('model', 'assignedTo', 'assetstatus', 'defaultLoc', 'assetlog', 'company')
|
||||
$assets = Asset::with( 'assignedTo', 'assetstatus', 'defaultLoc', 'assetloc', 'assetlog', 'company', 'model.category', 'model.depreciation')
|
||||
->orderBy('created_at', 'DESC')->get();
|
||||
|
||||
return view('reports/depreciation', compact('assets'));
|
||||
@@ -271,6 +271,20 @@ class ReportsController extends Controller
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Displays audit report.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0]
|
||||
* @return View
|
||||
*/
|
||||
public function audit()
|
||||
{
|
||||
return view('reports/audit');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Displays activity report.
|
||||
*
|
||||
@@ -376,7 +390,7 @@ class ReportsController extends Controller
|
||||
*/
|
||||
public function postCustom()
|
||||
{
|
||||
$assets = Asset::orderBy('created_at', 'DESC')->with('company', 'assigneduser', 'assetloc', 'defaultLoc', 'assigneduser.userloc', 'model', 'supplier', 'assetstatus', 'model.manufacturer')->get();
|
||||
$assets = Asset::orderBy('created_at', 'DESC')->with('company', 'assignedTo', 'assetloc', 'defaultLoc', 'model', 'supplier', 'assetstatus', 'model.manufacturer')->get();
|
||||
$customfields = CustomField::get();
|
||||
|
||||
$rows = [ ];
|
||||
@@ -449,7 +463,7 @@ class ReportsController extends Controller
|
||||
}
|
||||
|
||||
if (e(Input::get('notes')) == '1') {
|
||||
$header[] = 'Notes';
|
||||
$header[] = trans('general.notes');
|
||||
}
|
||||
|
||||
|
||||
@@ -538,8 +552,8 @@ class ReportsController extends Controller
|
||||
|
||||
if (e(Input::get('username')) == '1') {
|
||||
// Only works if we're checked out to a user, not anything else.
|
||||
if ($asset->assigneduser) {
|
||||
$row[] = '"' .e($asset->assigneduser->username). '"';
|
||||
if ($asset->checkedOutToUser()) {
|
||||
$row[] = '"' .e($asset->assignedTo->username). '"';
|
||||
} else {
|
||||
$row[] = ''; // Empty string if unassigned
|
||||
}
|
||||
@@ -547,8 +561,8 @@ class ReportsController extends Controller
|
||||
|
||||
if (e(Input::get('employee_num')) == '1') {
|
||||
// Only works if we're checked out to a user, not anything else.
|
||||
if ($asset->assigneduser) {
|
||||
$row[] = '"' .e($asset->assigneduser->employee_num). '"';
|
||||
if ($asset->checkedOutToUser()) {
|
||||
$row[] = '"' .e($asset->assignedTo->employee_num). '"';
|
||||
} else {
|
||||
$row[] = ''; // Empty string if unassigned
|
||||
}
|
||||
@@ -590,9 +604,9 @@ class ReportsController extends Controller
|
||||
|
||||
if (e(Input::get('notes')) == '1') {
|
||||
if ($asset->notes) {
|
||||
$row[] = '"' .$asset->notes. '"';
|
||||
$row[] = '"' .$asset->notes . '"';
|
||||
} else {
|
||||
$row[] = ''; // Empty string if unassigned
|
||||
$row[] = '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ use Auth;
|
||||
use App\Models\User;
|
||||
use App\Http\Requests\SetupUserRequest;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Http\Requests\SettingsLdapRequest;
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to Settings for
|
||||
@@ -184,6 +185,7 @@ class SettingsController extends Controller
|
||||
$settings->site_name = e(Input::get('site_name'));
|
||||
$settings->alert_email = e(Input::get('email'));
|
||||
$settings->alerts_enabled = 1;
|
||||
$settings->pwd_secure_min = 10;
|
||||
$settings->brand = 1;
|
||||
$settings->locale = 'en';
|
||||
$settings->default_currency = 'USD';
|
||||
@@ -259,6 +261,13 @@ class SettingsController extends Controller
|
||||
Artisan::call('migrate', ['--force' => true]);
|
||||
|
||||
$output = Artisan::output();
|
||||
|
||||
if ((!file_exists(storage_path().'/oauth-private.key')) || (!file_exists(storage_path().'/oauth-public.key'))) {
|
||||
Artisan::call('passport:install');
|
||||
Artisan::call('migrate', ['--force' => true]);
|
||||
}
|
||||
|
||||
|
||||
return view('setup/migrate')
|
||||
->with('output', $output)
|
||||
->with('step', 2)
|
||||
@@ -329,7 +338,10 @@ class SettingsController extends Controller
|
||||
$setting->email_format = $request->input('email_format');
|
||||
$setting->username_format = $request->input('username_format');
|
||||
$setting->require_accept_signature = $request->input('require_accept_signature');
|
||||
$setting->login_note = $request->input('login_note');
|
||||
if (!config('app.lock_passwords')) {
|
||||
$setting->login_note = $request->input('login_note');
|
||||
}
|
||||
|
||||
$setting->default_eula_text = $request->input('default_eula_text');
|
||||
$setting->thumbnail_max_h = $request->input('thumbnail_max_h');
|
||||
|
||||
@@ -462,6 +474,15 @@ class SettingsController extends Controller
|
||||
|
||||
}
|
||||
|
||||
$setting->pwd_secure_uncommon = (int) $request->input('pwd_secure_uncommon');
|
||||
$setting->pwd_secure_min = (int) $request->input('pwd_secure_min');
|
||||
$setting->pwd_secure_complexity = '';
|
||||
|
||||
if ($request->has('pwd_secure_complexity')) {
|
||||
$setting->pwd_secure_complexity = implode('|', $request->input('pwd_secure_complexity'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ($setting->save()) {
|
||||
return redirect()->route('settings.index')
|
||||
@@ -545,10 +566,12 @@ class SettingsController extends Controller
|
||||
$alert_email = rtrim($request->input('alert_email'), ',');
|
||||
$alert_email = trim($alert_email);
|
||||
|
||||
$setting->alert_email = e($alert_email);
|
||||
$setting->alert_email = $alert_email;
|
||||
$setting->alerts_enabled = $request->input('alerts_enabled', '0');
|
||||
$setting->alert_interval = $request->input('alert_interval');
|
||||
$setting->alert_threshold = $request->input('alert_threshold');
|
||||
$setting->audit_interval = $request->input('audit_interval');
|
||||
$setting->audit_warning_days = $request->input('audit_warning_days');
|
||||
|
||||
if ($setting->save()) {
|
||||
return redirect()->route('settings.index')
|
||||
@@ -972,6 +995,8 @@ class SettingsController extends Controller
|
||||
{
|
||||
if (!config('app.lock_passwords')) {
|
||||
if (Input::get('confirm_purge')=='DELETE') {
|
||||
// Run a backup immediately before processing
|
||||
Artisan::call('backup:run');
|
||||
Artisan::call('snipeit:purge', ['--force'=>'true','--no-interaction'=>true]);
|
||||
$output = Artisan::output();
|
||||
return view('settings/purge')
|
||||
|
||||
@@ -12,9 +12,7 @@ use App\Models\Company;
|
||||
use App\Models\Location;
|
||||
use App\Models\License;
|
||||
use App\Models\Setting;
|
||||
use App\Models\Statuslabel;
|
||||
use App\Http\Requests\SaveUserRequest;
|
||||
use App\Http\Requests\UpdateUserRequest;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
use App\Models\User;
|
||||
use App\Models\Ldap;
|
||||
@@ -23,7 +21,6 @@ use Config;
|
||||
use Crypt;
|
||||
use DB;
|
||||
use HTML;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Input;
|
||||
use Lang;
|
||||
use League\Csv\Reader;
|
||||
@@ -169,7 +166,7 @@ class UsersController extends Controller
|
||||
* @since [v1.8]
|
||||
* @return string JSON
|
||||
*/
|
||||
public function apiStore(Request $request)
|
||||
public function apiStore(SaveUserRequest $request)
|
||||
{
|
||||
$this->authorize('create', User::class);
|
||||
|
||||
@@ -270,7 +267,7 @@ class UsersController extends Controller
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(UpdateUserRequest $request, $id = null)
|
||||
public function update(SaveUserRequest $request, $id = null)
|
||||
{
|
||||
// We need to reverse the UI specific logic for our
|
||||
// permissions here before we update the user.
|
||||
@@ -309,14 +306,11 @@ class UsersController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
// Do we want to update the user password?
|
||||
if ($request->has('password')) {
|
||||
$user->password = bcrypt($request->input('password'));
|
||||
}
|
||||
|
||||
if ($request->has('username')) {
|
||||
$user->username = e($request->input('username'));
|
||||
$user->username = $request->input('username');
|
||||
}
|
||||
$user->email = e($request->input('email'));
|
||||
$user->email = $request->input('email');
|
||||
|
||||
|
||||
// Update the user
|
||||
@@ -334,6 +328,12 @@ class UsersController extends Controller
|
||||
$user->notes = $request->input('notes');
|
||||
$user->department_id = $request->input('department_id', null);
|
||||
|
||||
|
||||
// Do we want to update the user password?
|
||||
if ($request->has('password')) {
|
||||
$user->password = bcrypt($request->input('password'));
|
||||
}
|
||||
|
||||
// Strip out the superuser permission if the user isn't a superadmin
|
||||
$permissions_array = $request->input('permission');
|
||||
|
||||
@@ -370,15 +370,20 @@ class UsersController extends Controller
|
||||
// Authorize takes care of many of our logic checks now.
|
||||
$this->authorize('delete', User::class);
|
||||
|
||||
if ($user->assets()->count() > 0) {
|
||||
// Check if we are not trying to delete ourselves
|
||||
if ($user->id === Auth::user()->id) {
|
||||
// Redirect to the user management page
|
||||
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->assets()->count() . ' assets associated with them.');
|
||||
}
|
||||
|
||||
if ($user->licenses()->count() > 0) {
|
||||
|
||||
if (count($user->assets) > 0) {
|
||||
// Redirect to the user management page
|
||||
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->licenses()->count() . ' licenses associated with them.');
|
||||
return redirect()->route('users.index')->with('error', 'This user still has ' . count($user->assets) . ' assets associated with them.');
|
||||
}
|
||||
|
||||
if ($user->licenses()->count() > 0) {
|
||||
// Redirect to the user management page
|
||||
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->assets()->count() . ' assets associated with them.');
|
||||
}
|
||||
|
||||
if ($user->accessories()->count() > 0) {
|
||||
@@ -386,6 +391,11 @@ class UsersController extends Controller
|
||||
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->accessories()->count() . ' accessories associated with them.');
|
||||
}
|
||||
|
||||
if ($user->managedLocations()->count() > 0) {
|
||||
// Redirect to the user management page
|
||||
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->managedLocations()->count() . ' locations that they manage.');
|
||||
}
|
||||
|
||||
// Delete the user
|
||||
$user->delete();
|
||||
|
||||
@@ -528,10 +538,7 @@ class UsersController extends Controller
|
||||
if (($key = array_search(Auth::user()->id, $user_raw_array)) !== false) {
|
||||
unset($user_raw_array[$key]);
|
||||
}
|
||||
|
||||
if (!Auth::user()->isSuperUser()) {
|
||||
return redirect()->route('users.index')->with('error', trans('admin/users/message.insufficient_permissions'));
|
||||
}
|
||||
|
||||
|
||||
if (!config('app.lock_passwords')) {
|
||||
|
||||
@@ -832,7 +839,6 @@ class UsersController extends Controller
|
||||
'permissions' => '{"user":1}',
|
||||
'notes' => 'Imported user'
|
||||
);
|
||||
//dd($newuser);
|
||||
|
||||
DB::table('users')->insert($newuser);
|
||||
|
||||
@@ -924,7 +930,6 @@ class UsersController extends Controller
|
||||
$user = User::find($userId);
|
||||
$destinationPath = config('app.private_uploads').'/users';
|
||||
|
||||
// the license is valid
|
||||
if (isset($user->id)) {
|
||||
$this->authorize('update', $user);
|
||||
$log = Actionlog::find($fileId);
|
||||
@@ -1147,21 +1152,7 @@ class UsersController extends Controller
|
||||
}
|
||||
return redirect()->route('ldap/user')->with('success', "LDAP Import successful.")->with('summary', $summary);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return JSON containing a list of assets assigned to a user.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v3.0]
|
||||
* @param $userId
|
||||
* @return string JSON
|
||||
*/
|
||||
public function getAssetList($userId)
|
||||
{
|
||||
$this->authorize('view', User::class);
|
||||
$assets = Asset::where('assigned_to', '=', $userId)->with('model')->get();
|
||||
return response()->json($assets);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Exports users to CSV
|
||||
|
||||
@@ -68,8 +68,8 @@ class ViewAssetsController extends Controller
|
||||
public function getRequestableIndex()
|
||||
{
|
||||
|
||||
$assets = Asset::with('model', 'defaultLoc', 'assetloc', 'assignedTo')->Hardware()->RequestableAssets()->get();
|
||||
$models = AssetModel::with('category')->RequestableModels()->get();
|
||||
$assets = Asset::with('model', 'defaultLoc', 'assetloc', 'assignedTo', 'requests')->Hardware()->RequestableAssets()->get();
|
||||
$models = AssetModel::with('category', 'requests', 'assets')->RequestableModels()->get();
|
||||
|
||||
return view('account/requestable-assets', compact('user', 'assets', 'models'));
|
||||
}
|
||||
|
||||
@@ -19,10 +19,12 @@ class Kernel extends HttpKernel
|
||||
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
||||
\App\Http\Middleware\FrameGuard::class,
|
||||
\App\Http\Middleware\XssProtectHeader::class,
|
||||
\App\Http\Middleware\ReferrerPolicyHeader::class,
|
||||
\App\Http\Middleware\NosniffGuard::class,
|
||||
\App\Http\Middleware\CheckForSetup::class,
|
||||
\Fideloper\Proxy\TrustProxies::class,
|
||||
\App\Http\Middleware\CheckForDebug::class,
|
||||
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
|
||||
class ReferrerPolicyHeader
|
||||
{
|
||||
/**
|
||||
* Handle the given request and get the response.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
$response = $next($request);
|
||||
$response->headers->set('Referrer-Policy', config('app.referrer_policy'));
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
@@ -14,8 +14,9 @@ class XssProtectHeader
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
$mode = '1;mode=block';
|
||||
$response = $next($request);
|
||||
$response->headers->set('X-XSS-Protection', '1');
|
||||
$response->headers->set('X-XSS-Protection', $mode);
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Models\Setting;
|
||||
|
||||
class SaveUserRequest extends Request
|
||||
{
|
||||
@@ -23,12 +24,38 @@ class SaveUserRequest extends Request
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'first_name' => 'required|string|min:1',
|
||||
'email' => 'email',
|
||||
'password' => 'required|min:6',
|
||||
'password_confirm' => 'sometimes|required_with:password',
|
||||
'username' => 'required|string|min:2|unique:users,username,NULL,deleted_at',
|
||||
];
|
||||
|
||||
$rules = [];
|
||||
|
||||
switch($this->method())
|
||||
{
|
||||
|
||||
// Brand new asset
|
||||
case 'POST':
|
||||
{
|
||||
$rules['first_name'] = 'required|string|min:1';
|
||||
$rules['username'] = 'required_unless:ldap_import,1|string|min:1';
|
||||
$rules['password'] = Setting::passwordComplexityRulesSaving('store');
|
||||
}
|
||||
|
||||
// Save all fields
|
||||
case 'PUT':
|
||||
$rules['first_name'] = 'required|string|min:1';
|
||||
$rules['username'] = 'required_unless:ldap_import,1|string|min:1';
|
||||
$rules['password'] = Setting::passwordComplexityRulesSaving('update');
|
||||
|
||||
// Save only what's passed
|
||||
case 'PATCH':
|
||||
{
|
||||
$rules['password'] = Setting::passwordComplexityRulesSaving('update');
|
||||
}
|
||||
|
||||
default:break;
|
||||
}
|
||||
|
||||
$rules['password_confirm'] = 'sometimes|required_with:password';
|
||||
|
||||
return $rules;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use Session;
|
||||
|
||||
class SettingsLdapRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
$rules = [
|
||||
"ldap_server" => 'sometimes|required_if:ldap_enabled,1|url|nullable',
|
||||
"ldap_uname" => 'sometimes|required_if:ldap_enabled,1|nullable',
|
||||
"ldap_basedn" => 'sometimes|required_if:ldap_enabled,1|nullable',
|
||||
"ldap_filter" => 'sometimes|required_if:ldap_enabled,1|nullable',
|
||||
"ldap_username_field" => 'sometimes|required_if:ldap_enabled,1|nullable',
|
||||
"ldap_fname_field" => 'sometimes|required_if:ldap_enabled,1|nullable',
|
||||
"ldap_lname_field" => 'sometimes|required_if:ldap_enabled,1|nullable',
|
||||
"ldap_auth_filter_query" => 'sometimes|required_if:ldap_enabled,1|nullable',
|
||||
"ldap_version" => 'sometimes|required_if:ldap_enabled,1|nullable',
|
||||
];
|
||||
|
||||
return $rules;
|
||||
|
||||
}
|
||||
|
||||
public function response(array $errors)
|
||||
{
|
||||
$this->session()->flash('errors', Session::get('errors', new \Illuminate\Support\ViewErrorBag)
|
||||
->put('default', new \Illuminate\Support\MessageBag($errors)));
|
||||
\Input::flash();
|
||||
return parent::response($errors);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
|
||||
class UpdateUserRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'first_name' => 'required|string|min:1',
|
||||
'email' => 'email',
|
||||
'password_confirm' => 'sometimes|required_with:password',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -59,13 +59,30 @@ class AccessoriesTransformer
|
||||
}
|
||||
|
||||
|
||||
public function transformCheckedoutAccessories (Collection $accessories_users, $total)
|
||||
public function transformCheckedoutAccessory (Accessory $accessory, $total)
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
$array = array();
|
||||
foreach ($accessories_users as $user) {
|
||||
$array[] = (new UsersTransformer)->transformUser($user);
|
||||
foreach ($accessory->users as $user) {
|
||||
$array[] = [
|
||||
'assigned_pivot_id' => $user->pivot->id,
|
||||
'id' => (int) $user->id,
|
||||
'username' => e($user->username),
|
||||
'name' => e($user->getFullNameAttribute()),
|
||||
'first_name'=> e($user->first_name),
|
||||
'last_name'=> e($user->last_name),
|
||||
'employee_number' => e($user->employee_num),
|
||||
'type' => 'user',
|
||||
'available_actions' => ['checkin' => true]
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return (new DatatablesTransformer)->transformDatatables($array, $total);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
namespace App\Http\Transformers;
|
||||
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Setting;
|
||||
use Gate;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use App\Helpers\Helper;
|
||||
@@ -12,23 +13,32 @@ class ActionlogsTransformer
|
||||
public function transformActionlogs (Collection $actionlogs, $total)
|
||||
{
|
||||
$array = array();
|
||||
$settings = Setting::getSettings();
|
||||
foreach ($actionlogs as $actionlog) {
|
||||
$array[] = self::transformActionlog($actionlog);
|
||||
$array[] = self::transformActionlog($actionlog, $settings);
|
||||
}
|
||||
return (new DatatablesTransformer)->transformDatatables($array, $total);
|
||||
}
|
||||
|
||||
public function transformActionlog (Actionlog $actionlog)
|
||||
public function transformActionlog (Actionlog $actionlog, $settings = null)
|
||||
{
|
||||
$array = [
|
||||
'id' => (int) $actionlog->id,
|
||||
'icon' => $actionlog->present()->icon(),
|
||||
'image' => (method_exists($actionlog->item, 'getImageUrl')) ? $actionlog->item->getImageUrl() : null,
|
||||
'item' => ($actionlog->item) ? [
|
||||
'id' => (int) $actionlog->item->id,
|
||||
'name' => e($actionlog->item->getDisplayNameAttribute()),
|
||||
'type' => e($actionlog->itemType()),
|
||||
] : null,
|
||||
'location' => ($actionlog->location) ? [
|
||||
'id' => (int) $actionlog->location->id,
|
||||
'name' => e($actionlog->location->name)
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($actionlog->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($actionlog->updated_at, 'datetime'),
|
||||
'next_audit_date' => ($actionlog->itemType()=='asset') ? Helper::getFormattedDateObject($actionlog->calcNextAuditDate(), 'date'): null,
|
||||
'days_to_next_audit' => $actionlog->daysUntilNextAudit($settings->audit_interval, $actionlog->item),
|
||||
'action_type' => $actionlog->present()->actionType(),
|
||||
'admin' => ($actionlog->user) ? [
|
||||
'id' => (int) $actionlog->user->id,
|
||||
@@ -42,7 +52,8 @@ class ActionlogsTransformer
|
||||
'type' => e($actionlog->targetType()),
|
||||
] : null,
|
||||
|
||||
'note' => e($actionlog->note),
|
||||
'note' => ($actionlog->note) ? e($actionlog->note): null,
|
||||
'signature_file' => ($actionlog->accept_signature) ? route('log.signature.view', ['filename' => $actionlog->accept_signature ]) : null,
|
||||
|
||||
|
||||
];
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
namespace App\Http\Transformers;
|
||||
|
||||
use App\Models\AssetMaintenance;
|
||||
use Gate;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use App\Helpers\Helper;
|
||||
|
||||
class AssetMaintenancesTransformer
|
||||
{
|
||||
|
||||
public function transformAssetMaintenances (Collection $assetmaintenances, $total)
|
||||
{
|
||||
$array = array();
|
||||
foreach ($assetmaintenances as $assetmaintenance) {
|
||||
$array[] = self::transformAssetMaintenance($assetmaintenance);
|
||||
}
|
||||
return (new DatatablesTransformer)->transformDatatables($array, $total);
|
||||
}
|
||||
|
||||
public function transformAssetMaintenance (AssetMaintenance $assetmaintenance)
|
||||
{
|
||||
$array = [
|
||||
'id' => (int) $assetmaintenance->id,
|
||||
'asset_name' => ($assetmaintenance->asset) ? ['id' => $assetmaintenance->asset->id,'name'=> e($assetmaintenance->asset->name)] : null,
|
||||
'title' => ($assetmaintenance->title) ? e($assetmaintenance->title) : null,
|
||||
'notes' => ($assetmaintenance->notes) ? e($assetmaintenance->notes) : null,
|
||||
'supplier' => ($assetmaintenance->supplier) ? ['id' => $assetmaintenance->supplier->id,'name'=> e($assetmaintenance->supplier->name)] : null,
|
||||
'cost' => Helper::formatCurrencyOutput($assetmaintenance->cost),
|
||||
'asset_maintenance_type' => e($assetmaintenance->asset_maintenance_type),
|
||||
'start_date' => Helper::getFormattedDateObject($assetmaintenance->start_date, 'datetime'),
|
||||
'asset_maintenance_time' => $assetmaintenance->asset_maintenance_time,
|
||||
'completion_date' => Helper::getFormattedDateObject($assetmaintenance->completion_date, 'datetime'),
|
||||
'user_id' => ($assetmaintenance->admin) ? ['id' => $assetmaintenance->admin->id,'name'=> e($assetmaintenance->admin->getFullNameAttribute())] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($assetmaintenance->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($assetmaintenance->updated_at, 'datetime'),
|
||||
|
||||
];
|
||||
|
||||
$permissions_array['available_actions'] = [
|
||||
'update' => (bool) Gate::allows('update', Asset::class),
|
||||
'delete' => (bool) Gate::allows('delete', Asset::class),
|
||||
];
|
||||
|
||||
$array += $permissions_array;
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -33,7 +33,8 @@ class AssetsTransformer
|
||||
'model_number' => ($asset->model) ? e($asset->model->model_number) : null,
|
||||
'status_label' => ($asset->assetstatus) ? [
|
||||
'id' => (int) $asset->assetstatus->id,
|
||||
'name'=> e($asset->assetstatus->name)
|
||||
'name'=> e($asset->assetstatus->name),
|
||||
'status_type' => e($asset->assetstatus->getStatuslabelType()),
|
||||
] : null,
|
||||
'category' => ($asset->model->category) ? [
|
||||
'id' => (int) $asset->model->category->id,
|
||||
@@ -62,14 +63,7 @@ class AssetsTransformer
|
||||
'name'=> e($asset->defaultLoc->name)
|
||||
] : null,
|
||||
'image' => ($asset->getImageUrl()) ? $asset->getImageUrl() : null,
|
||||
'assigned_to' => ($asset->assigneduser) ? [
|
||||
'id' => (int) $asset->assigneduser->id,
|
||||
'username' => e($asset->assigneduser->username),
|
||||
'name' => e($asset->assigneduser->getFullNameAttribute()),
|
||||
'first_name'=> e($asset->assigneduser->first_name),
|
||||
'last_name'=> e($asset->assigneduser->last_name),
|
||||
'employee_number' => e($asset->assigneduser->employee_num),
|
||||
] : null,
|
||||
'assigned_to' => $this->transformAssignedTo($asset),
|
||||
'warranty' => ($asset->warranty_months > 0) ? e($asset->warranty_months . ' ' . trans('admin/hardware/form.months')) : null,
|
||||
'warranty_expires' => ($asset->warranty_months > 0) ? Helper::getFormattedDateObject($asset->warranty_expires, 'date') : null,
|
||||
'created_at' => Helper::getFormattedDateObject($asset->created_at, 'datetime'),
|
||||
@@ -82,8 +76,9 @@ class AssetsTransformer
|
||||
];
|
||||
|
||||
|
||||
if ($asset->model->fieldset) {
|
||||
if (($asset->model->fieldset) && (count($asset->model->fieldset->fields)> 0)) {
|
||||
$fields_array = array();
|
||||
|
||||
foreach ($asset->model->fieldset->fields as $field) {
|
||||
|
||||
if ($field->isFieldDecryptable($asset->{$field->convertUnicodeDbSlug()})) {
|
||||
@@ -110,6 +105,8 @@ class AssetsTransformer
|
||||
//array += $fields_array;
|
||||
$array['custom_fields'] = $fields_array;
|
||||
}
|
||||
} else {
|
||||
$array['custom_fields'] = array();
|
||||
}
|
||||
|
||||
$permissions_array['available_actions'] = [
|
||||
@@ -128,4 +125,24 @@ class AssetsTransformer
|
||||
{
|
||||
return (new DatatablesTransformer)->transformDatatables($assets);
|
||||
}
|
||||
|
||||
public function transformAssignedTo($asset)
|
||||
{
|
||||
if ($asset->checkedOutToUser()) {
|
||||
return $asset->assignedTo ? [
|
||||
'id' => (int) $asset->assignedTo->id,
|
||||
'username' => e($asset->assignedTo->username),
|
||||
'name' => e($asset->assignedTo->getFullNameAttribute()),
|
||||
'first_name'=> e($asset->assignedTo->first_name),
|
||||
'last_name'=> e($asset->assignedTo->last_name),
|
||||
'employee_number' => e($asset->assignedTo->employee_num),
|
||||
'type' => 'user'
|
||||
] : null;
|
||||
}
|
||||
return $asset->assignedTo ? [
|
||||
'id' => $asset->assignedTo->id,
|
||||
'name' => $asset->assignedTo->display_name,
|
||||
'type' => $asset->assignedType()
|
||||
] : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Http\Transformers;
|
||||
use App\Models\Category;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Gate;
|
||||
use App\Helpers\Helper;
|
||||
|
||||
class CategoriesTransformer
|
||||
{
|
||||
@@ -22,15 +23,18 @@ class CategoriesTransformer
|
||||
if ($category) {
|
||||
|
||||
$array = [
|
||||
'id' => e($category->id),
|
||||
'id' => (int) $category->id,
|
||||
'name' => e($category->name),
|
||||
'type' => e($category->category_type),
|
||||
'use_default_eula' => ($category->use_default_eula =='1') ? true : false,
|
||||
'checkin_email' => ($category->checkin_email =='1') ? true : false,
|
||||
'require_acceptance' => ($category->require_acceptance =='1') ? true : false,
|
||||
'assets_count' => $category->assets_count,
|
||||
'accessories_count' => $category->accessories_count,
|
||||
'consumables_count' => $category->consumables_count,
|
||||
'components_count' => $category->components_count,
|
||||
'created_at' => Helper::getFormattedDateObject($category->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($category->updated_at, 'datetime'),
|
||||
];
|
||||
|
||||
$permissions_array['available_actions'] = [
|
||||
|
||||
@@ -23,7 +23,7 @@ class CompaniesTransformer
|
||||
if ($company) {
|
||||
|
||||
$array = [
|
||||
'id' => e($company->id),
|
||||
'id' => (int) $company->id,
|
||||
'name' => e($company->name),
|
||||
"created_at" => Helper::getFormattedDateObject($company->created_at, 'datetime'),
|
||||
"updated_at" => Helper::getFormattedDateObject($company->updated_at, 'datetime'),
|
||||
|
||||
@@ -25,7 +25,7 @@ class CustomFieldsTransformer
|
||||
'name' => e($field->name),
|
||||
'db_column_name' => e($field->db_column_name()),
|
||||
'format' => e($field->format),
|
||||
'required' => $field->pivot->required,
|
||||
'required' => $field->pivot ? $field->pivot->required : false,
|
||||
'created_at' => Helper::getFormattedDateObject($field->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($field->updated_at, 'datetime'),
|
||||
];
|
||||
|
||||
@@ -23,7 +23,7 @@ class GroupsTransformer
|
||||
$array = [
|
||||
'id' => (int) $group->id,
|
||||
'name' => e($group->name),
|
||||
'permissions' => $group->permissions,
|
||||
'permissions' => json_decode($group->permissions),
|
||||
'users_count' => (int) $group->users_count,
|
||||
'created_at' => Helper::getFormattedDateObject($group->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($group->updated_at, 'datetime'),
|
||||
|
||||
@@ -33,8 +33,9 @@ class LicensesTransformer
|
||||
'depreciation' => ($license->depreciation) ? ['id' => (int) $license->depreciation->id,'name'=> e($license->depreciation->name)] : null,
|
||||
'notes' => e($license->notes),
|
||||
'expiration_date' => Helper::getFormattedDateObject($license->expiration_date, 'date'),
|
||||
'total_seats' => (int) $license->total_seats,
|
||||
'remaining_qty' => $license->remaincount(),
|
||||
'total_seats' => (int) $license->seats,
|
||||
'next_seat' => ($license->freeSeat()) ? (int) $license->freeSeat()->id : null,
|
||||
'remaining_qty' => (int) $license->remaincount(),
|
||||
'min_qty' => $license->remaincount(),
|
||||
'license_name' => e($license->license_name),
|
||||
'license_email' => e($license->license_email),
|
||||
|
||||
@@ -9,7 +9,7 @@ use App\Helpers\Helper;
|
||||
class LocationsTransformer
|
||||
{
|
||||
|
||||
public function transformLocations (Collection $locations, $total)
|
||||
public function transformLocations(Collection $locations, $total)
|
||||
{
|
||||
$array = array();
|
||||
foreach ($locations as $location) {
|
||||
@@ -18,18 +18,16 @@ class LocationsTransformer
|
||||
return (new DatatablesTransformer)->transformDatatables($array, $total);
|
||||
}
|
||||
|
||||
public function transformLocation (Location $location = null)
|
||||
public function transformLocation(Location $location = null)
|
||||
{
|
||||
if ($location) {
|
||||
|
||||
$assets_arr = [];
|
||||
foreach($location->assets() as $asset) {
|
||||
$assets_arr = ['id' => $asset->id];
|
||||
}
|
||||
|
||||
$children_arr = [];
|
||||
foreach($location->childLocations() as $child) {
|
||||
$children_arr = ['id' => $child->id];
|
||||
foreach($location->childLocations as $child) {
|
||||
$children_arr[] = [
|
||||
'id' => (int) $child->id,
|
||||
'name' => $child->name
|
||||
];
|
||||
}
|
||||
|
||||
$array = [
|
||||
@@ -38,13 +36,20 @@ class LocationsTransformer
|
||||
'address' => e($location->address),
|
||||
'city' => e($location->city),
|
||||
'state' => e($location->state),
|
||||
'country' => e($location->country),
|
||||
'zip' => e($location->zip),
|
||||
'assets_checkedout' => $location->assets()->count(),
|
||||
'assets_default' => $location->assignedassets()->count(),
|
||||
'country' => e($location->country),
|
||||
'assets' => $assets_arr,
|
||||
|
||||
'created_at' => Helper::getFormattedDateObject($location->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($location->updated_at, 'datetime'),
|
||||
'parent_id' => ($location->parent_id) ? (int) $location->parent_id : null,
|
||||
'parent' => ($location->parent) ? [
|
||||
'id' => (int) $location->parent->id,
|
||||
'name'=> e($location->parent->name)
|
||||
] : null,
|
||||
'manager' => ($location->manager) ? (new UsersTransformer)->transformUser($location->manager) : null,
|
||||
|
||||
|
||||
'children' => $children_arr,
|
||||
];
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ class SuppliersTransformer
|
||||
'city' => ($supplier->city) ? e($supplier->city) : null,
|
||||
'state' => ($supplier->state) ? e($supplier->state) : null,
|
||||
'country' => ($supplier->country) ? e($supplier->country) : null,
|
||||
'zip' => ($supplier->zip) ? e($supplier->zip) : null,
|
||||
'fax' => ($supplier->fax) ? e($supplier->fax) : null,
|
||||
'phone' => ($supplier->phone) ? e($supplier->phone) : null,
|
||||
'email' => ($supplier->email) ? e($supplier->email) : null,
|
||||
@@ -37,6 +38,7 @@ class SuppliersTransformer
|
||||
'assets_count' => (int) $supplier->assets_count,
|
||||
'licenses_count' => (int) $supplier->licenses_count,
|
||||
'image' => ($supplier->image) ? e($supplier->image) : null,
|
||||
'notes' => ($supplier->notes) ? e($supplier->notes) : null,
|
||||
'created_at' => Helper::getFormattedDateObject($supplier->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($supplier->updated_at, 'datetime'),
|
||||
|
||||
|
||||
@@ -32,11 +32,6 @@ class UsersTransformer
|
||||
'id' => (int) $user->manager->id,
|
||||
'name'=> e($user->manager->username)
|
||||
] : null,
|
||||
|
||||
'groups' => ($user->groups) ? [
|
||||
'id' => (int) $user->userloc->id,
|
||||
'name'=> e($user->userloc->name)
|
||||
] : null,
|
||||
'jobtitle' => ($user->jobtitle) ? e($user->jobtitle) : null,
|
||||
'email' => e($user->email),
|
||||
'department' => ($user->department) ? [
|
||||
@@ -61,13 +56,32 @@ class UsersTransformer
|
||||
];
|
||||
|
||||
$permissions_array['available_actions'] = [
|
||||
'update' => Gate::allows('update', User::class) ? true : false,
|
||||
'delete' => Gate::allows('delete', User::class) ? true : false,
|
||||
'clone' => Gate::allows('create', User::class) ? true : false,
|
||||
'update' => (Gate::allows('update', User::class) && ($user->deleted_at=='')) ? true : false,
|
||||
'delete' => (Gate::allows('delete', User::class) && ($user->deleted_at=='')) ? true : false,
|
||||
'clone' => (Gate::allows('create', User::class) && ($user->deleted_at=='')) ,
|
||||
'restore' => (Gate::allows('create', User::class) && ($user->deleted_at!='')) ? true : false,
|
||||
];
|
||||
|
||||
$array += $permissions_array;
|
||||
|
||||
|
||||
$numGroups = count($user->groups);
|
||||
if($numGroups > 0)
|
||||
{
|
||||
$groups["total"] = $numGroups;
|
||||
foreach($user->groups as $group)
|
||||
{
|
||||
$groups["rows"][] = [
|
||||
'id' => (int) $group->id,
|
||||
'name' => e($group->name)
|
||||
];
|
||||
}
|
||||
$array["groups"] = $groups;
|
||||
}
|
||||
else {
|
||||
$array["groups"] = null;
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,9 @@ class AssetImporter extends ItemImporter
|
||||
$this->item['image'] = $this->findCsvMatch($row, "image");
|
||||
$this->item['warranty_months'] = intval($this->findCsvMatch($row, "warranty"));
|
||||
$this->item['model_id'] = $this->createOrFetchAssetModel($row);
|
||||
if (!$this->item['status_id'] && !$editingAsset) {
|
||||
|
||||
// If no status ID is found
|
||||
if (!array_key_exists('status_id', $this->item) && !$editingAsset) {
|
||||
$this->log("No status field found, defaulting to first status.");
|
||||
$this->item['status_id'] = $this->defaultStatusLabelId;
|
||||
}
|
||||
|
||||
@@ -109,7 +109,15 @@ abstract class Importer
|
||||
{
|
||||
$headerRow = $this->csv->fetchOne();
|
||||
$results = $this->normalizeInputArray($this->csv->fetchAssoc());
|
||||
$this->customFields = CustomField::All(['name']);
|
||||
|
||||
// Stolen From https://adamwathan.me/2016/07/14/customizing-keys-when-mapping-collections/
|
||||
// This 'inverts' the fields such that we have a collection of fields indexed by name.
|
||||
$cFs = CustomField::All();
|
||||
$this->customFields = $cFs->reduce(function ($nameLookup, $field) {
|
||||
$nameLookup[$field['name']] = $field;
|
||||
return $nameLookup;
|
||||
});
|
||||
|
||||
DB::transaction(function () use (&$results) {
|
||||
Model::unguard();
|
||||
$resultsCount = sizeof($results);
|
||||
@@ -136,14 +144,12 @@ abstract class Importer
|
||||
* @param $default string
|
||||
* @return string
|
||||
*/
|
||||
public function findCsvMatch(array $array, $key, $default = '')
|
||||
public function findCsvMatch(array $array, $key, $default = null)
|
||||
{
|
||||
|
||||
$val = $default;
|
||||
|
||||
if ($customKey = $this->lookupCustomKey($key)) {
|
||||
$key = $customKey;
|
||||
}
|
||||
$key = $this->lookupCustomKey($key);
|
||||
|
||||
$this->log("Custom Key: ${key}");
|
||||
if (array_key_exists($key, $array)) {
|
||||
@@ -163,13 +169,12 @@ abstract class Importer
|
||||
*/
|
||||
public function lookupCustomKey($key)
|
||||
{
|
||||
// dd($this->fieldMap);
|
||||
|
||||
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];
|
||||
}
|
||||
return null;
|
||||
// Otherwise no custom key, return original.
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,6 +10,7 @@ use App\Models\Location;
|
||||
use App\Models\Manufacturer;
|
||||
use App\Models\Statuslabel;
|
||||
use App\Models\Supplier;
|
||||
use App\Models\User;
|
||||
|
||||
class ItemImporter extends Importer
|
||||
{
|
||||
@@ -68,6 +69,7 @@ class ItemImporter extends Importer
|
||||
if(get_class($this) !== UserImporter::class) {
|
||||
if ($this->item["user"] = $this->createOrFetchUser($row)) {
|
||||
$this->item['assigned_to'] = $this->item['user']->id;
|
||||
$this->item['assigned_type'] = User::class;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,7 +92,6 @@ class ItemImporter extends Importer
|
||||
$item = collect($this->item);
|
||||
// First Filter the item down to the model's fillable fields
|
||||
$item = $item->only($model->getFillable());
|
||||
|
||||
// Then iterate through the item and, if we are updating, remove any blank values.
|
||||
if ($updating) {
|
||||
$item = $item->reject(function ($value) {
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace App\LegacyEncrypter;
|
||||
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
|
||||
abstract class BaseEncrypter
|
||||
{
|
||||
/**
|
||||
* The encryption key.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $key;
|
||||
|
||||
/**
|
||||
* Create a MAC for the given value.
|
||||
*
|
||||
* @param string $iv
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function hash($iv, $value)
|
||||
{
|
||||
return hash_hmac('sha256', $iv.$value, $this->key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JSON array from the given payload.
|
||||
*
|
||||
* @param string $payload
|
||||
* @return array
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Encryption\DecryptException
|
||||
*/
|
||||
protected function getJsonPayload($payload)
|
||||
{
|
||||
$payload = json_decode(base64_decode($payload), true);
|
||||
|
||||
// If the payload is not valid JSON or does not have the proper keys set we will
|
||||
// assume it is invalid and bail out of the routine since we will not be able
|
||||
// to decrypt the given value. We'll also check the MAC for this encryption.
|
||||
if (! $payload || $this->invalidPayload($payload)) {
|
||||
throw new DecryptException('The payload is invalid.');
|
||||
}
|
||||
|
||||
if (! $this->validMac($payload)) {
|
||||
throw new DecryptException('The MAC is invalid.');
|
||||
}
|
||||
|
||||
return $payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the encryption payload is valid.
|
||||
*
|
||||
* @param array|mixed $data
|
||||
* @return bool
|
||||
*/
|
||||
protected function invalidPayload($data)
|
||||
{
|
||||
return ! is_array($data) || ! isset($data['iv']) || ! isset($data['value']) || ! isset($data['mac']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the MAC for the given payload is valid.
|
||||
*
|
||||
* @param array $payload
|
||||
* @return bool
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function validMac(array $payload)
|
||||
{
|
||||
$bytes = random_bytes(16);
|
||||
|
||||
$calcMac = hash_hmac('sha256', $this->hash($payload['iv'], $payload['value']), $bytes, true);
|
||||
|
||||
return hash_equals(hash_hmac('sha256', $payload['mac'], $bytes, true), $calcMac);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
<?php
|
||||
|
||||
namespace App\LegacyEncrypter;
|
||||
|
||||
use Exception;
|
||||
use RuntimeException;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Illuminate\Contracts\Encryption\EncryptException;
|
||||
use Illuminate\Contracts\Encryption\Encrypter as EncrypterContract;
|
||||
|
||||
/**
|
||||
* @deprecated since version 5.1. Use Illuminate\Encryption\Encrypter.
|
||||
*/
|
||||
class McryptEncrypter extends BaseEncrypter implements EncrypterContract
|
||||
{
|
||||
/**
|
||||
* The algorithm used for encryption.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $cipher;
|
||||
|
||||
/**
|
||||
* The block size of the cipher.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $block;
|
||||
|
||||
/**
|
||||
* Create a new encrypter instance.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $cipher
|
||||
* @return void
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function __construct($key, $cipher = MCRYPT_RIJNDAEL_128)
|
||||
{
|
||||
$key = (string) $key;
|
||||
|
||||
if (static::supported($key, $cipher)) {
|
||||
$this->key = $key;
|
||||
$this->cipher = $cipher;
|
||||
$this->block = mcrypt_get_iv_size($this->cipher, MCRYPT_MODE_CBC);
|
||||
} else {
|
||||
throw new RuntimeException('The only supported ciphers are MCRYPT_RIJNDAEL_128 and MCRYPT_RIJNDAEL_256.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given key and cipher combination is valid.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $cipher
|
||||
* @return bool
|
||||
*/
|
||||
public static function supported($key, $cipher)
|
||||
{
|
||||
return defined('MCRYPT_RIJNDAEL_128') &&
|
||||
($cipher === MCRYPT_RIJNDAEL_128 || $cipher === MCRYPT_RIJNDAEL_256);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt the given value.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Encryption\EncryptException
|
||||
*/
|
||||
public function encrypt($value, $serialize = true)
|
||||
{
|
||||
$iv = mcrypt_create_iv($this->getIvSize(), $this->getRandomizer());
|
||||
|
||||
$value = base64_encode($this->padAndMcrypt($value, $iv));
|
||||
|
||||
// Once we have the encrypted value we will go ahead base64_encode the input
|
||||
// vector and create the MAC for the encrypted value so we can verify its
|
||||
// authenticity. Then, we'll JSON encode the data in a "payload" array.
|
||||
$mac = $this->hash($iv = base64_encode($iv), $value);
|
||||
|
||||
$json = json_encode(compact('iv', 'value', 'mac'));
|
||||
|
||||
if (! is_string($json)) {
|
||||
throw new EncryptException('Could not encrypt the data.');
|
||||
}
|
||||
|
||||
return base64_encode($json);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pad and use mcrypt on the given value and input vector.
|
||||
*
|
||||
* @param string $value
|
||||
* @param string $iv
|
||||
* @return string
|
||||
*/
|
||||
protected function padAndMcrypt($value, $iv)
|
||||
{
|
||||
$value = $this->addPadding(serialize($value));
|
||||
|
||||
return mcrypt_encrypt($this->cipher, $this->key, $value, MCRYPT_MODE_CBC, $iv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt the given value.
|
||||
*
|
||||
* @param string $payload
|
||||
* @return string
|
||||
*/
|
||||
public function decrypt($payload, $unserialize = true)
|
||||
{
|
||||
$payload = $this->getJsonPayload($payload);
|
||||
|
||||
// We'll go ahead and remove the PKCS7 padding from the encrypted value before
|
||||
// we decrypt it. Once we have the de-padded value, we will grab the vector
|
||||
// and decrypt the data, passing back the unserialized from of the value.
|
||||
$value = base64_decode($payload['value']);
|
||||
|
||||
$iv = base64_decode($payload['iv']);
|
||||
|
||||
return unserialize($this->stripPadding($this->mcryptDecrypt($value, $iv)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the mcrypt decryption routine for the value.
|
||||
*
|
||||
* @param string $value
|
||||
* @param string $iv
|
||||
* @return string
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Encryption\DecryptException
|
||||
*/
|
||||
protected function mcryptDecrypt($value, $iv)
|
||||
{
|
||||
try {
|
||||
return mcrypt_decrypt($this->cipher, $this->key, $value, MCRYPT_MODE_CBC, $iv);
|
||||
} catch (Exception $e) {
|
||||
throw new DecryptException($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add PKCS7 padding to a given value.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function addPadding($value)
|
||||
{
|
||||
$pad = $this->block - (strlen($value) % $this->block);
|
||||
|
||||
return $value.str_repeat(chr($pad), $pad);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the padding from the given value.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function stripPadding($value)
|
||||
{
|
||||
$pad = ord($value[($len = strlen($value)) - 1]);
|
||||
|
||||
return $this->paddingIsValid($pad, $value) ? substr($value, 0, $len - $pad) : $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given padding for a value is valid.
|
||||
*
|
||||
* @param string $pad
|
||||
* @param string $value
|
||||
* @return bool
|
||||
*/
|
||||
protected function paddingIsValid($pad, $value)
|
||||
{
|
||||
$beforePad = strlen($value) - $pad;
|
||||
|
||||
return substr($value, $beforePad) == str_repeat(substr($value, -1), $pad);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the IV size for the cipher.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function getIvSize()
|
||||
{
|
||||
return mcrypt_get_iv_size($this->cipher, MCRYPT_MODE_CBC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the random data source available for the OS.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function getRandomizer()
|
||||
{
|
||||
if (defined('MCRYPT_DEV_URANDOM')) {
|
||||
return MCRYPT_DEV_URANDOM;
|
||||
}
|
||||
|
||||
if (defined('MCRYPT_DEV_RANDOM')) {
|
||||
return MCRYPT_DEV_RANDOM;
|
||||
}
|
||||
|
||||
mt_srand();
|
||||
|
||||
return MCRYPT_RAND;
|
||||
}
|
||||
}
|
||||
@@ -60,6 +60,7 @@ class Accessory extends SnipeModel
|
||||
'purchase_cost',
|
||||
'purchase_date',
|
||||
'model_number',
|
||||
'manufacturer_id',
|
||||
'qty',
|
||||
'requestable'
|
||||
];
|
||||
|
||||
@@ -5,6 +5,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Response;
|
||||
use Carbon;
|
||||
|
||||
/**
|
||||
* Model for the Actionlog (the table that keeps a historical log of
|
||||
@@ -123,6 +124,10 @@ class Actionlog extends SnipeModel
|
||||
return $this->belongsTo('\App\Models\ActionLog', 'thread_id');
|
||||
}
|
||||
|
||||
public function location() {
|
||||
return $this->belongsTo('\App\Models\Location', 'location_id' )->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the file exists, and if it does, force a download
|
||||
**/
|
||||
@@ -149,6 +154,33 @@ class Actionlog extends SnipeModel
|
||||
}
|
||||
}
|
||||
|
||||
public function daysUntilNextAudit($monthInterval = 12, $asset = null) {
|
||||
|
||||
$now = Carbon::now();
|
||||
$last_audit_date = $this->created_at;
|
||||
$next_audit = $last_audit_date->addMonth($monthInterval);
|
||||
$next_audit_days = $now->diffInDays($next_audit);
|
||||
|
||||
// Override the default setting for interval if the asset has its own next audit date
|
||||
if (($asset) && ($asset->next_audit_date)) {
|
||||
$override_default_next = \Carbon::parse($asset->next_audit_date);
|
||||
$next_audit_days = $override_default_next->diffInDays($now);
|
||||
}
|
||||
|
||||
return $next_audit_days;
|
||||
}
|
||||
|
||||
public function calcNextAuditDate($monthInterval = 12, $asset = null) {
|
||||
|
||||
$last_audit_date = Carbon::parse($this->created_at);
|
||||
// If there is an asset-specific next date already given,
|
||||
if (($asset) && ($asset->next_audit_date)) {
|
||||
return \Carbon::parse($asset->next_audit_date);
|
||||
}
|
||||
|
||||
return \Carbon::parse($last_audit_date)->addMonths($monthInterval)->toDateString();
|
||||
}
|
||||
|
||||
/**
|
||||
* getListingOfActionLogsChronologicalOrder
|
||||
*
|
||||
|
||||
+61
-57
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace App\Models;
|
||||
|
||||
use App\Exceptions\CheckoutNotAllowed;
|
||||
use App\Http\Traits\UniqueUndeletedTrait;
|
||||
use App\Presenters\Presentable;
|
||||
use AssetPresenter;
|
||||
@@ -10,6 +11,7 @@ use Config;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Log;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
|
||||
/**
|
||||
* Model for Assets.
|
||||
@@ -19,7 +21,7 @@ use Watson\Validating\ValidatingTrait;
|
||||
class Asset extends Depreciable
|
||||
{
|
||||
protected $presenter = 'App\Presenters\AssetPresenter';
|
||||
use Loggable, Requestable, Presentable;
|
||||
use Loggable, Requestable, Presentable, Notifiable;
|
||||
use SoftDeletes;
|
||||
|
||||
const LOCATION = 'location';
|
||||
@@ -66,6 +68,7 @@ class Asset extends Depreciable
|
||||
'asset_tag' => 'required|min:1|max:255|unique_undeleted',
|
||||
'status' => 'integer',
|
||||
'purchase_cost' => 'numeric|nullable',
|
||||
'next_audit_date' => 'date|nullable',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -76,6 +79,7 @@ class Asset extends Depreciable
|
||||
protected $fillable = [
|
||||
'asset_tag',
|
||||
'assigned_to',
|
||||
'assigned_type',
|
||||
'company_id',
|
||||
'image',
|
||||
'model_id',
|
||||
@@ -140,7 +144,7 @@ class Asset extends Depreciable
|
||||
* @return bool
|
||||
*/
|
||||
//FIXME: The admin parameter is never used. Can probably be removed.
|
||||
public function checkOut($target, $admin, $checkout_at = null, $expected_checkin = null, $note = null, $name = null)
|
||||
public function checkOut($target, $admin = null, $checkout_at = null, $expected_checkin = null, $note = null, $name = null)
|
||||
{
|
||||
if (!$target) {
|
||||
return false;
|
||||
@@ -160,41 +164,19 @@ class Asset extends Depreciable
|
||||
}
|
||||
|
||||
if ($this->requireAcceptance()) {
|
||||
if(get_class($target) != User::class) {
|
||||
throw new CheckoutNotAllowed;
|
||||
}
|
||||
$this->accepted="pending";
|
||||
}
|
||||
|
||||
if ($this->save()) {
|
||||
$this->logCheckout($note, $target);
|
||||
// if ((($this->requireAcceptance()=='1') || ($this->getEula())) && ($user->email!='')) {
|
||||
// $this->checkOutNotifyMail($log->id, $user, $checkout_at, $expected_checkin, $note);
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkOutNotifyMail($log_id, $user, $checkout_at, $expected_checkin, $note)
|
||||
{
|
||||
$data['log_id'] = $log_id;
|
||||
$data['eula'] = $this->getEula();
|
||||
$data['first_name'] = $user->first_name;
|
||||
$data['item_name'] = $this->present()->name();
|
||||
$data['checkout_date'] = $checkout_at;
|
||||
$data['expected_checkin'] = $expected_checkin;
|
||||
$data['item_tag'] = $this->asset_tag;
|
||||
$data['note'] = $note;
|
||||
$data['item_serial'] = $this->serial;
|
||||
$data['require_acceptance'] = $this->requireAcceptance();
|
||||
|
||||
if ((($this->requireAcceptance()=='1') || ($this->getEula())) && (!config('app.lock_passwords'))) {
|
||||
\Mail::send('emails.accept-asset', $data, function ($m) use ($user) {
|
||||
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
|
||||
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
|
||||
$m->subject(trans('mail.Confirm_asset_delivery'));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public function getDetailedNameAttribute()
|
||||
{
|
||||
if ($this->assignedTo) {
|
||||
@@ -246,16 +228,14 @@ class Asset extends Depreciable
|
||||
->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Even though we allow allow for checkout to things beyond users
|
||||
* this method is an easy way of seeing if we are checked out to a user.
|
||||
* @return mixed
|
||||
*/
|
||||
public function assigneduser()
|
||||
public function checkedOutToUser()
|
||||
{
|
||||
return $this->belongsTo('\App\Models\User', 'assigned_to')
|
||||
->withTrashed();
|
||||
return $this->assignedType() === self::USER;
|
||||
}
|
||||
|
||||
public function assignedTo()
|
||||
@@ -274,15 +254,20 @@ class Asset extends Depreciable
|
||||
public function assetLoc()
|
||||
{
|
||||
if (!empty($this->assignedType())) {
|
||||
// dd($this->assignedType());
|
||||
if ($this->assignedType() == self::ASSET) {
|
||||
return $this->assignedTo->assetloc(); // Recurse until we have a final location
|
||||
} elseif ($this->assignedType() == self::LOCATION) {
|
||||
return $this->assignedto->assetloc(); // Recurse until we have a final location
|
||||
}
|
||||
if ($this->assignedType() == self::LOCATION) {
|
||||
return $this->assignedTo();
|
||||
} elseif (!$this->assignedTo) {
|
||||
return $this->defaultLoc();
|
||||
} elseif ($this->assignedType() == self::USER) {
|
||||
}
|
||||
if ($this->assignedType() == self::USER) {
|
||||
if (!$this->assignedTo) {
|
||||
return $this->defaultLoc();
|
||||
}
|
||||
return $this->assignedTo->userLoc();
|
||||
}
|
||||
|
||||
}
|
||||
return $this->defaultLoc();
|
||||
}
|
||||
@@ -544,7 +529,7 @@ class Asset extends Depreciable
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope for pending assets
|
||||
* Query builder scope for searching location
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
*
|
||||
@@ -554,8 +539,17 @@ class Asset extends Depreciable
|
||||
public function scopeAssetsByLocation($query, $location)
|
||||
{
|
||||
return $query->where(function ($query) use ($location) {
|
||||
$query->whereHas('assigneduser', function ($query) use ($location) {
|
||||
$query->where('users.location_id', '=', $location->id);
|
||||
$query->whereHas('assignedTo', function ($query) use ($location) {
|
||||
$query->where([
|
||||
['users.location_id', '=', $location->id],
|
||||
['assets.assigned_type', '=', User::class]
|
||||
])->orWhere([
|
||||
['locations.id', '=', $location->id],
|
||||
['assets.assigned_type', '=', Location::class]
|
||||
])->orWhere([
|
||||
['assets.rtd_location_id', '=', $location->id],
|
||||
['assets.assigned_type', '=', Asset::class]
|
||||
]);
|
||||
})->orWhere(function ($query) use ($location) {
|
||||
$query->where('assets.rtd_location_id', '=', $location->id);
|
||||
$query->whereNull('assets.assigned_to');
|
||||
@@ -775,18 +769,26 @@ class Asset extends Depreciable
|
||||
$query->whereHas('defaultLoc', function ($query) use ($search) {
|
||||
$query->where('locations.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
})->orWhere(function ($query) use ($search) {
|
||||
$query->whereHas('assigneduser', function ($query) use ($search) {
|
||||
$query->where(function ($query) use ($search) {
|
||||
$query->where('users.first_name', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('users.last_name', 'LIKE', '%'.$search.'%')
|
||||
->orWhere(function ($query) use ($search) {
|
||||
$query->whereHas('userloc', function ($query) use ($search) {
|
||||
$query->where('locations.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
//FIXME: This needs attention to work with checkout to not-users.
|
||||
// })->orWhere(function ($query) use ($search) {
|
||||
// $query->whereHas('assignedTo', function ($query) use ($search) {
|
||||
// $query->where(function ($query) use ($search) {
|
||||
// $query->where('assets.assigned_type', '=', User::class)
|
||||
// ->join('users', 'users.id', '=', 'assets.assigned_to')
|
||||
// ->where(function($query) use ($search) {
|
||||
// $query->where('users.first_name', 'LIKE', '%'.$search.'%')
|
||||
// ->orWhere('users.last_name', 'LIKE', '%'.$search.'%');
|
||||
// });
|
||||
// })->orWhere(function ($query) use ($search) {
|
||||
// $query->where('assets.assigned_type', '=', Location::class)
|
||||
// ->join('locations', 'locations.id', '=', 'assets.assigned_to')
|
||||
// ->where('locations.name', 'LIKE', '%'.$search.'%');
|
||||
// })->orWhere(function ($query) use ($search) {
|
||||
// $query->where('assets.assigned_type', '=', Asset::class)
|
||||
// ->join('assets as assigned_asset', 'assigned_assets.id', '=', 'assets.assigned_to')
|
||||
// ->where('assigned_assets.name', 'LIKE', '%'.$search.'%');
|
||||
// });
|
||||
// });
|
||||
})->orWhere('assets.name', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('assets.asset_tag', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('assets.serial', 'LIKE', '%'.$search.'%')
|
||||
@@ -1088,14 +1090,16 @@ class Asset extends Depreciable
|
||||
return $query->where(function ($query) use ($search) {
|
||||
$query->whereHas('defaultLoc', function ($query) use ($search) {
|
||||
$query->where('locations.id', '=', $search);
|
||||
})->whereNull('assigned_to');
|
||||
})->orWhere(function ($query) use ($search) {
|
||||
$query->whereHas('assigneduser', function ($query) use ($search) {
|
||||
$query->whereHas('userloc', function ($query) use ($search) {
|
||||
$query->where('locations.id', '=', $search);
|
||||
});
|
||||
});
|
||||
});
|
||||
// FIXME: This needs porting to checkout to non-user.
|
||||
// ->orWhere(function ($query) use ($search) {
|
||||
// $query->whereHas('assigneduser', function ($query) use ($search) {
|
||||
// $query->whereHas('userloc', function ($query) use ($search) {
|
||||
// $query->where('locations.id', '=', $search);
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ class AssetModel extends SnipeModel
|
||||
// Declare the rules for the model validation
|
||||
protected $rules = array(
|
||||
'name' => 'required|min:1|max:255',
|
||||
'model_number' => 'min:1|max:255',
|
||||
'model_number' => 'max:255|nullable',
|
||||
'category_id' => 'required|integer|exists:categories,id',
|
||||
'manufacturer_id' => 'required|integer|exists:manufacturers,id',
|
||||
'eol' => 'integer:min:0|max:240|nullable',
|
||||
@@ -55,7 +55,7 @@ class AssetModel extends SnipeModel
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = ['name','manufacturer_id','category_id','eol', 'user_id', 'fieldset_id'];
|
||||
protected $fillable = ['name','manufacturer_id','category_id','eol', 'user_id', 'fieldset_id', 'model_number', 'notes'];
|
||||
|
||||
public function assets()
|
||||
{
|
||||
|
||||
@@ -53,6 +53,7 @@ class Component extends SnipeModel
|
||||
'name',
|
||||
'purchase_cost',
|
||||
'purchase_date',
|
||||
'min_amt',
|
||||
'qty',
|
||||
];
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ class Consumable extends SnipeModel
|
||||
return $this->belongsTo('\App\Models\User', 'user_id');
|
||||
}
|
||||
|
||||
public function consumableAssigments()
|
||||
public function consumableAssignments()
|
||||
{
|
||||
return $this->hasMany('\App\Models\ConsumableAssignment');
|
||||
}
|
||||
|
||||
+11
-12
@@ -38,12 +38,10 @@ class CustomField extends Model
|
||||
public static function boot()
|
||||
{
|
||||
self::created(function ($custom_field) {
|
||||
\Log::debug("\n\nCreating Original Name: ".$custom_field->name);
|
||||
\Log::debug('Creating Column Name: '.$custom_field->convertUnicodeDbSlug());
|
||||
|
||||
|
||||
// column exists - nothing to do here
|
||||
if (Schema::hasColumn(CustomField::$table_name, $custom_field->convertUnicodeDbSlug())) {
|
||||
\Log::debug('Column exists. Nothing to do here.');
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -57,18 +55,13 @@ class CustomField extends Model
|
||||
|
||||
|
||||
self::updating(function ($custom_field) {
|
||||
\Log::debug('Updating column name');
|
||||
\Log::debug('Updating Original Name: '.$custom_field->getOriginal("name"));
|
||||
\Log::debug('Updating New Column Name: '.$custom_field->convertUnicodeDbSlug());
|
||||
|
||||
// Column already exists. Nothing to update.
|
||||
if ($custom_field->isDirty("name")) {
|
||||
if (Schema::hasColumn(CustomField::$table_name, $custom_field->convertUnicodeDbSlug())) {
|
||||
\Log::debug('Column already exists. Nothing to update.');
|
||||
return true;
|
||||
}
|
||||
|
||||
\Log::debug('Updating column name to.'.$custom_field->convertUnicodeDbSlug());
|
||||
|
||||
return Schema::table(CustomField::$table_name, function ($table) use ($custom_field) {
|
||||
$table->renameColumn($custom_field->convertUnicodeDbSlug($custom_field->getOriginal("name")), $custom_field->convertUnicodeDbSlug());
|
||||
});
|
||||
@@ -85,7 +78,7 @@ class CustomField extends Model
|
||||
|
||||
public function fieldset()
|
||||
{
|
||||
return $this->belongsToMany('\App\Models\CustomFieldset'); //?!?!?!?!?!?
|
||||
return $this->belongsToMany('\App\Models\CustomFieldset');
|
||||
}
|
||||
|
||||
public function user()
|
||||
@@ -102,10 +95,9 @@ class CustomField extends Model
|
||||
public function db_column_name()
|
||||
{
|
||||
return $this->db_column;
|
||||
// return self::convertUnicodeDbSlug();
|
||||
}
|
||||
|
||||
//mutators for 'format' attribute
|
||||
// mutators for 'format' attribute
|
||||
public function getFormatAttribute($value)
|
||||
{
|
||||
foreach (self::$PredefinedFormats as $name => $pattern) {
|
||||
@@ -116,6 +108,13 @@ class CustomField extends Model
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a value string as an array for select boxes and checkboxes.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v3.4]
|
||||
* @return Array
|
||||
*/
|
||||
public function setFormatAttribute($value)
|
||||
{
|
||||
if (isset(self::$PredefinedFormats[$value])) {
|
||||
|
||||
+2
-1
@@ -48,6 +48,7 @@ class Ldap extends Model
|
||||
// Needed for AD
|
||||
ldap_set_option($connection, LDAP_OPT_REFERRALS, 0);
|
||||
ldap_set_option($connection, LDAP_OPT_PROTOCOL_VERSION, $ldap_version);
|
||||
ldap_set_option($connection, LDAP_OPT_NETWORK_TIMEOUT, 20);
|
||||
|
||||
if ($ldap_use_tls=='1') {
|
||||
ldap_start_tls($connection);
|
||||
@@ -110,7 +111,7 @@ class Ldap extends Model
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$user = array_change_key_case(ldap_get_attributes($connection, $entry), CASE_LOWER)) {
|
||||
if (!$user = ldap_get_attributes($connection, $entry)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+23
-6
@@ -31,10 +31,10 @@ class License extends Depreciable
|
||||
protected $rules = array(
|
||||
'name' => 'required|string|min:3|max:255',
|
||||
'seats' => 'required|min:1|max:1000000|integer',
|
||||
'license_email' => 'email|min:0|max:120',
|
||||
'license_name' => 'string|min:0|max:100',
|
||||
'note' => 'string',
|
||||
'notes' => 'string|min:0',
|
||||
'license_email' => 'email|nullable|max:120',
|
||||
'license_name' => 'string|nullable|max:100',
|
||||
'note' => 'string|nullable',
|
||||
'notes' => 'string|nullable',
|
||||
'company_id' => 'integer|nullable',
|
||||
);
|
||||
|
||||
@@ -332,14 +332,17 @@ class License extends Depreciable
|
||||
return $this->belongsTo('\App\Models\Supplier', 'supplier_id');
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the next available free seat - used by
|
||||
* the API to populate next_seat
|
||||
*/
|
||||
public function freeSeat()
|
||||
{
|
||||
$seat = LicenseSeat::where('license_id', '=', $this->id)
|
||||
return $this->licenseseats()
|
||||
->whereNull('deleted_at')
|
||||
->whereNull('assigned_to')
|
||||
->whereNull('asset_id')
|
||||
->first();
|
||||
return $seat->id;
|
||||
}
|
||||
|
||||
public static function getExpiringLicenses($days = 60)
|
||||
@@ -401,6 +404,20 @@ class License extends Depreciable
|
||||
->orderBy('manufacturers.name', $order);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to order on supplier
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeOrderSupplier($query, $order)
|
||||
{
|
||||
return $query->leftJoin('suppliers', 'licenses.supplier_id', '=', 'suppliers.id')->select('licenses.*')
|
||||
->orderBy('suppliers.name', $order);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to order on company
|
||||
*
|
||||
|
||||
@@ -24,6 +24,7 @@ class Location extends SnipeModel
|
||||
'address' => 'max:80|nullable',
|
||||
'address2' => 'max:80|nullable',
|
||||
'zip' => 'min:3|max:10|nullable',
|
||||
// 'manager_id' => 'exists:users'
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -63,7 +64,12 @@ class Location extends SnipeModel
|
||||
|
||||
public function parent()
|
||||
{
|
||||
return $this->belongsTo('\App\Models\Location', 'parent_id');
|
||||
return $this->belongsTo('\App\Models\Location', 'parent_id','id');
|
||||
}
|
||||
|
||||
public function manager()
|
||||
{
|
||||
return $this->belongsTo('\App\Models\User', 'manager_id');
|
||||
}
|
||||
|
||||
public function childLocations()
|
||||
|
||||
+86
-43
@@ -7,6 +7,7 @@ use App\Models\Asset;
|
||||
use App\Models\CheckoutRequest;
|
||||
use App\Models\User;
|
||||
use App\Notifications\CheckinNotification;
|
||||
use App\Notifications\AuditNotification;
|
||||
use App\Notifications\CheckoutNotification;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
@@ -29,11 +30,59 @@ trait Loggable
|
||||
* @since [v3.4]
|
||||
* @return \App\Models\Actionlog
|
||||
*/
|
||||
public function logCheckout($note, $target = null /*target is overridable for components*/)
|
||||
public function logCheckout($note, $target /* What are we checking out to? */)
|
||||
{
|
||||
$log = new Actionlog;
|
||||
$log = $this->determineLogItemType($log);
|
||||
$log->user_id = Auth::user()->id;
|
||||
|
||||
// We need to special case licenses because of license_seat vs license. So much for clean polymorphism :)
|
||||
if (!isset($target)) {
|
||||
throw new Exception('All checkout logs require a target');
|
||||
return;
|
||||
}
|
||||
$log->target_type = get_class($target);
|
||||
$log->target_id = $target->id;
|
||||
|
||||
$target_class = get_class($target);
|
||||
|
||||
// Figure out what the target is
|
||||
if ($target_class == Location::class) {
|
||||
// We can checkout to a location
|
||||
$log->location_id = $target->id;
|
||||
} elseif ($target_class== Asset::class) {
|
||||
$log->location_id = $target->rtd_location_id;
|
||||
} else {
|
||||
$log->location_id = $target->location_id;
|
||||
}
|
||||
|
||||
$log->note = $note;
|
||||
$log->logaction('checkout');
|
||||
|
||||
$params = [
|
||||
'item' => $log->item,
|
||||
'target' => $target,
|
||||
'admin' => $log->user,
|
||||
'note' => $note,
|
||||
'log_id' => $log->id
|
||||
];
|
||||
|
||||
if ($settings = Setting::getSettings()) {
|
||||
$settings->notify(new CheckoutNotification($params));
|
||||
}
|
||||
|
||||
if (method_exists($target, 'notify')) {
|
||||
$target->notify(new CheckoutNotification($params));
|
||||
}
|
||||
|
||||
return $log;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to determine the log item type
|
||||
*/
|
||||
private function determineLogItemType($log)
|
||||
{
|
||||
// We need to special case licenses because of license_seat vs license. So much for clean polymorphism :
|
||||
if (static::class == LicenseSeat::class) {
|
||||
$log->item_type = License::class;
|
||||
$log->item_id = $this->license_id;
|
||||
@@ -42,49 +91,8 @@ trait Loggable
|
||||
$log->item_id = $this->id;
|
||||
}
|
||||
|
||||
$log->user_id = Auth::user()->id;
|
||||
|
||||
// @FIXME This needs to be generalized with new asset checkout.
|
||||
if(isset($target)) {
|
||||
$log->target_type = get_class($target);
|
||||
$log->target_id = $target->id;
|
||||
} else {
|
||||
if (!is_null($this->asset_id)) {
|
||||
$log->target_type = Asset::class;
|
||||
$log->target_id = $this->asset_id;
|
||||
} elseif (!is_null($this->assigned_to)) {
|
||||
$log->target_type = User::class;
|
||||
$log->target_id = $this->assigned_to;
|
||||
}
|
||||
}
|
||||
|
||||
$item = call_user_func(array($log->target_type, 'find'), $log->target_id);
|
||||
if($this->assignedTo) {
|
||||
$item = $this->assignedTo;
|
||||
}
|
||||
$class = get_class($item);
|
||||
if($class == Location::class) {
|
||||
// We can checkout to a location
|
||||
$log->location_id = $item->id;
|
||||
} else if ($class== Asset::class) {
|
||||
$log->location_id = $item->rtd_location_id;
|
||||
} else {
|
||||
$log->location_id = $item->location_id;
|
||||
}
|
||||
$log->note = $note;
|
||||
$log->logaction('checkout');
|
||||
|
||||
$params = [
|
||||
'item' => $log->item,
|
||||
'target' => $log->target,
|
||||
'admin' => $log->user,
|
||||
'note' => $note
|
||||
];
|
||||
Setting::getSettings()->notify(new CheckoutNotification($params));
|
||||
|
||||
return $log;
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Daniel Meltzer <parallelgrapefruit@gmail.com
|
||||
* @since [v3.4]
|
||||
@@ -117,6 +125,41 @@ trait Loggable
|
||||
return $log;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v4.0]
|
||||
* @return \App\Models\Actionlog
|
||||
*/
|
||||
public function logAudit($note, $location_id)
|
||||
{
|
||||
$log = new Actionlog;
|
||||
$location = Location::find($location_id);
|
||||
if (static::class == LicenseSeat::class) {
|
||||
$log->item_type = License::class;
|
||||
$log->item_id = $this->license_id;
|
||||
} else {
|
||||
$log->item_type = static::class;
|
||||
$log->item_id = $this->id;
|
||||
}
|
||||
$log->location_id = ($location_id) ? $location_id : null;
|
||||
$log->note = $note;
|
||||
$log->user_id = Auth::user()->id;
|
||||
$log->logaction('audit');
|
||||
|
||||
$params = [
|
||||
'item' => $log->item,
|
||||
'admin' => $log->user,
|
||||
'location' => ($location) ? $location->name : '',
|
||||
'note' => $note
|
||||
];
|
||||
Setting::getSettings()->notify(new AuditNotification($params));
|
||||
|
||||
return $log;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @author Daniel Meltzer <parallelgrapefruit@gmail.com
|
||||
* @since [v3.5]
|
||||
|
||||
@@ -19,9 +19,9 @@ trait Requestable
|
||||
|
||||
public function isRequestedBy(User $user)
|
||||
{
|
||||
return $this->requests()
|
||||
->where('user_id', $user->id)
|
||||
->exists();
|
||||
$requests = $this->requests->where('user_id', $user->id);
|
||||
|
||||
return $requests->count() > 0;
|
||||
}
|
||||
|
||||
public function scopeRequestedBy($query, User $user)
|
||||
|
||||
+41
-21
@@ -14,36 +14,30 @@ class Setting extends Model
|
||||
|
||||
protected $rules = [
|
||||
"brand" => 'required|min:1|numeric',
|
||||
"qr_text" => 'max:31',
|
||||
"qr_text" => 'max:31|nullable',
|
||||
"logo_img" => 'mimes:jpeg,bmp,png,gif',
|
||||
"alert_email" => 'email_array',
|
||||
"alert_email" => 'email_array|nullable',
|
||||
"default_currency" => 'required',
|
||||
"locale" => 'required',
|
||||
"slack_endpoint" => 'url|required_with:slack_channel',
|
||||
"slack_channel" => 'regex:/(?<!\w)#\w+/|required_with:slack_endpoint',
|
||||
"slack_endpoint" => 'url|required_with:slack_channel|nullable',
|
||||
"slack_channel" => 'regex:/(?<!\w)#\w+/|required_with:slack_endpoint|nullable',
|
||||
"slack_botname" => 'string|nullable',
|
||||
'labels_per_page' => 'numeric',
|
||||
'labels_width' => 'numeric',
|
||||
'labels_height' => 'numeric',
|
||||
'labels_pmargin_left' => 'numeric',
|
||||
'labels_pmargin_right' => 'numeric',
|
||||
'labels_pmargin_top' => 'numeric',
|
||||
'labels_pmargin_bottom' => 'numeric',
|
||||
'labels_display_bgutter' => 'numeric',
|
||||
'labels_display_sgutter' => 'numeric',
|
||||
'labels_pmargin_left' => 'numeric|nullable',
|
||||
'labels_pmargin_right' => 'numeric|nullable',
|
||||
'labels_pmargin_top' => 'numeric|nullable',
|
||||
'labels_pmargin_bottom' => 'numeric|nullable',
|
||||
'labels_display_bgutter' => 'numeric|nullable',
|
||||
'labels_display_sgutter' => 'numeric|nullable',
|
||||
'labels_fontsize' => 'numeric|min:5',
|
||||
'labels_pagewidth' => 'numeric',
|
||||
'labels_pageheight' => 'numeric',
|
||||
"ldap_server" => 'sometimes|required_if:ldap_enabled,1|url',
|
||||
"ldap_uname" => 'sometimes|required_if:ldap_enabled,1',
|
||||
"ldap_basedn" => 'sometimes|required_if:ldap_enabled,1',
|
||||
"ldap_filter" => 'sometimes|required_if:ldap_enabled,1',
|
||||
"ldap_username_field" => 'sometimes|required_if:ldap_enabled,1',
|
||||
"ldap_fname_field" => 'sometimes|required_if:ldap_enabled,1',
|
||||
"ldap_lname_field" => 'sometimes|required_if:ldap_enabled,1',
|
||||
"ldap_auth_filter_query" => 'sometimes|required_if:ldap_enabled,1',
|
||||
"ldap_version" => 'sometimes|required_if:ldap_enabled,1',
|
||||
'labels_pagewidth' => 'numeric|nullable',
|
||||
'labels_pageheight' => 'numeric|nullable',
|
||||
"thumbnail_max_h" => 'numeric|max:500|min:25',
|
||||
"pwd_secure_min" => "numeric|required|min:5",
|
||||
"audit_warning_days" => "numeric|nullable",
|
||||
"audit_interval" => "numeric|nullable",
|
||||
];
|
||||
|
||||
protected $fillable = ['site_name','email_domain','email_format','username_format'];
|
||||
@@ -158,4 +152,30 @@ class Setting extends Model
|
||||
// In the future this may want to be adapted for individual notifications.
|
||||
return $this->slack_endpoint;
|
||||
}
|
||||
|
||||
public static function passwordComplexityRulesSaving($action = 'update')
|
||||
{
|
||||
$security_rules = '';
|
||||
$settings = Setting::getSettings();
|
||||
|
||||
// Check if they have uncommon password enforcement selected in settings
|
||||
if ($settings->pwd_secure_uncommon == 1) {
|
||||
$security_rules .= '|dumbpwd';
|
||||
}
|
||||
|
||||
// Check for any secure password complexity rules that may have been selected
|
||||
if ($settings->pwd_secure_complexity!='') {
|
||||
$security_rules .= '|'.$settings->pwd_secure_complexity;
|
||||
}
|
||||
|
||||
if ($action == 'update') {
|
||||
return 'nullable|min:'.$settings->pwd_secure_min.$security_rules;
|
||||
}
|
||||
|
||||
return 'required|min:'.$settings->pwd_secure_min.$security_rules;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -77,6 +77,25 @@ class SnipeModel extends Model
|
||||
return;
|
||||
}
|
||||
|
||||
public function setMinAmtAttribute($value)
|
||||
{
|
||||
if ($value == '') {
|
||||
$value = null;
|
||||
}
|
||||
$this->attributes['min_amt'] = $value;
|
||||
return;
|
||||
}
|
||||
|
||||
public function setParentIdAttribute($value)
|
||||
{
|
||||
if ($value == '') {
|
||||
$value = null;
|
||||
}
|
||||
$this->attributes['parent_id'] = $value;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
public function getDisplayNameAttribute()
|
||||
{
|
||||
|
||||
@@ -45,7 +45,7 @@ class Supplier extends SnipeModel
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = ['name'];
|
||||
protected $fillable = ['name','address','address2','city','state','country','zip','phone','fax','email','contact','url','notes'];
|
||||
|
||||
|
||||
// Eager load counts.
|
||||
|
||||
+10
-2
@@ -51,9 +51,9 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo
|
||||
protected $rules = [
|
||||
'first_name' => 'required|string|min:1',
|
||||
'username' => 'required|string|min:1|unique_undeleted',
|
||||
'email' => 'email',
|
||||
'email' => 'email|nullable',
|
||||
'password' => 'required|min:6',
|
||||
'locale' => 'max:10'
|
||||
'locale' => 'max:10|nullable'
|
||||
];
|
||||
|
||||
|
||||
@@ -205,6 +205,14 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo
|
||||
return $this->belongsTo('\App\Models\User', 'manager_id')->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any locations the user manages.
|
||||
**/
|
||||
public function managedLocations()
|
||||
{
|
||||
return $this->hasMany('\App\Models\Location', 'manager_id')->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user groups
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use App\Models\Setting;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Messages\SlackMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
|
||||
class AuditNotification extends Notification
|
||||
{
|
||||
use Queueable;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
private $params;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @param $params
|
||||
*/
|
||||
public function __construct($params)
|
||||
{
|
||||
//
|
||||
$this->params = $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function via($notifiable)
|
||||
{
|
||||
$notifyBy = [];
|
||||
if (Setting::getSettings()->slack_endpoint) {
|
||||
$notifyBy[] = 'slack';
|
||||
}
|
||||
|
||||
return $notifyBy;
|
||||
}
|
||||
|
||||
public function toSlack($notifiable)
|
||||
{
|
||||
|
||||
return (new SlackMessage)
|
||||
->success()
|
||||
->content(class_basename(get_class($this->params['item'])) . " Audited")
|
||||
->attachment(function ($attachment) use ($notifiable) {
|
||||
$item = $this->params['item'];
|
||||
$admin_user = $this->params['admin'];
|
||||
$fields = [
|
||||
'By' => '<'.$admin_user->present()->viewUrl().'|'.$admin_user->present()->fullName().'>'
|
||||
];
|
||||
array_key_exists('note', $this->params) && $fields['Notes'] = $this->params['note'];
|
||||
array_key_exists('location', $this->params) && $fields['Location'] = $this->params['location'];
|
||||
|
||||
$attachment->title($item->present()->name, $item->present()->viewUrl())
|
||||
->fields($fields);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return \Illuminate\Notifications\Messages\MailMessage
|
||||
*/
|
||||
public function toMail($notifiable)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($notifiable)
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -5,10 +5,11 @@ namespace App\Notifications;
|
||||
use App\Models\Setting;
|
||||
use App\Models\SnipeModel;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Messages\SlackMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Messages\SlackMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
class CheckoutNotification extends Notification
|
||||
{
|
||||
@@ -43,11 +44,12 @@ class CheckoutNotification extends Notification
|
||||
}
|
||||
$item = $this->params['item'];
|
||||
|
||||
if ((method_exists($item, 'requireAcceptance') && ($item->requireAcceptance()=='1'))
|
||||
|| (method_exists($item, 'getEula') && ($item->getEula()))
|
||||
) {
|
||||
$notifyBy[] = 'mail';
|
||||
}
|
||||
$notifyBy[]='mail';
|
||||
// if ((method_exists($item, 'requireAcceptance') && ($item->requireAcceptance()=='1'))
|
||||
// || (method_exists($item, 'getEula') && ($item->getEula()))
|
||||
// ) {
|
||||
// $notifyBy[] = 'mail';
|
||||
// }
|
||||
return $notifyBy;
|
||||
}
|
||||
|
||||
@@ -79,10 +81,30 @@ class CheckoutNotification extends Notification
|
||||
*/
|
||||
public function toMail($notifiable)
|
||||
{
|
||||
//TODO: Expand for non assets.
|
||||
$item = $this->params['item'];
|
||||
$admin_user = $this->params['admin'];
|
||||
$target = $this->params['target'];
|
||||
$data = [
|
||||
'eula' => method_exists($item, 'getEula') ? $item->getEula() : '',
|
||||
'first_name' => $target->present()->fullName(),
|
||||
'item_name' => $item->present()->name(),
|
||||
'checkout_date' => $item->last_checkout,
|
||||
'expected_checkin' => $item->expected_checkin,
|
||||
'item_tag' => $item->asset_tag,
|
||||
'note' => $this->params['note'],
|
||||
'item_serial' => $item->serial,
|
||||
'require_acceptance' => method_exists($item, 'requireAcceptance') ? $item->requireAcceptance() : '',
|
||||
'log_id' => $this->params['log_id'],
|
||||
];
|
||||
return (new MailMessage)
|
||||
->line('The introduction to the notification.')
|
||||
->action('Notification Action', 'https://laravel.com')
|
||||
->line('Thank you for using our application!');
|
||||
->view('emails.accept-asset', $data)
|
||||
->subject(trans('mail.Confirm_asset_delivery'));
|
||||
// \Mail::send('emails.accept-asset', $data, function ($m) use ($target) {
|
||||
// $m->to($target->email, $target->first_name . ' ' . $target->last_name);
|
||||
// $m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
|
||||
// $m->subject(trans('mail.Confirm_asset_delivery'));
|
||||
// });
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use App\Models\Setting;
|
||||
use App\Models\SnipeModel;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class ExpectedCheckinNotification extends Notification
|
||||
{
|
||||
use Queueable;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
private $params;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @param $params
|
||||
*/
|
||||
public function __construct($params)
|
||||
{
|
||||
$this->params = $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function via($notifiable)
|
||||
{
|
||||
$notifyBy = [];
|
||||
$item = $this->params['item'];
|
||||
|
||||
$notifyBy[]='mail';
|
||||
return $notifyBy;
|
||||
}
|
||||
|
||||
public function toSlack($notifiable)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*
|
||||
* @param mixed $asset
|
||||
* @return \Illuminate\Notifications\Messages\MailMessage
|
||||
*/
|
||||
public function toMail($params)
|
||||
{
|
||||
$formatted_due = Carbon::parse($this->params->expected_checkin)->format('D, M j, Y');
|
||||
return (new MailMessage)
|
||||
->error()
|
||||
->subject('Reminder: '.$this->params->present()->name().' checkin deadline approaching')
|
||||
->line('Hi, '.$this->params->assignedto->first_name)
|
||||
->greeting('An asset checked out to you is due to be checked back in on '.$formatted_due.'.')
|
||||
->line('Asset: '.$this->params->present()->name())
|
||||
->line('Serial: '.$this->params->serial)
|
||||
->line('Asset Tag: '.$this->params->asset_tag)
|
||||
->action('View Your Assets', route('view-assets'));
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($notifiable)
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -28,8 +28,7 @@ class AccessoryObserver
|
||||
|
||||
|
||||
/**
|
||||
* Listen to the Accessory created event, and increment
|
||||
* the next_auto_tag_base value in the settings table when i
|
||||
* Listen to the Accessory created event when
|
||||
* a new accessory is created.
|
||||
*
|
||||
* @param Accessory $accessory
|
||||
@@ -37,9 +36,6 @@ class AccessoryObserver
|
||||
*/
|
||||
public function created(Accessory $accessory)
|
||||
{
|
||||
$settings = Setting::first();
|
||||
$settings->increment('next_auto_tag_base');
|
||||
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = Accessory::class;
|
||||
$logAction->item_id = $accessory->id;
|
||||
|
||||
@@ -18,7 +18,9 @@ class AssetObserver
|
||||
public function updating(Asset $asset)
|
||||
{
|
||||
|
||||
if (($asset->getAttributes()['assigned_to'] == $asset->getOriginal()['assigned_to'])
|
||||
|
||||
if ((isset($asset->getOriginal()['assigned_to'])) && ($asset->getAttributes()['assigned_to'] == $asset->getOriginal()['assigned_to'])
|
||||
&& ($asset->getAttributes()['next_audit_date'] == $asset->getOriginal()['next_audit_date'])
|
||||
&& ($asset->getAttributes()['last_checkout'] == $asset->getOriginal()['last_checkout'])
|
||||
&& ($asset->getAttributes()['status_id'] == $asset->getOriginal()['status_id']))
|
||||
{
|
||||
@@ -43,8 +45,9 @@ class AssetObserver
|
||||
*/
|
||||
public function created(Asset $asset)
|
||||
{
|
||||
$settings = Setting::first();
|
||||
$settings->increment('next_auto_tag_base');
|
||||
if ($settings = Setting::first()) {
|
||||
$settings->increment('next_auto_tag_base');
|
||||
}
|
||||
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = Asset::class;
|
||||
|
||||
@@ -28,8 +28,7 @@ class ComponentObserver
|
||||
|
||||
|
||||
/**
|
||||
* Listen to the Component created event, and increment
|
||||
* the next_auto_tag_base value in the settings table when i
|
||||
* Listen to the Component created event when
|
||||
* a new component is created.
|
||||
*
|
||||
* @param Component $component
|
||||
@@ -37,9 +36,6 @@ class ComponentObserver
|
||||
*/
|
||||
public function created(Component $component)
|
||||
{
|
||||
$settings = Setting::first();
|
||||
$settings->increment('next_auto_tag_base');
|
||||
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = Component::class;
|
||||
$logAction->item_id = $component->id;
|
||||
|
||||
@@ -28,8 +28,7 @@ class ConsumableObserver
|
||||
|
||||
|
||||
/**
|
||||
* Listen to the Consumable created event, and increment
|
||||
* the next_auto_tag_base value in the settings table when i
|
||||
* Listen to the Consumable created event when
|
||||
* a new consumable is created.
|
||||
*
|
||||
* @param Consumable $consumable
|
||||
@@ -37,8 +36,6 @@ class ConsumableObserver
|
||||
*/
|
||||
public function created(Consumable $consumable)
|
||||
{
|
||||
$settings = Setting::first();
|
||||
$settings->increment('next_auto_tag_base');
|
||||
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = Consumable::class;
|
||||
|
||||
@@ -28,8 +28,7 @@ class LicenseObserver
|
||||
|
||||
|
||||
/**
|
||||
* Listen to the License created event, and increment
|
||||
* the next_auto_tag_base value in the settings table when i
|
||||
* Listen to the License created event when
|
||||
* a new license is created.
|
||||
*
|
||||
* @param License $license
|
||||
@@ -37,8 +36,6 @@ class LicenseObserver
|
||||
*/
|
||||
public function created(License $license)
|
||||
{
|
||||
$settings = Setting::first();
|
||||
$settings->increment('next_auto_tag_base');
|
||||
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = License::class;
|
||||
|
||||
@@ -98,15 +98,14 @@ class AssetPresenter extends Presenter
|
||||
"sortable" => true,
|
||||
"title" => trans('admin/hardware/form.checkedout_to'),
|
||||
"visible" => true,
|
||||
"formatter" => "usersLinkObjFormatter"
|
||||
"formatter" => "polymorphicItemFormatter"
|
||||
], [
|
||||
"field" => "assigned_to",
|
||||
"field" => "employee_number",
|
||||
"searchable" => false,
|
||||
"sortable" => false,
|
||||
"title" => trans('admin/users/table.employee_num'),
|
||||
"visible" => false,
|
||||
"formatter" => "employeeNumFormatter"
|
||||
|
||||
],[
|
||||
"field" => "location",
|
||||
"searchable" => true,
|
||||
|
||||
@@ -61,6 +61,14 @@ class LicensePresenter extends Presenter
|
||||
"searchable" => true,
|
||||
"sortable" => true,
|
||||
"title" => trans('admin/licenses/form.to_name'),
|
||||
], [
|
||||
"field" => "supplier",
|
||||
"searchable" => true,
|
||||
"sortable" => true,
|
||||
"switchable" => true,
|
||||
"title" => trans('general.supplier'),
|
||||
"visible" => false,
|
||||
"formatter" => "suppliersLinkObjFormatter"
|
||||
], [
|
||||
"field" => "manufacturer",
|
||||
"searchable" => true,
|
||||
@@ -138,6 +146,16 @@ class LicensePresenter extends Presenter
|
||||
return (string)link_to_route('licenses.show', $this->name, $this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Link to this licenses Name
|
||||
* @return string
|
||||
*/
|
||||
public function fullName()
|
||||
{
|
||||
return 'poop';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Link to this licenses serial
|
||||
* @return string
|
||||
|
||||
@@ -42,4 +42,8 @@ class LocationPresenter extends Presenter
|
||||
{
|
||||
return '<i class="fa fa-globe"></i>';
|
||||
}
|
||||
|
||||
public function fullName() {
|
||||
return $this->name;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,11 @@ abstract class Presenter
|
||||
return '';
|
||||
}
|
||||
|
||||
public function name()
|
||||
{
|
||||
return $this->model->name;
|
||||
}
|
||||
|
||||
public function __get($property)
|
||||
{
|
||||
if (method_exists($this, $property)) {
|
||||
|
||||
@@ -67,11 +67,15 @@ class AppServiceProvider extends ServiceProvider
|
||||
// This works around the use case where multiple deleted items have the same unique attribute.
|
||||
// (I think this is a bug in Laravel's validator?)
|
||||
Validator::extend('unique_undeleted', function ($attribute, $value, $parameters, $validator) {
|
||||
$count = DB::table($parameters[0])->select('id')->where($attribute, '=', $value)->whereNull('deleted_at')->where('id', '!=', $parameters[1])->count();
|
||||
return $count < 1;
|
||||
|
||||
if (count($parameters)) {
|
||||
$count = DB::table($parameters[0])->select('id')->where($attribute, '=', $value)->whereNull('deleted_at')->where('id', '!=', $parameters[1])->count();
|
||||
return $count < 1;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Share common variables with all views.
|
||||
// Share common setting variables with all views.
|
||||
view()->composer('*', function ($view) {
|
||||
$view->with('snipeSettings', \App\Models\Setting::getSettings());
|
||||
});
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
{"version":3,"file":"css/AdminLTE.css","sources":[],"mappings":";;;;;;","sourceRoot":""}
|
||||
{"version":3,"file":"css/AdminLTE.css","sources":[],"mappings":";;;;;;A","sourceRoot":""}
|
||||
+3
-3
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
{"version":3,"file":"css/app.css","sources":[],"mappings":";;;;;;;;","sourceRoot":""}
|
||||
{"version":3,"file":"css/app.css","sources":[],"mappings":";;;;;;;;A","sourceRoot":""}
|
||||
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user