Compare commits
203 Commits
v4.0-beta2
...
v4.0.5
| 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 | |||
| 5347b19910 | |||
| 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 |
@@ -728,6 +728,33 @@
|
||||
"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,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)
|
||||
[](#contributors)
|
||||
|
||||
|
||||
## Snipe-IT - Open Source Asset Management System
|
||||
@@ -67,7 +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://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!
|
||||
@@ -76,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.
|
||||
|
||||
@@ -47,6 +47,7 @@ class RecryptFromMcrypt extends Command
|
||||
// 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) {
|
||||
@@ -54,11 +55,23 @@ class RecryptFromMcrypt extends Command
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that the app key is 32 characters
|
||||
|
||||
// Do some basic legacy app key length checks
|
||||
if (strlen($legacy_key) == 32) {
|
||||
$this->comment('INFO: Your LEGACY_APP_KEY is 32 characters. Okay to continue.');
|
||||
$legacy_length_check = true;
|
||||
} elseif (array_key_exists('1', $key_parts) && (strlen($key_parts[1])==44)) {
|
||||
$legacy_length_check = true;
|
||||
} else {
|
||||
$this->error('ERROR: Your LEGACY_APP_KEY is not the correct length (32 characters). Please locate your old APP_KEY and use that as your LEGACY_APP_KEY in your .env file to continue.');
|
||||
$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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,6 +17,7 @@ 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,
|
||||
@@ -38,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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
<?php
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Models\AssetMaintenance;
|
||||
use Carbon\Carbon;
|
||||
use App\Models\Company;
|
||||
use App\Models\Asset;
|
||||
use App\Helpers\Helper;
|
||||
use Auth;
|
||||
use Gate;
|
||||
use Illuminate\Http\Request;
|
||||
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
|
||||
|
||||
@@ -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'));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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'));
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -9,6 +9,7 @@ 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
|
||||
{
|
||||
@@ -51,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'));
|
||||
}
|
||||
@@ -182,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')!='') {
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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';
|
||||
@@ -336,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');
|
||||
|
||||
@@ -561,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')
|
||||
@@ -988,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')
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,14 +34,14 @@ class SaveUserRequest extends Request
|
||||
case 'POST':
|
||||
{
|
||||
$rules['first_name'] = 'required|string|min:1';
|
||||
$rules['username'] = '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|string|min:1';
|
||||
$rules['username'] = 'required_unless:ldap_import,1|string|min:1';
|
||||
$rules['password'] = Setting::passwordComplexityRulesSaving('update');
|
||||
|
||||
// Save only what's passed
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
|
||||
];
|
||||
|
||||
@@ -38,6 +38,7 @@ class AssetMaintenancesTransformer
|
||||
];
|
||||
|
||||
$permissions_array['available_actions'] = [
|
||||
'update' => (bool) Gate::allows('update', Asset::class),
|
||||
'delete' => (bool) Gate::allows('delete', Asset::class),
|
||||
];
|
||||
|
||||
|
||||
@@ -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()})) {
|
||||
@@ -130,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,16 +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' => ($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,
|
||||
];
|
||||
|
||||
|
||||
@@ -56,9 +56,10 @@ 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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
+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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
-46
@@ -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,52 +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
|
||||
];
|
||||
|
||||
if ($settings = Setting::getSettings()) {
|
||||
$settings->notify(new CheckoutNotification($params));
|
||||
}
|
||||
|
||||
return $log;
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Daniel Meltzer <parallelgrapefruit@gmail.com
|
||||
* @since [v3.4]
|
||||
@@ -120,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)
|
||||
|
||||
@@ -34,17 +34,10 @@ class Setting extends Model
|
||||
'labels_fontsize' => 'numeric|min:5',
|
||||
'labels_pagewidth' => 'numeric|nullable',
|
||||
'labels_pageheight' => 'numeric|nullable',
|
||||
"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',
|
||||
"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'];
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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 [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ class AssetObserver
|
||||
|
||||
|
||||
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']))
|
||||
{
|
||||
|
||||
@@ -98,7 +98,7 @@ class AssetPresenter extends Presenter
|
||||
"sortable" => true,
|
||||
"title" => trans('admin/hardware/form.checkedout_to'),
|
||||
"visible" => true,
|
||||
"formatter" => "usersLinkObjFormatter"
|
||||
"formatter" => "polymorphicItemFormatter"
|
||||
], [
|
||||
"field" => "employee_number",
|
||||
"searchable" => false,
|
||||
|
||||
@@ -146,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)) {
|
||||
|
||||
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
+10
-21
@@ -1,23 +1,12 @@
|
||||
{
|
||||
"/build/vue.js": "/build/vue.js",
|
||||
"/mix.js": "/mix.js",
|
||||
"/build/app.css": "/build/app.535d8af1016a2377e449920c617f0197.css",
|
||||
"/build/AdminLTE.css": "/build/AdminLTE.3d8a2b2e33baa060b1b324363ad5e1c2.css",
|
||||
"/build/overrides.css": "/build/overrides.617623c6a96be3e0cbd11c5d4039ec10.css",
|
||||
"/css/all.css": "/css/all.css",
|
||||
"/js/all.js": "/js/all.js",
|
||||
"/css/app.css": "/css/app.css",
|
||||
"/css/dist/all.css": "/css/dist/all.css",
|
||||
"/js/dist/all.js": "/js/dist/all.js",
|
||||
"/css/AdminLTE.css": "/css/AdminLTE.css",
|
||||
"/css/overrides.css": "/css/overrides.css",
|
||||
"/css/skin-blue.css": "/css/skin-blue.css",
|
||||
"/vue.js": "/vue.js",
|
||||
"/vue.js.map": "/vue.js.map",
|
||||
"/mix.js.map": "/mix.js.map",
|
||||
"/css/AdminLTE.css.map": "/css/AdminLTE.css.map",
|
||||
"/css/app.css.map": "/css/app.css.map",
|
||||
"/css/overrides.css.map": "/css/overrides.css.map",
|
||||
"public/css/dist/all.css": "public/css/dist/all.css",
|
||||
"public/js/dist/all.js": "public/js/dist/all.js"
|
||||
"/vue.js": "/vue.js",
|
||||
"/css/AdminLTE.css": "/css/AdminLTE.css",
|
||||
"/css/app.css": "/css/app.css",
|
||||
"/css/overrides.css": "/css/overrides.css",
|
||||
"/vue.js.map": "/vue.js.map",
|
||||
"/css/AdminLTE.css.map": "/css/AdminLTE.css.map",
|
||||
"/css/app.css.map": "/css/app.css.map",
|
||||
"/css/overrides.css.map": "/css/overrides.css.map",
|
||||
"/public/css/dist/all.css": "/public/css/dist/all.css",
|
||||
"/public/js/dist/all.js": "/public/js/dist/all.js"
|
||||
}
|
||||
+1
-63
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
@@ -155,6 +155,21 @@ return [
|
||||
'allow_iframing' => env('ALLOW_IFRAMING', false),
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| REFERRER-POLICY
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This is an additional security header that browsers use to determine
|
||||
| whether they should report back URL referrer information.
|
||||
|
|
||||
| Read more: https://www.w3.org/TR/referrer-policy/
|
||||
|
|
||||
*/
|
||||
|
||||
'referrer_policy' => env('REFERRER_POLICY', 'strict-origin'),
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Demo Mode Lockdown
|
||||
|
||||
+2
-2
@@ -65,8 +65,8 @@ return [
|
||||
'database' => env('DB_DATABASE', 'forge'),
|
||||
'username' => env('DB_USERNAME', 'forge'),
|
||||
'password' => env('DB_PASSWORD', ''),
|
||||
'charset' => 'utf8mb4',
|
||||
'collation' => 'utf8mb4_unicode_ci',
|
||||
'charset' => env('DB_CHARSET', 'utf8mb4'),
|
||||
'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
|
||||
'prefix' => env('DB_PREFIX', null),
|
||||
'strict' => false,
|
||||
'engine' => null,
|
||||
|
||||
@@ -22,6 +22,8 @@ return [
|
||||
base_path('public/uploads'),
|
||||
base_path('config'),
|
||||
base_path('storage/private_uploads'),
|
||||
base_path('storage/oauth-private.key'),
|
||||
base_path('storage/oauth-public.key'),
|
||||
],
|
||||
|
||||
/*
|
||||
|
||||
@@ -85,8 +85,8 @@ return array(
|
||||
array(
|
||||
'permission' => 'assets.audit',
|
||||
'label' => 'Audit ',
|
||||
'note' => '',
|
||||
'display' => false,
|
||||
'note' => 'Allows the user to mark an asset as physically inventoried.',
|
||||
'display' => true,
|
||||
),
|
||||
|
||||
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
return array (
|
||||
'app_version' => 'v4.0',
|
||||
'build_version' => 'beta 2',
|
||||
'hash_version' => '46',
|
||||
'full_hash' => 'v4.0-beta-246-g73ce5f9',
|
||||
'app_version' => 'v4.0.5',
|
||||
'build_version' => '40',
|
||||
'hash_version' => 'g42c2a66',
|
||||
'full_hash' => 'v4.0.5-40-g42c2a66',
|
||||
);
|
||||
|
||||
@@ -20,7 +20,7 @@ $factory->defineAs(Actionlog::class, 'asset-checkout', function (Faker\Generator
|
||||
$user = factory(App\Models\User::class)->create(['company_id' => $company->id]);
|
||||
$target = factory(App\Models\User::class)->create(['company_id' => $company->id]);
|
||||
// $item = factory(App\Models\Asset::class)->create(['company_id' => $company->id]);
|
||||
|
||||
// dd($item);
|
||||
return [
|
||||
'user_id' => $user->id,
|
||||
'action_type' => 'checkout',
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Category;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -69,6 +71,13 @@ $factory->state(Asset::class, 'assigned-to-asset', function ($faker) {
|
||||
];
|
||||
});
|
||||
|
||||
$factory->state(Asset::class, 'requires-acceptance', function ($faker) {
|
||||
$cat = factory(Category::class)->states('asset-category', 'requires-acceptance')->create();
|
||||
$model = factory(AssetModel::class)->create(['category_id' => $cat->id]);
|
||||
return [
|
||||
'model_id' => $model->id
|
||||
];
|
||||
});
|
||||
|
||||
$factory->define(App\Models\AssetModel::class, function (Faker\Generator $faker) {
|
||||
return [
|
||||
|
||||
@@ -15,7 +15,7 @@ $factory->define(App\Models\Category::class, function (Faker\Generator $faker) {
|
||||
'name' => $faker->text(20),
|
||||
'category_type' => $faker->randomElement(['asset', 'accessory', 'component', 'consumable']),
|
||||
'eula_text' => $faker->paragraph(),
|
||||
'require_acceptance' => $faker->boolean(),
|
||||
'require_acceptance' => false,
|
||||
'use_default_eula' => $faker->boolean(),
|
||||
'checkin_email' => $faker->boolean()
|
||||
];
|
||||
@@ -44,3 +44,9 @@ $factory->state(App\Models\Category::class, 'consumable-category', function ($fa
|
||||
'category_type' => 'consumable',
|
||||
];
|
||||
});
|
||||
|
||||
$factory->state(App\Models\Category::class, 'requires-acceptance', function ($faker) {
|
||||
return [
|
||||
'require_acceptance' => true,
|
||||
];
|
||||
});
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
|
||||
$factory->define(App\Models\CustomField::class, function (Faker\Generator $faker) {
|
||||
return [
|
||||
'name' => $faker->catchPhrase,
|
||||
'format' => 'IP',
|
||||
'element' => 'text',
|
||||
];
|
||||
});
|
||||
|
||||
$factory->define(App\Models\CustomFieldset::class, function (Faker\Generator $faker) {
|
||||
return [
|
||||
'name' => $faker->catchPhrase,
|
||||
'user_id' => Auth::id()
|
||||
];
|
||||
});
|
||||
@@ -97,14 +97,6 @@ $factory->define(App\Models\Consumable::class, function (Faker\Generator $faker)
|
||||
];
|
||||
});
|
||||
|
||||
$factory->define(App\Models\CustomField::class, function (Faker\Generator $faker) {
|
||||
return [
|
||||
'name' => $faker->catchPhrase,
|
||||
'format' => 'IP',
|
||||
'element' => 'text',
|
||||
];
|
||||
});
|
||||
|
||||
$factory->define(App\Models\Department::class, function (Faker\Generator $faker) {
|
||||
return [
|
||||
'name' => $faker->catchPhrase,
|
||||
@@ -210,5 +202,6 @@ $factory->define(App\Models\Setting::class, function ($faker) {
|
||||
'brand' => 1,
|
||||
'default_currency' => $faker->currencyCode,
|
||||
'locale' => $faker->locale,
|
||||
'pwd_secure_min' => 5,
|
||||
];
|
||||
});
|
||||
|
||||
@@ -12,10 +12,13 @@ class AddSoftDeletedToLog extends Migration {
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
|
||||
Schema::table('asset_logs', function ($table) {
|
||||
$table->string('asset_type',100)->nullable()->change();
|
||||
});
|
||||
|
||||
$platform = Schema::getConnection()->getDoctrineSchemaManager()->getDatabasePlatform();
|
||||
$platform->registerDoctrineTypeMapping('enum', 'string');
|
||||
|
||||
Schema::table('asset_logs', function ($table) {
|
||||
$table->string('asset_type',100)->nullable()->change();
|
||||
});
|
||||
|
||||
// DB::statement('ALTER TABLE ' . DB::getTablePrefix() . 'asset_logs MODIFY column asset_type varchar(100) null');
|
||||
// DB::statement('ALTER TABLE ' . DB::getTablePrefix() . 'asset_logs MODIFY column added_on timestamp default "0000-00-00 00:00:00"');
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddManagerToLocationsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('locations', function (Blueprint $table) {
|
||||
//
|
||||
$table->integer('manager_id')->nullable()->default(null);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('locations', function (Blueprint $table) {
|
||||
//
|
||||
$table->dropColumn('manager_id');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,9 @@ class SetAssetArchivedToZeroDefault extends Migration
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
$platform = Schema::getConnection()->getDoctrineSchemaManager()->getDatabasePlatform();
|
||||
$platform->registerDoctrineTypeMapping('enum', 'string');
|
||||
|
||||
Schema::table('assets', function (Blueprint $table) {
|
||||
$table->boolean('archived')->default(0)->change();
|
||||
});
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddAuditingTables extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('assets', function (Blueprint $table) {
|
||||
$table->date('next_audit_date')->nullable()->default(NULL);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('assets', function (Blueprint $table) {
|
||||
$table->dropColumn('next_audit_date');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddAuditingToSettings extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
$table->integer('audit_interval')->nullable()->default(NULL);
|
||||
$table->integer('audit_warning_days')->nullable()->default(NULL);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
$table->dropColumn('audit_interval');
|
||||
$table->dropColumn('audit_warning_days');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Asset;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class FixAssignedTypeNotBeingNulled extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
* There was a point in the v4 beta process where assigned_type was not nulled on checkin
|
||||
* This manually nulls all assets where there is an assigned_type but not an assigned_to.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
// There was a point in the v4 beta process where assigned_type was not nulled on checkin
|
||||
// This manually nulls all assets where there is an assigned_type but not an assigned_to.
|
||||
Asset::whereNotNull('assigned_type')->whereNull('assigned_to')->update(['assigned_type' => null]);
|
||||
|
||||
// Additionally, the importer did not set assigned_type when importing.
|
||||
// In the case where we have an assigned_to but not an assigned_type, set the assigned_type to User.
|
||||
Asset::whereNotNull('assigned_to')->whereNull('assigned_type')->update(['assigned_type' => 'App\Models\User']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
-80
@@ -1,80 +0,0 @@
|
||||
var elixir = require('laravel-elixir');
|
||||
require('laravel-elixir-codeception-standalone');
|
||||
require('laravel-elixir-phpcs');
|
||||
require('laravel-elixir-vue-2');
|
||||
var bowerPath = './bower_components';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Elixir Asset Management
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Elixir provides a clean, fluent API for defining some basic Gulp tasks
|
||||
| for your Laravel application. By default, we are compiling the Sass
|
||||
| file for our application, as well as publishing vendor resources.
|
||||
|
|
||||
*/
|
||||
|
||||
|
||||
elixir(function(mix) {
|
||||
|
||||
mix.less(
|
||||
[
|
||||
'app.less',
|
||||
bowerPath + '/iCheck/skins/minimal/*',
|
||||
'AdminLTE.less',
|
||||
'skins/skin-blue.less',
|
||||
'overrides.less'
|
||||
], 'public/assets/css/')
|
||||
.copy(bowerPath + '/bootstrap-less/assets/fonts/bootstrap/**', 'public/assets/fonts')
|
||||
.copy(bowerPath + '/font-awesome/fonts/*', 'public/build/fonts');
|
||||
|
||||
|
||||
|
||||
mix.webpack(
|
||||
// jQuery is loaded from vue.js webpack process
|
||||
'./resources/assets/js/vue.js',
|
||||
'./resources/assets/js/vue-dist.js'
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
mix.scripts([
|
||||
bowerPath + '/tether/dist/js/tether.js',
|
||||
'vue-dist.js',
|
||||
bowerPath + '/jquery-ui/jquery-ui.js',
|
||||
bowerPath + '/jquery-slimscroll/jquery.slimscroll.js',
|
||||
bowerPath + '/jquery.iframe-transport/jquery.iframe-transport.js',
|
||||
bowerPath + '/blueimp-file-upload/js/jquery.fileupload.js',
|
||||
bowerPath + '/fastclick/lib/fastclick.js',
|
||||
bowerPath + '/bootstrap-colorpicker/dist/js/bootstrap-colorpicker.js',
|
||||
bowerPath + '/bootstrap-datepicker/dist/js/bootstrap-datepicker.js',
|
||||
bowerPath + '/iCheck/icheck.js',
|
||||
bowerPath + '/select2/dist/js/select2.full.js',
|
||||
bowerPath + '/ekko-lightbox/dist/ekko-lightbox.js',
|
||||
'snipeit.js',
|
||||
'app.js'
|
||||
|
||||
],'public/assets/js');
|
||||
mix.version(['assets/css/app.css','assets/js/all.js']);
|
||||
|
||||
|
||||
// mix.codeception(null, { flags: '--report' });
|
||||
|
||||
|
||||
// mix.phpcs([
|
||||
// 'app/**/*.php',
|
||||
// 'tests/unit/*.php',
|
||||
// 'tests/functional/*.php',
|
||||
// 'tests/acceptance/*.php'
|
||||
// ], {
|
||||
// bin: 'vendor/bin/phpcs',
|
||||
// standard: 'PSR2'
|
||||
// });
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
+7
-5
@@ -10,14 +10,14 @@
|
||||
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js "
|
||||
},
|
||||
"devDependencies": {
|
||||
"axios": "^0.15.3",
|
||||
"axios": "^0.16.2",
|
||||
"babel-preset-latest": "^6.24.1",
|
||||
"cross-env": "^3.2.4",
|
||||
"cross-env": "^5.0.5",
|
||||
"jquery": "^3.1.1",
|
||||
"laravel-mix": "0.12.1",
|
||||
"laravel-mix": "1.4.3",
|
||||
"lodash": "^4.17.4",
|
||||
"vue": "2.3.3",
|
||||
"vue-template-compiler": "2.3.3"
|
||||
"vue": "2.4.4",
|
||||
"vue-template-compiler": "2.4.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"blueimp-file-upload": "^9.18.0",
|
||||
@@ -32,6 +32,8 @@
|
||||
"jquery-ui": "^1.12.1",
|
||||
"jquery-ui-bundle": "^1.12.1",
|
||||
"jquery.iframe-transport": "^1.0.0",
|
||||
"less": "^2.7.2",
|
||||
"less-loader": "^4.0.5",
|
||||
"papaparse": "^4.3.3",
|
||||
"select2": "^4.0.3",
|
||||
"tether": "^1.4.0",
|
||||
|
||||
Vendored
+5
-7
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