Compare commits
113 Commits
features/a
...
v6.2.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9a1dab827 | ||
|
|
a95fae0e94 | ||
|
|
9596826259 | ||
|
|
8384786e8b | ||
|
|
a5fd218c23 | ||
|
|
d2435c6f86 | ||
|
|
4e6764428e | ||
|
|
c45ede2d17 | ||
|
|
352e53a036 | ||
|
|
581e56198c | ||
|
|
3de656f5c6 | ||
|
|
cfe6b07b3a | ||
|
|
68c9fac971 | ||
|
|
ac7f85fea9 | ||
|
|
3aeea007b2 | ||
|
|
0c31d5749c | ||
|
|
16498fdcf8 | ||
|
|
13bee63fe9 | ||
|
|
5a5b07f5a5 | ||
|
|
d84d26febf | ||
|
|
d7790cd16b | ||
|
|
8ecc0651ed | ||
|
|
8bdecb1da9 | ||
|
|
341f711385 | ||
|
|
9bd357e2d4 | ||
|
|
cce90c6ce0 | ||
|
|
20da6cccbc | ||
|
|
467609e561 | ||
|
|
9c608dd6ff | ||
|
|
5b88089ffc | ||
|
|
cf36c31eac | ||
|
|
2a94fd17ee | ||
|
|
32407b531b | ||
|
|
521fcd45b0 | ||
|
|
faa865fd48 | ||
|
|
2a1aa53ba6 | ||
|
|
821c3085f0 | ||
|
|
587a787b5d | ||
|
|
305804f260 | ||
|
|
319cb2305d | ||
|
|
0f43388a2b | ||
|
|
b93adf44c8 | ||
|
|
a1897298dc | ||
|
|
0a47706e46 | ||
|
|
9f291d7e4b | ||
|
|
bb61134dd5 | ||
|
|
24a9deb735 | ||
|
|
cb3db51fe0 | ||
|
|
8e9fa613e3 | ||
|
|
384428148b | ||
|
|
8810059427 | ||
|
|
2848465dd2 | ||
|
|
06ed8b2f2d | ||
|
|
2ddf5c9a0b | ||
|
|
949a88e560 | ||
|
|
28b1461cb4 | ||
|
|
7504c0df13 | ||
|
|
1c02a7d590 | ||
|
|
8e0b7bee41 | ||
|
|
642a09f139 | ||
|
|
716e13e5b1 | ||
|
|
ec2556f991 | ||
|
|
6134dfa8f2 | ||
|
|
7df3be3a54 | ||
|
|
70903f068c | ||
|
|
5a43c5906f | ||
|
|
4b2bf057c7 | ||
|
|
3091d2cdf0 | ||
|
|
c52a1f94dc | ||
|
|
ff3bdebb9a | ||
|
|
f699d9680b | ||
|
|
d26bc19e3f | ||
|
|
19df0b82b1 | ||
|
|
74a5bcd490 | ||
|
|
bc91181917 | ||
|
|
92e7e79faf | ||
|
|
1fa703387a | ||
|
|
3203f8f97c | ||
|
|
8bc8ecfc67 | ||
|
|
db8c37cd5b | ||
|
|
43d419f051 | ||
|
|
66875ff0dc | ||
|
|
8c74e906ef | ||
|
|
3a6d8ef684 | ||
|
|
a56b040143 | ||
|
|
61fd427678 | ||
|
|
32747cafde | ||
|
|
e18c3e08be | ||
|
|
33b1a31ed3 | ||
|
|
1b71ab6d86 | ||
|
|
af26ec471f | ||
|
|
4dd71e0332 | ||
|
|
4908082240 | ||
|
|
ead5f039b4 | ||
|
|
2c23c71823 | ||
|
|
4cb9c25e83 | ||
|
|
c377e0617c | ||
|
|
2ac4449ea3 | ||
|
|
83708e1be9 | ||
|
|
f552bcef78 | ||
|
|
fc6c5eadd7 | ||
|
|
924d0b25e8 | ||
|
|
fc5b02e392 | ||
|
|
18eda15ec1 | ||
|
|
c05a4452bc | ||
|
|
a3a64be19b | ||
|
|
f1b4bba3ae | ||
|
|
dbae01f545 | ||
|
|
5be993df8d | ||
|
|
37f75c5001 | ||
|
|
b1fda46e11 | ||
|
|
6b7a7b8aee | ||
|
|
63c660f306 |
@@ -2961,42 +2961,6 @@
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Singrity",
|
||||
"name": "Bogdan",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/58479551?v=4",
|
||||
"profile": "http://@singrity",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "mmanjos",
|
||||
"name": "mmanjos",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/3483684?v=4",
|
||||
"profile": "https://github.com/mmanjos",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Azooz2014",
|
||||
"name": "Abdelaziz Faki",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/7429229?v=4",
|
||||
"profile": "https://azooz2014.github.io/",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "bilias",
|
||||
"name": "bilias",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/47315739?v=4",
|
||||
"profile": "https://github.com/bilias",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -159,7 +159,6 @@ LOG_CHANNEL=stderr
|
||||
LOG_MAX_DAYS=10
|
||||
APP_LOCKED=false
|
||||
APP_CIPHER=AES-256-CBC
|
||||
APP_FORCE_TLS=false
|
||||
GOOGLE_MAPS_API=
|
||||
LDAP_MEM_LIM=500M
|
||||
LDAP_TIME_LIM=600
|
||||
|
||||
11
.env.example
11
.env.example
@@ -127,17 +127,6 @@ PUBLIC_AWS_BUCKET=null
|
||||
PUBLIC_AWS_URL=null
|
||||
PUBLIC_AWS_BUCKET_ROOT=null
|
||||
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: Digital Ocean Spaces File Settings
|
||||
# --------------------------------------------
|
||||
DIGITALOCEAN_SPACES_KEY=null
|
||||
DIGITALOCEAN_SPACES_SECRET=null
|
||||
DIGITALOCEAN_SPACES_ENDPOINT=https://region.digitaloceanspaces.com
|
||||
DIGITALOCEAN_SPACES_REGION=null
|
||||
DIGITALOCEAN_SPACES_BUCKET=null
|
||||
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: PRIVATE S3 Settings
|
||||
# --------------------------------------------
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[](https://crowdin.com/project/snipe-it) [](https://hub.docker.com/r/snipe/snipe-it/) [](https://twitter.com/snipeitapp) [](https://www.codacy.com/app/snipe/snipe-it?utm_source=github.com&utm_medium=referral&utm_content=snipe/snipe-it&utm_campaign=Badge_Grade)
|
||||
[](#contributors) [](https://discord.gg/yZFtShAcKk) [](https://huntr.dev)
|
||||
[](#contributors) [](https://discord.gg/yZFtShAcKk) [](https://huntr.dev)
|
||||
|
||||
## Snipe-IT - Open Source Asset Management System
|
||||
|
||||
@@ -145,8 +145,7 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
|
||||
| [<img src="https://avatars.githubusercontent.com/u/28321?v=4" width="110px;"/><br /><sub>Chris Hartjes</sub>](http://www.littlehart.net/atthekeyboard)<br />[💻](https://github.com/snipe/snipe-it/commits?author=chartjes "Code") | [<img src="https://avatars.githubusercontent.com/u/2404584?v=4" width="110px;"/><br /><sub>geo-chen</sub>](https://github.com/geo-chen)<br />[💻](https://github.com/snipe/snipe-it/commits?author=geo-chen "Code") | [<img src="https://avatars.githubusercontent.com/u/6006620?v=4" width="110px;"/><br /><sub>Phan Nguyen</sub>](https://github.com/nh314)<br />[💻](https://github.com/snipe/snipe-it/commits?author=nh314 "Code") | [<img src="https://avatars.githubusercontent.com/u/115993812?v=4" width="110px;"/><br /><sub>Iisakki Jaakkola</sub>](https://github.com/StarlessNights)<br />[💻](https://github.com/snipe/snipe-it/commits?author=StarlessNights "Code") | [<img src="https://avatars.githubusercontent.com/u/22633385?v=4" width="110px;"/><br /><sub>Ikko Ashimine</sub>](https://bandism.net/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=eltociear "Code") | [<img src="https://avatars.githubusercontent.com/u/56871540?v=4" width="110px;"/><br /><sub>Lukas Fehling</sub>](https://github.com/lukasfehling)<br />[💻](https://github.com/snipe/snipe-it/commits?author=lukasfehling "Code") | [<img src="https://avatars.githubusercontent.com/u/1975990?v=4" width="110px;"/><br /><sub>Fernando Almeida</sub>](https://github.com/fernando-almeida)<br />[💻](https://github.com/snipe/snipe-it/commits?author=fernando-almeida "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/116301219?v=4" width="110px;"/><br /><sub>akemidx</sub>](https://github.com/akemidx)<br />[💻](https://github.com/snipe/snipe-it/commits?author=akemidx "Code") | [<img src="https://avatars.githubusercontent.com/u/144778?v=4" width="110px;"/><br /><sub>Oguz Bilgic</sub>](http://oguz.site)<br />[💻](https://github.com/snipe/snipe-it/commits?author=oguzbilgic "Code") | [<img src="https://avatars.githubusercontent.com/u/9262438?v=4" width="110px;"/><br /><sub>Scooter Crawford</sub>](https://github.com/scoo73r)<br />[💻](https://github.com/snipe/snipe-it/commits?author=scoo73r "Code") | [<img src="https://avatars.githubusercontent.com/u/5957345?v=4" width="110px;"/><br /><sub>subdriven</sub>](https://github.com/subdriven)<br />[💻](https://github.com/snipe/snipe-it/commits?author=subdriven "Code") | [<img src="https://avatars.githubusercontent.com/u/658865?v=4" width="110px;"/><br /><sub>Andrew Savinykh</sub>](https://github.com/AndrewSav)<br />[💻](https://github.com/snipe/snipe-it/commits?author=AndrewSav "Code") | [<img src="https://avatars.githubusercontent.com/u/1155067?v=4" width="110px;"/><br /><sub>Tadayuki Onishi</sub>](https://kenchan0130.github.io)<br />[💻](https://github.com/snipe/snipe-it/commits?author=kenchan0130 "Code") | [<img src="https://avatars.githubusercontent.com/u/112496896?v=4" width="110px;"/><br /><sub>Florian</sub>](https://github.com/floschoepfer)<br />[💻](https://github.com/snipe/snipe-it/commits?author=floschoepfer "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/7305753?v=4" width="110px;"/><br /><sub>Spencer Long</sub>](http://spencerlong.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=spencerrlongg "Code") | [<img src="https://avatars.githubusercontent.com/u/1141514?v=4" width="110px;"/><br /><sub>Marcus Moore</sub>](https://github.com/marcusmoore)<br />[💻](https://github.com/snipe/snipe-it/commits?author=marcusmoore "Code") | [<img src="https://avatars.githubusercontent.com/u/570639?v=4" width="110px;"/><br /><sub>Martin Meredith</sub>](https://github.com/Mezzle)<br /> | [<img src="https://avatars.githubusercontent.com/u/5731963?v=4" width="110px;"/><br /><sub>dboth</sub>](http://dboth.de)<br />[💻](https://github.com/snipe/snipe-it/commits?author=dboth "Code") | [<img src="https://avatars.githubusercontent.com/u/87536651?v=4" width="110px;"/><br /><sub>Zachary Fleck</sub>](https://github.com/zacharyfleck)<br />[💻](https://github.com/snipe/snipe-it/commits?author=zacharyfleck "Code") | [<img src="https://avatars.githubusercontent.com/u/74609912?v=4" width="110px;"/><br /><sub>VIKAAS-A</sub>](https://github.com/vikaas-cyper)<br />[💻](https://github.com/snipe/snipe-it/commits?author=vikaas-cyper "Code") | [<img src="https://avatars.githubusercontent.com/u/88882041?v=4" width="110px;"/><br /><sub>Abdul Kareem</sub>](https://github.com/ak-piracha)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ak-piracha "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/111287779?v=4" width="110px;"/><br /><sub>NojoudAlshehri</sub>](https://github.com/NojoudAlshehri)<br />[💻](https://github.com/snipe/snipe-it/commits?author=NojoudAlshehri "Code") | [<img src="https://avatars.githubusercontent.com/u/54367449?v=4" width="110px;"/><br /><sub>Stefan Stidl</sub>](https://github.com/stefanstidlffg)<br />[💻](https://github.com/snipe/snipe-it/commits?author=stefanstidlffg "Code") | [<img src="https://avatars.githubusercontent.com/u/87803479?v=4" width="110px;"/><br /><sub>Quentin Aymard</sub>](https://github.com/qay21)<br />[💻](https://github.com/snipe/snipe-it/commits?author=qay21 "Code") | [<img src="https://avatars.githubusercontent.com/u/5396871?v=4" width="110px;"/><br /><sub>Grant Le Roux</sub>](https://github.com/cram42)<br />[💻](https://github.com/snipe/snipe-it/commits?author=cram42 "Code") | [<img src="https://avatars.githubusercontent.com/u/58479551?v=4" width="110px;"/><br /><sub>Bogdan</sub>](http://@singrity)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Singrity "Code") | [<img src="https://avatars.githubusercontent.com/u/3483684?v=4" width="110px;"/><br /><sub>mmanjos</sub>](https://github.com/mmanjos)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mmanjos "Code") | [<img src="https://avatars.githubusercontent.com/u/7429229?v=4" width="110px;"/><br /><sub>Abdelaziz Faki</sub>](https://azooz2014.github.io/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Azooz2014 "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/47315739?v=4" width="110px;"/><br /><sub>bilias</sub>](https://github.com/bilias)<br />[💻](https://github.com/snipe/snipe-it/commits?author=bilias "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/111287779?v=4" width="110px;"/><br /><sub>NojoudAlshehri</sub>](https://github.com/NojoudAlshehri)<br />[💻](https://github.com/snipe/snipe-it/commits?author=NojoudAlshehri "Code") | [<img src="https://avatars.githubusercontent.com/u/54367449?v=4" width="110px;"/><br /><sub>Stefan Stidl</sub>](https://github.com/stefanstidlffg)<br />[💻](https://github.com/snipe/snipe-it/commits?author=stefanstidlffg "Code") | [<img src="https://avatars.githubusercontent.com/u/87803479?v=4" width="110px;"/><br /><sub>Quentin Aymard</sub>](https://github.com/qay21)<br />[💻](https://github.com/snipe/snipe-it/commits?author=qay21 "Code") | [<img src="https://avatars.githubusercontent.com/u/5396871?v=4" width="110px;"/><br /><sub>Grant Le Roux</sub>](https://github.com/cram42)<br />[💻](https://github.com/snipe/snipe-it/commits?author=cram42 "Code") |
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
|
||||
|
||||
@@ -18,7 +18,7 @@ class LdapSync extends Command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'snipeit:ldap-sync {--location=} {--location_id=*} {--base_dn=} {--filter=} {--summary} {--json_summary}';
|
||||
protected $signature = 'snipeit:ldap-sync {--location=} {--location_id=} {--base_dn=} {--filter=} {--summary} {--json_summary}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
@@ -83,16 +83,7 @@ class LdapSync extends Command
|
||||
$summary = [];
|
||||
|
||||
try {
|
||||
if ( $this->option('location_id') != '') {
|
||||
|
||||
foreach($this->option('location_id') as $location_id){
|
||||
$location_ou= Location::where('id', '=', $location_id)->value('ldap_ou');
|
||||
$search_base = $location_ou;
|
||||
Log::debug('Importing users from specified location OU: \"'.$search_base.'\".');
|
||||
}
|
||||
}
|
||||
|
||||
else if ($this->option('base_dn') != '') {
|
||||
if ($this->option('base_dn') != '') {
|
||||
$search_base = $this->option('base_dn');
|
||||
Log::debug('Importing users from specified base DN: \"'.$search_base.'\".');
|
||||
} else {
|
||||
@@ -115,21 +106,17 @@ class LdapSync extends Command
|
||||
|
||||
/* Determine which location to assign users to by default. */
|
||||
$location = null; // TODO - this would be better called "$default_location", which is more explicit about its purpose
|
||||
if ($this->option('location') != '') {
|
||||
if ($location = Location::where('name', '=', $this->option('location'))->first()) {
|
||||
Log::debug('Location name ' . $this->option('location') . ' passed');
|
||||
Log::debug('Importing to ' . $location->name . ' (' . $location->id . ')');
|
||||
}
|
||||
|
||||
} elseif ($this->option('location_id') != '') {
|
||||
foreach($this->option('location_id') as $location_id) {
|
||||
if ($location = Location::where('id', '=', $location_id)->first()) {
|
||||
Log::debug('Location ID ' . $location_id . ' passed');
|
||||
Log::debug('Importing to ' . $location->name . ' (' . $location->id . ')');
|
||||
}
|
||||
|
||||
}
|
||||
if ($this->option('location') != '') {
|
||||
$location = Location::where('name', '=', $this->option('location'))->first();
|
||||
Log::debug('Location name '.$this->option('location').' passed');
|
||||
Log::debug('Importing to '.$location->name.' ('.$location->id.')');
|
||||
} elseif ($this->option('location_id') != '') {
|
||||
$location = Location::where('id', '=', $this->option('location_id'))->first();
|
||||
Log::debug('Location ID '.$this->option('location_id').' passed');
|
||||
Log::debug('Importing to '.$location->name.' ('.$location->id.')');
|
||||
}
|
||||
|
||||
if (! isset($location)) {
|
||||
Log::debug('That location is invalid or a location was not provided, so no location will be assigned by default.');
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ use App\Models\CustomField;
|
||||
use App\Models\Setting;
|
||||
use Artisan;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Illuminate\Encryption\Encrypter;
|
||||
|
||||
class RotateAppKey extends Command
|
||||
@@ -17,17 +16,14 @@ class RotateAppKey extends Command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'snipeit:rotate-key
|
||||
{previous_key? : The previous key to rotate from}
|
||||
{--emergency : Emergency mode - rotate from .env APP_KEY to newly-generated one, modifying .env}
|
||||
{--force : Skip interactive confirmation}';
|
||||
protected $signature = 'snipeit:rotate-key';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Rotates APP_KEY to a new value, optionally taking the previous key as an argument';
|
||||
protected $description = 'Command description';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
@@ -46,42 +42,26 @@ class RotateAppKey extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
//make sure they specify only exactly one of --emergency, or a filename. Not neither, and not both.
|
||||
if ( (!$this->option('emergency') && !$this->argument('previous_key')) || ( $this->option('emergency') && $this->argument('previous_key'))) {
|
||||
$this->error("Specify only one of --emergency, or an app key value, in order to rotate keys");
|
||||
return 1;
|
||||
}
|
||||
if ( $this->option('emergency') ) {
|
||||
$msg = "\n****************************************************\nTHIS WILL MODIFY YOUR APP_KEY AND DE-CRYPT YOUR ENCRYPTED CUSTOM FIELDS AND \nRE-ENCRYPT THEM WITH A NEWLY GENERATED KEY. \n\nThere is NO undo. \n\nMake SURE you have a database backup and a backup of your .env generated BEFORE running this command. \n\nIf you do not save the newly generated APP_KEY to your .env in this process, \nyour encrypted data will no longer be decryptable. \n\nAre you SURE you wish to continue, and have confirmed you have a database backup and an .env backup? ";
|
||||
} else {
|
||||
$msg = "\n****************************************************\nTHIS WILL DE-CRYPT YOUR ENCRYPTED CUSTOM FIELDS AND RE-ENCRYPT THEM WITH YOUR\nAPP_KEY.\n\nThere is NO undo. \n\nMake SURE you have a database backup BEFORE running this command. \n\nAre you SURE you wish to continue, and have confirmed you have a database backup? ";
|
||||
}
|
||||
if ($this->option('force') || $this->confirm($msg)) {
|
||||
if ($this->confirm("\n****************************************************\nTHIS WILL MODIFY YOUR APP_KEY AND DE-CRYPT YOUR ENCRYPTED CUSTOM FIELDS AND \nRE-ENCRYPT THEM WITH A NEWLY GENERATED KEY. \n\nThere is NO undo. \n\nMake SURE you have a database backup and a backup of your .env generated BEFORE running this command. \n\nIf you do not save the newly generated APP_KEY to your .env in this process, \nyour encrypted data will no longer be decryptable. \n\nAre you SURE you wish to continue, and have confirmed you have a database backup and an .env backup? ")) {
|
||||
|
||||
// Get the existing app_key and ciphers
|
||||
// We put them in a variable since we clear the cache partway through here.
|
||||
if ($this->option('emergency')) {
|
||||
$old_app_key = config('app.key');
|
||||
$cipher = config('app.cipher');
|
||||
$old_app_key = config('app.key');
|
||||
$cipher = config('app.cipher');
|
||||
|
||||
// Generate a new one
|
||||
Artisan::call('key:generate', ['--show' => true]);
|
||||
$new_app_key = trim(Artisan::output());
|
||||
// Generate a new one
|
||||
Artisan::call('key:generate', ['--show' => true]);
|
||||
$new_app_key = Artisan::output();
|
||||
|
||||
// Clear the config cache
|
||||
Artisan::call('config:clear');
|
||||
// Clear the config cache
|
||||
Artisan::call('config:clear');
|
||||
|
||||
// Write the new app key to the .env file
|
||||
$this->writeNewEnvironmentFileWith($new_app_key);
|
||||
} elseif ($this->argument('previous_key')) {
|
||||
$old_app_key = $this->argument('previous_key');
|
||||
$cipher = config('app.cipher'); // just a guess?
|
||||
$new_app_key = config('app.key');
|
||||
}
|
||||
$this->warn('Your app cipher is: '.$cipher);
|
||||
$this->warn('Your old APP_KEY is: '.$old_app_key);
|
||||
$this->warn('Your new APP_KEY is: '.$new_app_key);
|
||||
|
||||
$this->warn('Your app cipher is: ' . $cipher);
|
||||
$this->warn('Your old APP_KEY is: ' . $old_app_key);
|
||||
$this->warn('Your new APP_KEY is: ' . $new_app_key);
|
||||
// Write the new app key to the .env file
|
||||
$this->writeNewEnvironmentFileWith($new_app_key);
|
||||
|
||||
// Manually create an old encrypter instance using the old app key
|
||||
// and also create a new encrypter instance so we can re-crypt the field
|
||||
@@ -95,16 +75,8 @@ class RotateAppKey extends Command
|
||||
$assets = Asset::whereNotNull($field->db_column)->get();
|
||||
|
||||
foreach ($assets as $asset) {
|
||||
try {
|
||||
$asset->{$field->db_column} = $oldEncrypter->decrypt($asset->{$field->db_column});
|
||||
$this->line('DECRYPTED: ' . $field->db_column);
|
||||
} catch (DecryptException $e) {
|
||||
$this->line('Could not decrypt '. $field->db_column.' using "old key" - skipping...');
|
||||
continue;
|
||||
} catch (\Exception $e) {
|
||||
$this->error("Error decrypting ".$field->db_column.", reason: ".$e->getMessage().". Aborting key rotation");
|
||||
throw $e;
|
||||
}
|
||||
$asset->{$field->db_column} = $oldEncrypter->decrypt($asset->{$field->db_column});
|
||||
$this->line('DECRYPTED: '.$field->db_column);
|
||||
$asset->{$field->db_column} = $newEncrypter->encrypt($asset->{$field->db_column});
|
||||
$this->line('ENCRYPTED: '.$field->db_column);
|
||||
$asset->save();
|
||||
@@ -114,14 +86,10 @@ class RotateAppKey extends Command
|
||||
// Handle the LDAP password if one is provided
|
||||
$setting = Setting::first();
|
||||
if ($setting->ldap_pword != '') {
|
||||
try {
|
||||
$setting->ldap_pword = $oldEncrypter->decrypt($setting->ldap_pword);
|
||||
$setting->ldap_pword = $newEncrypter->encrypt($setting->ldap_pword);
|
||||
$setting->save();
|
||||
$this->warn('LDAP password has been re-encrypted.');
|
||||
} catch(DecryptException $e) {
|
||||
$this->warn("Unable to decrypt old LDAP password; skipping");
|
||||
}
|
||||
$setting->ldap_pword = $oldEncrypter->decrypt($setting->ldap_pword);
|
||||
$setting->ldap_pword = $newEncrypter->encrypt($setting->ldap_pword);
|
||||
$setting->save();
|
||||
$this->warn('LDAP password has been re-encrypted.');
|
||||
}
|
||||
} else {
|
||||
$this->info('This operation has been canceled. No changes have been made.');
|
||||
@@ -138,7 +106,7 @@ class RotateAppKey extends Command
|
||||
{
|
||||
file_put_contents($this->laravel->environmentFilePath(), preg_replace(
|
||||
$this->keyReplacementPattern(),
|
||||
'APP_KEY="'.$key.'"',
|
||||
'APP_KEY='.$key,
|
||||
file_get_contents($this->laravel->environmentFilePath())
|
||||
));
|
||||
}
|
||||
@@ -150,7 +118,7 @@ class RotateAppKey extends Command
|
||||
*/
|
||||
protected function keyReplacementPattern()
|
||||
{
|
||||
$escaped = '="?'.preg_quote($this->laravel['config']['app.key'], '/').'"?';
|
||||
$escaped = preg_quote('='.$this->laravel['config']['app.key'], '/');
|
||||
|
||||
return "/^APP_KEY{$escaped}/m";
|
||||
}
|
||||
|
||||
@@ -150,11 +150,6 @@ class Handler extends ExceptionHandler
|
||||
return redirect()->guest('login');
|
||||
}
|
||||
|
||||
protected function invalidJson($request, ValidationException $exception)
|
||||
{
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $exception->errors()), 200);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A list of the inputs that are never flashed for validation exceptions.
|
||||
|
||||
@@ -73,14 +73,10 @@ class Helper
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v3.3]
|
||||
* @return string
|
||||
* @return array
|
||||
*/
|
||||
public static function defaultChartColors(int $index = 0)
|
||||
public static function defaultChartColors($index = 0)
|
||||
{
|
||||
if ($index < 0) {
|
||||
$index = 0;
|
||||
}
|
||||
|
||||
$colors = [
|
||||
'#008941',
|
||||
'#FF4A46',
|
||||
@@ -353,19 +349,7 @@ class Helper
|
||||
$total_colors = count($colors);
|
||||
|
||||
if ($index >= $total_colors) {
|
||||
|
||||
\Log::error('Status label count is '.$index.' and exceeds the allowed count of 266.');
|
||||
//patch fix for array key overflow (color count starts at 1, array starts at 0)
|
||||
$index = $index - $total_colors - 1;
|
||||
|
||||
//constraints to keep result in 0-265 range. This should never be needed, but if something happens
|
||||
//to create this many status labels and it DOES happen, this will keep it from failing at least.
|
||||
if($index < 0) {
|
||||
$index = 0;
|
||||
}
|
||||
elseif($index >($total_colors - 1)) {
|
||||
$index = $total_colors - 1;
|
||||
}
|
||||
$index = $index - $total_colors;
|
||||
}
|
||||
|
||||
return $colors[$index];
|
||||
|
||||
@@ -146,8 +146,9 @@ class AccessoriesFilesController extends Controller
|
||||
$this->authorize('view', $accessory);
|
||||
$this->authorize('accessories.files', $accessory);
|
||||
|
||||
if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $accessory->id)->find($fileId)) {
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/users/message.log_record_not_found'));
|
||||
if (! $log = Actionlog::find($fileId)) {
|
||||
return response('No matching record for that asset/file', 500)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
$file = 'private_uploads/accessories/'.$log->filename;
|
||||
|
||||
@@ -18,36 +18,31 @@ class AccessoryCheckoutController extends Controller
|
||||
* Return the form to checkout an Accessory to a user.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $id
|
||||
* @param int $accessoryId
|
||||
* @return View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create($id)
|
||||
public function create($accessoryId)
|
||||
{
|
||||
|
||||
if ($accessory = Accessory::withCount('users as users_count')->find($id)) {
|
||||
|
||||
$this->authorize('checkout', $accessory);
|
||||
|
||||
if ($accessory->category) {
|
||||
// Make sure there is at least one available to checkout
|
||||
if ($accessory->numRemaining() <= 0){
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.checkout.unavailable'));
|
||||
}
|
||||
|
||||
// Return the checkout view
|
||||
return view('accessories/checkout', compact('accessory'));
|
||||
}
|
||||
|
||||
// Invalid category
|
||||
return redirect()->route('accessories.edit', ['accessory' => $accessory->id])
|
||||
->with('error', trans('general.invalid_item_category_single', ['type' => trans('general.accessory')]));
|
||||
|
||||
// Check if the accessory exists
|
||||
if (is_null($accessory = Accessory::withCount('users as users_count')->find($accessoryId))) {
|
||||
// Redirect to the accessory management page with error
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.not_found'));
|
||||
}
|
||||
|
||||
// Not found
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.not_found'));
|
||||
// Make sure there is at least one available to checkout
|
||||
if ($accessory->numRemaining() <= 0){
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.checkout.unavailable'));
|
||||
}
|
||||
|
||||
if ($accessory->category) {
|
||||
$this->authorize('checkout', $accessory);
|
||||
|
||||
// Get the dropdown of users and then pass it to the checkout view
|
||||
return view('accessories/checkout', compact('accessory'));
|
||||
}
|
||||
|
||||
return redirect()->back()->with('error', 'The category type for this accessory is not valid. Edit the accessory and select a valid accessory category.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -33,7 +33,6 @@ use TCPDF;
|
||||
use Validator;
|
||||
use Route;
|
||||
|
||||
|
||||
/**
|
||||
* This class controls all actions related to assets for
|
||||
* the Snipe-IT Asset Management application.
|
||||
@@ -49,7 +48,7 @@ class AssetsController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $assetId
|
||||
* @since [v4.0]
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function index(Request $request, $audit = null)
|
||||
{
|
||||
@@ -296,7 +295,7 @@ class AssetsController extends Controller
|
||||
}
|
||||
|
||||
if ($request->filled('order_number')) {
|
||||
$assets->where('assets.order_number', '=', strval($request->get('order_number')));
|
||||
$assets->where('assets.order_number', '=', $request->get('order_number'));
|
||||
}
|
||||
|
||||
// This is kinda gross, but we need to do this because the Bootstrap Tables
|
||||
@@ -347,7 +346,7 @@ class AssetsController extends Controller
|
||||
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $assets->count()) ? $assets->count() : app('api_offset_value');
|
||||
$offset = ($request->input('offset') > $assets->count()) ? $assets->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
$total = $assets->count();
|
||||
@@ -444,7 +443,7 @@ class AssetsController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $assetId
|
||||
* @since [v4.0]
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function show(Request $request, $id)
|
||||
{
|
||||
@@ -475,7 +474,7 @@ class AssetsController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0.16]
|
||||
* @see \App\Http\Transformers\SelectlistTransformer
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
*/
|
||||
public function selectlist(Request $request)
|
||||
{
|
||||
@@ -531,12 +530,12 @@ class AssetsController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param \App\Http\Requests\ImageUploadRequest $request
|
||||
* @since [v4.0]
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function store(ImageUploadRequest $request)
|
||||
{
|
||||
$this->authorize('create', Asset::class);
|
||||
|
||||
|
||||
$asset = new Asset();
|
||||
$asset->model()->associate(AssetModel::find((int) $request->get('model_id')));
|
||||
|
||||
@@ -546,7 +545,8 @@ class AssetsController extends Controller
|
||||
$asset->model_id = $request->get('model_id');
|
||||
$asset->order_number = $request->get('order_number');
|
||||
$asset->notes = $request->get('notes');
|
||||
$asset->asset_tag = $request->get('asset_tag', Asset::autoincrement_asset());
|
||||
$asset->asset_tag = $request->get('asset_tag', Asset::autoincrement_asset()); //yup, problem :/
|
||||
// NO IT IS NOT!!! This is never firing; we SHOW the asset_tag you're going to get, so it *will* be filled in!
|
||||
$asset->user_id = Auth::id();
|
||||
$asset->archived = '0';
|
||||
$asset->physical = '1';
|
||||
@@ -639,7 +639,7 @@ class AssetsController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param \App\Http\Requests\ImageUploadRequest $request
|
||||
* @since [v4.0]
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(ImageUploadRequest $request, $id)
|
||||
{
|
||||
@@ -666,11 +666,10 @@ class AssetsController extends Controller
|
||||
$request->offsetSet('image', $request->offsetGet('image_source'));
|
||||
}
|
||||
|
||||
$asset = $request->handleImages($asset);
|
||||
$model = AssetModel::find($asset->model_id);
|
||||
$asset = $request->handleImages($asset);
|
||||
|
||||
// Update custom fields
|
||||
if (($model) && (isset($model->fieldset))) {
|
||||
if (($model = AssetModel::find($asset->model_id)) && (isset($model->fieldset))) {
|
||||
foreach ($model->fieldset->fields as $field) {
|
||||
if ($request->has($field->db_column)) {
|
||||
if ($field->field_encrypted == '1') {
|
||||
@@ -721,7 +720,7 @@ class AssetsController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $assetId
|
||||
* @since [v4.0]
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
@@ -750,28 +749,38 @@ class AssetsController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $assetId
|
||||
* @since [v5.1.18]
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function restore(Request $request, $assetId = null)
|
||||
{
|
||||
// Get asset information
|
||||
$asset = Asset::withTrashed()->find($assetId);
|
||||
$this->authorize('delete', $asset);
|
||||
|
||||
if ($asset = Asset::withTrashed()->find($assetId)) {
|
||||
$this->authorize('delete', $asset);
|
||||
if (isset($asset->id)) {
|
||||
|
||||
if ($asset->deleted_at == '') {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', trans('general.not_deleted', ['item_type' => trans('general.asset')])), 200);
|
||||
if ($asset->deleted_at=='') {
|
||||
$message = 'Asset was not deleted. No data was changed.';
|
||||
|
||||
} else {
|
||||
|
||||
$message = trans('admin/hardware/message.restore.success');
|
||||
// Restore the asset
|
||||
Asset::withTrashed()->where('id', $assetId)->restore();
|
||||
|
||||
$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;
|
||||
$logaction->logaction('restored');
|
||||
}
|
||||
|
||||
if ($asset->restore()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', trans('admin/hardware/message.restore.success')), 200);
|
||||
}
|
||||
return response()->json(Helper::formatStandardApiResponse('success', (new AssetsTransformer)->transformAsset($asset, $request), $message));
|
||||
|
||||
|
||||
// Check validation to make sure we're not restoring an asset with the same asset tag (or unique attribute) as an existing asset
|
||||
return response()->json(Helper::formatStandardApiResponse('error', trans('general.could_not_restore', ['item_type' => trans('general.asset'), 'error' => $asset->getErrors()->first()])), 200);
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -780,7 +789,7 @@ class AssetsController extends Controller
|
||||
* @author [N. Butler]
|
||||
* @param string $tag
|
||||
* @since [v6.0.5]
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function checkoutByTag(AssetCheckoutRequest $request, $tag)
|
||||
{
|
||||
@@ -796,7 +805,7 @@ class AssetsController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $assetId
|
||||
* @since [v4.0]
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function checkout(AssetCheckoutRequest $request, $asset_id)
|
||||
{
|
||||
@@ -880,7 +889,7 @@ class AssetsController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $assetId
|
||||
* @since [v4.0]
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function checkin(Request $request, $asset_id)
|
||||
{
|
||||
@@ -936,7 +945,7 @@ class AssetsController extends Controller
|
||||
*
|
||||
* @author [A. Janes] [<ajanes@adagiohealth.org>]
|
||||
* @since [v6.0]
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function checkinByTag(Request $request, $tag = null)
|
||||
{
|
||||
@@ -962,7 +971,7 @@ class AssetsController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $id
|
||||
* @since [v4.0]
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function audit(Request $request)
|
||||
|
||||
@@ -1023,54 +1032,24 @@ class AssetsController extends Controller
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0]
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function requestable(Request $request)
|
||||
{
|
||||
$this->authorize('viewRequestable', Asset::class);
|
||||
|
||||
$allowed_columns = [
|
||||
'name',
|
||||
'asset_tag',
|
||||
'serial',
|
||||
'model_number',
|
||||
'image',
|
||||
'purchase_cost',
|
||||
'expected_checkin',
|
||||
];
|
||||
|
||||
$all_custom_fields = CustomField::all(); //used as a 'cache' of custom fields throughout this page load
|
||||
|
||||
foreach ($all_custom_fields as $field) {
|
||||
$allowed_columns[] = $field->db_column_name();
|
||||
}
|
||||
|
||||
$assets = Asset::select('assets.*')
|
||||
->with('location', 'assetstatus', 'assetlog', 'company','assignedTo',
|
||||
'model.category', 'model.manufacturer', 'model.fieldset', 'supplier', 'requests')
|
||||
->with('location', 'assetstatus', 'assetlog', 'company', 'defaultLoc','assignedTo',
|
||||
'model.category', 'model.manufacturer', 'model.fieldset', 'supplier')
|
||||
->requestableAssets();
|
||||
|
||||
|
||||
|
||||
|
||||
$offset = request('offset', 0);
|
||||
$limit = $request->input('limit', 50);
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
if ($request->filled('search')) {
|
||||
$assets->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
// Search custom fields by column name
|
||||
foreach ($all_custom_fields as $field) {
|
||||
if ($request->filled($field->db_column_name())) {
|
||||
$assets->where($field->db_column_name(), '=', $request->input($field->db_column_name()));
|
||||
}
|
||||
}
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort_override = str_replace('custom_fields.', '', $request->input('sort'));
|
||||
|
||||
// This handles all the pivot sorting (versus the assets.* fields
|
||||
// in the allowed_columns array)
|
||||
$column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'assets.created_at';
|
||||
|
||||
switch ($request->input('sort')) {
|
||||
case 'model':
|
||||
$assets->OrderModels($order);
|
||||
@@ -1078,19 +1057,17 @@ class AssetsController extends Controller
|
||||
case 'model_number':
|
||||
$assets->OrderModelNumber($order);
|
||||
break;
|
||||
case 'location':
|
||||
$assets->OrderLocation($order);
|
||||
case 'category':
|
||||
$assets->OrderCategory($order);
|
||||
break;
|
||||
case 'manufacturer':
|
||||
$assets->OrderManufacturer($order);
|
||||
break;
|
||||
default:
|
||||
$assets->orderBy($column_sort, $order);
|
||||
$assets->orderBy('assets.created_at', $order);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $assets->count()) ? $assets->count() : app('api_offset_value');
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
$total = $assets->count();
|
||||
$assets = $assets->skip($offset)->take($limit)->get();
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ class CategoriesController extends Controller
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $categories->count()) ? $categories->count() : app('api_offset_value');
|
||||
$offset = ($request->input('offset') > $categories->count()) ? $categories->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
|
||||
@@ -56,7 +56,7 @@ class CompaniesController extends Controller
|
||||
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $companies->count()) ? $companies->count() : app('api_offset_value');
|
||||
$offset = ($request->input('offset') > $companies->count()) ? $companies->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ class ComponentsController extends Controller
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $components->count()) ? $components->count() : app('api_offset_value');
|
||||
$offset = ($request->input('offset') > $components->count()) ? $components->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
@@ -263,7 +263,7 @@ class ComponentsController extends Controller
|
||||
}
|
||||
|
||||
// Make sure there is at least one available to checkout
|
||||
if ($component->numRemaining() < $request->get('assigned_qty')) {
|
||||
if ($component->numRemaining() <= $request->get('assigned_qty')) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/components/message.checkout.unavailable', ['remaining' => $component->numRemaining(), 'requested' => $request->get('assigned_qty')])));
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ class ConsumablesController extends Controller
|
||||
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $consumables->count()) ? $consumables->count() : app('api_offset_value');
|
||||
$offset = ($request->input('offset') > $consumables->count()) ? $consumables->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
$allowed_columns = ['id', 'name', 'order_number', 'min_amt', 'purchase_date', 'purchase_cost', 'company', 'category', 'model_number', 'item_no', 'manufacturer', 'location', 'qty', 'image'];
|
||||
@@ -263,14 +263,9 @@ class ConsumablesController extends Controller
|
||||
// Make sure there is at least one available to checkout
|
||||
if ($consumable->numRemaining() <= 0) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/consumables/message.checkout.unavailable')));
|
||||
\Log::debug('No enough remaining');
|
||||
}
|
||||
|
||||
// Make sure there is a valid category
|
||||
if (!$consumable->category){
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.invalid_item_category_single', ['type' => trans('general.consumable')])));
|
||||
}
|
||||
|
||||
|
||||
// Check if the user exists - @TODO: this should probably be handled via validation, not here??
|
||||
if (!$user = User::find($request->input('assigned_to'))) {
|
||||
// Return error message
|
||||
|
||||
@@ -61,7 +61,7 @@ class DepartmentsController extends Controller
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $departments->count()) ? $departments->count() : app('api_offset_value');
|
||||
$offset = ($request->input('offset') > $departments->count()) ? $departments->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
|
||||
@@ -29,7 +29,7 @@ class DepreciationsController extends Controller
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $depreciations->count()) ? $depreciations->count() : app('api_offset_value');
|
||||
$offset = ($request->input('offset') > $depreciations->count()) ? $depreciations->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
|
||||
@@ -36,7 +36,7 @@ class GroupsController extends Controller
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $groups->count()) ? $groups->count() : app('api_offset_value');
|
||||
$offset = ($request->input('offset') > $groups->count()) ? $groups->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
@@ -63,7 +63,7 @@ class GroupsController extends Controller
|
||||
$group = new Group;
|
||||
|
||||
$group->name = $request->input('name');
|
||||
$group->permissions = json_encode($request->input('permissions')); // Todo - some JSON validation stuff here
|
||||
$group->permissions = $request->input('permissions'); // Todo - some JSON validation stuff here
|
||||
|
||||
if ($group->save()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $group, trans('admin/groups/message.create.success')));
|
||||
|
||||
@@ -41,7 +41,7 @@ class LicenseSeatsController extends Controller
|
||||
$total = $seats->count();
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $seats->count()) ? $seats->count() : app('api_offset_value');
|
||||
$offset = ($request->input('offset') > $seats->count()) ? $seats->count() : abs($request->input('offset'));
|
||||
|
||||
if ($offset >= $total ){
|
||||
$offset = 0;
|
||||
|
||||
@@ -95,7 +95,7 @@ class LicensesController extends Controller
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $licenses->count()) ? $licenses->count() : app('api_offset_value');
|
||||
$offset = ($request->input('offset') > $licenses->count()) ? $licenses->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
|
||||
@@ -81,7 +81,7 @@ class LocationsController extends Controller
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $locations->count()) ? $locations->count() : app('api_offset_value');
|
||||
$offset = ($request->input('offset') > $locations->count()) ? $locations->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
|
||||
@@ -6,11 +6,9 @@ use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Transformers\ManufacturersTransformer;
|
||||
use App\Http\Transformers\SelectlistTransformer;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Manufacturer;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class ManufacturersController extends Controller
|
||||
@@ -64,7 +62,7 @@ class ManufacturersController extends Controller
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $manufacturers->count()) ? $manufacturers->count() : app('api_offset_value');
|
||||
$offset = ($request->input('offset') > $manufacturers->count()) ? $manufacturers->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
@@ -161,44 +159,6 @@ class ManufacturersController extends Controller
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore a given Manufacturer (mark as un-deleted)
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v6.3.4]
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function restore($id)
|
||||
{
|
||||
$this->authorize('delete', Manufacturer::class);
|
||||
|
||||
if ($manufacturer = Manufacturer::withTrashed()->find($id)) {
|
||||
|
||||
if ($manufacturer->deleted_at == '') {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', trans('general.not_deleted', ['item_type' => trans('general.manufacturer')])), 200);
|
||||
}
|
||||
|
||||
if ($manufacturer->restore()) {
|
||||
|
||||
$logaction = new Actionlog();
|
||||
$logaction->item_type = Manufacturer::class;
|
||||
$logaction->item_id = $manufacturer->id;
|
||||
$logaction->created_at = date('Y-m-d H:i:s');
|
||||
$logaction->user_id = Auth::user()->id;
|
||||
$logaction->logaction('restore');
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', trans('admin/manufacturers/message.restore.success')), 200);
|
||||
}
|
||||
|
||||
// Check validation to make sure we're not restoring an item with the same unique attributes as a non-deleted one
|
||||
return response()->json(Helper::formatStandardApiResponse('error', trans('general.could_not_restore', ['item_type' => trans('general.manufacturer'), 'error' => $manufacturer->getErrors()->first()])), 200);
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/manufacturers/message.does_not_exist')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a paginated collection for the select2 menus
|
||||
*
|
||||
|
||||
@@ -30,7 +30,7 @@ class PredefinedKitsController extends Controller
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $kits->count()) ? $kits->count() : app('api_offset_value');
|
||||
$offset = ($request->input('offset') > $kits->count()) ? $kits->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
$order = $request->input('order') === 'desc' ? 'desc' : 'asc';
|
||||
|
||||
@@ -11,7 +11,6 @@ use Illuminate\Http\Request;
|
||||
use Laravel\Passport\TokenRepository;
|
||||
use Illuminate\Contracts\Validation\Factory as ValidationFactory;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use App\Models\CustomField;
|
||||
use DB;
|
||||
|
||||
class ProfileController extends Controller
|
||||
@@ -49,23 +48,14 @@ class ProfileController extends Controller
|
||||
{
|
||||
$checkoutRequests = CheckoutRequest::where('user_id', '=', Auth::user()->id)->get();
|
||||
|
||||
$results = array();
|
||||
$show_field = array();
|
||||
$showable_fields = array();
|
||||
$results = [];
|
||||
$results['total'] = $checkoutRequests->count();
|
||||
|
||||
$all_custom_fields = CustomField::all(); //used as a 'cache' of custom fields throughout this page load
|
||||
foreach ($all_custom_fields as $field) {
|
||||
if (($field->field_encrypted=='0') && ($field->show_in_requestable_list=='1')) {
|
||||
$showable_fields[] = $field->db_column_name();
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($checkoutRequests as $checkoutRequest) {
|
||||
|
||||
// Make sure the asset and request still exist
|
||||
if ($checkoutRequest && $checkoutRequest->itemRequested()) {
|
||||
$assets = [
|
||||
$results['rows'][] = [
|
||||
'image' => e($checkoutRequest->itemRequested()->present()->getImageUrl()),
|
||||
'name' => e($checkoutRequest->itemRequested()->present()->name()),
|
||||
'type' => e($checkoutRequest->itemType()),
|
||||
@@ -74,16 +64,7 @@ class ProfileController extends Controller
|
||||
'expected_checkin' => Helper::getFormattedDateObject($checkoutRequest->itemRequested()->expected_checkin, 'datetime'),
|
||||
'request_date' => Helper::getFormattedDateObject($checkoutRequest->created_at, 'datetime'),
|
||||
];
|
||||
|
||||
foreach ($showable_fields as $showable_field_name) {
|
||||
$show_field['custom_fields.'.$showable_field_name] = $checkoutRequest->itemRequested()->{$showable_field_name};
|
||||
}
|
||||
|
||||
// Merge the plain asset data and the custom fields data
|
||||
$results['rows'][] = array_merge($assets, $show_field);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return $results;
|
||||
|
||||
@@ -56,7 +56,7 @@ class ReportsController extends Controller
|
||||
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $actionlogs->count()) ? $actionlogs->count() : app('api_offset_value');
|
||||
$offset = ($request->input('offset') > $actionlogs->count()) ? $actionlogs->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
|
||||
|
||||
@@ -52,7 +52,7 @@ class StatuslabelsController extends Controller
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $statuslabels->count()) ? $statuslabels->count() : app('api_offset_value');
|
||||
$offset = ($request->input('offset') > $statuslabels->count()) ? $statuslabels->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
|
||||
@@ -94,7 +94,7 @@ class SuppliersController extends Controller
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $suppliers->count()) ? $suppliers->count() : app('api_offset_value');
|
||||
$offset = ($request->input('offset') > $suppliers->count()) ? $suppliers->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
|
||||
@@ -11,7 +11,6 @@ use App\Http\Transformers\ConsumablesTransformer;
|
||||
use App\Http\Transformers\LicensesTransformer;
|
||||
use App\Http\Transformers\SelectlistTransformer;
|
||||
use App\Http\Transformers\UsersTransformer;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Company;
|
||||
use App\Models\License;
|
||||
@@ -193,7 +192,7 @@ class UsersController extends Controller
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $users->count()) ? $users->count() : app('api_offset_value');
|
||||
$offset = ($request->input('offset') > $users->count()) ? $users->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
|
||||
@@ -689,31 +688,17 @@ class UsersController extends Controller
|
||||
*/
|
||||
public function restore($userId = null)
|
||||
{
|
||||
// Get asset information
|
||||
$user = User::withTrashed()->find($userId);
|
||||
$this->authorize('delete', $user);
|
||||
if (isset($user->id)) {
|
||||
// Restore the user
|
||||
User::withTrashed()->where('id', $userId)->restore();
|
||||
|
||||
if ($user = User::withTrashed()->find($userId)) {
|
||||
$this->authorize('delete', $user);
|
||||
|
||||
if ($user->deleted_at == '') {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', trans('general.not_deleted', ['item_type' => trans('general.user')])), 200);
|
||||
}
|
||||
|
||||
if ($user->restore()) {
|
||||
|
||||
$logaction = new Actionlog();
|
||||
$logaction->item_type = User::class;
|
||||
$logaction->item_id = $user->id;
|
||||
$logaction->created_at = date('Y-m-d H:i:s');
|
||||
$logaction->user_id = Auth::user()->id;
|
||||
$logaction->logaction('restore');
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', trans('admin/users/message.restore.success')), 200);
|
||||
}
|
||||
|
||||
// Check validation to make sure we're not restoring a user with the same username as an existing user
|
||||
return response()->json(Helper::formatStandardApiResponse('error', trans('general.could_not_restore', ['item_type' => trans('general.user'), 'error' => $user->getErrors()->first()])), 200);
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.success.restored')));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found')), 200);
|
||||
|
||||
|
||||
$id = $userId;
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found', compact('id'))), 200);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,7 @@ namespace App\Http\Controllers;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
@@ -182,14 +179,9 @@ class AssetModelsController extends Controller
|
||||
|
||||
if ($model->save()) {
|
||||
if ($model->wasChanged('eol')) {
|
||||
if ($model->eol > 0) {
|
||||
$newEol = $model->eol;
|
||||
$model->assets()->whereNotNull('purchase_date')->where('eol_explicit', false)
|
||||
->update(['asset_eol_date' => DB::raw('DATE_ADD(purchase_date, INTERVAL ' . $newEol . ' MONTH)')]);
|
||||
} elseif ($model->eol == 0) {
|
||||
$model->assets()->whereNotNull('purchase_date')->where('eol_explicit', false)
|
||||
->update(['asset_eol_date' => DB::raw('null')]);
|
||||
}
|
||||
$newEol = $model->eol;
|
||||
$model->assets()->whereNotNull('purchase_date')->where('eol_explicit', false)
|
||||
->update(['asset_eol_date' => DB::raw('DATE_ADD(purchase_date, INTERVAL ' . $newEol . ' MONTH)')]);
|
||||
}
|
||||
return redirect()->route('models.index')->with('success', trans('admin/models/message.update.success'));
|
||||
}
|
||||
@@ -212,7 +204,7 @@ class AssetModelsController extends Controller
|
||||
$this->authorize('delete', AssetModel::class);
|
||||
// Check if the model exists
|
||||
if (is_null($model = AssetModel::find($modelId))) {
|
||||
return redirect()->route('models.index')->with('error', trans('admin/models/message.does_not_exist'));
|
||||
return redirect()->route('models.index')->with('error', trans('admin/models/message.not_found'));
|
||||
}
|
||||
|
||||
if ($model->assets()->count() > 0) {
|
||||
@@ -240,42 +232,22 @@ class AssetModelsController extends Controller
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $id
|
||||
* @param int $modelId
|
||||
* @return Redirect
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function getRestore($id)
|
||||
public function getRestore($modelId = null)
|
||||
{
|
||||
$this->authorize('create', AssetModel::class);
|
||||
// Get user information
|
||||
$model = AssetModel::withTrashed()->find($modelId);
|
||||
|
||||
if ($model = AssetModel::withTrashed()->find($id)) {
|
||||
if (isset($model->id)) {
|
||||
$model->restore();
|
||||
|
||||
if ($model->deleted_at == '') {
|
||||
return redirect()->back()->with('error', trans('general.not_deleted', ['item_type' => trans('general.asset_model')]));
|
||||
}
|
||||
|
||||
if ($model->restore()) {
|
||||
$logaction = new Actionlog();
|
||||
$logaction->item_type = User::class;
|
||||
$logaction->item_id = $model->id;
|
||||
$logaction->created_at = date('Y-m-d H:i:s');
|
||||
$logaction->user_id = Auth::user()->id;
|
||||
$logaction->logaction('restore');
|
||||
|
||||
|
||||
// Redirect them to the deleted page if there are more, otherwise the section index
|
||||
$deleted_models = AssetModel::onlyTrashed()->count();
|
||||
if ($deleted_models > 0) {
|
||||
return redirect()->back()->with('success', trans('admin/models/message.restore.success'));
|
||||
}
|
||||
return redirect()->route('models.index')->with('success', trans('admin/models/message.restore.success'));
|
||||
}
|
||||
|
||||
// Check validation
|
||||
return redirect()->back()->with('error', trans('general.could_not_restore', ['item_type' => trans('general.asset_model'), 'error' => $model->getErrors()->first()]));
|
||||
return redirect()->route('models.index')->with('success', trans('admin/models/message.restore.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->with('error', trans('admin/models/message.does_not_exist'));
|
||||
return redirect()->back()->with('error', trans('admin/models/message.not_found'));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ class AssetFilesController extends Controller
|
||||
if (isset($asset->id)) {
|
||||
$this->authorize('view', $asset);
|
||||
|
||||
if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $asset->id)->find($fileId)) {
|
||||
if (! $log = Actionlog::find($fileId)) {
|
||||
return response('No matching record for that asset/file', 500)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Manufacturer;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
@@ -138,7 +137,7 @@ class AssetsController extends Controller
|
||||
$asset->warranty_months = request('warranty_months', null);
|
||||
$asset->purchase_cost = request('purchase_cost');
|
||||
$asset->purchase_date = request('purchase_date', null);
|
||||
$asset->asset_eol_date = request('asset_eol_date', null);
|
||||
$asset->asset_eol_date = request('asset_eol_date', $asset->present()->eol_date());
|
||||
$asset->assigned_to = request('assigned_to', null);
|
||||
$asset->supplier_id = request('supplier_id', null);
|
||||
$asset->requestable = request('requestable', 0);
|
||||
@@ -205,9 +204,12 @@ class AssetsController extends Controller
|
||||
}
|
||||
|
||||
if ($success) {
|
||||
\Log::debug(e($asset->asset_tag));
|
||||
// Redirect to the asset listing page
|
||||
$minutes = 518400;
|
||||
// dd( $_POST['options']);
|
||||
// Cookie::queue(Cookie::make('optional_info', json_decode($_POST['options']), $minutes));
|
||||
return redirect()->route('hardware.index')
|
||||
->with('success-unescaped', trans('admin/hardware/message.create.success_linked', ['link' => route('hardware.show', $asset->id), 'id', 'tag' => e($asset->asset_tag)]));
|
||||
->with('success', trans('admin/hardware/message.create.success'));
|
||||
|
||||
|
||||
}
|
||||
@@ -307,15 +309,14 @@ class AssetsController extends Controller
|
||||
$asset->warranty_months = $request->input('warranty_months', null);
|
||||
$asset->purchase_cost = $request->input('purchase_cost', null);
|
||||
$asset->purchase_date = $request->input('purchase_date', null);
|
||||
if ($request->filled('purchase_date') && !$request->filled('asset_eol_date') && ($asset->model->eol > 0)) {
|
||||
if ($request->filled('purchase_date') && !$request->filled('asset_eol_date') && $asset->model->eol) {
|
||||
$asset->purchase_date = $request->input('purchase_date', null);
|
||||
$asset->asset_eol_date = Carbon::parse($request->input('purchase_date'))->addMonths($asset->model->eol)->format('Y-m-d');
|
||||
$asset->eol_explicit = false;
|
||||
} elseif ($request->filled('asset_eol_date')) {
|
||||
$asset->asset_eol_date = $request->input('asset_eol_date', null);
|
||||
$months = Carbon::parse($asset->asset_eol_date)->diffInMonths($asset->purchase_date);
|
||||
if($asset->model->eol) {
|
||||
if($months != $asset->model->eol > 0) {
|
||||
if($months != $asset->model->eol) {
|
||||
$asset->eol_explicit = true;
|
||||
} else {
|
||||
$asset->eol_explicit = false;
|
||||
@@ -323,9 +324,6 @@ class AssetsController extends Controller
|
||||
} else {
|
||||
$asset->eol_explicit = true;
|
||||
}
|
||||
} elseif (!$request->filled('asset_eol_date') && (($asset->model->eol) == 0)) {
|
||||
$asset->asset_eol_date = null;
|
||||
$asset->eol_explicit = false;
|
||||
}
|
||||
$asset->supplier_id = $request->input('supplier_id', null);
|
||||
$asset->expected_checkin = $request->input('expected_checkin', null);
|
||||
@@ -796,24 +794,21 @@ class AssetsController extends Controller
|
||||
*/
|
||||
public function getRestore($assetId = null)
|
||||
{
|
||||
if ($asset = Asset::withTrashed()->find($assetId)) {
|
||||
$this->authorize('delete', $asset);
|
||||
// Get asset information
|
||||
$asset = Asset::withTrashed()->find($assetId);
|
||||
$this->authorize('delete', $asset);
|
||||
if (isset($asset->id)) {
|
||||
// Restore the asset
|
||||
Asset::withTrashed()->where('id', $assetId)->restore();
|
||||
|
||||
if ($asset->deleted_at == '') {
|
||||
return redirect()->back()->with('error', trans('general.not_deleted', ['item_type' => trans('general.asset')]));
|
||||
}
|
||||
$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;
|
||||
$logaction->logaction('restored');
|
||||
|
||||
if ($asset->restore()) {
|
||||
// Redirect them to the deleted page if there are more, otherwise the section index
|
||||
$deleted_assets = Asset::onlyTrashed()->count();
|
||||
if ($deleted_assets > 0) {
|
||||
return redirect()->back()->with('success', trans('admin/hardware/message.restore.success'));
|
||||
}
|
||||
return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.restore.success'));
|
||||
}
|
||||
|
||||
// Check validation to make sure we're not restoring an asset with the same asset tag (or unique attribute) as an existing asset
|
||||
return redirect()->back()->with('error', trans('general.could_not_restore', ['item_type' => trans('general.asset'), 'error' => $asset->getErrors()->first()]));
|
||||
return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.restore.success'));
|
||||
}
|
||||
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
|
||||
@@ -7,8 +7,6 @@ use App\Helpers\Helper;
|
||||
use App\Http\Controllers\CheckInOutRequest;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Statuslabel;
|
||||
use App\Models\Setting;
|
||||
use App\View\Label;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -25,13 +23,6 @@ class BulkAssetsController extends Controller
|
||||
/**
|
||||
* Display the bulk edit page.
|
||||
*
|
||||
* This method is super weird because it's kinda of like a controller within a controller.
|
||||
* It's main function is to determine what the bulk action in, and then return a view with
|
||||
* the information that view needs, be it bulk delete, bulk edit, restore, etc.
|
||||
*
|
||||
* This is something that made sense at the time, but sort of doesn't make sense now. A JS front-end to determine form
|
||||
* action would make a lot more sense here and make things a lot more clear.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @return View
|
||||
* @internal param int $assetId
|
||||
@@ -41,10 +32,7 @@ class BulkAssetsController extends Controller
|
||||
public function edit(Request $request)
|
||||
{
|
||||
$this->authorize('view', Asset::class);
|
||||
|
||||
/**
|
||||
* No asset IDs were passed
|
||||
*/
|
||||
|
||||
if (! $request->filled('ids')) {
|
||||
return redirect()->back()->with('error', trans('admin/hardware/message.update.no_assets_selected'));
|
||||
}
|
||||
@@ -53,52 +41,59 @@ class BulkAssetsController extends Controller
|
||||
$bulk_back_url = request()->headers->get('referer');
|
||||
session(['bulk_back_url' => $bulk_back_url]);
|
||||
|
||||
$asset_ids = array_values(array_unique($request->input('ids')));
|
||||
|
||||
//custom fields logic
|
||||
$asset_custom_field = Asset::with(['model.fieldset.fields', 'model'])->whereIn('id', $asset_ids)->whereHas('model', function ($query) {
|
||||
return $query->where('fieldset_id', '!=', null);
|
||||
})->get();
|
||||
|
||||
$asset_ids = $request->input('ids');
|
||||
$assets = Asset::with('assignedTo', 'location', 'model')->find($asset_ids);
|
||||
|
||||
$models = $assets->unique('model_id');
|
||||
$models = $asset_custom_field->unique('model_id');
|
||||
$modelNames = [];
|
||||
foreach($models as $model) {
|
||||
$modelNames[] = $model->model->name;
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->filled('bulk_actions')) {
|
||||
|
||||
|
||||
switch ($request->input('bulk_actions')) {
|
||||
case 'labels':
|
||||
$this->authorize('view', Asset::class);
|
||||
$assets_found = Asset::find($asset_ids);
|
||||
|
||||
if ($assets_found->isEmpty()){
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
return (new Label)
|
||||
->with('assets', $assets)
|
||||
->with('assets', $assets_found)
|
||||
->with('settings', Setting::getSettings())
|
||||
->with('bulkedit', true)
|
||||
->with('count', 0);
|
||||
|
||||
case 'delete':
|
||||
$this->authorize('delete', Asset::class);
|
||||
$assets->each(function ($assets) {
|
||||
$this->authorize('delete', $assets);
|
||||
$assets = Asset::with('assignedTo', 'location')->find($asset_ids);
|
||||
$assets->each(function ($asset) {
|
||||
$this->authorize('delete', $asset);
|
||||
});
|
||||
|
||||
return view('hardware/bulk-delete')->with('assets', $assets);
|
||||
|
||||
case 'restore':
|
||||
$this->authorize('update', Asset::class);
|
||||
$assets = Asset::withTrashed()->find($asset_ids);
|
||||
$assets = Asset::withTrashed()->find($asset_ids);
|
||||
$assets->each(function ($asset) {
|
||||
$this->authorize('delete', $asset);
|
||||
});
|
||||
|
||||
return view('hardware/bulk-restore')->with('assets', $assets);
|
||||
|
||||
case 'edit':
|
||||
$this->authorize('update', Asset::class);
|
||||
|
||||
return view('hardware/bulk')
|
||||
->with('assets', $asset_ids)
|
||||
->with('statuslabel_list', Helper::statusLabelList())
|
||||
->with('models', $models->pluck(['model']))
|
||||
->with('models', $models->pluck(['model']))
|
||||
->with('modelNames', $modelNames);
|
||||
}
|
||||
}
|
||||
@@ -117,36 +112,30 @@ class BulkAssetsController extends Controller
|
||||
public function update(Request $request)
|
||||
{
|
||||
$this->authorize('update', Asset::class);
|
||||
$has_errors = 0;
|
||||
$error_array = array();
|
||||
$error_bag = [];
|
||||
|
||||
// Get the back url from the session and then destroy the session
|
||||
$bulk_back_url = route('hardware.index');
|
||||
|
||||
if ($request->session()->has('bulk_back_url')) {
|
||||
$bulk_back_url = $request->session()->pull('bulk_back_url');
|
||||
}
|
||||
|
||||
$custom_field_columns = CustomField::all()->pluck('db_column')->toArray();
|
||||
|
||||
$custom_field_columns = CustomField::all()->pluck('db_column')->toArray();
|
||||
|
||||
if (! $request->filled('ids') || count($request->input('ids')) == 0) {
|
||||
if(Session::exists('ids')) {
|
||||
$assets = Session::get('ids');
|
||||
} elseif (! $request->filled('ids') || count($request->input('ids')) <= 0) {
|
||||
return redirect($bulk_back_url)->with('error', trans('admin/hardware/message.update.no_assets_selected'));
|
||||
}
|
||||
|
||||
|
||||
$assets = Asset::whereIn('id', array_keys($request->input('ids')))->get();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* If ANY of these are filled, prepare to update the values on the assets.
|
||||
*
|
||||
* Additional checks will be needed for some of them to make sure the values
|
||||
* make sense (for example, changing the status ID to something incompatible with
|
||||
* its checkout status.
|
||||
*/
|
||||
|
||||
|
||||
$assets = array_keys($request->input('ids'));
|
||||
|
||||
if ($request->anyFilled($custom_field_columns)) {
|
||||
$custom_fields_present = true;
|
||||
} else {
|
||||
$custom_fields_present = false;
|
||||
}
|
||||
if (($request->filled('purchase_date'))
|
||||
|| ($request->filled('expected_checkin'))
|
||||
|| ($request->filled('purchase_cost'))
|
||||
@@ -165,32 +154,23 @@ class BulkAssetsController extends Controller
|
||||
|| ($request->anyFilled($custom_field_columns))
|
||||
|
||||
) {
|
||||
// Let's loop through those assets and build an update array
|
||||
foreach ($assets as $asset) {
|
||||
foreach ($assets as $assetId) {
|
||||
|
||||
$this->update_array = [];
|
||||
|
||||
/**
|
||||
* Leave out model_id and status here because we do math on that later. We have to do some extra
|
||||
* validation and checks on those two.
|
||||
*
|
||||
* It's tempting to make these match the request check above, but some of these values require
|
||||
* extra work to make sure the data makes sense.
|
||||
*/
|
||||
$this->conditionallyAddItem('purchase_date')
|
||||
->conditionallyAddItem('expected_checkin')
|
||||
->conditionallyAddItem('model_id')
|
||||
->conditionallyAddItem('order_number')
|
||||
->conditionallyAddItem('requestable')
|
||||
->conditionallyAddItem('status_id')
|
||||
->conditionallyAddItem('supplier_id')
|
||||
->conditionallyAddItem('warranty_months')
|
||||
->conditionallyAddItem('next_audit_date');
|
||||
foreach ($custom_field_columns as $key => $custom_field_column) {
|
||||
$this->conditionallyAddItem($custom_field_column);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Blank out fields that were requested to be blanked out via checkbox
|
||||
*/
|
||||
if ($request->input('null_purchase_date')=='1') {
|
||||
$this->update_array['purchase_date'] = null;
|
||||
}
|
||||
@@ -214,150 +194,69 @@ class BulkAssetsController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We're trying to change the model ID - we need to do some extra checks here to make sure
|
||||
* the custom field values work for the custom fieldset rules around this asset. Uniqueness
|
||||
* and requiredness across the fieldset is particularly important, since those are
|
||||
* fieldset-specific attributes.
|
||||
*/
|
||||
if ($request->filled('model_id')) {
|
||||
$this->update_array['model_id'] = AssetModel::find($request->input('model_id'))->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* We're trying to change the status ID - we need to do some extra checks here to
|
||||
* make sure the status label type is one that makes sense for the state of the asset,
|
||||
* for example, we shouldn't be able to make an asset archived if it's currently assigned
|
||||
* to someone/something.
|
||||
*/
|
||||
if ($request->filled('status_id')) {
|
||||
$updated_status = Statuslabel::find($request->input('status_id'));
|
||||
|
||||
// We cannot assign a non-deployable status type if the asset is already assigned.
|
||||
// This could probably be added to a form request.
|
||||
// If the asset isn't assigned, we don't care what the status is.
|
||||
// Otherwise we need to make sure the status type is still a deployable one.
|
||||
if (
|
||||
($asset->assigned_to == '')
|
||||
|| ($updated_status->deployable == '1') && ($asset->assetstatus->deployable == '1')
|
||||
) {
|
||||
$this->update_array['status_id'] = $updated_status->id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* We're changing the location ID - figure out which location we should apply
|
||||
* this change to:
|
||||
*
|
||||
* 0 - RTD location only
|
||||
* 1 - location ID and RTD location ID
|
||||
* 2 - location ID only
|
||||
*
|
||||
* Note: this is kinda dumb and we should just use human-readable values IMHO. - snipe
|
||||
*/
|
||||
if ($request->filled('rtd_location_id')) {
|
||||
|
||||
if (($request->filled('update_real_loc')) && (($request->input('update_real_loc')) == '0')) {
|
||||
$this->update_array['rtd_location_id'] = $request->input('rtd_location_id');
|
||||
}
|
||||
|
||||
$this->update_array['rtd_location_id'] = $request->input('rtd_location_id');
|
||||
if (($request->filled('update_real_loc')) && (($request->input('update_real_loc')) == '1')) {
|
||||
$this->update_array['location_id'] = $request->input('rtd_location_id');
|
||||
$this->update_array['rtd_location_id'] = $request->input('rtd_location_id');
|
||||
}
|
||||
|
||||
if (($request->filled('update_real_loc')) && (($request->input('update_real_loc')) == '2')) {
|
||||
$this->update_array['location_id'] = $request->input('rtd_location_id');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------------------
|
||||
* ANYTHING that happens past this foreach
|
||||
* WILL NOT BE logged in the edit log_meta data
|
||||
* ------------------------------------------------------------------------------
|
||||
*/
|
||||
$changed = [];
|
||||
$assetCollection = Asset::where('id' ,$assetId)->get();
|
||||
|
||||
foreach ($this->update_array as $key => $value) {
|
||||
|
||||
if ($this->update_array[$key] != $asset->{$key}) {
|
||||
$changed[$key]['old'] = $asset->{$key};
|
||||
if ($this->update_array[$key] != $assetCollection->toArray()[0][$key]) {
|
||||
$changed[$key]['old'] = $assetCollection->toArray()[0][$key];
|
||||
$changed[$key]['new'] = $this->update_array[$key];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Start all the custom fields shenanigans
|
||||
*/
|
||||
|
||||
// Does the model have a fieldset?
|
||||
if ($asset->model->fieldset) {
|
||||
foreach ($asset->model->fieldset->fields as $field) {
|
||||
|
||||
if ((array_key_exists($field->db_column, $this->update_array)) && ($field->field_encrypted == '1')) {
|
||||
$decrypted_old = Helper::gracefulDecrypt($field, $asset->{$field->db_column});
|
||||
|
||||
/*
|
||||
* Check if the decrypted existing value is different from one we just submitted
|
||||
* and if not, pull it out of the object since it shouldn't really be updating at all.
|
||||
* If we don't do this, it will try to re-encrypt it, and the same value encrypted two
|
||||
* different times will have different values, so it will *look* like it was updated
|
||||
* but it wasn't.
|
||||
*/
|
||||
if ($decrypted_old != $this->update_array[$field->db_column]) {
|
||||
$asset->{$field->db_column} = \Crypt::encrypt($this->update_array[$field->db_column]);
|
||||
} else {
|
||||
/*
|
||||
* Remove the encrypted custom field from the update_array, since nothing changed
|
||||
*/
|
||||
unset($this->update_array[$field->db_column]);
|
||||
unset($asset->{$field->db_column});
|
||||
}
|
||||
|
||||
/*
|
||||
* These custom fields aren't encrypted, just carry on as usual
|
||||
*/
|
||||
} else {
|
||||
|
||||
if ((array_key_exists($field->db_column, $this->update_array)) && ($asset->{$field->db_column} != $this->update_array[$field->db_column])) {
|
||||
|
||||
// Check if this is an array, and if so, flatten it
|
||||
if (is_array($this->update_array[$field->db_column])) {
|
||||
$asset->{$field->db_column} = implode(', ', $this->update_array[$field->db_column]);
|
||||
} else {
|
||||
$asset->{$field->db_column} = $this->update_array[$field->db_column];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // endforeach
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = Asset::class;
|
||||
$logAction->item_id = $assetId;
|
||||
$logAction->created_at = date("Y-m-d H:i:s");
|
||||
$logAction->user_id = Auth::id();
|
||||
$logAction->log_meta = json_encode($changed);
|
||||
$logAction->logaction('update');
|
||||
|
||||
if($custom_fields_present) {
|
||||
$asset = Asset::find($assetId);
|
||||
$assetCustomFields = $asset->model()->first()->fieldset;
|
||||
if($assetCustomFields && $assetCustomFields->fields) {
|
||||
foreach ($assetCustomFields->fields as $field) {
|
||||
if (array_key_exists($field->db_column, $this->update_array)) {
|
||||
$asset->{$field->db_column} = $this->update_array[$field->db_column];
|
||||
$saved = $asset->save();
|
||||
if(!$saved) {
|
||||
$error_bag[] = $asset->getErrors();
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
$array = $this->update_array;
|
||||
array_except($array, $field->db_column);
|
||||
$asset->save($array);
|
||||
}
|
||||
if (!$asset->save()) {
|
||||
$error_bag[] = $asset->getErrors();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check if it passes validation, and then try to save
|
||||
if (!$asset->update($this->update_array)) {
|
||||
|
||||
// Build the error array
|
||||
foreach ($asset->getErrors()->toArray() as $key => $message) {
|
||||
for ($x = 0; $x < count($message); $x++) {
|
||||
$error_array[$key][] = trans('general.asset') . ' ' . $asset->id . ': ' . $message[$x];
|
||||
$has_errors++;
|
||||
}
|
||||
} else {
|
||||
Asset::find($assetId)->update($this->update_array);
|
||||
}
|
||||
}
|
||||
if(!empty($error_bag)) {
|
||||
$errors = [];
|
||||
//find the customfield name from the name of the messagebag items
|
||||
foreach ($error_bag as $key => $bag) {
|
||||
foreach($bag->keys() as $key => $value) {
|
||||
CustomField::where('db_column', $value)->get()->map(function($item) use (&$errors) {
|
||||
$errors[] = $item->name;
|
||||
});
|
||||
}
|
||||
|
||||
} // end if saved
|
||||
|
||||
} // end asset foreach
|
||||
|
||||
if ($has_errors > 0) {
|
||||
return redirect($bulk_back_url)->with('bulk_asset_errors', $error_array);
|
||||
}
|
||||
|
||||
}
|
||||
return redirect($bulk_back_url)->with('bulk_errors', array_unique($errors));
|
||||
}
|
||||
return redirect($bulk_back_url)->with('success', trans('admin/hardware/message.update.success'));
|
||||
}
|
||||
// no values given, nothing to update
|
||||
|
||||
@@ -56,6 +56,7 @@ class LoginController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware('guest', ['except' => ['logout', 'postTwoFactorAuth', 'getTwoFactorAuth', 'getTwoFactorEnroll']]);
|
||||
Session::put('backUrl', \URL::previous());
|
||||
// $this->ldap = $ldap;
|
||||
$this->saml = $saml;
|
||||
}
|
||||
|
||||
@@ -81,6 +82,7 @@ class LoginController extends Controller
|
||||
}
|
||||
|
||||
if (Setting::getSettings()->login_common_disabled == '1') {
|
||||
\Log::debug('login_common_disabled is set to 1 - return a 403');
|
||||
return view('errors.403');
|
||||
}
|
||||
|
||||
@@ -121,7 +123,7 @@ class LoginController extends Controller
|
||||
|
||||
if ($user = Auth::user()) {
|
||||
$user->last_login = \Carbon::now();
|
||||
$user->saveQuietly();
|
||||
$user->save();
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
@@ -197,7 +199,7 @@ class LoginController extends Controller
|
||||
$user->email = $ldap_attr['email'];
|
||||
$user->first_name = $ldap_attr['firstname'];
|
||||
$user->last_name = $ldap_attr['lastname']; //FIXME (or TODO?) - do we need to map additional fields that we now support? E.g. country, phone, etc.
|
||||
$user->saveQuietly();
|
||||
$user->save();
|
||||
} // End if(!user)
|
||||
return $user;
|
||||
}
|
||||
@@ -317,7 +319,7 @@ class LoginController extends Controller
|
||||
if ($user = Auth::user()) {
|
||||
$user->last_login = \Carbon::now();
|
||||
$user->activated = 1;
|
||||
$user->saveQuietly();
|
||||
$user->save();
|
||||
}
|
||||
// Redirect to the users page
|
||||
return redirect()->intended()->with('success', trans('auth/message.signin.success'));
|
||||
@@ -369,7 +371,7 @@ class LoginController extends Controller
|
||||
[-2, -2, -2, -2]
|
||||
);
|
||||
|
||||
$user->saveQuietly(); // make sure to save *AFTER* displaying the barcode, or else we might save a two_factor_secret that we never actually displayed to the user if the barcode fails
|
||||
$user->save(); // make sure to save *AFTER* displaying the barcode, or else we might save a two_factor_secret that we never actually displayed to the user if the barcode fails
|
||||
|
||||
return view('auth.two_factor_enroll')->with('barcode_obj', $barcode_obj);
|
||||
}
|
||||
@@ -424,7 +426,7 @@ class LoginController extends Controller
|
||||
|
||||
if (Google2FA::verifyKey($user->two_factor_secret, $secret)) {
|
||||
$user->two_factor_enrolled = 1;
|
||||
$user->saveQuietly();
|
||||
$user->save();
|
||||
$request->session()->put('2fa_authed', $user->id);
|
||||
|
||||
return redirect()->route('home')->with('success', 'You are logged in!');
|
||||
|
||||
@@ -96,8 +96,8 @@ class ComponentCheckinController extends Controller
|
||||
$asset = Asset::find($component_assets->asset_id);
|
||||
|
||||
event(new CheckoutableCheckedIn($component, $asset, Auth::user(), $request->input('note'), Carbon::now()));
|
||||
if ($backto == 'asset'){
|
||||
return redirect()->route('hardware.show', $asset->id)->with('success',
|
||||
if($backto == 'asset'){
|
||||
return redirect()->route('hardware.view', $asset->id)->with('success',
|
||||
trans('admin/components/message.checkin.success'));
|
||||
}
|
||||
|
||||
|
||||
@@ -20,38 +20,25 @@ class ComponentCheckoutController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ComponentCheckoutController::store() method that stores the data.
|
||||
* @since [v3.0]
|
||||
* @param int $id
|
||||
* @param int $componentId
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create($id)
|
||||
public function create($componentId)
|
||||
{
|
||||
// Check if the component exists
|
||||
if (is_null($component = Component::find($componentId))) {
|
||||
// Redirect to the component management page with error
|
||||
return redirect()->route('components.index')->with('error', trans('admin/components/message.not_found'));
|
||||
}
|
||||
$this->authorize('checkout', $component);
|
||||
|
||||
if ($component = Component::find($id)) {
|
||||
|
||||
$this->authorize('checkout', $component);
|
||||
|
||||
// Make sure the category is valid
|
||||
if ($component->category) {
|
||||
|
||||
// Make sure there is at least one available to checkout
|
||||
if ($component->numRemaining() <= 0){
|
||||
return redirect()->route('components.index')
|
||||
->with('error', trans('admin/components/message.checkout.unavailable'));
|
||||
}
|
||||
|
||||
// Return the checkout view
|
||||
return view('components/checkout', compact('component'));
|
||||
}
|
||||
|
||||
// Invalid category
|
||||
return redirect()->route('components.edit', ['component' => $component->id])
|
||||
->with('error', trans('general.invalid_item_category_single', ['type' => trans('general.component')]));
|
||||
// Make sure there is at least one available to checkout
|
||||
if ($component->numRemaining() <= 0){
|
||||
return redirect()->route('components.index')->with('error', trans('admin/components/message.checkout.unavailable'));
|
||||
}
|
||||
|
||||
// Not found
|
||||
return redirect()->route('components.index')->with('error', trans('admin/components/message.not_found'));
|
||||
|
||||
return view('components/checkout', compact('component'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -142,7 +142,7 @@ class ComponentsFilesController extends Controller
|
||||
$this->authorize('view', $component);
|
||||
$this->authorize('components.files', $component);
|
||||
|
||||
if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $component->id)->find($fileId)) {
|
||||
if (! $log = Actionlog::find($fileId)) {
|
||||
return response('No matching record for that asset/file', 500)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace App\Http\Controllers\Consumables;
|
||||
|
||||
use App\Events\CheckoutableCheckedOut;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -19,38 +18,25 @@ class ConsumableCheckoutController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ConsumableCheckoutController::store() method that stores the data.
|
||||
* @since [v1.0]
|
||||
* @param int $id
|
||||
* @param int $consumableId
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create($id)
|
||||
public function create($consumableId)
|
||||
{
|
||||
|
||||
if ($consumable = Consumable::with('users')->find($id)) {
|
||||
|
||||
$this->authorize('checkout', $consumable);
|
||||
|
||||
// Make sure the category is valid
|
||||
if ($consumable->category) {
|
||||
|
||||
// Make sure there is at least one available to checkout
|
||||
if ($consumable->numRemaining() <= 0){
|
||||
return redirect()->route('consumables.index')
|
||||
->with('error', trans('admin/consumables/message.checkout.unavailable'));
|
||||
}
|
||||
|
||||
// Return the checkout view
|
||||
return view('consumables/checkout', compact('consumable'));
|
||||
}
|
||||
|
||||
// Invalid category
|
||||
return redirect()->route('consumables.edit', ['consumable' => $consumable->id])
|
||||
->with('error', trans('general.invalid_item_category_single', ['type' => trans('general.consumable')]));
|
||||
if (is_null($consumable = Consumable::with('users')->find($consumableId))) {
|
||||
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist'));
|
||||
}
|
||||
|
||||
// Not found
|
||||
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist'));
|
||||
// Make sure there is at least one available to checkout
|
||||
if ($consumable->numRemaining() <= 0){
|
||||
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.checkout.unavailable'));
|
||||
}
|
||||
|
||||
$this->authorize('checkout', $consumable);
|
||||
|
||||
return view('consumables/checkout', compact('consumable'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -140,7 +140,7 @@ class ConsumablesFilesController extends Controller
|
||||
$this->authorize('view', $consumable);
|
||||
$this->authorize('consumables.files', $consumable);
|
||||
|
||||
if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $consumable->id)->find($fileId)) {
|
||||
if (! $log = Actionlog::find($fileId)) {
|
||||
return response('No matching record for that asset/file', 500)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
@@ -110,7 +110,6 @@ class CustomFieldsController extends Controller
|
||||
"display_in_user_view" => $display_in_user_view,
|
||||
"auto_add_to_fieldsets" => $request->get("auto_add_to_fieldsets", 0),
|
||||
"show_in_listview" => $request->get("show_in_listview", 0),
|
||||
"show_in_requestable_list" => $request->get("show_in_requestable_list", 0),
|
||||
"user_id" => Auth::id()
|
||||
]);
|
||||
|
||||
@@ -268,7 +267,6 @@ class CustomFieldsController extends Controller
|
||||
$field->display_in_user_view = $display_in_user_view;
|
||||
$field->auto_add_to_fieldsets = $request->get("auto_add_to_fieldsets", 0);
|
||||
$field->show_in_listview = $request->get("show_in_listview", 0);
|
||||
$field->show_in_requestable_list = $request->get("show_in_requestable_list", 0);
|
||||
|
||||
if ($request->get('format') == 'CUSTOM REGEX') {
|
||||
$field->format = e($request->get('custom_format'));
|
||||
|
||||
@@ -7,10 +7,8 @@ use App\Models\AssetModel;
|
||||
use App\Models\Category;
|
||||
use App\Models\Company;
|
||||
use App\Models\Labels\Label;
|
||||
use App\Models\Location;
|
||||
use App\Models\Manufacturer;
|
||||
use App\Models\Setting;
|
||||
use App\Models\Supplier;
|
||||
use App\Models\User;
|
||||
use App\View\Label as LabelView;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
@@ -35,20 +33,18 @@ class LabelsController extends Controller
|
||||
$exampleAsset->name = 'JEN-867-5309';
|
||||
$exampleAsset->asset_tag = '100001';
|
||||
$exampleAsset->serial = 'SN9876543210';
|
||||
$exampleAsset->asset_eol_date = '2025-01-01';
|
||||
$exampleAsset->order_number = '12345';
|
||||
$exampleAsset->purchase_date = '2023-01-01';
|
||||
$exampleAsset->status_id = 1;
|
||||
|
||||
$exampleAsset->company = new Company([
|
||||
'name' => 'Test Company Limited',
|
||||
'phone' => '1-555-555-5555',
|
||||
'email' => 'company@example.com',
|
||||
]);
|
||||
$exampleAsset->company = new Company();
|
||||
$exampleAsset->company->id = 999999;
|
||||
$exampleAsset->company->name = 'Test Company Limited';
|
||||
$exampleAsset->company->image = 'company-image-test.png';
|
||||
|
||||
$exampleAsset->setRelation('assignedTo', new User(['first_name' => 'Luke', 'last_name' => 'Skywalker']));
|
||||
$exampleAsset->defaultLoc = new Location(['name' => 'Building 1', 'phone' => '1-555-555-5555']);
|
||||
$exampleAsset->location = new Location(['name' => 'Building 2', 'phone' => '1-555-555-5555']);
|
||||
$exampleAsset->assignedto = new User();
|
||||
$exampleAsset->assignedto->id = 999999;
|
||||
$exampleAsset->assignedto->first_name = 'Test';
|
||||
$exampleAsset->assignedto->last_name = 'Person';
|
||||
$exampleAsset->assignedto->username = 'Test.Person';
|
||||
$exampleAsset->assignedto->employee_num = '0123456789';
|
||||
|
||||
$exampleAsset->model = new AssetModel();
|
||||
$exampleAsset->model->id = 999999;
|
||||
@@ -57,10 +53,6 @@ class LabelsController extends Controller
|
||||
$exampleAsset->model->manufacturer = new Manufacturer();
|
||||
$exampleAsset->model->manufacturer->id = 999999;
|
||||
$exampleAsset->model->manufacturer->name = 'Test Manufacturing Inc.';
|
||||
$exampleAsset->model->manufacturer->support_email = 'support@test.com';
|
||||
$exampleAsset->model->manufacturer->support_phone = '1-555-555-5555';
|
||||
$exampleAsset->model->manufacturer->support_url = 'https://example.com';
|
||||
$exampleAsset->supplier = new Supplier(['name' => 'Test Company Limited']);
|
||||
$exampleAsset->model->category = new Category();
|
||||
$exampleAsset->model->category->id = 999999;
|
||||
$exampleAsset->model->category->name = 'Test Category';
|
||||
|
||||
@@ -101,7 +101,7 @@ class LicenseCheckinController extends Controller
|
||||
|
||||
// Was the asset updated?
|
||||
if ($licenseSeat->save()) {
|
||||
event(new CheckoutableCheckedIn($licenseSeat, $return_to, Auth::user(), $request->input('notes')));
|
||||
event(new CheckoutableCheckedIn($licenseSeat, $return_to, Auth::user(), $request->input('note')));
|
||||
|
||||
if ($backTo == 'user') {
|
||||
return redirect()->route('users.show', $return_to->id)->with('success', trans('admin/licenses/message.checkin.success'));
|
||||
|
||||
@@ -5,7 +5,6 @@ namespace App\Http\Controllers\Licenses;
|
||||
use App\Events\CheckoutableCheckedOut;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\LicenseCheckoutRequest;
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Asset;
|
||||
use App\Models\License;
|
||||
use App\Models\LicenseSeat;
|
||||
@@ -22,35 +21,23 @@ class LicenseCheckoutController extends Controller
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param $id
|
||||
* @param $licenseId
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create($id)
|
||||
public function create($licenseId)
|
||||
{
|
||||
|
||||
if ($license = License::find($id)) {
|
||||
// Check that the license is valid
|
||||
if ($license = License::find($licenseId)) {
|
||||
|
||||
$this->authorize('checkout', $license);
|
||||
|
||||
if ($license->category) {
|
||||
|
||||
// Make sure there is at least one available to checkout
|
||||
if ($license->availCount()->count() < 1){
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.checkout.not_enough_seats'));
|
||||
}
|
||||
|
||||
// Return the checkout view
|
||||
return view('licenses/checkout', compact('license'));
|
||||
// If the license is valid, check that there is an available seat
|
||||
if ($license->avail_seats_count < 1) {
|
||||
return redirect()->route('licenses.index')->with('error', 'There are no available seats for this license');
|
||||
}
|
||||
|
||||
// Invalid category
|
||||
return redirect()->route('licenses.edit', ['license' => $license->id])
|
||||
->with('error', trans('general.invalid_item_category_single', ['type' => trans('general.license')]));
|
||||
|
||||
return view('licenses/checkout', compact('license'));
|
||||
}
|
||||
|
||||
// Not found
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found'));
|
||||
|
||||
|
||||
@@ -118,7 +105,7 @@ class LicenseCheckoutController extends Controller
|
||||
$licenseSeat->assigned_to = $target->assigned_to;
|
||||
}
|
||||
if ($licenseSeat->save()) {
|
||||
event(new CheckoutableCheckedOut($licenseSeat, $target, Auth::user(), request('notes')));
|
||||
event(new CheckoutableCheckedOut($licenseSeat, $target, Auth::user(), request('note')));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -135,7 +122,7 @@ class LicenseCheckoutController extends Controller
|
||||
$licenseSeat->assigned_to = request('assigned_to');
|
||||
|
||||
if ($licenseSeat->save()) {
|
||||
event(new CheckoutableCheckedOut($licenseSeat, $target, Auth::user(), request('notes')));
|
||||
event(new CheckoutableCheckedOut($licenseSeat, $target, Auth::user(), request('note')));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ class LicenseFilesController extends Controller
|
||||
$this->authorize('view', $license);
|
||||
$this->authorize('licenses.files', $license);
|
||||
|
||||
if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $license->id)->find($fileId)) {
|
||||
if (! $log = Actionlog::find($fileId)) {
|
||||
return response('No matching record for that asset/file', 500)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
@@ -2,12 +2,8 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Manufacturer;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
@@ -222,37 +218,22 @@ class ManufacturersController extends Controller
|
||||
* @return Redirect
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function restore($id)
|
||||
public function restore($manufacturers_id)
|
||||
{
|
||||
$this->authorize('delete', Manufacturer::class);
|
||||
$this->authorize('create', Manufacturer::class);
|
||||
$manufacturer = Manufacturer::onlyTrashed()->where('id', $manufacturers_id)->first();
|
||||
|
||||
if ($manufacturer = Manufacturer::withTrashed()->find($id)) {
|
||||
|
||||
if ($manufacturer->deleted_at == '') {
|
||||
return redirect()->back()->with('error', trans('general.not_deleted', ['item_type' => trans('general.manufacturer')]));
|
||||
}
|
||||
if ($manufacturer) {
|
||||
|
||||
// Not sure why this is necessary - it shouldn't fail validation here, but it fails without this, so....
|
||||
$manufacturer->setValidating(false);
|
||||
if ($manufacturer->restore()) {
|
||||
$logaction = new Actionlog();
|
||||
$logaction->item_type = Manufacturer::class;
|
||||
$logaction->item_id = $manufacturer->id;
|
||||
$logaction->created_at = date('Y-m-d H:i:s');
|
||||
$logaction->user_id = Auth::user()->id;
|
||||
$logaction->logaction('restore');
|
||||
|
||||
// Redirect them to the deleted page if there are more, otherwise the section index
|
||||
$deleted_manufacturers = Manufacturer::onlyTrashed()->count();
|
||||
if ($deleted_manufacturers > 0) {
|
||||
return redirect()->back()->with('success', trans('admin/manufacturers/message.success.restored'));
|
||||
}
|
||||
return redirect()->route('manufacturers.index')->with('success', trans('admin/manufacturers/message.restore.success'));
|
||||
}
|
||||
|
||||
// Check validation to make sure we're not restoring an asset with the same asset tag (or unique attribute) as an existing asset
|
||||
return redirect()->back()->with('error', trans('general.could_not_restore', ['item_type' => trans('general.manufacturer'), 'error' => $manufacturer->getErrors()->first()]));
|
||||
return redirect()->back()->with('error', 'Could not restore.');
|
||||
}
|
||||
|
||||
return redirect()->route('manufacturers.index')->with('error', trans('admin/manufacturers/message.does_not_exist'));
|
||||
|
||||
return redirect()->back()->with('error', trans('admin/manufacturers/message.does_not_exist'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,7 +134,6 @@ class ProfileController extends Controller
|
||||
];
|
||||
|
||||
$validator = \Validator::make($request->all(), $rules);
|
||||
|
||||
$validator->after(function ($validator) use ($request, $user) {
|
||||
if (! Hash::check($request->input('current_password'), $user->password)) {
|
||||
$validator->errors()->add('current_password', trans('validation.custom.hashed_pass'));
|
||||
@@ -160,14 +159,12 @@ class ProfileController extends Controller
|
||||
});
|
||||
|
||||
if (! $validator->fails()) {
|
||||
|
||||
$user->password = Hash::make($request->input('password'));
|
||||
// We have to use saveQuietly here because for some reason this method was calling the User Oserver twice :(
|
||||
$user->saveQuietly();
|
||||
|
||||
$user->save();
|
||||
|
||||
// Log the user out of other devices
|
||||
Auth::logoutOtherDevices($request->input('password'));
|
||||
return redirect()->route('account')->with('success', trans('passwords.password_change'));
|
||||
return redirect()->route('account.password.index')->with('success', 'Password updated!');
|
||||
|
||||
}
|
||||
return redirect()->back()->withInput()->withErrors($validator);
|
||||
|
||||
@@ -23,7 +23,6 @@ use Input;
|
||||
use League\Csv\Reader;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
use League\Csv\EscapeFormula;
|
||||
use App\Http\Requests\CustomAssetReportRequest;
|
||||
|
||||
|
||||
/**
|
||||
@@ -247,9 +246,6 @@ class ReportsController extends Controller
|
||||
trans('general.action'),
|
||||
trans('general.type'),
|
||||
trans('general.item'),
|
||||
trans('general.license_serial'),
|
||||
trans('general.model_name'),
|
||||
trans('general.model_no'),
|
||||
'To',
|
||||
trans('general.notes'),
|
||||
'Changed',
|
||||
@@ -292,9 +288,6 @@ class ReportsController extends Controller
|
||||
$actionlog->present()->actionType(),
|
||||
e($actionlog->itemType()),
|
||||
($actionlog->itemType() == 'user') ? $actionlog->filename : $item_name,
|
||||
($actionlog->item->serial) ? $actionlog->item->serial : null,
|
||||
($actionlog->item->model) ? htmlspecialchars($actionlog->item->model->name, ENT_NOQUOTES) : null,
|
||||
($actionlog->item->model) ? $actionlog->item->model->model_number : null,
|
||||
$target_name,
|
||||
($actionlog->note) ? e($actionlog->note) : '',
|
||||
$actionlog->log_meta,
|
||||
@@ -410,12 +403,11 @@ class ReportsController extends Controller
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function postCustom(CustomAssetReportRequest $request)
|
||||
public function postCustom(Request $request)
|
||||
{
|
||||
ini_set('max_execution_time', env('REPORT_TIME_LIMIT', 12000)); //12000 seconds = 200 minutes
|
||||
$this->authorize('reports.view');
|
||||
|
||||
|
||||
\Debugbar::disable();
|
||||
$customfields = CustomField::get();
|
||||
$response = new StreamedResponse(function () use ($customfields, $request) {
|
||||
@@ -534,30 +526,6 @@ class ReportsController extends Controller
|
||||
$header[] = trans('admin/users/table.title');
|
||||
}
|
||||
|
||||
if ($request->filled('phone')) {
|
||||
$header[] = trans('admin/users/table.phone');
|
||||
}
|
||||
|
||||
if ($request->filled('user_address')) {
|
||||
$header[] = trans('admin/reports/general.custom_export.user_address');
|
||||
}
|
||||
|
||||
if ($request->filled('user_city')) {
|
||||
$header[] = trans('admin/reports/general.custom_export.user_city');
|
||||
}
|
||||
|
||||
if ($request->filled('user_state')) {
|
||||
$header[] = trans('admin/reports/general.custom_export.user_state');
|
||||
}
|
||||
|
||||
if ($request->filled('user_country')) {
|
||||
$header[] = trans('admin/reports/general.custom_export.user_country');
|
||||
}
|
||||
|
||||
if ($request->filled('user_zip')) {
|
||||
$header[] = trans('admin/reports/general.custom_export.user_zip');
|
||||
}
|
||||
|
||||
if ($request->filled('status')) {
|
||||
$header[] = trans('general.status');
|
||||
}
|
||||
@@ -677,7 +645,7 @@ class ReportsController extends Controller
|
||||
if (($request->filled('created_start')) && ($request->filled('created_end'))) {
|
||||
$created_start = \Carbon::parse($request->input('created_start'))->startOfDay();
|
||||
$created_end = \Carbon::parse($request->input('created_end'))->endOfDay();
|
||||
|
||||
|
||||
$assets->whereBetween('assets.created_at', [$created_start, $created_end]);
|
||||
}
|
||||
if (($request->filled('checkout_date_start')) && ($request->filled('checkout_date_end'))) {
|
||||
@@ -688,22 +656,22 @@ class ReportsController extends Controller
|
||||
}
|
||||
|
||||
if (($request->filled('checkin_date_start'))) {
|
||||
$assets->whereBetween('last_checkin', [
|
||||
Carbon::parse($request->input('checkin_date_start'))->startOfDay(),
|
||||
// use today's date is `checkin_date_end` is not provided
|
||||
Carbon::parse($request->input('checkin_date_end', now()))->endOfDay(),
|
||||
]);
|
||||
$assets->whereBetween('last_checkin', [
|
||||
Carbon::parse($request->input('checkin_date_start'))->startOfDay(),
|
||||
// use today's date is `checkin_date_end` is not provided
|
||||
Carbon::parse($request->input('checkin_date_end', now()))->endOfDay(),
|
||||
]);
|
||||
}
|
||||
|
||||
if (($request->filled('expected_checkin_start')) && ($request->filled('expected_checkin_end'))) {
|
||||
$assets->whereBetween('assets.expected_checkin', [$request->input('expected_checkin_start'), $request->input('expected_checkin_end')]);
|
||||
$assets->whereBetween('assets.expected_checkin', [$request->input('expected_checkin_start'), $request->input('expected_checkin_end')]);
|
||||
}
|
||||
|
||||
if (($request->filled('last_audit_start')) && ($request->filled('last_audit_end'))) {
|
||||
$last_audit_start = \Carbon::parse($request->input('last_audit_start'))->startOfDay();
|
||||
$last_audit_end = \Carbon::parse($request->input('last_audit_end'))->endOfDay();
|
||||
$last_audit_start = \Carbon::parse($request->input('last_audit_start'))->startOfDay();
|
||||
$last_audit_end = \Carbon::parse($request->input('last_audit_end'))->endOfDay();
|
||||
|
||||
$assets->whereBetween('assets.last_audit_date', [$last_audit_start, $last_audit_end]);
|
||||
$assets->whereBetween('assets.last_audit_date', [$last_audit_start, $last_audit_end]);
|
||||
}
|
||||
|
||||
if (($request->filled('next_audit_start')) && ($request->filled('next_audit_end'))) {
|
||||
@@ -774,7 +742,7 @@ class ReportsController extends Controller
|
||||
}
|
||||
|
||||
if ($request->filled('eol')) {
|
||||
$row[] = ($asset->asset_eol_date) ? $asset->asset_eol_date : '';
|
||||
$row[] = ($asset->purchase_date != '') ? $asset->present()->eol_date() : '';
|
||||
}
|
||||
|
||||
if ($request->filled('order')) {
|
||||
@@ -858,54 +826,6 @@ class ReportsController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->filled('phone')) {
|
||||
if ($asset->checkedOutToUser()) {
|
||||
$row[] = ($asset->assignedto) ? $asset->assignedto->phone : '';
|
||||
} else {
|
||||
$row[] = ''; // Empty string if unassigned
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->filled('user_address')) {
|
||||
if ($asset->checkedOutToUser()) {
|
||||
$row[] = ($asset->assignedto) ? $asset->assignedto->address : '';
|
||||
} else {
|
||||
$row[] = ''; // Empty string if unassigned
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->filled('user_city')) {
|
||||
if ($asset->checkedOutToUser()) {
|
||||
$row[] = ($asset->assignedto) ? $asset->assignedto->city : '';
|
||||
} else {
|
||||
$row[] = ''; // Empty string if unassigned
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->filled('user_state')) {
|
||||
if ($asset->checkedOutToUser()) {
|
||||
$row[] = ($asset->assignedto) ? $asset->assignedto->state : '';
|
||||
} else {
|
||||
$row[] = ''; // Empty string if unassigned
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->filled('user_country')) {
|
||||
if ($asset->checkedOutToUser()) {
|
||||
$row[] = ($asset->assignedto) ? $asset->assignedto->country : '';
|
||||
} else {
|
||||
$row[] = ''; // Empty string if unassigned
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->filled('user_zip')) {
|
||||
if ($asset->checkedOutToUser()) {
|
||||
$row[] = ($asset->assignedto) ? $asset->assignedto->zip : '';
|
||||
} else {
|
||||
$row[] = ''; // Empty string if unassigned
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->filled('status')) {
|
||||
$row[] = ($asset->assetstatus) ? $asset->assetstatus->name.' ('.$asset->present()->statusMeta.')' : '';
|
||||
}
|
||||
@@ -1123,34 +1043,27 @@ class ReportsController extends Controller
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @version v1.0
|
||||
*/
|
||||
public function sentAssetAcceptanceReminder(Request $request)
|
||||
public function sentAssetAcceptanceReminder($acceptanceId = null)
|
||||
{
|
||||
$this->authorize('reports.view');
|
||||
|
||||
if (!$acceptance = CheckoutAcceptance::pending()->find($request->input('acceptance_id'))) {
|
||||
\Log::debug('No pending acceptances');
|
||||
if (!$acceptance = CheckoutAcceptance::pending()->find($acceptanceId)) {
|
||||
// Redirect to the unaccepted assets report page with error
|
||||
return redirect()->route('reports/unaccepted_assets')->with('error', trans('general.bad_data'));
|
||||
}
|
||||
|
||||
$assetItem = $acceptance->checkoutable;
|
||||
|
||||
\Log::debug(print_r($assetItem, true));
|
||||
|
||||
if (is_null($acceptance->created_at)){
|
||||
\Log::debug('No acceptance created_at');
|
||||
return redirect()->route('reports/unaccepted_assets')->with('error', trans('general.bad_data'));
|
||||
} else {
|
||||
$logItem_res = $assetItem->checkouts()->where('created_at', '=', $acceptance->created_at)->get();
|
||||
|
||||
if ($logItem_res->isEmpty()){
|
||||
\Log::debug('Acceptance date mismatch');
|
||||
return redirect()->route('reports/unaccepted_assets')->with('error', trans('general.bad_data'));
|
||||
}
|
||||
$logItem = $logItem_res[0];
|
||||
}
|
||||
|
||||
if (!$assetItem->assignedTo->locale){
|
||||
if(!$assetItem->assignedTo->locale){
|
||||
Notification::locale(Setting::getSettings()->locale)->send(
|
||||
$assetItem->assignedTo,
|
||||
new CheckoutAssetNotification($assetItem, $assetItem->assignedTo, $logItem->user, $acceptance, $logItem->note)
|
||||
|
||||
@@ -7,7 +7,6 @@ use App\Helpers\StorageHelper;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Http\Requests\SettingsSamlRequest;
|
||||
use App\Http\Requests\SetupUserRequest;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\Group;
|
||||
use App\Models\Setting;
|
||||
use App\Models\Asset;
|
||||
@@ -27,7 +26,7 @@ use Response;
|
||||
use App\Http\Requests\SlackSettingsRequest;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Validator;
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to Settings for
|
||||
@@ -810,10 +809,9 @@ class SettingsController extends Controller
|
||||
*/
|
||||
public function getLabels()
|
||||
{
|
||||
return view('settings.labels', [
|
||||
'setting' => Setting::getSettings(),
|
||||
'customFields' => CustomField::all(),
|
||||
]);
|
||||
$setting = Setting::getSettings();
|
||||
|
||||
return view('settings.labels', compact('setting'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1250,11 +1248,13 @@ class SettingsController extends Controller
|
||||
if (!$request->hasFile('file')) {
|
||||
return redirect()->route('settings.backups.index')->with('error', 'No file uploaded');
|
||||
} else {
|
||||
|
||||
$max_file_size = Helper::file_upload_max_size();
|
||||
$validator = Validator::make($request->all(), [
|
||||
|
||||
$rules = [
|
||||
'file' => 'required|mimes:zip|max:'.$max_file_size,
|
||||
]);
|
||||
];
|
||||
|
||||
$validator = \Validator::make($request->all(), $rules);
|
||||
|
||||
if ($validator->passes()) {
|
||||
|
||||
@@ -1265,7 +1265,7 @@ class SettingsController extends Controller
|
||||
return redirect()->route('settings.backups.index')->with('success', 'File uploaded');
|
||||
}
|
||||
|
||||
return redirect()->route('settings.backups.index')->withErrors($validator);
|
||||
return redirect()->route('settings.backups.index')->withErrors($request->getErrors());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -125,26 +125,10 @@ class BulkUsersController extends Controller
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the user wants to actually blank out the values vs skip them
|
||||
*/
|
||||
if ($request->input('null_location_id')=='1') {
|
||||
$this->update_array['location_id'] = null;
|
||||
}
|
||||
|
||||
if ($request->input('null_department_id')=='1') {
|
||||
$this->update_array['department_id'] = null;
|
||||
}
|
||||
|
||||
if ($request->input('null_manager_id')=='1') {
|
||||
$this->update_array['manager_id'] = null;
|
||||
}
|
||||
|
||||
if ($request->input('null_company_id')=='1') {
|
||||
$this->update_array['company_id'] = null;
|
||||
}
|
||||
|
||||
|
||||
if (! $manager_conflict) {
|
||||
$this->conditionallyAddItem('manager_id');
|
||||
}
|
||||
|
||||
@@ -49,19 +49,15 @@ class LDAPImportController extends Controller
|
||||
{
|
||||
$this->authorize('update', User::class);
|
||||
// Call Artisan LDAP import command.
|
||||
|
||||
Artisan::call('snipeit:ldap-sync', ['--location_id' => $request->input('location_id'), '--json_summary' => true]);
|
||||
$location_id = $request->input('location_id');
|
||||
Artisan::call('snipeit:ldap-sync', ['--location_id' => $location_id, '--json_summary' => true]);
|
||||
|
||||
// Collect and parse JSON summary.
|
||||
$ldap_results_json = Artisan::output();
|
||||
$ldap_results = json_decode($ldap_results_json, true);
|
||||
if (!$ldap_results) {
|
||||
return redirect()->back()->withInput()->with('error', trans('general.no_results'));
|
||||
}
|
||||
|
||||
// Direct user to appropriate status page.
|
||||
if ($ldap_results['error']) {
|
||||
|
||||
return redirect()->back()->withInput()->with('error', $ldap_results['error_message']);
|
||||
}
|
||||
|
||||
|
||||
@@ -136,11 +136,6 @@ class UserFilesController extends Controller
|
||||
*/
|
||||
public function show($userId = null, $fileId = null)
|
||||
{
|
||||
|
||||
if (empty($fileId)) {
|
||||
return redirect()->route('users.show')->with('error', 'Invalid file request');
|
||||
}
|
||||
|
||||
$user = User::find($userId);
|
||||
|
||||
// the license is valid
|
||||
@@ -148,20 +143,18 @@ class UserFilesController extends Controller
|
||||
|
||||
$this->authorize('view', $user);
|
||||
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $user->id)->find($fileId)) {
|
||||
$log = Actionlog::find($fileId);
|
||||
|
||||
// Display the file inline
|
||||
if (request('inline') == 'true') {
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
return Storage::download('private_uploads/users/'.$log->filename, $log->filename, $headers);
|
||||
}
|
||||
|
||||
return Storage::download('private_uploads/users/'.$log->filename);
|
||||
// Display the file inline
|
||||
if (request('inline') == 'true') {
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
return Storage::download('private_uploads/users/'.$log->filename, $log->filename, $headers);
|
||||
}
|
||||
|
||||
return redirect()->route('users.index')->with('error', trans('admin/users/message.log_record_not_found'));
|
||||
return Storage::download('private_uploads/users/'.$log->filename);
|
||||
|
||||
}
|
||||
|
||||
// Redirect to the user management page if the user doesn't exist
|
||||
|
||||
@@ -7,10 +7,10 @@ use App\Http\Controllers\Controller;
|
||||
use App\Http\Controllers\UserNotFoundException;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Http\Requests\SaveUserRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Company;
|
||||
use App\Models\Group;
|
||||
use App\Models\Ldap;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use App\Notifications\WelcomeNotification;
|
||||
@@ -385,35 +385,18 @@ class UsersController extends Controller
|
||||
*/
|
||||
public function getRestore($id = null)
|
||||
{
|
||||
if ($user = User::withTrashed()->find($id)) {
|
||||
$this->authorize('delete', $user);
|
||||
|
||||
if ($user->deleted_at == '') {
|
||||
return redirect()->back()->with('error', trans('general.not_deleted', ['item_type' => trans('general.user')]));
|
||||
}
|
||||
|
||||
if ($user->restore()) {
|
||||
$logaction = new Actionlog();
|
||||
$logaction->item_type = User::class;
|
||||
$logaction->item_id = $user->id;
|
||||
$logaction->created_at = date('Y-m-d H:i:s');
|
||||
$logaction->user_id = Auth::user()->id;
|
||||
$logaction->logaction('restore');
|
||||
|
||||
// Redirect them to the deleted page if there are more, otherwise the section index
|
||||
$deleted_users = User::onlyTrashed()->count();
|
||||
if ($deleted_users > 0) {
|
||||
return redirect()->back()->with('success', trans('admin/users/message.success.restored'));
|
||||
}
|
||||
return redirect()->route('users.index')->with('success', trans('admin/users/message.success.restored'));
|
||||
|
||||
}
|
||||
|
||||
// Check validation to make sure we're not restoring a user with the same username as an existing user
|
||||
return redirect()->back()->with('error', trans('general.could_not_restore', ['item_type' => trans('general.user'), 'error' => $user->getErrors()->first()]));
|
||||
$this->authorize('update', User::class);
|
||||
// Get user information
|
||||
if (! User::onlyTrashed()->find($id)) {
|
||||
return redirect()->route('users.index')->with('error', trans('admin/users/messages.user_not_found'));
|
||||
}
|
||||
|
||||
return redirect()->route('users.index')->with('error', trans('admin/users/message.does_not_exist'));
|
||||
// Restore the user
|
||||
if (User::withTrashed()->where('id', $id)->restore()) {
|
||||
return redirect()->route('users.index')->with('success', trans('admin/users/message.success.restored'));
|
||||
}
|
||||
|
||||
return redirect()->route('users.index')->with('error', 'User could not be restored.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
class CustomAssetReportRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'purchase_start' => 'date|date_format:Y-m-d|nullable',
|
||||
'purchase_end' => 'date|date_format:Y-m-d|nullable',
|
||||
'created_start' => 'date|date_format:Y-m-d|nullable',
|
||||
'created_end' => 'date|date_format:Y-m-d|nullable',
|
||||
'checkout_date_start' => 'date|date_format:Y-m-d|nullable',
|
||||
'checkout_date_end' => 'date|date_format:Y-m-d|nullable',
|
||||
'expected_checkin_start' => 'date|date_format:Y-m-d|nullable',
|
||||
'expected_checkin_end' => 'date|date_format:Y-m-d|nullable',
|
||||
'checkin_date_start' => 'date|date_format:Y-m-d|nullable',
|
||||
'checkin_date_end' => 'date|date_format:Y-m-d|nullable',
|
||||
'last_audit_start' => 'date|date_format:Y-m-d|nullable',
|
||||
'last_audit_end' => 'date|date_format:Y-m-d|nullable',
|
||||
'next_audit_start' => 'date|date_format:Y-m-d|nullable',
|
||||
'next_audit_end' => 'date|date_format:Y-m-d|nullable',
|
||||
];
|
||||
}
|
||||
|
||||
public function response(array $errors)
|
||||
{
|
||||
return $this->redirector->back()->withInput()->withErrors($errors, $this->errorBag);
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Models\Asset;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
||||
class StoreAssetRequest extends ImageUploadRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return Gate::allows('create', new Asset);
|
||||
}
|
||||
|
||||
public function prepareForValidation(): void
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = array_merge(
|
||||
(new Asset)->getRules(),
|
||||
parent::rules(),
|
||||
);
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
25
app/Http/Traits/UniqueSerialTrait.php
Normal file
25
app/Http/Traits/UniqueSerialTrait.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Traits;
|
||||
|
||||
use App\Models\Setting;
|
||||
|
||||
trait UniqueSerialTrait
|
||||
{
|
||||
/**
|
||||
* Prepare a unique_ids rule, adding a model identifier if required.
|
||||
*
|
||||
* @param array $parameters
|
||||
* @param string $field
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function prepareUniqueSerialRule($parameters, $field)
|
||||
{
|
||||
if ($settings = Setting::getSettings()) {
|
||||
if ($settings->unique_serial == '1') {
|
||||
return 'unique_undeleted:'.$this->table.','.$this->getKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ namespace App\Http\Transformers;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\Setting;
|
||||
use App\Models\Company;
|
||||
@@ -11,9 +10,6 @@ use App\Models\Supplier;
|
||||
use App\Models\Location;
|
||||
use App\Models\AssetModel;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
||||
class ActionlogsTransformer
|
||||
{
|
||||
@@ -73,43 +69,9 @@ class ActionlogsTransformer
|
||||
|
||||
if ($custom_field->db_column == $fieldname) {
|
||||
|
||||
if ($custom_field->field_encrypted == '1') {
|
||||
|
||||
// Unset these fields. We need to decrypt them, since even if the decrypted value
|
||||
// didn't change, their value in the DB will, so we have to compare the unencrypted version
|
||||
// to see if the values actually did change
|
||||
unset($clean_meta[$fieldname]);
|
||||
unset($clean_meta[$fieldname]);
|
||||
|
||||
$enc_old = '';
|
||||
$enc_new = '';
|
||||
|
||||
try {
|
||||
$enc_old = \Crypt::decryptString($this->clean_field($fieldata->old));
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Could not decrypt field - maybe the key changed?');
|
||||
}
|
||||
|
||||
try {
|
||||
$enc_new = \Crypt::decryptString($this->clean_field($fieldata->new));
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Could not decrypt field - maybe the key changed?');
|
||||
}
|
||||
|
||||
if ($enc_old != $enc_new) {
|
||||
\Log::debug('custom fields do not match');
|
||||
$clean_meta[$fieldname]['old'] = "************";
|
||||
$clean_meta[$fieldname]['new'] = "************";
|
||||
|
||||
// Display the changes if the user is an admin or superadmin
|
||||
if (Gate::allows('admin')) {
|
||||
$clean_meta[$fieldname]['old'] = ($enc_old) ? unserialize($enc_old): '';
|
||||
$clean_meta[$fieldname]['new'] = ($enc_new) ? unserialize($enc_new): '';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if ($custom_field->field_encrypted == '1') {
|
||||
$clean_meta[$fieldname]['old'] = "************";
|
||||
$clean_meta[$fieldname]['new'] = "************";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -216,31 +178,15 @@ class ActionlogsTransformer
|
||||
|
||||
|
||||
if(array_key_exists('rtd_location_id',$clean_meta)) {
|
||||
|
||||
$oldRtd = $location->find($clean_meta['rtd_location_id']['old']);
|
||||
$oldRtdName = $oldRtd ? e($oldRtd->name) : trans('general.deleted');
|
||||
|
||||
$newRtd = $location->find($clean_meta['rtd_location_id']['new']);
|
||||
$newRtdName = $newRtd ? e($newRtd->name) : trans('general.deleted');
|
||||
|
||||
$clean_meta['rtd_location_id']['old'] = $clean_meta['rtd_location_id']['old'] ? "[id: ".$clean_meta['rtd_location_id']['old']."] ". $oldRtdName : '';
|
||||
$clean_meta['rtd_location_id']['new'] = $clean_meta['rtd_location_id']['new'] ? "[id: ".$clean_meta['rtd_location_id']['new']."] ". $newRtdName : '';
|
||||
$clean_meta['rtd_location_id']['old'] = $clean_meta['rtd_location_id']['old'] ? "[id: ".$clean_meta['rtd_location_id']['old']."] ". e($location->find($clean_meta['rtd_location_id']['old'])->name) : trans('general.unassigned');
|
||||
$clean_meta['rtd_location_id']['new'] = $clean_meta['rtd_location_id']['new'] ? "[id: ".$clean_meta['rtd_location_id']['new']."] ". e($location->find($clean_meta['rtd_location_id']['new'])->name) : trans('general.unassigned');
|
||||
$clean_meta['Default Location'] = $clean_meta['rtd_location_id'];
|
||||
unset($clean_meta['rtd_location_id']);
|
||||
}
|
||||
|
||||
|
||||
if (array_key_exists('location_id', $clean_meta)) {
|
||||
|
||||
$oldLocation = $location->find($clean_meta['location_id']['old']);
|
||||
$oldLocationName = $oldLocation ? e($oldLocation->name) : trans('general.deleted');
|
||||
|
||||
$newLocation = $location->find($clean_meta['location_id']['new']);
|
||||
$newLocationName = $newLocation ? e($newLocation->name) : trans('general.deleted');
|
||||
|
||||
|
||||
$clean_meta['location_id']['old'] = $clean_meta['location_id']['old'] ? "[id: ".$clean_meta['location_id']['old']."] ". $oldLocationName : '';
|
||||
$clean_meta['location_id']['new'] = $clean_meta['location_id']['new'] ? "[id: ".$clean_meta['location_id']['new']."] ". $newLocationName : '';
|
||||
$clean_meta['location_id']['old'] = $clean_meta['location_id']['old'] ? "[id: ".$clean_meta['location_id']['old']."] ".e($location->find($clean_meta['location_id']['old'])->name): trans('general.unassigned');
|
||||
$clean_meta['location_id']['new'] = $clean_meta['location_id']['new'] ? "[id: ".$clean_meta['location_id']['new']."] ".e($location->find($clean_meta['location_id']['new'])->name) : trans('general.unassigned');
|
||||
$clean_meta['Current Location'] = $clean_meta['location_id'];
|
||||
unset($clean_meta['location_id']);
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ class AssetModelsTransformer
|
||||
|
||||
$permissions_array['available_actions'] = [
|
||||
'update' => (Gate::allows('update', AssetModel::class) && ($assetmodel->deleted_at == '')),
|
||||
'delete' => $assetmodel->isDeletable(),
|
||||
'delete' => (Gate::allows('delete', AssetModel::class) && ($assetmodel->assets_count == 0)),
|
||||
'clone' => (Gate::allows('create', AssetModel::class) && ($assetmodel->deleted_at == '')),
|
||||
'restore' => (Gate::allows('create', AssetModel::class) && ($assetmodel->deleted_at != '')),
|
||||
];
|
||||
|
||||
@@ -7,8 +7,7 @@ use App\Models\Asset;
|
||||
use App\Models\Setting;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Carbon\Carbon;
|
||||
use Auth;
|
||||
|
||||
|
||||
class AssetsTransformer
|
||||
{
|
||||
@@ -39,7 +38,7 @@ class AssetsTransformer
|
||||
'byod' => ($asset->byod ? true : false),
|
||||
|
||||
'model_number' => (($asset->model) && ($asset->model->model_number)) ? e($asset->model->model_number) : null,
|
||||
'eol' => (($asset->asset_eol_date != '') && ($asset->purchase_date != '')) ? Carbon::parse($asset->asset_eol_date)->diffInMonths($asset->purchase_date).' months' : null,
|
||||
'eol' => (($asset->model) && ($asset->model->eol != '')) ? $asset->model->eol : null,
|
||||
'asset_eol_date' => ($asset->asset_eol_date != '') ? Helper::getFormattedDateObject($asset->asset_eol_date, 'date') : null,
|
||||
'status_label' => ($asset->assetstatus) ? [
|
||||
'id' => (int) $asset->assetstatus->id,
|
||||
@@ -147,7 +146,7 @@ class AssetsTransformer
|
||||
'clone' => Gate::allows('create', Asset::class) ? true : false,
|
||||
'restore' => ($asset->deleted_at!='' && Gate::allows('create', Asset::class)) ? true : false,
|
||||
'update' => ($asset->deleted_at=='' && Gate::allows('update', Asset::class)) ? true : false,
|
||||
'delete' => ($asset->deleted_at=='' && $asset->assigned_to =='' && Gate::allows('delete', Asset::class) && ($asset->deleted_at == '')) ? true : false,
|
||||
'delete' => ($asset->deleted_at=='' && $asset->assigned_to =='' && Gate::allows('delete', Asset::class)) ? true : false,
|
||||
];
|
||||
|
||||
|
||||
@@ -232,29 +231,6 @@ class AssetsTransformer
|
||||
'assigned_to_self' => ($asset->assigned_to == \Auth::user()->id),
|
||||
];
|
||||
|
||||
if (($asset->model) && ($asset->model->fieldset) && ($asset->model->fieldset->fields->count() > 0)) {
|
||||
$fields_array = [];
|
||||
|
||||
foreach ($asset->model->fieldset->fields as $field) {
|
||||
|
||||
// Only display this if it's allowed via the custom field setting
|
||||
if (($field->field_encrypted=='0') && ($field->show_in_requestable_list=='1')) {
|
||||
|
||||
$value = $asset->{$field->db_column};
|
||||
if (($field->format == 'DATE') && (!is_null($value)) && ($value != '')) {
|
||||
$value = Helper::getFormattedDateObject($value, 'date', false);
|
||||
}
|
||||
|
||||
$fields_array[$field->db_column] = e($value);
|
||||
}
|
||||
|
||||
$array['custom_fields'] = $fields_array;
|
||||
}
|
||||
} else {
|
||||
$array['custom_fields'] = new \stdClass; // HACK to force generation of empty object instead of empty list
|
||||
}
|
||||
|
||||
|
||||
$permissions_array['available_actions'] = [
|
||||
'cancel' => ($asset->isRequestedBy(\Auth::user())) ? true : false,
|
||||
'request' => ($asset->isRequestedBy(\Auth::user())) ? false : true,
|
||||
|
||||
@@ -79,7 +79,7 @@ class UsersTransformer
|
||||
|
||||
$permissions_array['available_actions'] = [
|
||||
'update' => (Gate::allows('update', User::class) && ($user->deleted_at == '')),
|
||||
'delete' => $user->isDeletable(),
|
||||
'delete' => (Gate::allows('delete', User::class) && ($user->assets_count == 0) && ($user->licenses_count == 0) && ($user->accessories_count == 0)),
|
||||
'clone' => (Gate::allows('create', User::class) && ($user->deleted_at == '')),
|
||||
'restore' => (Gate::allows('create', User::class) && ($user->deleted_at != '')),
|
||||
];
|
||||
|
||||
@@ -34,7 +34,7 @@ class AccessoryImporter extends ItemImporter
|
||||
}
|
||||
|
||||
$this->log('Updating Accessory');
|
||||
$this->item['model_number'] = trim($this->findCsvMatch($row, "model_number"));
|
||||
$this->item['model_number'] = $this->findCsvMatch($row, "model_number");
|
||||
$accessory->update($this->sanitizeItemForUpdating($accessory));
|
||||
$accessory->save();
|
||||
|
||||
|
||||
@@ -5,9 +5,6 @@ namespace App\Importer;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Statuslabel;
|
||||
use App\Models\User;
|
||||
use App\Events\CheckoutableCheckedIn;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class AssetImporter extends ItemImporter
|
||||
@@ -83,13 +80,13 @@ class AssetImporter extends ItemImporter
|
||||
$this->log('No Matching Asset, Creating a new one');
|
||||
$asset = new Asset;
|
||||
}
|
||||
$this->item['notes'] = trim($this->findCsvMatch($row, 'asset_notes'));
|
||||
$this->item['image'] = trim($this->findCsvMatch($row, 'image'));
|
||||
$this->item['requestable'] = trim(($this->fetchHumanBoolean($this->findCsvMatch($row, 'requestable'))) == 1) ? '1' : 0;
|
||||
$this->item['notes'] = $this->findCsvMatch($row, 'asset_notes');
|
||||
$this->item['image'] = $this->findCsvMatch($row, 'image');
|
||||
$this->item['requestable'] = ($this->fetchHumanBoolean($this->findCsvMatch($row, 'requestable')) == 1) ? '1' : 0;
|
||||
$asset->requestable = $this->item['requestable'];
|
||||
$this->item['warranty_months'] = intval(trim($this->findCsvMatch($row, 'warranty_months')));
|
||||
$this->item['warranty_months'] = intval($this->findCsvMatch($row, 'warranty_months'));
|
||||
$this->item['model_id'] = $this->createOrFetchAssetModel($row);
|
||||
$this->item['byod'] = ($this->fetchHumanBoolean(trim($this->findCsvMatch($row, 'byod'))) == 1) ? '1' : 0;
|
||||
$this->item['byod'] = ($this->fetchHumanBoolean($this->findCsvMatch($row, 'byod')) == 1) ? '1' : 0;
|
||||
|
||||
|
||||
// If no status ID is found
|
||||
@@ -144,13 +141,7 @@ class AssetImporter extends ItemImporter
|
||||
// If we have a target to checkout to, lets do so.
|
||||
//-- user_id is a property of the abstract class Importer, which this class inherits from and it's setted by
|
||||
//-- the class that needs to use it (command importer or GUI importer inside the project).
|
||||
if (isset($target) && ($target !== false)) {
|
||||
if (!is_null($asset->assigned_to)){
|
||||
if ($asset->assigned_to != $target->id){
|
||||
event(new CheckoutableCheckedIn($asset, User::find($asset->assigned_to), Auth::user(), $asset->notes, date('Y-m-d H:i:s')));
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($target)) {
|
||||
$asset->fresh()->checkOut($target, $this->user_id, date('Y-m-d H:i:s'), null, $asset->notes, $asset->name);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,8 +28,8 @@ class ComponentImporter extends ItemImporter
|
||||
{
|
||||
$component = null;
|
||||
$this->log('Creating Component');
|
||||
$component = Component::where('name', trim($this->item['name']))
|
||||
->where('serial', trim($this->item['serial']))
|
||||
$component = Component::where('name', $this->item['name'])
|
||||
->where('serial', $this->item['serial'])
|
||||
->first();
|
||||
|
||||
if ($component) {
|
||||
|
||||
@@ -26,7 +26,7 @@ class ConsumableImporter extends ItemImporter
|
||||
*/
|
||||
public function createConsumableIfNotExists($row)
|
||||
{
|
||||
$consumable = Consumable::where('name', trim($this->item['name']))->first();
|
||||
$consumable = Consumable::where('name', $this->item['name'])->first();
|
||||
if ($consumable) {
|
||||
if (! $this->updating) {
|
||||
$this->log('A matching Consumable '.$this->item['name'].' already exists. ');
|
||||
@@ -41,9 +41,9 @@ class ConsumableImporter extends ItemImporter
|
||||
}
|
||||
$this->log('No matching consumable, creating one');
|
||||
$consumable = new Consumable();
|
||||
$this->item['model_number'] = trim($this->findCsvMatch($row, 'model_number'));
|
||||
$this->item['item_no'] = trim($this->findCsvMatch($row, 'item_number'));
|
||||
$this->item['min_amt'] = trim($this->findCsvMatch($row, "min_amt"));
|
||||
$this->item['model_number'] = $this->findCsvMatch($row, 'model_number');
|
||||
$this->item['item_no'] = $this->findCsvMatch($row, 'item_number');
|
||||
$this->item['min_amt'] = $this->findCsvMatch($row, "min_amt");
|
||||
$consumable->fill($this->sanitizeItemForStoring($consumable));
|
||||
//FIXME: this disables model validation. Need to find a way to avoid double-logs without breaking everything.
|
||||
$consumable->unsetEventDispatcher();
|
||||
|
||||
@@ -19,76 +19,22 @@ abstract class Importer
|
||||
* Id of User performing import
|
||||
* @var
|
||||
*/
|
||||
|
||||
protected $user_id;
|
||||
/**
|
||||
* Are we updating items in the import
|
||||
* @var bool
|
||||
*/
|
||||
|
||||
protected $updating;
|
||||
|
||||
/**
|
||||
* Default Map of item fields->csv names
|
||||
*
|
||||
* This has been moved into app/Http/Livewire/Importer.php to be more granular.
|
||||
* This private variable is ONLY used for the cli-importer.
|
||||
* @todo - remove references to this property since we don't use it anymore.
|
||||
*
|
||||
* @todo - find a way to make this less duplicative
|
||||
* @var array
|
||||
*/
|
||||
private $defaultFieldMap = [
|
||||
'asset_tag' => 'asset tag',
|
||||
'activated' => 'activated',
|
||||
'category' => 'category',
|
||||
'checkout_class' => 'checkout type', // Supports Location or User for assets. Using checkout_class instead of checkout_type because type exists on asset already.
|
||||
'checkout_location' => 'checkout location',
|
||||
'company' => 'company',
|
||||
'item_name' => 'item name',
|
||||
'item_number' => 'item number',
|
||||
'image' => 'image',
|
||||
'expiration_date' => 'expiration date',
|
||||
'location' => 'location',
|
||||
'notes' => 'notes',
|
||||
'license_email' => 'licensed to email',
|
||||
'license_name' => 'licensed to name',
|
||||
'maintained' => 'maintained',
|
||||
'manufacturer' => 'manufacturer',
|
||||
'asset_model' => 'model name',
|
||||
'model_number' => 'model number',
|
||||
'order_number' => 'order number',
|
||||
'purchase_cost' => 'purchase cost',
|
||||
'purchase_date' => 'purchase date',
|
||||
'purchase_order' => 'purchase order',
|
||||
'qty' => 'quantity',
|
||||
'reassignable' => 'reassignable',
|
||||
'requestable' => 'requestable',
|
||||
'seats' => 'seats',
|
||||
'serial' => 'serial number',
|
||||
'status' => 'status',
|
||||
'supplier' => 'supplier',
|
||||
'termination_date' => 'termination date',
|
||||
'warranty_months' => 'warranty',
|
||||
'full_name' => 'full name',
|
||||
'email' => 'email',
|
||||
'username' => 'username',
|
||||
'address' => 'address',
|
||||
'address2' => 'address2',
|
||||
'city' => 'city',
|
||||
'state' => 'state',
|
||||
'country' => 'country',
|
||||
'zip' => 'zip',
|
||||
'jobtitle' => 'job title',
|
||||
'employee_num' => 'employee number',
|
||||
'phone_number' => 'phone number',
|
||||
'first_name' => 'first name',
|
||||
'last_name' => 'last name',
|
||||
'department' => 'department',
|
||||
'manager_name' => 'manager full name',
|
||||
'manager_username' => 'manager username',
|
||||
'min_amt' => 'minimum quantity',
|
||||
'remote' => 'remote',
|
||||
'vip' => 'vip',
|
||||
|
||||
];
|
||||
/**
|
||||
* Map of item fields->csv names
|
||||
@@ -335,11 +281,9 @@ abstract class Importer
|
||||
$user_array['email'] = User::generateEmailFromFullName($user_array['full_name']);
|
||||
}
|
||||
|
||||
// Get some variables for $user_formatted_array in case we need them later
|
||||
$user_formatted_array = User::generateFormattedNameFromFullName($user_array['full_name'], Setting::getSettings()->username_format);
|
||||
|
||||
if (empty($user_array['first_name'])) {
|
||||
// Get some fields for first name and last name based off of full name
|
||||
$user_formatted_array = User::generateFormattedNameFromFullName($user_array['full_name'], Setting::getSettings()->username_format);
|
||||
$user_array['first_name'] = $user_formatted_array['first_name'];
|
||||
$user_array['last_name'] = $user_formatted_array['last_name'];
|
||||
}
|
||||
|
||||
@@ -372,7 +372,7 @@ class ItemImporter extends Importer
|
||||
if (empty($asset_statuslabel_name)) {
|
||||
return null;
|
||||
}
|
||||
$status = Statuslabel::where(['name' => trim($asset_statuslabel_name)])->first();
|
||||
$status = Statuslabel::where(['name' => $asset_statuslabel_name])->first();
|
||||
|
||||
if ($status) {
|
||||
$this->log('A matching Status '.$asset_statuslabel_name.' already exists');
|
||||
@@ -381,7 +381,7 @@ class ItemImporter extends Importer
|
||||
}
|
||||
$this->log('Creating a new status');
|
||||
$status = new Statuslabel();
|
||||
$status->name = trim($asset_statuslabel_name);
|
||||
$status->name = $asset_statuslabel_name;
|
||||
|
||||
$status->deployable = 1;
|
||||
$status->pending = 0;
|
||||
@@ -420,7 +420,7 @@ class ItemImporter extends Importer
|
||||
|
||||
//Otherwise create a manufacturer.
|
||||
$manufacturer = new Manufacturer();
|
||||
$manufacturer->name = trim($item_manufacturer);
|
||||
$manufacturer->name = $item_manufacturer;
|
||||
$manufacturer->user_id = $this->user_id;
|
||||
|
||||
if ($manufacturer->save()) {
|
||||
|
||||
@@ -55,19 +55,19 @@ class LicenseImporter extends ItemImporter
|
||||
$this->log('No Matching License, Creating a new one');
|
||||
$license = new License;
|
||||
}
|
||||
$asset_tag = $this->item['asset_tag'] = trim($this->findCsvMatch($row, 'asset_tag')); // used for checkout out to an asset.
|
||||
$asset_tag = $this->item['asset_tag'] = $this->findCsvMatch($row, 'asset_tag'); // used for checkout out to an asset.
|
||||
|
||||
$this->item["expiration_date"] = null;
|
||||
if ($this->findCsvMatch($row, "expiration_date")!='') {
|
||||
$this->item["expiration_date"] = date("Y-m-d 00:00:01", strtotime(trim($this->findCsvMatch($row, "expiration_date"))));
|
||||
$this->item["expiration_date"] = date("Y-m-d 00:00:01", strtotime($this->findCsvMatch($row, "expiration_date")));
|
||||
}
|
||||
$this->item['license_email'] = trim($this->findCsvMatch($row, 'license_email'));
|
||||
$this->item['license_name'] = trim($this->findCsvMatch($row, 'license_name'));
|
||||
$this->item['maintained'] = trim($this->findCsvMatch($row, 'maintained'));
|
||||
$this->item['purchase_order'] = trim($this->findCsvMatch($row, 'purchase_order'));
|
||||
$this->item['order_number'] = trim($this->findCsvMatch($row, 'order_number'));
|
||||
$this->item['reassignable'] = trim($this->findCsvMatch($row, 'reassignable'));
|
||||
$this->item['manufacturer'] = $this->createOrFetchManufacturer(trim($this->findCsvMatch($row, 'manufacturer')));
|
||||
$this->item['license_email'] = $this->findCsvMatch($row, 'license_email');
|
||||
$this->item['license_name'] = $this->findCsvMatch($row, 'license_name');
|
||||
$this->item['maintained'] = $this->findCsvMatch($row, 'maintained');
|
||||
$this->item['purchase_order'] = $this->findCsvMatch($row, 'purchase_order');
|
||||
$this->item['order_number'] = $this->findCsvMatch($row, 'order_number');
|
||||
$this->item['reassignable'] = $this->findCsvMatch($row, 'reassignable');
|
||||
$this->item['manufacturer'] = $this->createOrFetchManufacturer($this->findCsvMatch($row, 'manufacturer'));
|
||||
|
||||
if($this->item['reassignable'] == "")
|
||||
{
|
||||
|
||||
@@ -53,21 +53,21 @@ class LocationImporter extends ItemImporter
|
||||
}
|
||||
|
||||
// Pull the records from the CSV to determine their values
|
||||
$this->item['name'] = trim($this->findCsvMatch($row, 'name'));
|
||||
$this->item['address'] = trim($this->findCsvMatch($row, 'address'));
|
||||
$this->item['address2'] = trim($this->findCsvMatch($row, 'address2'));
|
||||
$this->item['city'] = trim($this->findCsvMatch($row, 'city'));
|
||||
$this->item['state'] = trim($this->findCsvMatch($row, 'state'));
|
||||
$this->item['country'] = trim($this->findCsvMatch($row, 'country'));
|
||||
$this->item['zip'] = trim($this->findCsvMatch($row, 'zip'));
|
||||
$this->item['currency'] = trim($this->findCsvMatch($row, 'currency'));
|
||||
$this->item['ldap_ou'] = trim($this->findCsvMatch($row, 'ldap_ou'));
|
||||
$this->item['manager'] = trim($this->findCsvMatch($row, 'manager'));
|
||||
$this->item['manager_username'] = trim($this->findCsvMatch($row, 'manager_username'));
|
||||
$this->item['name'] = $this->findCsvMatch($row, 'name');
|
||||
$this->item['address'] = $this->findCsvMatch($row, 'address');
|
||||
$this->item['address2'] = $this->findCsvMatch($row, 'address2');
|
||||
$this->item['city'] = $this->findCsvMatch($row, 'city');
|
||||
$this->item['state'] = $this->findCsvMatch($row, 'state');
|
||||
$this->item['country'] = $this->findCsvMatch($row, 'country');
|
||||
$this->item['zip'] = $this->findCsvMatch($row, 'zip');
|
||||
$this->item['currency'] = $this->findCsvMatch($row, 'currency');
|
||||
$this->item['ldap_ou'] = $this->findCsvMatch($row, 'ldap_ou');
|
||||
$this->item['manager'] = $this->findCsvMatch($row, 'manager');
|
||||
$this->item['manager_username'] = $this->findCsvMatch($row, 'manager_username');
|
||||
$this->item['user_id'] = \Auth::user()->id;
|
||||
|
||||
if ($this->findCsvMatch($row, 'parent_location')) {
|
||||
$this->item['parent_id'] = $this->createOrFetchLocation(trim($this->findCsvMatch($row, 'parent_location')));
|
||||
$this->item['parent_id'] = $this->createOrFetchLocation($this->findCsvMatch($row, 'parent_location'));
|
||||
}
|
||||
|
||||
if (!empty($this->item['manager'])) {
|
||||
|
||||
@@ -42,32 +42,32 @@ class UserImporter extends ItemImporter
|
||||
public function createUserIfNotExists(array $row)
|
||||
{
|
||||
// Pull the records from the CSV to determine their values
|
||||
$this->item['id'] = trim($this->findCsvMatch($row, 'id'));
|
||||
$this->item['username'] = trim($this->findCsvMatch($row, 'username'));
|
||||
$this->item['first_name'] = trim($this->findCsvMatch($row, 'first_name'));
|
||||
$this->item['last_name'] = trim($this->findCsvMatch($row, 'last_name'));
|
||||
$this->item['email'] = trim($this->findCsvMatch($row, 'email'));
|
||||
$this->item['gravatar'] = trim($this->findCsvMatch($row, 'gravatar'));
|
||||
$this->item['phone'] = trim($this->findCsvMatch($row, 'phone_number'));
|
||||
$this->item['website'] = trim($this->findCsvMatch($row, 'website'));
|
||||
$this->item['jobtitle'] = trim($this->findCsvMatch($row, 'jobtitle'));
|
||||
$this->item['address'] = trim($this->findCsvMatch($row, 'address'));
|
||||
$this->item['city'] = trim($this->findCsvMatch($row, 'city'));
|
||||
$this->item['state'] = trim($this->findCsvMatch($row, 'state'));
|
||||
$this->item['country'] = trim($this->findCsvMatch($row, 'country'));
|
||||
$this->item['start_date'] = trim($this->findCsvMatch($row, 'start_date'));
|
||||
$this->item['end_date'] = trim($this->findCsvMatch($row, 'end_date'));
|
||||
$this->item['zip'] = trim($this->findCsvMatch($row, 'zip'));
|
||||
$this->item['activated'] = ($this->fetchHumanBoolean(trim($this->findCsvMatch($row, 'activated'))) == 1) ? '1' : 0;
|
||||
$this->item['employee_num'] = trim($this->findCsvMatch($row, 'employee_num'));
|
||||
$this->item['department_id'] = trim($this->createOrFetchDepartment(trim($this->findCsvMatch($row, 'department'))));
|
||||
$this->item['manager_id'] = $this->fetchManager(trim($this->findCsvMatch($row, 'manager_first_name')), trim($this->findCsvMatch($row, 'manager_last_name')));
|
||||
$this->item['remote'] = ($this->fetchHumanBoolean(trim($this->findCsvMatch($row, 'remote'))) == 1 ) ? '1' : 0;
|
||||
$this->item['vip'] = ($this->fetchHumanBoolean(trim($this->findCsvMatch($row, 'vip'))) ==1 ) ? '1' : 0;
|
||||
$this->item['autoassign_licenses'] = ($this->fetchHumanBoolean(trim($this->findCsvMatch($row, 'autoassign_licenses'))) ==1 ) ? '1' : 0;
|
||||
$this->item['id'] = $this->findCsvMatch($row, 'id');
|
||||
$this->item['username'] = $this->findCsvMatch($row, 'username');
|
||||
$this->item['first_name'] = $this->findCsvMatch($row, 'first_name');
|
||||
$this->item['last_name'] = $this->findCsvMatch($row, 'last_name');
|
||||
$this->item['email'] = $this->findCsvMatch($row, 'email');
|
||||
$this->item['gravatar'] = $this->findCsvMatch($row, 'gravatar');
|
||||
$this->item['phone'] = $this->findCsvMatch($row, 'phone_number');
|
||||
$this->item['website'] = $this->findCsvMatch($row, 'website');
|
||||
$this->item['jobtitle'] = $this->findCsvMatch($row, 'jobtitle');
|
||||
$this->item['address'] = $this->findCsvMatch($row, 'address');
|
||||
$this->item['city'] = $this->findCsvMatch($row, 'city');
|
||||
$this->item['state'] = $this->findCsvMatch($row, 'state');
|
||||
$this->item['country'] = $this->findCsvMatch($row, 'country');
|
||||
$this->item['start_date'] = $this->findCsvMatch($row, 'start_date');
|
||||
$this->item['end_date'] = $this->findCsvMatch($row, 'end_date');
|
||||
$this->item['zip'] = $this->findCsvMatch($row, 'zip');
|
||||
$this->item['activated'] = ($this->fetchHumanBoolean($this->findCsvMatch($row, 'activated')) == 1) ? '1' : 0;
|
||||
$this->item['employee_num'] = $this->findCsvMatch($row, 'employee_num');
|
||||
$this->item['department_id'] = $this->createOrFetchDepartment($this->findCsvMatch($row, 'department'));
|
||||
$this->item['manager_id'] = $this->fetchManager($this->findCsvMatch($row, 'manager_first_name'), $this->findCsvMatch($row, 'manager_last_name'));
|
||||
$this->item['remote'] =($this->fetchHumanBoolean($this->findCsvMatch($row, 'remote')) ==1 ) ? '1' : 0;
|
||||
$this->item['vip'] = ($this->fetchHumanBoolean($this->findCsvMatch($row, 'vip')) ==1 ) ? '1' : 0;
|
||||
$this->item['autoassign_licenses'] = ($this->fetchHumanBoolean($this->findCsvMatch($row, 'autoassign_licenses')) ==1 ) ? '1' : 0;
|
||||
|
||||
|
||||
$user_department = trim($this->findCsvMatch($row, 'department'));
|
||||
$user_department = $this->findCsvMatch($row, 'department');
|
||||
if ($this->shouldUpdateField($user_department)) {
|
||||
$this->item['department_id'] = $this->createOrFetchDepartment($user_department);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ use App\Notifications\CheckoutAccessoryNotification;
|
||||
use App\Notifications\CheckoutAssetNotification;
|
||||
use App\Notifications\CheckoutConsumableNotification;
|
||||
use App\Notifications\CheckoutLicenseSeatNotification;
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Exception;
|
||||
use Log;
|
||||
@@ -42,9 +41,14 @@ class CheckoutableListener
|
||||
/**
|
||||
* Make a checkout acceptance and attach it in the notification
|
||||
*/
|
||||
$acceptance = $this->getCheckoutAcceptance($event);
|
||||
$acceptance = $this->getCheckoutAcceptance($event);
|
||||
|
||||
try {
|
||||
if ($this->shouldSendWebhookNotification()) {
|
||||
Notification::route('slack', Setting::getSettings()->webhook_endpoint)
|
||||
->notify($this->getCheckoutNotification($event));
|
||||
}
|
||||
|
||||
if (! $event->checkedOutTo->locale) {
|
||||
Notification::locale(Setting::getSettings()->locale)->send(
|
||||
$this->getNotifiables($event),
|
||||
@@ -56,15 +60,8 @@ class CheckoutableListener
|
||||
$this->getCheckoutNotification($event, $acceptance)
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->shouldSendWebhookNotification()) {
|
||||
Notification::route('slack', Setting::getSettings()->webhook_endpoint)
|
||||
->notify($this->getCheckoutNotification($event));
|
||||
}
|
||||
} catch (ClientException $e) {
|
||||
Log::debug("Exception caught during checkout notification: " . $e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
Log::error("Exception caught during checkout notification: " . $e->getMessage());
|
||||
Log::error("Exception caught during checkout notification: ".$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +92,11 @@ class CheckoutableListener
|
||||
}
|
||||
|
||||
try {
|
||||
if ($this->shouldSendWebhookNotification()) {
|
||||
Notification::route('slack', Setting::getSettings()->webhook_endpoint)
|
||||
->notify($this->getCheckinNotification($event));
|
||||
}
|
||||
|
||||
// Use default locale
|
||||
if (! $event->checkedOutTo->locale) {
|
||||
Notification::locale(Setting::getSettings()->locale)->send(
|
||||
@@ -107,15 +109,8 @@ class CheckoutableListener
|
||||
$this->getCheckinNotification($event)
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->shouldSendWebhookNotification()) {
|
||||
Notification::route('slack', Setting::getSettings()->webhook_endpoint)
|
||||
->notify($this->getCheckinNotification($event));
|
||||
}
|
||||
} catch (ClientException $e) {
|
||||
Log::debug("Exception caught during checkout notification: " . $e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
Log::error("Exception caught during checkin notification: " . $e->getMessage());
|
||||
Log::error("Exception caught during checkin notification: ".$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ class LogListener
|
||||
$logaction->item()->associate($event->acceptance->checkoutable->license);
|
||||
}
|
||||
|
||||
\Log::debug('New onCheckoutAccepted Listener fired. logaction: '.print_r($logaction, true));
|
||||
$logaction->save();
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ use App\Events\AssetCheckedOut;
|
||||
use App\Events\CheckoutableCheckedOut;
|
||||
use App\Exceptions\CheckoutNotAllowed;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Traits\UniqueSerialTrait;
|
||||
use App\Http\Traits\UniqueUndeletedTrait;
|
||||
use App\Models\Traits\Acceptable;
|
||||
use App\Models\Traits\Searchable;
|
||||
@@ -31,7 +32,7 @@ class Asset extends Depreciable
|
||||
protected $presenter = \App\Presenters\AssetPresenter::class;
|
||||
|
||||
use CompanyableTrait;
|
||||
use HasFactory, Loggable, Requestable, Presentable, SoftDeletes, ValidatingTrait, UniqueUndeletedTrait;
|
||||
use HasFactory, Loggable, Requestable, Presentable, SoftDeletes, ValidatingTrait, UniqueUndeletedTrait, UniqueSerialTrait;
|
||||
|
||||
public const LOCATION = 'location';
|
||||
public const ASSET = 'asset';
|
||||
@@ -71,7 +72,8 @@ class Asset extends Depreciable
|
||||
|
||||
protected $casts = [
|
||||
'purchase_date' => 'date',
|
||||
'eol_explicit' => 'boolean',
|
||||
'asset_eol_date' => 'date',
|
||||
'eol_explicit' => 'boolean',
|
||||
'last_checkout' => 'datetime',
|
||||
'last_checkin' => 'datetime',
|
||||
'expected_checkin' => 'date',
|
||||
@@ -90,7 +92,7 @@ class Asset extends Depreciable
|
||||
|
||||
protected $rules = [
|
||||
'name' => 'max:255|nullable',
|
||||
'model_id' => 'required|integer|exists:models,id,deleted_at,NULL|not_array',
|
||||
'model_id' => 'required|integer|exists:models,id,deleted_at,NULL',
|
||||
'status_id' => 'required|integer|exists:status_labels,id',
|
||||
'company_id' => 'integer|nullable',
|
||||
'warranty_months' => 'numeric|nullable|digits_between:0,240',
|
||||
@@ -99,9 +101,9 @@ class Asset extends Depreciable
|
||||
'expected_checkin' => 'date|nullable',
|
||||
'location_id' => 'exists:locations,id|nullable',
|
||||
'rtd_location_id' => 'exists:locations,id|nullable',
|
||||
'asset_tag' => 'required|min:1|max:255|unique_undeleted:assets,asset_tag|not_array',
|
||||
'asset_tag' => 'required|min:1|max:255|unique_undeleted',
|
||||
'purchase_date' => 'date|date_format:Y-m-d|nullable',
|
||||
'serial' => 'unique_undeleted:assets,serial|nullable',
|
||||
'serial' => 'unique_serial|nullable',
|
||||
'purchase_cost' => 'numeric|nullable|gte:0',
|
||||
'supplier_id' => 'exists:suppliers,id|nullable',
|
||||
'asset_eol_date' => 'date|nullable',
|
||||
@@ -109,7 +111,6 @@ class Asset extends Depreciable
|
||||
'byod' => 'boolean',
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
@@ -212,16 +213,16 @@ class Asset extends Depreciable
|
||||
|
||||
$this->rules += $model->fieldset->validation_rules();
|
||||
|
||||
if ($this->model->fieldset){
|
||||
foreach ($this->model->fieldset->fields as $field){
|
||||
if($field->format == 'BOOLEAN'){
|
||||
$this->{$field->db_column} = filter_var($this->{$field->db_column}, FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
foreach ($this->model->fieldset->fields as $field){
|
||||
if($field->format == 'BOOLEAN'){
|
||||
$this->{$field->db_column} = filter_var($this->{$field->db_column}, FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return parent::save($params);
|
||||
}
|
||||
|
||||
@@ -266,7 +267,7 @@ class Asset extends Depreciable
|
||||
|
||||
/**
|
||||
* Determines if an asset is available for checkout.
|
||||
* This checks to see if it's checked out to an invalid (deleted) user
|
||||
* This checks to see if the it's checked out to an invalid (deleted) user
|
||||
* OR if the assigned_to and deleted_at fields on the asset are empty AND
|
||||
* that the status is deployable
|
||||
*
|
||||
@@ -753,7 +754,7 @@ class Asset extends Depreciable
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes the asset -> license seats relationship
|
||||
* Establishes the asset -> status relationship
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0]
|
||||
@@ -789,6 +790,7 @@ class Asset extends Depreciable
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the next autoincremented asset tag
|
||||
*
|
||||
@@ -921,27 +923,6 @@ class Asset extends Depreciable
|
||||
return $cost;
|
||||
}
|
||||
|
||||
/**
|
||||
* -----------------------------------------------
|
||||
* BEGIN MUTATORS
|
||||
* -----------------------------------------------
|
||||
**/
|
||||
|
||||
/**
|
||||
* This sets the requestable to a boolean 0 or 1. This accounts for forms or API calls that
|
||||
* explicitly pass the requestable field but it has a null or empty value.
|
||||
*
|
||||
* This will also correctly parse a 1/0 if "true"/"false" is passed.
|
||||
*
|
||||
* @param $value
|
||||
* @return void
|
||||
*/
|
||||
public function setRequestableAttribute($value)
|
||||
{
|
||||
$this->attributes['requestable'] = (int) filter_var($value, FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* -----------------------------------------------
|
||||
* BEGIN QUERY SCOPES
|
||||
@@ -972,7 +953,6 @@ class Asset extends Depreciable
|
||||
->orWhere('assets_users.first_name', 'LIKE', '%'.$term.'%')
|
||||
->orWhere('assets_users.last_name', 'LIKE', '%'.$term.'%')
|
||||
->orWhere('assets_users.username', 'LIKE', '%'.$term.'%')
|
||||
->orWhere('assets_users.employee_num', 'LIKE', '%'.$term.'%')
|
||||
->orWhereMultipleColumns([
|
||||
'assets_users.first_name',
|
||||
'assets_users.last_name',
|
||||
|
||||
@@ -6,7 +6,6 @@ use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
@@ -189,21 +188,6 @@ class AssetModel extends SnipeModel
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the model is deletable
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v6.3.4]
|
||||
* @return bool
|
||||
*/
|
||||
public function isDeletable()
|
||||
{
|
||||
return Gate::allows('delete', $this)
|
||||
&& ($this->assets_count == 0)
|
||||
&& ($this->deleted_at == '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get uploads for this model
|
||||
*
|
||||
|
||||
@@ -100,8 +100,7 @@ class Category extends SnipeModel
|
||||
{
|
||||
|
||||
return Gate::allows('delete', $this)
|
||||
&& ($this->itemCount() == 0)
|
||||
&& ($this->deleted_at == '');
|
||||
&& ($this->itemCount() == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -248,26 +247,6 @@ class Category extends SnipeModel
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* -----------------------------------------------
|
||||
* BEGIN MUTATORS
|
||||
* -----------------------------------------------
|
||||
**/
|
||||
|
||||
/**
|
||||
* This sets the checkin_value to a boolean 0 or 1. This accounts for forms or API calls that
|
||||
* explicitly pass the checkin_email field but it has a null or empty value.
|
||||
*
|
||||
* This will also correctly parse a 1/0 if "true"/"false" is passed.
|
||||
*
|
||||
* @param $value
|
||||
* @return void
|
||||
*/
|
||||
public function setCheckinEmailAttribute($value)
|
||||
{
|
||||
$this->attributes['checkin_email'] = (int) filter_var($value, FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* -----------------------------------------------
|
||||
* BEGIN QUERY SCOPES
|
||||
|
||||
@@ -53,12 +53,6 @@ class CustomField extends Model
|
||||
'field_encrypted' => 'nullable|boolean',
|
||||
'auto_add_to_fieldsets' => 'boolean',
|
||||
'show_in_listview' => 'boolean',
|
||||
'show_in_requestable_list' => 'boolean',
|
||||
'show_in_email' => 'boolean',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'show_in_requestable_list' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -78,8 +72,7 @@ class CustomField extends Model
|
||||
'display_in_user_view',
|
||||
'auto_add_to_fieldsets',
|
||||
'show_in_listview',
|
||||
'show_in_email',
|
||||
'show_in_requestable_list',
|
||||
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -250,6 +243,8 @@ class CustomField extends Model
|
||||
/**
|
||||
* Gets the DB column name.
|
||||
*
|
||||
* @todo figure out if this is still needed? I don't know WTF it's for.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v3.0]
|
||||
* @return string
|
||||
|
||||
@@ -92,8 +92,6 @@ class CustomFieldset extends Model
|
||||
|
||||
array_push($rule, $field->attributes['format']);
|
||||
$rules[$field->db_column_name()] = $rule;
|
||||
//add not_array to rules for all fields
|
||||
$rules[$field->db_column_name()][] = 'not_array';
|
||||
}
|
||||
|
||||
return $rules;
|
||||
|
||||
@@ -14,14 +14,6 @@ class FieldOption {
|
||||
|
||||
public function getValue(Asset $asset) {
|
||||
$dataPath = collect(explode('.', $this->dataSource));
|
||||
|
||||
// assignedTo directly on the asset is a special case where
|
||||
// we want to avoid returning the property directly
|
||||
// and instead return the entity's presented name.
|
||||
if ($dataPath[0] === 'assignedTo'){
|
||||
return $asset->assignedTo ? $asset->assignedTo->present()->fullName() : null;
|
||||
}
|
||||
|
||||
return $dataPath->reduce(function ($myValue, $path) {
|
||||
try { return $myValue ? $myValue->{$path} : ${$myValue}; }
|
||||
catch (\Exception $e) { return $myValue; }
|
||||
@@ -54,4 +46,4 @@ class FieldOption {
|
||||
return $option;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,6 @@ class License extends Depreciable
|
||||
protected $guarded = 'id';
|
||||
protected $table = 'licenses';
|
||||
|
||||
|
||||
protected $casts = [
|
||||
'purchase_date' => 'date',
|
||||
'expiration_date' => 'date',
|
||||
|
||||
@@ -77,8 +77,7 @@ class Manufacturer extends SnipeModel
|
||||
&& ($this->assets()->count() === 0)
|
||||
&& ($this->licenses()->count() === 0)
|
||||
&& ($this->consumables()->count() === 0)
|
||||
&& ($this->accessories()->count() === 0)
|
||||
&& ($this->deleted_at == '');
|
||||
&& ($this->accessories()->count() === 0);
|
||||
}
|
||||
|
||||
public function assets()
|
||||
|
||||
@@ -92,10 +92,6 @@ class Setting extends Model
|
||||
'google_client_secret',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'label2_asset_logo' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the app settings.
|
||||
* Cache is expired on Setting model saved in EventServiceProvider.
|
||||
|
||||
@@ -129,20 +129,8 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig
|
||||
'preferredLanguage' => AttributeMapping::eloquent('locale'), // Section 5.3.5 of [RFC7231]
|
||||
'locale' => null, // see RFC5646
|
||||
'timezone' => null, // see RFC6557
|
||||
'active' => (new AttributeMapping())->setAdd(
|
||||
function ($value, &$object) {
|
||||
$object->activated = $value;
|
||||
}
|
||||
)->setReplace(
|
||||
function ($value, &$object) {
|
||||
$object->activated = $value;
|
||||
}
|
||||
)->setRead(
|
||||
// this works as specified.
|
||||
function (&$object) {
|
||||
return (bool)$object->activated;
|
||||
}
|
||||
),
|
||||
'active' => AttributeMapping::eloquent('activated'),
|
||||
|
||||
'password' => AttributeMapping::eloquent('password')->disableRead(),
|
||||
|
||||
// Multi-Valued Attributes
|
||||
|
||||
@@ -17,7 +17,6 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Foundation\Auth\Access\Authorizable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Laravel\Passport\HasApiTokens;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
@@ -202,23 +201,6 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
return $this->checkPermissionSection('superuser');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the user is deletable
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v6.3.4]
|
||||
* @return bool
|
||||
*/
|
||||
public function isDeletable()
|
||||
{
|
||||
return Gate::allows('delete', $this)
|
||||
&& ($this->assets()->count() === 0)
|
||||
&& ($this->licenses()->count() === 0)
|
||||
&& ($this->consumables()->count() === 0)
|
||||
&& ($this->accessories()->count() === 0)
|
||||
&& ($this->deleted_at == '');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Establishes the user -> company relationship
|
||||
|
||||
@@ -26,6 +26,7 @@ class CheckinAccessoryNotification extends Notification
|
||||
$this->admin = $checkedInby;
|
||||
$this->note = $note;
|
||||
$this->settings = Setting::getSettings();
|
||||
\Log::debug('Constructor for notification fired');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
|
||||
@@ -11,7 +11,7 @@ use Carbon\Carbon;
|
||||
class AssetObserver
|
||||
{
|
||||
/**
|
||||
* Listen to the Asset updating event. This fires automatically every time an existing asset is saved.
|
||||
* Listen to the User created event.
|
||||
*
|
||||
* @param Asset $asset
|
||||
* @return void
|
||||
@@ -22,13 +22,6 @@ class AssetObserver
|
||||
$attributesOriginal = $asset->getRawOriginal();
|
||||
$same_checkout_counter = false;
|
||||
$same_checkin_counter = false;
|
||||
$restoring_or_deleting = false;
|
||||
|
||||
|
||||
// This is a gross hack to prevent the double logging when restoring an asset
|
||||
if (array_key_exists('deleted_at', $attributes) && array_key_exists('deleted_at', $attributesOriginal)){
|
||||
$restoring_or_deleting = (($attributes['deleted_at'] != $attributesOriginal['deleted_at']));
|
||||
}
|
||||
|
||||
if (array_key_exists('checkout_counter', $attributes) && array_key_exists('checkout_counter', $attributesOriginal)){
|
||||
$same_checkout_counter = (($attributes['checkout_counter'] == $attributesOriginal['checkout_counter']));
|
||||
@@ -40,10 +33,10 @@ class AssetObserver
|
||||
|
||||
// If the asset isn't being checked out or audited, log the update.
|
||||
// (Those other actions already create log entries.)
|
||||
if (($attributes['assigned_to'] == $attributesOriginal['assigned_to'])
|
||||
if (($attributes['assigned_to'] == $attributesOriginal['assigned_to'])
|
||||
&& ($same_checkout_counter) && ($same_checkin_counter)
|
||||
&& ((isset( $attributes['next_audit_date']) ? $attributes['next_audit_date'] : null) == (isset($attributesOriginal['next_audit_date']) ? $attributesOriginal['next_audit_date']: null))
|
||||
&& ($attributes['last_checkout'] == $attributesOriginal['last_checkout']) && (!$restoring_or_deleting))
|
||||
&& ($attributes['last_checkout'] == $attributesOriginal['last_checkout']))
|
||||
{
|
||||
$changed = [];
|
||||
|
||||
@@ -127,47 +120,18 @@ class AssetObserver
|
||||
$logAction->user_id = Auth::id();
|
||||
$logAction->logaction('delete');
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to the Asset deleting event.
|
||||
*
|
||||
* @param Asset $asset
|
||||
* @return void
|
||||
*/
|
||||
public function restoring(Asset $asset)
|
||||
{
|
||||
$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::id();
|
||||
$logAction->logaction('restore');
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes every time an asset is saved.
|
||||
*
|
||||
* This matters specifically because any database fields affected here MUST already exist on
|
||||
* the assets table (and/or any related models), or related migrations WILL fail.
|
||||
*
|
||||
* For example, if there is a database migration that's a bit older and modifies an asset, if the save
|
||||
* fires before a field gets created in a later migration and that field in the later migration
|
||||
* is used in this observer, it doesn't actually exist yet and the migration will break unless we
|
||||
* use saveQuietly() in the migration which skips this observer.
|
||||
*
|
||||
* @see https://github.com/snipe/snipe-it/issues/13723#issuecomment-1761315938
|
||||
*/
|
||||
|
||||
public function saving(Asset $asset)
|
||||
{
|
||||
// determine if calculated eol and then calculate it - this should only happen on a new asset
|
||||
if (is_null($asset->asset_eol_date) && !is_null($asset->purchase_date) && ($asset->model->eol > 0)){
|
||||
//determine if calculated eol and then calculate it - this should only happen on a new asset
|
||||
if(is_null($asset->asset_eol_date) && !is_null($asset->purchase_date) && !is_null($asset->model->eol)){
|
||||
$asset->asset_eol_date = $asset->purchase_date->addMonths($asset->model->eol)->format('Y-m-d');
|
||||
$asset->eol_explicit = false;
|
||||
}
|
||||
|
||||
// determine if explicit and set eol_explicit to true
|
||||
if (!is_null($asset->asset_eol_date) && !is_null($asset->purchase_date)) {
|
||||
if($asset->model->eol > 0) {
|
||||
//determine if explicit and set eol_explit to true
|
||||
if(!is_null($asset->asset_eol_date) && !is_null($asset->purchase_date)) {
|
||||
if($asset->model->eol) {
|
||||
$months = Carbon::parse($asset->asset_eol_date)->diffInMonths($asset->purchase_date);
|
||||
if($months != $asset->model->eol) {
|
||||
$asset->eol_explicit = true;
|
||||
@@ -176,7 +140,7 @@ class AssetObserver
|
||||
} elseif (!is_null($asset->asset_eol_date) && is_null($asset->purchase_date)) {
|
||||
$asset->eol_explicit = true;
|
||||
}
|
||||
if ((!is_null($asset->asset_eol_date)) && (!is_null($asset->purchase_date)) && (is_null($asset->model->eol) || ($asset->model->eol == 0))) {
|
||||
if ((!is_null($asset->asset_eol_date)) && (!is_null($asset->purchase_date)) && (is_null($asset->model->eol))) {
|
||||
$asset->eol_explicit = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Observers;
|
||||
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\User;
|
||||
use Auth;
|
||||
|
||||
class UserObserver
|
||||
{
|
||||
/**
|
||||
* Listen to the User updating event. This fires automatically every time an existing asset is saved.
|
||||
*
|
||||
* @param User $user
|
||||
* @return void
|
||||
*/
|
||||
public function updating(User $user)
|
||||
{
|
||||
|
||||
// ONLY allow these fields to be stored
|
||||
$allowed_fields = [
|
||||
'email',
|
||||
'activated',
|
||||
'first_name',
|
||||
'last_name',
|
||||
'website',
|
||||
'country',
|
||||
'gravatar',
|
||||
'location_id',
|
||||
'phone',
|
||||
'jobtitle',
|
||||
'manager_id',
|
||||
'employee_num',
|
||||
'username',
|
||||
'notes',
|
||||
'company_id',
|
||||
'ldap_import',
|
||||
'locale',
|
||||
'two_factor_enrolled',
|
||||
'two_factor_optin',
|
||||
'department_id',
|
||||
'address',
|
||||
'address2',
|
||||
'city',
|
||||
'state',
|
||||
'zip',
|
||||
'remote',
|
||||
'start_date',
|
||||
'end_date',
|
||||
'autoassign_licenses',
|
||||
'vip',
|
||||
'password'
|
||||
];
|
||||
|
||||
$changed = [];
|
||||
|
||||
foreach ($user->getRawOriginal() as $key => $value) {
|
||||
|
||||
// Make sure the info is in the allow fields array
|
||||
if (in_array($key, $allowed_fields)) {
|
||||
|
||||
// Check and see if the value changed
|
||||
if ($user->getRawOriginal()[$key] != $user->getAttributes()[$key]) {
|
||||
|
||||
$changed[$key]['old'] = $user->getRawOriginal()[$key];
|
||||
$changed[$key]['new'] = $user->getAttributes()[$key];
|
||||
|
||||
// Do not store the hashed password in changes
|
||||
if ($key == 'password') {
|
||||
$changed['password']['old'] = '*************';
|
||||
$changed['password']['new'] = '*************';
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (count($changed) > 0) {
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = User::class;
|
||||
$logAction->item_id = $user->id;
|
||||
$logAction->target_type = User::class; // can we instead say $logAction->item = $asset ?
|
||||
$logAction->target_id = $user->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->user_id = Auth::id();
|
||||
$logAction->log_meta = json_encode($changed);
|
||||
$logAction->logaction('update');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to the User created event, and increment
|
||||
* the next_auto_tag_base value in the settings table when i
|
||||
* a new asset is created.
|
||||
*
|
||||
* @param User $user
|
||||
* @return void
|
||||
*/
|
||||
public function created(User $user)
|
||||
{
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = User::class; // can we instead say $logAction->item = $asset ?
|
||||
$logAction->item_id = $user->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->user_id = Auth::id();
|
||||
$logAction->logaction('create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to the User deleting event.
|
||||
*
|
||||
* @param User $user
|
||||
* @return void
|
||||
*/
|
||||
public function deleting(User $user)
|
||||
{
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = User::class;
|
||||
$logAction->item_id = $user->id;
|
||||
$logAction->target_type = User::class; // can we instead say $logAction->item = $asset ?
|
||||
$logAction->target_id = $user->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->user_id = Auth::id();
|
||||
$logAction->logaction('delete');
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to the User deleting event.
|
||||
*
|
||||
* @param User $user
|
||||
* @return void
|
||||
*/
|
||||
public function restoring(User $user)
|
||||
{
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = User::class;
|
||||
$logAction->item_id = $user->id;
|
||||
$logAction->target_type = User::class; // can we instead say $logAction->item = $asset ?
|
||||
$logAction->target_id = $user->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->user_id = Auth::id();
|
||||
$logAction->logaction('restore');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -38,63 +38,22 @@ class ActionlogPresenter extends Presenter
|
||||
|
||||
public function icon()
|
||||
{
|
||||
|
||||
// User related icons
|
||||
if ($this->itemType() == 'user') {
|
||||
$itemicon = 'fas fa-paperclip';
|
||||
|
||||
if ($this->actionType()=='create new') {
|
||||
return 'fa-solid fa-user-plus';
|
||||
}
|
||||
|
||||
if ($this->actionType()=='merged') {
|
||||
return 'fa-solid fa-people-arrows';
|
||||
}
|
||||
|
||||
if ($this->actionType()=='delete') {
|
||||
return 'fa-solid fa-user-minus';
|
||||
}
|
||||
|
||||
if ($this->actionType()=='delete') {
|
||||
return 'fa-solid fa-user-minus';
|
||||
}
|
||||
|
||||
if ($this->actionType()=='update') {
|
||||
return 'fa-solid fa-user-pen';
|
||||
}
|
||||
return 'fa-solid fa-user';
|
||||
if ($this->itemType() == 'asset') {
|
||||
return 'fas fa-barcode';
|
||||
} elseif ($this->itemType() == 'accessory') {
|
||||
return 'far fa-keyboard';
|
||||
} elseif ($this->itemType() == 'consumable') {
|
||||
return 'fas fa-tint';
|
||||
} elseif ($this->itemType() == 'license') {
|
||||
return 'far fa-save';
|
||||
} elseif ($this->itemType() == 'component') {
|
||||
return 'far fa-hdd';
|
||||
} elseif ($this->itemType() == 'user') {
|
||||
return 'fa-solid fa-people-arrows';
|
||||
}
|
||||
|
||||
// Everything else
|
||||
if ($this->actionType()=='create new') {
|
||||
return 'fa-solid fa-plus';
|
||||
}
|
||||
|
||||
if ($this->actionType()=='delete') {
|
||||
return 'fa-solid fa-user-xmark';
|
||||
}
|
||||
|
||||
if ($this->actionType()=='update') {
|
||||
return 'fa-solid fa-pen';
|
||||
}
|
||||
|
||||
if ($this->actionType()=='restore') {
|
||||
return 'fa-solid fa-trash-arrow-up';
|
||||
}
|
||||
|
||||
if ($this->actionType()=='upload') {
|
||||
return 'fas fa-paperclip';
|
||||
}
|
||||
|
||||
if ($this->actionType()=='checkout') {
|
||||
return 'fa-solid fa-rotate-left';
|
||||
}
|
||||
|
||||
if ($this->actionType()=='checkin from') {
|
||||
return 'fa-solid fa-rotate-right';
|
||||
}
|
||||
|
||||
return 'fa-solid fa-rotate-right';
|
||||
|
||||
}
|
||||
|
||||
public function actionType()
|
||||
|
||||
@@ -104,7 +104,7 @@ class AssetModelPresenter extends Presenter
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => trans('admin/hardware/form.eol_rate'),
|
||||
'title' => trans('general.eol'),
|
||||
'visible' => true,
|
||||
],
|
||||
[
|
||||
|
||||
@@ -173,7 +173,7 @@ class AssetPresenter extends Presenter
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'visible' => false,
|
||||
'title' => trans('admin/hardware/form.eol_rate'),
|
||||
'title' => trans('general.eol'),
|
||||
],
|
||||
[
|
||||
'field' => 'asset_eol_date',
|
||||
|
||||
@@ -106,7 +106,7 @@ class LocationPresenter extends Presenter
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => trans('admin/locations/table.address2'),
|
||||
'title' => trans('admin/locations/table.address'),
|
||||
'visible' => false,
|
||||
],
|
||||
[
|
||||
|
||||
@@ -7,12 +7,10 @@ use App\Models\Asset;
|
||||
use App\Models\Component;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\License;
|
||||
use App\Models\User;
|
||||
use App\Models\Setting;
|
||||
use App\Models\SnipeSCIMConfig;
|
||||
use App\Observers\AccessoryObserver;
|
||||
use App\Observers\AssetObserver;
|
||||
use App\Observers\UserObserver;
|
||||
use App\Observers\ComponentObserver;
|
||||
use App\Observers\ConsumableObserver;
|
||||
use App\Observers\LicenseObserver;
|
||||
@@ -60,7 +58,6 @@ class AppServiceProvider extends ServiceProvider
|
||||
|
||||
Schema::defaultStringLength(191);
|
||||
Asset::observe(AssetObserver::class);
|
||||
User::observe(UserObserver::class);
|
||||
Accessory::observe(AccessoryObserver::class);
|
||||
Component::observe(ComponentObserver::class);
|
||||
Consumable::observe(ConsumableObserver::class);
|
||||
|
||||
@@ -33,33 +33,18 @@ class SettingsServiceProvider extends ServiceProvider
|
||||
// Make sure the limit is actually set, is an integer and does not exceed system limits
|
||||
\App::singleton('api_limit_value', function () {
|
||||
$limit = config('app.max_results');
|
||||
$int_limit = intval(request('limit'));
|
||||
|
||||
if ((abs($int_limit) > 0) && ($int_limit <= config('app.max_results'))) {
|
||||
$limit = abs($int_limit);
|
||||
if ((abs(intval(request('limit'))) > 0) && (abs(request('limit')) <= config('app.max_results'))) {
|
||||
$limit = abs(request('limit'));
|
||||
}
|
||||
|
||||
// \Log::debug('Max in env: '.config('app.max_results'));
|
||||
// \Log::debug('Original requested limit: '.request('limit'));
|
||||
// \Log::debug('Int limit: '.$int_limit);
|
||||
// \Log::debug('Modified limit: '.$limit);
|
||||
// \Log::debug('------------------------------');
|
||||
|
||||
\Log::debug('Max in env: '.config('app.max_results'));
|
||||
\Log::debug('Original requested limit: '.request('limit'));
|
||||
\Log::debug('Modified limit: '.$limit);
|
||||
\Log::debug('------------------------------');
|
||||
|
||||
return $limit;
|
||||
});
|
||||
|
||||
// Make sure the offset is actually set and is an integer
|
||||
\App::singleton('api_offset_value', function () {
|
||||
$offset = intval(request('offset'));
|
||||
// \Log::debug('Original requested offset: '.request('offset'));
|
||||
// \Log::debug('Modified offset: '.$offset);
|
||||
// \Log::debug('------------------------------');
|
||||
|
||||
|
||||
return $offset;
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Set some common variables so that they're globally available.
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Models\Department;
|
||||
use App\Models\Setting;
|
||||
use DB;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Validation\Rule;
|
||||
@@ -46,87 +45,30 @@ class ValidationServiceProvider extends ServiceProvider
|
||||
return $validator->passes();
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Unique only if undeleted.
|
||||
*
|
||||
* This works around the use case where multiple deleted items have the same unique attribute.
|
||||
* (I think this is a bug in Laravel's validator?)
|
||||
*
|
||||
* $attribute is the FIELDNAME you're checking against
|
||||
* $value is the VALUE of the item you're checking against the existing values in the fieldname
|
||||
* $parameters[0] is the TABLE NAME you're querying
|
||||
* $parameters[1] is the ID of the item you're querying - this makes it work on saving, checkout, etc,
|
||||
* since it defaults to 0 if there is no item created yet (new item), but populates the ID if editing
|
||||
*
|
||||
* The UniqueUndeletedTrait prefills these parameters, so you can just use
|
||||
* `unique_undeleted:table,fieldname` in your rules out of the box
|
||||
*/
|
||||
// Unique only if undeleted
|
||||
// This works around the use case where multiple deleted items have the same unique attribute.
|
||||
// (I think this is a bug in Laravel's validator?)
|
||||
Validator::extend('unique_undeleted', function ($attribute, $value, $parameters, $validator) {
|
||||
|
||||
if (count($parameters)) {
|
||||
$count = DB::table($parameters[0])->select('id')->where($attribute, '=', $value)->whereNull('deleted_at')->where('id', '!=', $parameters[1])->count();
|
||||
|
||||
// This is a bit of a shim, but serial doesn't have any other rules around it other than that it's nullable
|
||||
if (($parameters[0]=='assets') && ($attribute == 'serial') && (Setting::getSettings()->unique_serial != '1')) {
|
||||
return true;
|
||||
return $count < 1;
|
||||
}
|
||||
});
|
||||
|
||||
// Unique if undeleted for two columns
|
||||
// Same as unique_undeleted but taking the combination of two columns as unique constrain.
|
||||
Validator::extend('two_column_unique_undeleted', function ($attribute, $value, $parameters, $validator) {
|
||||
if (count($parameters)) {
|
||||
$count = DB::table($parameters[0])
|
||||
->select('id')->where($attribute, '=', $value)
|
||||
->whereNull('deleted_at')
|
||||
->where('id', '!=', $parameters[1])
|
||||
->where($parameters[2], $parameters[3])->count();
|
||||
|
||||
return $count < 1;
|
||||
}
|
||||
|
||||
$count = DB::table($parameters[0])
|
||||
->select('id')
|
||||
->where($attribute, '=', $value)
|
||||
->whereNull('deleted_at')
|
||||
->where('id', '!=', $parameters[1])->count();
|
||||
|
||||
return $count < 1;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Unique if undeleted for two columns
|
||||
*
|
||||
* Same as unique_undeleted but taking the combination of two columns as unique constrain.
|
||||
* This uses the Validator::replacer('two_column_unique_undeleted') below for nicer translations.
|
||||
*
|
||||
* $parameters[0] - the name of the first table we're looking at
|
||||
* $parameters[1] - the ID (this will be 0 on new creations)
|
||||
* $parameters[2] - the name of the second table we're looking at
|
||||
* $parameters[3] - the value that the request is passing for the second table we're
|
||||
* checking for uniqueness across
|
||||
*
|
||||
*/
|
||||
Validator::extend('two_column_unique_undeleted', function ($attribute, $value, $parameters, $validator) {
|
||||
if (count($parameters)) {
|
||||
$count = DB::table($parameters[0])
|
||||
->select('id')->where($attribute, '=', $value)
|
||||
->whereNull('deleted_at')
|
||||
->where('id', '!=', $parameters[1])
|
||||
->where($parameters[2], $parameters[3])->count();
|
||||
|
||||
return $count < 1;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* This is the validator replace static method that allows us to pass the $parameters of the table names
|
||||
* into the translation string in validation.two_column_unique_undeleted for two_column_unique_undeleted
|
||||
* validation messages.
|
||||
*
|
||||
* This is invoked automatically by Validator::extend('two_column_unique_undeleted') above and
|
||||
* produces a translation like: "The name value must be unique across categories and category type."
|
||||
*
|
||||
* The $parameters passed coincide with the ones the two_column_unique_undeleted custom validator above
|
||||
* uses, so $parameter[0] is the first table and so $parameter[2] is the second table.
|
||||
*/
|
||||
Validator::replacer('two_column_unique_undeleted', function($message, $attribute, $rule, $parameters) {
|
||||
$message = str_replace(':table1', $parameters[0], $message);
|
||||
$message = str_replace(':table2', $parameters[2], $message);
|
||||
|
||||
// Change underscores to spaces for a friendlier display
|
||||
$message = str_replace('_', ' ', $message);
|
||||
return $message;
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// Prevent circular references
|
||||
//
|
||||
@@ -290,10 +232,6 @@ class ValidationServiceProvider extends ServiceProvider
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
Validator::extend('not_array', function ($attribute, $value, $parameters, $validator) {
|
||||
return !is_array($value);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -103,12 +103,19 @@ class Label implements View
|
||||
|
||||
$logo = null;
|
||||
|
||||
// Should we use the assets assigned company logo? (A.K.A. "Is `Labels > Use Asset Logo` enabled?"), and do we have a company logo?
|
||||
if ($settings->label2_asset_logo && $asset->company && $asset->company->image!='') {
|
||||
$logo = Storage::disk('public')->path('companies/'.e($asset->company->image));
|
||||
} elseif (!empty($settings->label_logo)) {
|
||||
// Use the general site label logo, if available
|
||||
$logo = Storage::disk('public')->path('/'.e($settings->label_logo));
|
||||
// Should we be trying to use a logo at all?
|
||||
if ($settings->label2_asset_logo='1') {
|
||||
|
||||
// If we don't have a company image, fall back to the general site label image
|
||||
if (!empty($settings->label_logo)) {
|
||||
$logo = Storage::disk('public')->path('/'.e($settings->label_logo));
|
||||
}
|
||||
|
||||
// If we have a company logo, use that first
|
||||
if (($asset->company) && ($asset->company->image!='')) {
|
||||
$logo = Storage::disk('public')->path('companies/'.e($asset->company->image));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!empty($logo)) {
|
||||
|
||||
@@ -74,16 +74,12 @@
|
||||
"unicodeveloper/laravel-password": "^1.0",
|
||||
"watson/validating": "^6.1"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-ldap": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"brianium/paratest": "^6.6",
|
||||
"fakerphp/faker": "^1.16",
|
||||
"mockery/mockery": "^1.4",
|
||||
"nunomaduro/larastan": "^1.0",
|
||||
"nunomaduro/phpinsights": "^2.7",
|
||||
"php-mock/php-mock-phpunit": "^2.8",
|
||||
"phpunit/php-token-stream": "^3.1",
|
||||
"phpunit/phpunit": "^9.0",
|
||||
"squizlabs/php_codesniffer": "^3.5",
|
||||
|
||||
224
composer.lock
generated
224
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "f4f3b6b02d044ed3e54cdd509b01c3dc",
|
||||
"content-hash": "348f96db24a0f8dfb595ee38b38b34eb",
|
||||
"packages": [
|
||||
{
|
||||
"name": "alek13/slack",
|
||||
@@ -7011,16 +7011,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpseclib/phpseclib",
|
||||
"version": "3.0.34",
|
||||
"version": "3.0.14",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpseclib/phpseclib.git",
|
||||
"reference": "56c79f16a6ae17e42089c06a2144467acc35348a"
|
||||
"reference": "2f0b7af658cbea265cbb4a791d6c29a6613f98ef"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/56c79f16a6ae17e42089c06a2144467acc35348a",
|
||||
"reference": "56c79f16a6ae17e42089c06a2144467acc35348a",
|
||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/2f0b7af658cbea265cbb4a791d6c29a6613f98ef",
|
||||
"reference": "2f0b7af658cbea265cbb4a791d6c29a6613f98ef",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -7032,7 +7032,6 @@
|
||||
"phpunit/phpunit": "*"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-dom": "Install the DOM extension to load XML formatted public keys.",
|
||||
"ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.",
|
||||
"ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.",
|
||||
"ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
|
||||
@@ -7101,7 +7100,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/phpseclib/phpseclib/issues",
|
||||
"source": "https://github.com/phpseclib/phpseclib/tree/3.0.34"
|
||||
"source": "https://github.com/phpseclib/phpseclib/tree/3.0.14"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -7117,7 +7116,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-11-27T11:13:31+00:00"
|
||||
"time": "2022-04-04T05:15:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpspec/prophecy",
|
||||
@@ -14101,213 +14100,6 @@
|
||||
},
|
||||
"time": "2022-02-21T01:04:05+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-mock/php-mock",
|
||||
"version": "2.4.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-mock/php-mock.git",
|
||||
"reference": "6240b6f0a76d7b9d1ee4d70e686a7cc711619a9d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-mock/php-mock/zipball/6240b6f0a76d7b9d1ee4d70e686a7cc711619a9d",
|
||||
"reference": "6240b6f0a76d7b9d1ee4d70e686a7cc711619a9d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.6 || ^7.0 || ^8.0",
|
||||
"phpunit/php-text-template": "^1 || ^2 || ^3"
|
||||
},
|
||||
"replace": {
|
||||
"malkusch/php-mock": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.0 || ^9.0 || ^10.0",
|
||||
"squizlabs/php_codesniffer": "^3.5"
|
||||
},
|
||||
"suggest": {
|
||||
"php-mock/php-mock-phpunit": "Allows integration into PHPUnit testcase with the trait PHPMock."
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"autoload.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"phpmock\\": [
|
||||
"classes/",
|
||||
"tests/"
|
||||
]
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"WTFPL"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Markus Malkusch",
|
||||
"email": "markus@malkusch.de",
|
||||
"homepage": "http://markus.malkusch.de",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "PHP-Mock can mock built-in PHP functions (e.g. time()). PHP-Mock relies on PHP's namespace fallback policy. No further extension is needed.",
|
||||
"homepage": "https://github.com/php-mock/php-mock",
|
||||
"keywords": [
|
||||
"BDD",
|
||||
"TDD",
|
||||
"function",
|
||||
"mock",
|
||||
"stub",
|
||||
"test",
|
||||
"test double",
|
||||
"testing"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-mock/php-mock/issues",
|
||||
"source": "https://github.com/php-mock/php-mock/tree/2.4.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/michalbundyra",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-06-12T20:48:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-mock/php-mock-integration",
|
||||
"version": "2.2.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-mock/php-mock-integration.git",
|
||||
"reference": "04f4a8d5442ca457b102b5204673f77323e3edb5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-mock/php-mock-integration/zipball/04f4a8d5442ca457b102b5204673f77323e3edb5",
|
||||
"reference": "04f4a8d5442ca457b102b5204673f77323e3edb5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.6",
|
||||
"php-mock/php-mock": "^2.4",
|
||||
"phpunit/php-text-template": "^1 || ^2 || ^3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^5.7.27 || ^6 || ^7 || ^8 || ^9 || ^10"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"phpmock\\integration\\": "classes/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"WTFPL"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Markus Malkusch",
|
||||
"email": "markus@malkusch.de",
|
||||
"homepage": "http://markus.malkusch.de",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "Integration package for PHP-Mock",
|
||||
"homepage": "https://github.com/php-mock/php-mock-integration",
|
||||
"keywords": [
|
||||
"BDD",
|
||||
"TDD",
|
||||
"function",
|
||||
"mock",
|
||||
"stub",
|
||||
"test",
|
||||
"test double"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-mock/php-mock-integration/issues",
|
||||
"source": "https://github.com/php-mock/php-mock-integration/tree/2.2.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/michalbundyra",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-02-13T09:51:29+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-mock/php-mock-phpunit",
|
||||
"version": "2.8.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-mock/php-mock-phpunit.git",
|
||||
"reference": "56edee85ad3232caa0202f98f2a3c899ab16bdb7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-mock/php-mock-phpunit/zipball/56edee85ad3232caa0202f98f2a3c899ab16bdb7",
|
||||
"reference": "56edee85ad3232caa0202f98f2a3c899ab16bdb7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7",
|
||||
"php-mock/php-mock-integration": "^2.2.1",
|
||||
"phpunit/phpunit": "^6 || ^7 || ^8 || ^9 || ^10.0.17"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^1.3.6"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"autoload.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"phpmock\\phpunit\\": "classes/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"WTFPL"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Markus Malkusch",
|
||||
"email": "markus@malkusch.de",
|
||||
"homepage": "http://markus.malkusch.de",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "Mock built-in PHP functions (e.g. time()) with PHPUnit. This package relies on PHP's namespace fallback policy. No further extension is needed.",
|
||||
"homepage": "https://github.com/php-mock/php-mock-phpunit",
|
||||
"keywords": [
|
||||
"BDD",
|
||||
"TDD",
|
||||
"function",
|
||||
"mock",
|
||||
"phpunit",
|
||||
"stub",
|
||||
"test",
|
||||
"test double",
|
||||
"testing"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-mock/php-mock-phpunit/issues",
|
||||
"source": "https://github.com/php-mock/php-mock-phpunit/tree/2.8.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/michalbundyra",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-10-30T07:06:12+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-parallel-lint/php-parallel-lint",
|
||||
"version": "v1.3.2",
|
||||
@@ -16808,5 +16600,5 @@
|
||||
"ext-pdo": "*"
|
||||
},
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.6.0"
|
||||
"plugin-api-version": "2.3.0"
|
||||
}
|
||||
|
||||
@@ -82,27 +82,6 @@ $config = [
|
||||
'visibility' => 'private'
|
||||
],
|
||||
|
||||
'digitalocean_private' => [
|
||||
'driver' => 's3',
|
||||
'key' => env('DIGITALOCEAN_SPACES_KEY'),
|
||||
'secret' => env('DIGITALOCEAN_SPACES_SECRET'),
|
||||
'endpoint' => env('DIGITALOCEAN_SPACES_ENDPOINT'),
|
||||
'region' => env('DIGITALOCEAN_SPACES_REGION'),
|
||||
'bucket' => env('DIGITALOCEAN_SPACES_BUCKET'),
|
||||
'visibility' => 'private'
|
||||
],
|
||||
|
||||
'digitalocean' => [
|
||||
'driver' => 's3',
|
||||
'key' => env('DIGITALOCEAN_SPACES_KEY'),
|
||||
'secret' => env('DIGITALOCEAN_SPACES_SECRET'),
|
||||
'endpoint' => env('DIGITALOCEAN_SPACES_ENDPOINT'),
|
||||
'region' => env('DIGITALOCEAN_SPACES_REGION'),
|
||||
'bucket' => env('DIGITALOCEAN_SPACES_BUCKET'),
|
||||
'visibility' => 'public'
|
||||
],
|
||||
|
||||
|
||||
'rackspace' => [
|
||||
'driver' => 'rackspace',
|
||||
'username' => env('RACKSPACE_USERNAME'),
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
return array (
|
||||
'app_version' => 'v6.2.4-pre',
|
||||
'full_app_version' => 'v6.2.4-pre - build 12090-g776b16d37',
|
||||
'build_version' => '12090',
|
||||
'app_version' => 'v6.2.2',
|
||||
'full_app_version' => 'v6.2.2 - build 11714-ga95fae0e9',
|
||||
'build_version' => '11714',
|
||||
'prerelease_version' => '',
|
||||
'hash_version' => 'g776b16d37',
|
||||
'full_hash' => 'v6.2.4-pre-329-g776b16d37',
|
||||
'branch' => 'develop',
|
||||
'hash_version' => 'ga95fae0e9',
|
||||
'full_hash' => 'v6.2.2-85-ga95fae0e9',
|
||||
'branch' => 'master',
|
||||
);
|
||||
@@ -38,7 +38,7 @@ class ActionlogFactory extends Factory
|
||||
{
|
||||
return $this->state(function () {
|
||||
$target = User::inRandomOrder()->first();
|
||||
$asset = Asset::inRandomOrder()->RTD()->first();
|
||||
$asset = Asset::RTD()->inRandomOrder()->first();
|
||||
|
||||
$asset->update(
|
||||
[
|
||||
|
||||
@@ -26,7 +26,6 @@ class CustomFieldFactory extends Factory
|
||||
'format' => '',
|
||||
'element' => 'text',
|
||||
'auto_add_to_fieldsets' => '0',
|
||||
'show_in_requestable_list' => '0',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -67,7 +66,6 @@ class CustomFieldFactory extends Factory
|
||||
return [
|
||||
'name' => 'CPU',
|
||||
'help_text' => 'The speed of the processor on this device.',
|
||||
'show_in_requestable_list' => '1',
|
||||
];
|
||||
});
|
||||
}
|
||||
@@ -81,28 +79,4 @@ class CustomFieldFactory extends Factory
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
public function testEncrypted()
|
||||
{
|
||||
return $this->state(function () {
|
||||
return [
|
||||
'name' => 'Test Encrypted',
|
||||
'field_encrypted' => '1',
|
||||
'help_text' => 'This is a sample encrypted field.',
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
public function testCheckbox()
|
||||
{
|
||||
return $this->state(function () {
|
||||
return [
|
||||
'name' => 'Test Checkbox',
|
||||
'help_text' => 'This is a sample checkbox.',
|
||||
'field_values' => "One\nTwo\nThree",
|
||||
'element' => 'checkbox',
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,30 +17,19 @@ class AddEolDateOnAssetsTable extends Migration
|
||||
{
|
||||
|
||||
Schema::table('assets', function (Blueprint $table) {
|
||||
|
||||
if (!Schema::hasColumn('assets', 'asset_eol_date')) {
|
||||
$table->date('asset_eol_date')->after('purchase_date')->nullable()->default(null);
|
||||
}
|
||||
|
||||
// This is a temporary shim so we don't have to modify the asset observer for migrations where
|
||||
// there is a large version difference. (See the AssetObserver notes). This column gets created
|
||||
// later in 2023_07_13_052204_denormalized_eol_and_add_column_for_explicit_date_to_assets.php
|
||||
// but we have to temporarily create it now so the save method below doesn't break
|
||||
if (!Schema::hasColumn('assets', 'eol_explicit')) {
|
||||
$table->boolean('eol_explicit')->default(false)->after('asset_eol_date');
|
||||
}
|
||||
});
|
||||
|
||||
// Chunk the model query to get the models that do have an EOL date
|
||||
// We use saveQuietly() here to skip the AssetObserver, since it modifies fields
|
||||
// that do not yet exist on the assets table.
|
||||
AssetModel::whereNotNull('eol')->chunk(10, function ($models) {
|
||||
foreach ($models as $model) {
|
||||
foreach ($model->assets as $asset) {
|
||||
|
||||
if ($asset->purchase_date!='') {
|
||||
$asset->asset_eol_date = $asset->present()->eol_date();
|
||||
$asset->saveQuietly();
|
||||
$asset->save();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
use App\Models\Asset;
|
||||
use Carbon\CarbonImmutable;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Query\Expression;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
@@ -19,9 +18,7 @@ class DenormalizedEolAndAddColumnForExplicitDateToAssets extends Migration
|
||||
public function up()
|
||||
{
|
||||
Schema::table('assets', function (Blueprint $table) {
|
||||
if (!Schema::hasColumn('assets', 'eol_explicit')) {
|
||||
$table->boolean('eol_explicit')->default(false)->after('asset_eol_date');
|
||||
}
|
||||
$table->boolean('eol_explicit')->default(false)->after('asset_eol_date');
|
||||
});
|
||||
|
||||
|
||||
@@ -51,7 +48,7 @@ class DenormalizedEolAndAddColumnForExplicitDateToAssets extends Migration
|
||||
->whereNotNull('model_id')
|
||||
->join('models', 'assets.model_id', '=', 'models.id')
|
||||
->update([
|
||||
'asset_eol_date' => $this->eolUpdateExpression(),
|
||||
'asset_eol_date' => DB::raw('DATE_ADD(purchase_date, INTERVAL models.eol MONTH)')
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -67,22 +64,4 @@ class DenormalizedEolAndAddColumnForExplicitDateToAssets extends Migration
|
||||
$table->dropColumn('eol_explicit');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the correct database expression for either
|
||||
* mysql, postgres, or sqlite depending on the driver being used.
|
||||
*/
|
||||
private function eolUpdateExpression(): Expression
|
||||
{
|
||||
if (DB::getDriverName() === 'sqlite') {
|
||||
return DB::raw("DATE(purchase_date, '+' || (SELECT eol FROM " . DB::getTablePrefix() . "models WHERE models.id = assets.model_id) || ' months')");
|
||||
}
|
||||
|
||||
if (DB::getDriverName() === 'pgsql') {
|
||||
return DB::raw("date(purchase_date + interval '1 month' * (SELECT eol FROM " . DB::getTablePrefix() . "models WHERE models.id = assets.model_id))");
|
||||
}
|
||||
|
||||
// Default to MySQL's method
|
||||
return DB::raw('DATE_ADD(purchase_date, INTERVAL ' . DB::getTablePrefix() . 'models.eol MONTH)');
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user