Compare commits

..

8 Commits

Author SHA1 Message Date
snipe
141b0b410b Change variable name to be clearer 2019-07-23 18:23:51 -07:00
snipe
d40f06373e DIsable CORS allowed origins by default to replicate existing behavior 2019-07-23 18:23:39 -07:00
snipe
56753fa4cd More clarification 2019-07-23 18:07:45 -07:00
snipe
8a7bafb575 Clarified header comments 2019-07-23 18:05:07 -07:00
snipe
82f91cb944 Fixed typo 2019-07-23 18:03:53 -07:00
snipe
41b226e5fc Added APP_CORS_ALLOWED_ORIGINS env option 2019-07-23 18:02:51 -07:00
snipe
ae6048a6ea Changed order so CORS will still work if throttle hit 2019-07-23 18:02:27 -07:00
snipe
ef41e0060a Added CORS support to API 2019-07-23 17:17:01 -07:00
648 changed files with 11643 additions and 32460 deletions

View File

@@ -1659,78 +1659,6 @@
"contributions": [
"code"
]
},
{
"login": "mskrip",
"name": "Marián Skrip",
"avatar_url": "https://avatars0.githubusercontent.com/u/17459600?v=4",
"profile": "https://github.com/mskrip",
"contributions": [
"code"
]
},
{
"login": "Godmartinz",
"name": "Godfrey Martinez",
"avatar_url": "https://avatars2.githubusercontent.com/u/47435081?v=4",
"profile": "https://github.com/Godmartinz",
"contributions": [
"code"
]
},
{
"login": "bigtreeEdo",
"name": "bigtreeEdo",
"avatar_url": "https://avatars1.githubusercontent.com/u/2075128?v=4",
"profile": "https://github.com/bigtreeEdo",
"contributions": [
"code"
]
},
{
"login": "ColinMcNeil",
"name": "Colin McNeil",
"avatar_url": "https://avatars0.githubusercontent.com/u/5000430?v=4",
"profile": "https://colinmcneil.me/",
"contributions": [
"code"
]
},
{
"login": "JoKneeMo",
"name": "JoKneeMo",
"avatar_url": "https://avatars0.githubusercontent.com/u/421625?v=4",
"profile": "https://github.com/JoKneeMo",
"contributions": [
"code"
]
},
{
"login": "joshi-redbridge",
"name": "Joshi",
"avatar_url": "https://avatars0.githubusercontent.com/u/54849013?v=4",
"profile": "http://www.redbridge.se",
"contributions": [
"code"
]
},
{
"login": "anthonypburns",
"name": "Anthony Burns",
"avatar_url": "https://avatars2.githubusercontent.com/u/15731458?v=4",
"profile": "https://github.com/anthonypburns",
"contributions": [
"code"
]
},
{
"login": "alek13",
"name": "Alexander Chibrikin",
"avatar_url": "https://avatars2.githubusercontent.com/u/1972329?v=4",
"profile": "http://phpprofi.ru/",
"contributions": [
"code"
]
}
]
}

View File

@@ -7,7 +7,6 @@ APP_KEY=ChangeMe
APP_URL=null
APP_TIMEZONE='UTC'
APP_LOCALE=en
MAX_RESULTS=500
# --------------------------------------------
# REQUIRED: DATABASE SETTINGS
@@ -26,7 +25,6 @@ DB_COLLATION=utf8mb4_unicode_ci
# OPTIONAL: SSL DATABASE SETTINGS
# --------------------------------------------
DB_SSL=false
DB_SSL_IS_PAAS=false
DB_SSL_KEY_PATH=null
DB_SSL_CERT_PATH=null
DB_SSL_CA_PATH=null
@@ -66,12 +64,9 @@ SECURE_COOKIES=false
# --------------------------------------------
# OPTIONAL: SECURITY HEADER SETTINGS
# --------------------------------------------
APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1
ALLOW_IFRAMING=false
REFERRER_POLICY=same-origin
ENABLE_CSP=false
CORS_ALLOWED_ORIGINS=null
ENABLE_HSTS=false
# --------------------------------------------
# OPTIONAL: CACHE SETTINGS
@@ -115,8 +110,8 @@ APP_LOG=single
APP_LOG_MAX_FILES=10
APP_LOCKED=false
FILESYSTEM_DISK=local
APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1
ALLOW_IFRAMING=false
APP_CIPHER=AES-256-CBC
GOOGLE_MAPS_API=
BACKUP_ENV=true
LDAP_MEM_LIM=500M
LDAP_TIME_LIM=600

1
.nvmrc
View File

@@ -1 +0,0 @@
v6.11.3

View File

@@ -1,5 +1,5 @@
[![Build Status](https://travis-ci.org/snipe/snipe-it.svg?branch=master)](https://travis-ci.org/snipe/snipe-it) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/snipe-it/localized.svg)](https://crowdin.com/project/snipe-it) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/snipe/snipe-it?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Docker Pulls](https://img.shields.io/docker/pulls/snipe/snipe-it.svg)](https://hub.docker.com/r/snipe/snipe-it/) [![Twitter Follow](https://img.shields.io/twitter/follow/snipeitapp.svg?style=social)](https://twitter.com/snipeitapp) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/553ce52037fc43ea99149785afcfe641)](https://www.codacy.com/app/snipe/snipe-it?utm_source=github.com&utm_medium=referral&utm_content=snipe/snipe-it&utm_campaign=Badge_Grade)
[![All Contributors](https://img.shields.io/badge/all_contributors-189-orange.svg?style=flat-square)](#contributors) [![Open Source Helpers](https://www.codetriage.com/snipe/snipe-it/badges/users.svg)](https://www.codetriage.com/snipe/snipe-it)
[![All Contributors](https://img.shields.io/badge/all_contributors-181-orange.svg?style=flat-square)](#contributors) [![Open Source Helpers](https://www.codetriage.com/snipe/snipe-it/badges/users.svg)](https://www.codetriage.com/snipe/snipe-it)
## Snipe-IT - Open Source Asset Management System
@@ -61,8 +61,6 @@ Since the release of the JSON REST API, several third-party developers have been
- [jamf2snipe](https://github.com/ParadoxGuitarist/jamf2snipe) by [@ParadoxGuitarist](https://github.com/ParadoxGuitarist) - Python script to sync assets between a JAMFPro instance and a Snipe-IT instance
- [Marksman](https://github.com/Scope-IT/marksman) - A Windows agent for Snipe-IT
- [Snipe-IT plugin for Jira Service Desk (beta)](https://marketplace.atlassian.com/apps/1220379/snipe-it-for-jira-service-desk-beta?hosting=cloud&tab=overview) - for the upcoming Snipe-IT v5 only
- [Python 3 CSV importer](https://github.com/gastamper/snipeit-csvimporter) - allows importing assets into Snipe-IT based on Item Name rather than Asset Tag.
- [Snipe-IT Kubernetes Helm Chart](https://github.com/t3n/helm-charts/tree/master/snipeit) - For more information, [click here](https://hub.helm.sh/charts/t3n/snipeit).
As these were created by third-parties, Snipe-IT cannot provide support for these project, and you should contact the developers directly if you need assistance. Additionally, Snipe-IT makes no guarantees as to the reliability, accuracy or maintainability of these libraries. Use at your own risk. :)
@@ -105,8 +103,7 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
| [<img src="https://avatars2.githubusercontent.com/u/982885?v=4" width="110px;"/><br /><sub>Martin Stub</sub>](http://martinstub.dk)<br />[🌍](#translation-stubben "Translation") | [<img src="https://avatars2.githubusercontent.com/u/28959963?v=4" width="110px;"/><br /><sub>Meyer Flavio</sub>](https://github.com/meyerf99)<br />[🌍](#translation-meyerf99 "Translation") | [<img src="https://avatars3.githubusercontent.com/u/796443?v=4" width="110px;"/><br /><sub>Micael Rodrigues</sub>](https://github.com/MicaelRodrigues)<br />[🌍](#translation-MicaelRodrigues "Translation") | [<img src="https://avatars0.githubusercontent.com/u/10481331?v=4" width="110px;"/><br /><sub>Mikael Rasmussen</sub>](http://rubixy.com/)<br />[🌍](#translation-mikaelssen "Translation") | [<img src="https://avatars1.githubusercontent.com/u/1544552?v=4" width="110px;"/><br /><sub>IxFail</sub>](https://github.com/IxFail)<br />[🌍](#translation-IxFail "Translation") | [<img src="https://avatars3.githubusercontent.com/u/18483118?v=4" width="110px;"/><br /><sub>Mohammed Fota</sub>](http://www.mohammedfota.com)<br />[🌍](#translation-MohammedFota "Translation") | [<img src="https://avatars0.githubusercontent.com/u/227080?v=4" width="110px;"/><br /><sub>Moayad Alserihi</sub>](https://github.com/omego)<br />[🌍](#translation-omego "Translation") |
| [<img src="https://avatars0.githubusercontent.com/u/1680266?v=4" width="110px;"/><br /><sub>saymd</sub>](https://github.com/saymd)<br />[🌍](#translation-saymd "Translation") | [<img src="https://avatars0.githubusercontent.com/u/1826808?v=4" width="110px;"/><br /><sub>Patrik Larsson</sub>](https://nordsken.se)<br />[🌍](#translation-pooot "Translation") | [<img src="https://avatars1.githubusercontent.com/u/20584746?v=4" width="110px;"/><br /><sub>drcryo</sub>](https://github.com/drcryo)<br />[🌍](#translation-drcryo "Translation") | [<img src="https://avatars1.githubusercontent.com/u/19408004?v=4" width="110px;"/><br /><sub>pawel1615</sub>](https://github.com/pawel1615)<br />[🌍](#translation-pawel1615 "Translation") | [<img src="https://avatars2.githubusercontent.com/u/23340468?v=4" width="110px;"/><br /><sub>bodrovics</sub>](https://github.com/bodrovics)<br />[🌍](#translation-bodrovics "Translation") | [<img src="https://avatars0.githubusercontent.com/u/3257654?v=4" width="110px;"/><br /><sub>priatna</sub>](https://github.com/priatna)<br />[🌍](#translation-priatna "Translation") | [<img src="https://avatars1.githubusercontent.com/u/5358374?v=4" width="110px;"/><br /><sub>Fan Jiang</sub>](https://amayume.net)<br />[🌍](#translation-ProfFan "Translation") |
| [<img src="https://avatars1.githubusercontent.com/u/22555451?v=4" width="110px;"/><br /><sub>ragnarcx</sub>](https://github.com/ragnarcx)<br />[🌍](#translation-ragnarcx "Translation") | [<img src="https://avatars2.githubusercontent.com/u/18654582?v=4" width="110px;"/><br /><sub>Rein van Haaren</sub>](http://www.reinvanhaaren.nl/)<br />[🌍](#translation-reinvanhaaren "Translation") | [<img src="https://avatars1.githubusercontent.com/u/386672?v=4" width="110px;"/><br /><sub>Teguh Dwicaksana</sub>](http://dheche.songolimo.net)<br />[🌍](#translation-dheche "Translation") | [<img src="https://avatars2.githubusercontent.com/u/2572552?v=4" width="110px;"/><br /><sub>fraccie</sub>](https://github.com/FRaccie)<br />[🌍](#translation-FRaccie "Translation") | [<img src="https://avatars0.githubusercontent.com/u/35182720?v=4" width="110px;"/><br /><sub>vinzruzell</sub>](https://github.com/vinzruzell)<br />[🌍](#translation-vinzruzell "Translation") | [<img src="https://avatars1.githubusercontent.com/u/7883603?v=4" width="110px;"/><br /><sub>Kevin Austin</sub>](http://kevinaustin.com)<br />[🌍](#translation-vipsystem "Translation") | [<img src="https://avatars3.githubusercontent.com/u/3861828?v=4" width="110px;"/><br /><sub>Wira Sandy</sub>](http://azuraweb.xyz)<br />[🌍](#translation-wira-sandy "Translation") |
| [<img src="https://avatars2.githubusercontent.com/u/8663789?v=4" width="110px;"/><br /><sub>Илья</sub>](https://github.com/GrayHoax)<br />[🌍](#translation-GrayHoax "Translation") | [<img src="https://avatars3.githubusercontent.com/u/30119111?v=4" width="110px;"/><br /><sub>GodUseVPN</sub>](https://github.com/godusevpn)<br />[🌍](#translation-godusevpn "Translation") | [<img src="https://avatars1.githubusercontent.com/u/745576?v=4" width="110px;"/><br /><sub>周周</sub>](https://github.com/EngrZhou)<br />[🌍](#translation-EngrZhou "Translation") | [<img src="https://avatars3.githubusercontent.com/u/1631095?v=4" width="110px;"/><br /><sub>Sam</sub>](https://github.com/takuy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=takuy "Code") | [<img src="https://avatars1.githubusercontent.com/u/264022?v=4" width="110px;"/><br /><sub>Azerothian</sub>](https://www.illisian.com.au)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Azerothian "Code") | [<img src="https://avatars1.githubusercontent.com/u/7632599?v=4" width="110px;"/><br /><sub>Tim Farmer</sub>](https://github.com/timothyfarmer)<br />[💻](https://github.com/snipe/snipe-it/commits?author=timothyfarmer "Code") | [<img src="https://avatars0.githubusercontent.com/u/17459600?v=4" width="110px;"/><br /><sub>Marián Skrip</sub>](https://github.com/mskrip)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mskrip "Code") |
| [<img src="https://avatars2.githubusercontent.com/u/47435081?v=4" width="110px;"/><br /><sub>Godfrey Martinez</sub>](https://github.com/Godmartinz)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Godmartinz "Code") | [<img src="https://avatars1.githubusercontent.com/u/2075128?v=4" width="110px;"/><br /><sub>bigtreeEdo</sub>](https://github.com/bigtreeEdo)<br />[💻](https://github.com/snipe/snipe-it/commits?author=bigtreeEdo "Code") | [<img src="https://avatars0.githubusercontent.com/u/5000430?v=4" width="110px;"/><br /><sub>Colin McNeil</sub>](https://colinmcneil.me/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ColinMcNeil "Code") | [<img src="https://avatars0.githubusercontent.com/u/421625?v=4" width="110px;"/><br /><sub>JoKneeMo</sub>](https://github.com/JoKneeMo)<br />[💻](https://github.com/snipe/snipe-it/commits?author=JoKneeMo "Code") | [<img src="https://avatars0.githubusercontent.com/u/54849013?v=4" width="110px;"/><br /><sub>Joshi</sub>](http://www.redbridge.se)<br />[💻](https://github.com/snipe/snipe-it/commits?author=joshi-redbridge "Code") | [<img src="https://avatars2.githubusercontent.com/u/15731458?v=4" width="110px;"/><br /><sub>Anthony Burns</sub>](https://github.com/anthonypburns)<br />[💻](https://github.com/snipe/snipe-it/commits?author=anthonypburns "Code") | [<img src="https://avatars2.githubusercontent.com/u/1972329?v=4" width="110px;"/><br /><sub>Alexander Chibrikin</sub>](http://phpprofi.ru/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=alek13 "Code") |
| [<img src="https://avatars2.githubusercontent.com/u/8663789?v=4" width="110px;"/><br /><sub>Илья</sub>](https://github.com/GrayHoax)<br />[🌍](#translation-GrayHoax "Translation") | [<img src="https://avatars3.githubusercontent.com/u/30119111?v=4" width="110px;"/><br /><sub>GodUseVPN</sub>](https://github.com/godusevpn)<br />[🌍](#translation-godusevpn "Translation") | [<img src="https://avatars1.githubusercontent.com/u/745576?v=4" width="110px;"/><br /><sub>周周</sub>](https://github.com/EngrZhou)<br />[🌍](#translation-EngrZhou "Translation") | [<img src="https://avatars3.githubusercontent.com/u/1631095?v=4" width="110px;"/><br /><sub>Sam</sub>](https://github.com/takuy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=takuy "Code") | [<img src="https://avatars1.githubusercontent.com/u/264022?v=4" width="110px;"/><br /><sub>Azerothian</sub>](https://www.illisian.com.au)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Azerothian "Code") | [<img src="https://avatars1.githubusercontent.com/u/7632599?v=4" width="110px;"/><br /><sub>Tim Farmer</sub>](https://github.com/timothyfarmer)<br />[💻](https://github.com/snipe/snipe-it/commits?author=timothyfarmer "Code") |
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!

View File

View File

@@ -1,112 +0,0 @@
<?php
namespace App\Console\Commands;
use App\Models\LicenseSeat;
use Illuminate\Console\Command;
use App\Models\User;
use App\Models\License;
use Illuminate\Database\Eloquent\Model;
class CheckoutLicenseToAllUsers extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'snipeit:checkout-to-all {--license_id=} {--notify}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$license_id = $this->option('license_id');
$notify = $this->option('notify');
if (!$license_id) {
$this->error('ERROR: License ID is required.');
return false;
}
if (!$license = License::where('id','=',$license_id)->with('assignedusers')->first()) {
$this->error('Invalid license ID');
return false;
}
$users = User::whereNull('deleted_at')->with('licenses')->get();
if ($users->count() > $license->getAvailSeatsCountAttribute()) {
$this->info('You do not have enough free seats to complete this task, so we will check out as many as we can. ');
}
$this->info('Checking out '.$users->count().' of '.$license->getAvailSeatsCountAttribute().' seats for '.$license->name);
if (!$notify) {
$this->info('No mail will be sent.');
}
foreach ($users as $user) {
// Check to make sure this user doesn't already have this license checked out
// to them
if ($user->licenses->where('id', '=', $license_id)->count()) {
$this->info($user->username .' already has this license checked out to them. Skipping... ');
continue;
}
// If the license is valid, check that there is an available seat
if ($license->availCount()->count() < 1) {
$this->error('ERROR: No available seats');
return false;
}
$this->info($license->availCount()->count().' seats left');
// Get the seat ID
$licenseSeat = $license->freeSeat();
// Update the seat with checkout info,
$licenseSeat->assigned_to = $user->id;
if ($licenseSeat->save()) {
// Temporarily null the user's email address so we don't send mail if we're not supposed to
if (!$notify) {
$user->email = null;
}
// Log the checkout
$licenseSeat->logCheckout('Checked out via cli tool', $user);
$this->info('License '.$license_id.' seat '.$licenseSeat->id.' checked out to '.$user->username);
}
}
}
}

View File

@@ -42,8 +42,9 @@ class LdapSync extends Command
*/
public function handle()
{
ini_set('max_execution_time', env('LDAP_TIME_LIM', 600)); //600 seconds = 10 minutes
ini_set('memory_limit', env('LDAP_MEM_LIM', '500M'));
ini_set('max_execution_time', 600); //600 seconds = 10 minutes
ini_set('memory_limit', '500M');
$ldap_result_username = Setting::getSettings()->ldap_username_field;
$ldap_result_last_name = Setting::getSettings()->ldap_lname_field;
$ldap_result_first_name = Setting::getSettings()->ldap_fname_field;
@@ -188,7 +189,7 @@ class LdapSync extends Command
// Sync activated state for Active Directory.
if ( array_key_exists('useraccountcontrol', $results[$i]) ) {
$enabled_accounts = [
'512', '544', '66048', '66080', '262656', '262688', '328192', '328224', '4260352'
'512', '544', '66048', '66080', '262656', '262688', '328192', '328224'
];
$user->activated = ( in_array($results[$i]['useraccountcontrol'][0], $enabled_accounts) ) ? 1 : 0;
}

View File

@@ -1,109 +0,0 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\User;
use Carbon\Carbon;
class MergeUsersByUsername extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'snipeit:merge-users';
/**
* The console command description.
*
* @var string
*/
protected $description = 'This command allows you to merge the history of users. It looks for users without an email address as their username and merges them into the version that does have an email username.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
// Get the list of users who have an email address as their username
$users = User::where('username', 'LIKE', '%@%')->whereNull('deleted_at')->get();
foreach ($users as $user) {
$parts = explode("@", $user->username);
$bad_users = User::where('username', '=', $parts[0])->whereNull('deleted_at')->with('assets', 'manager', 'userlog', 'licenses', 'consumables', 'accessories', 'managedLocations')->get();
foreach ($bad_users as $bad_user) {
$this->info($bad_user->username.' ('.$bad_user->id.') will be merged into '.$user->username.' ('.$user->id.') ');
// Walk the list of assets
foreach ($bad_user->assets as $asset) {
$this->info( 'Updating asset '.$asset->asset_tag.' '.$asset->id.' to user '.$user->id);
$asset->assigned_to = $user->id;
$asset->save();
}
// Walk the list of licenses
foreach ($bad_user->licenses as $license) {
$this->info( 'Updating license '.$license->name.' '.$license->id.' to user '.$user->id);
$bad_user->licenses()->updateExistingPivot($license->id, ['assigned_to' => $user->id]);
}
// Walk the list of consumables
foreach ($bad_user->consumables as $consumable) {
$this->info( 'Updating consumable '.$consumable->id.' to user '.$user->id);
$bad_user->consumables()->updateExistingPivot($consumable->id, ['assigned_to' => $user->id]);
}
// Walk the list of accessories
foreach ($bad_user->accessories as $accessory) {
$this->info( 'Updating accessory '.$accessory->id.' to user '.$user->id);
$bad_user->accessories()->updateExistingPivot($accessory->id, ['assigned_to' => $user->id]);
}
// Walk the list of logs
foreach ($bad_user->userlog as $log) {
$this->info( 'Updating action log record '.$log->id.' to user '.$user->id);
$log->target_id = $user->id;
$log->save();
}
// Update any manager IDs
$this->info( 'Updating managed user records to user '.$user->id);
User::where('manager_id', '=', $bad_user->id)->update(['manager_id' => $user->id]);
// Update location manager IDs
foreach ($bad_user->managedLocations as $managedLocation) {
$this->info( 'Updating managed location record '.$managedLocation->name.' to manager '.$user->id);
$managedLocation->manager_id = $user->id;
$managedLocation->save();
}
// Mark the user as deleted
$this->info( 'Marking the user as deleted');
$bad_user->deleted_at = Carbon::now()->timestamp;
$bad_user->save();
}
}
}
}

View File

@@ -1,135 +0,0 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Artisan;
use App\Models\CustomField;
use App\Models\Asset;
use App\Models\Setting;
use \Illuminate\Encryption\Encrypter;
class RotateAppKey extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'snipeit:rotate-key';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
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.
$old_app_key = config('app.key');
$cipher = config('app.cipher');
// Generate a new one
Artisan::call('key:generate', ['--show' => true]);
$new_app_key = Artisan::output();
// Clear the config cache
Artisan::call('config:clear');
$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
// using the newly generated app key
$oldEncrypter = new Encrypter(base64_decode(substr($old_app_key, 7)), $cipher);
$newEncrypter = new Encrypter(base64_decode(substr($new_app_key, 7)), $cipher);
$fields = CustomField::where('field_encrypted', '1')->get();
foreach ($fields as $field) {
$assets = Asset::whereNotNull($field->db_column)->get();
foreach ($assets as $asset) {
$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();
}
}
// Handle the LDAP password if one is provided
$setting = Setting::first();
if ($setting->ldap_pword!='') {
$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.');
}
}
/**
* Write a new environment file with the given key.
*
* @param string $key
* @return void
*/
protected function writeNewEnvironmentFileWith($key)
{
file_put_contents($this->laravel->environmentFilePath(), preg_replace(
$this->keyReplacementPattern(),
'APP_KEY='.$key,
file_get_contents($this->laravel->environmentFilePath())
));
}
/**
* Get a regex pattern that will match env APP_KEY with any random key.
*
* @return string
*/
protected function keyReplacementPattern()
{
$escaped = preg_quote('='.$this->laravel['config']['app.key'], '/');
return "/^APP_KEY{$escaped}/m";
}
}

View File

@@ -3,13 +3,40 @@
namespace App\Console;
use App\Console\Commands\ImportLocations;
use App\Console\Commands\ReEncodeCustomFieldNames;
use App\Console\Commands\RestoreDeletedUsers;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [
Commands\PaveIt::class,
Commands\CreateAdmin::class,
Commands\SendExpirationAlerts::class,
Commands\SendInventoryAlerts::class,
Commands\SendExpectedCheckinAlerts::class,
Commands\ObjectImportCommand::class,
Commands\Version::class,
Commands\SystemBackup::class,
Commands\DisableLDAP::class,
Commands\Purge::class,
Commands\LdapSync::class,
Commands\FixDoubleEscape::class,
Commands\RecryptFromMcrypt::class,
Commands\ResetDemoSettings::class,
Commands\SyncAssetLocations::class,
Commands\RegenerateAssetTags::class,
Commands\SyncAssetCounters::class,
Commands\RestoreDeletedUsers::class,
Commands\SendUpcomingAuditReport::class,
Commands\ImportLocations::class,
Commands\ReEncodeCustomFieldNames::class,
];
/**
* Define the application's command schedule.

View File

@@ -85,7 +85,26 @@ class AccessoriesController extends Controller
$accessory->qty = request('qty');
$accessory->user_id = Auth::user()->id;
$accessory->supplier_id = request('supplier_id');
$accessory = $request->handleImages($accessory,600, public_path().'/uploads/accessories');
if ($request->hasFile('image')) {
if (!config('app.lock_passwords')) {
$image = $request->file('image');
$ext = $image->getClientOriginalExtension();
$file_name = "accessory-".str_random(18).'.'.$ext;
$path = public_path('/uploads/accessories');
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(null, 800, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path.'/'.$file_name);
} else {
$image->move($path, $file_name);
}
$accessory->image = $file_name;
}
}
// Was the accessory created?
@@ -146,7 +165,28 @@ class AccessoriesController extends Controller
$accessory->qty = request('qty');
$accessory->supplier_id = request('supplier_id');
$accessory = $request->handleImages($accessory,600, public_path().'/uploads/accessories');
if ($request->hasFile('image')) {
if (!config('app.lock_passwords')) {
$image = $request->file('image');
$ext = $image->getClientOriginalExtension();
$file_name = "accessory-".str_random(18).'.'.$ext;
$path = public_path('/uploads/accessories');
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(null, 800, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path.'/'.$file_name);
} else {
$image->move($path, $file_name);
}
if (($accessory->image) && (file_exists($path.'/'.$accessory->image))) {
unlink($path.'/'.$accessory->image);
}
$accessory->image = $file_name;
}
}
// Was the accessory updated?
@@ -198,7 +238,7 @@ class AccessoriesController extends Controller
if (isset($accessory->id)) {
return view('accessories/view', compact('accessory'));
}
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist', compact('id')));
}
/**

View File

@@ -8,10 +8,7 @@ use App\Helpers\Helper;
use App\Models\Accessory;
use App\Http\Transformers\AccessoriesTransformer;
use App\Models\Company;
use App\Models\User;
use Carbon\Carbon;
use Auth;
use DB;
class AccessoriesController extends Controller
{
@@ -49,14 +46,8 @@ class AccessoriesController extends Controller
$accessories->where('supplier_id','=',$request->input('supplier_id'));
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($accessories) && ($request->get('offset') > $accessories->count())) ? $accessories->count() : $request->get('offset', 0);
// Check to make sure the limit is not higher than the max allowed
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
$offset = (($accessories) && (request('offset') > $accessories->count())) ? 0 : request('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
@@ -200,94 +191,4 @@ class AccessoriesController extends Controller
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/accessories/message.delete.success')));
}
/**
* Save the Accessory checkout information.
*
* If Slack is enabled and/or asset acceptance is enabled, it will also
* trigger a Slack message and send an email.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $accessoryId
* @return Redirect
*/
public function checkout(Request $request, $accessoryId)
{
// Check if the accessory exists
if (is_null($accessory = Accessory::find($accessoryId))) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/accessories/message.does_not_exist')));
}
$this->authorize('checkout', $accessory);
if ($accessory->numRemaining() > 0) {
if (!$user = User::find($request->input('assigned_to'))) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/accessories/message.checkout.user_does_not_exist')));
}
// Update the accessory data
$accessory->assigned_to = $request->input('assigned_to');
$accessory->users()->attach($accessory->id, [
'accessory_id' => $accessory->id,
'created_at' => Carbon::now(),
'user_id' => Auth::id(),
'assigned_to' => $request->get('assigned_to')
]);
$accessory->logCheckout($request->input('note'), $user);
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/accessories/message.checkout.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, 'No accessories remaining'));
}
/**
* Check in the item so that it can be checked out again to someone else
*
* @uses Accessory::checkin_email() to determine if an email can and should be sent
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param Request $request
* @param integer $accessoryUserId
* @param string $backto
* @return Redirect
* @internal param int $accessoryId
*/
public function checkin(Request $request, $accessoryUserId = null)
{
if (is_null($accessory_user = DB::table('accessories_users')->find($accessoryUserId))) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/accessories/message.does_not_exist')));
}
$accessory = Accessory::find($accessory_user->accessory_id);
$this->authorize('checkin', $accessory);
$logaction = $accessory->logCheckin(User::find($accessoryUserId), $request->input('note'));
// Was the accessory updated?
if (DB::table('accessories_users')->where('id', '=', $accessory_user->id)->delete()) {
if (!is_null($accessory_user->assigned_to)) {
$user = User::find($accessory_user->assigned_to);
}
$data['log_id'] = $logaction->id;
$data['first_name'] = $user->first_name;
$data['last_name'] = $user->last_name;
$data['item_name'] = $accessory->name;
$data['checkin_date'] = $logaction->created_at;
$data['item_tag'] = '';
$data['note'] = $logaction->note;
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/accessories/message.checkin.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/accessories/message.checkin.error')));
}
}

View File

@@ -44,13 +44,8 @@ class AssetMaintenancesController extends Controller
$maintenances->where('asset_id', '=', $request->input('asset_id'));
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($maintenances) && ($request->get('offset') > $maintenances->count())) ? $maintenances->count() : $request->get('offset', 0);
// Check to make sure the limit is not higher than the max allowed
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
$offset = (($maintenances) && (request('offset') > $maintenances->count())) ? 0 : request('offset', 0);
$limit = request('limit', 50);
$allowed_columns = [
'id',

View File

@@ -60,13 +60,8 @@ class AssetModelsController extends Controller
$assetmodels->TextSearch($request->input('search'));
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($assetmodels) && ($request->get('offset') > $assetmodels->count())) ? $assetmodels->count() : $request->get('offset', 0);
// Check to make sure the limit is not higher than the max allowed
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
$offset = (($assetmodels) && (request('offset') > $assetmodels->count())) ? 0 : request('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'models.created_at';

View File

@@ -121,10 +121,6 @@ class AssetsController extends Controller
$assets->where('assets.location_id', '=', $request->input('location_id'));
}
if ($request->filled('rtd_location_id')) {
$assets->where('assets.rtd_location_id', '=', $request->input('rtd_location_id'));
}
if ($request->filled('supplier_id')) {
$assets->where('assets.supplier_id', '=', $request->input('supplier_id'));
}
@@ -148,15 +144,8 @@ class AssetsController extends Controller
$request->filled('order_number') ? $assets = $assets->where('assets.order_number', '=', e($request->get('order_number'))) : '';
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($assets) && ($request->get('offset') > $assets->count())) ? $assets->count() : $request->get('offset', 0);
// Check to make sure the limit is not higher than the max allowed
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
$offset = (($assets) && (request('offset') > $assets->count())) ? 0 : request('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
// This is used by the audit reporting routes
@@ -453,7 +442,6 @@ class AssetsController extends Controller
$asset->supplier_id = $request->get('supplier_id', 0);
$asset->requestable = $request->get('requestable', 0);
$asset->rtd_location_id = $request->get('rtd_location_id', null);
$asset->location_id = $request->get('rtd_location_id', null);
// Update custom fields in the database.
// Validation for these fields is handled through the AssetRequest form request
@@ -534,10 +522,6 @@ class AssetsController extends Controller
$location = $target->location_id;
} elseif (($request->filled('assigned_asset')) && ($target = Asset::find($request->get('assigned_asset')))) {
$location = $target->location_id;
Asset::where('assigned_type', '\\App\\Models\\Asset')->where('assigned_to', $id)
->update(['location_id' => $target->location_id]);
} elseif (($request->filled('assigned_location')) && ($target = Location::find($request->get('assigned_location')))) {
$location = $target->id;
}
@@ -621,14 +605,16 @@ class AssetsController extends Controller
$target = Asset::where('id','!=',$asset_id)->find(request('assigned_asset'));
$asset->location_id = $target->rtd_location_id;
// Override with the asset's location_id if it has one
$asset->location_id = (($target) && (isset($target->location_id))) ? $target->location_id : '';
if ($target->location_id!='') {
$asset->location_id = ($target) ? $target->location_id : '';
}
$error_payload['target_id'] = $request->input('assigned_asset');
$error_payload['target_type'] = 'asset';
} elseif (request('checkout_to_type')=='user') {
// Fetch the target and set the asset's new location_id
$target = User::find(request('assigned_user'));
$asset->location_id = (($target) && (isset($target->location_id))) ? $target->location_id : '';
$asset->location_id = ($target) ? $target->location_id : '';
$error_payload['target_id'] = $request->input('assigned_user');
$error_payload['target_type'] = 'user';
}
@@ -647,12 +633,11 @@ class AssetsController extends Controller
$asset_name = request('name', null);
// Set the location ID to the RTD location id if there is one
// Wait, why are we doing this? This overrides the stuff we set further up, which makes no sense.
// TODO: Follow up here. WTF. Commented out for now.
if ($asset->rtd_location_id!='') {
$asset->location_id = $target->rtd_location_id;
}
// if ((isset($target->rtd_location_id)) && ($asset->rtd_location_id!='')) {
// $asset->location_id = $target->rtd_location_id;
// }
@@ -660,7 +645,7 @@ class AssetsController extends Controller
return response()->json(Helper::formatStandardApiResponse('success', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkout.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkout.error')));
return response()->json(Helper::formatStandardApiResponse('error', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkout.error')))->withErrors($asset->getErrors());
}
@@ -689,11 +674,7 @@ class AssetsController extends Controller
$asset->assigned_to = null;
$asset->assignedTo()->disassociate($asset);
$asset->accepted = null;
if ($request->filled('name')) {
$asset->name = $request->input('name');
}
$asset->name = Input::get('name');
$asset->location_id = $asset->rtd_location_id;
if ($request->filled('location_id')) {

View File

@@ -30,13 +30,8 @@ class CategoriesController extends Controller
$categories = $categories->TextSearch($request->input('search'));
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($categories) && ($request->get('offset') > $categories->count())) ? $categories->count() : $request->get('offset', 0);
// Check to make sure the limit is not higher than the max allowed
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
$offset = (($categories) && (request('offset') > $categories->count())) ? 0 : request('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'assets_count';
$categories->orderBy($sort, $order);

View File

@@ -41,13 +41,8 @@ class CompaniesController extends Controller
$companies->TextSearch($request->input('search'));
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($companies) && ($request->get('offset') > $companies->count())) ? $companies->count() : $request->get('offset', 0);
// Check to make sure the limit is not higher than the max allowed
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
$offset = (($companies) && (request('offset') > $companies->count())) ? 0 : request('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
$companies->orderBy($sort, $order);

View File

@@ -43,12 +43,8 @@ class ComponentsController extends Controller
$components->where('location_id','=',$request->input('location_id'));
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($components) && ($request->get('offset') > $components->count())) ? $components->count() : $request->get('offset', 0);
// Check to make sure the limit is not higher than the max allowed
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
$offset = (($components) && (request('offset') > $components->count())) ? 0 : request('offset', 0);
$limit = request('limit', 50);
$allowed_columns = ['id','name','min_amt','order_number','serial','purchase_date','purchase_cost','company','category','qty','location','image'];
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';

View File

@@ -44,13 +44,8 @@ class ConsumablesController extends Controller
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($consumables) && ($request->get('offset') > $consumables->count())) ? $consumables->count() : $request->get('offset', 0);
// Check to make sure the limit is not higher than the max allowed
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
$offset = (($consumables) && (request('offset') > $consumables->count())) ? 0 : request('offset', 0);
$limit = request('limit', 50);
$allowed_columns = ['id','name','order_number','min_amt','purchase_date','purchase_cost','company','category','model_number', 'item_no', 'manufacturer','location','qty','image'];
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';

View File

@@ -24,7 +24,7 @@ class CustomFieldsController extends Controller
public function index()
{
$this->authorize('index', CustomField::class);
$this->authorize('index', CustomFields::class);
$fields = CustomField::get();
return (new CustomFieldsTransformer)->transformCustomFields($fields, $fields->count());
}
@@ -38,7 +38,7 @@ class CustomFieldsController extends Controller
*/
public function show($id)
{
$this->authorize('view', CustomField::class);
$this->authorize('show', CustomField::class);
if ($field = CustomField::find($id)) {
return (new CustomFieldsTransformer)->transformCustomField($field);
}

View File

@@ -58,7 +58,7 @@ class CustomFieldsetsController extends Controller
*/
public function show($id)
{
$this->authorize('view', CustomFieldset::class);
$this->authorize('show', CustomFieldset::class);
if ($fieldset = CustomFieldset::find($id)) {
return (new CustomFieldsetsTransformer)->transformCustomFieldset($fieldset);
}

View File

@@ -15,7 +15,7 @@ class DepartmentsController extends Controller
/**
* Display a listing of the resource.
*
* @author [Godfrey Martinez] [<snipe@snipe.net>]
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return \Illuminate\Http\Response
*/
@@ -39,13 +39,8 @@ class DepartmentsController extends Controller
$departments = $departments->TextSearch($request->input('search'));
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($departments) && ($request->get('offset') > $departments->count())) ? $departments->count() : $request->get('offset', 0);
// Check to make sure the limit is not higher than the max allowed
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
$offset = (($departments) && (request('offset') > $departments->count())) ? 0 : request('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
@@ -163,28 +158,5 @@ class DepartmentsController extends Controller
return (new SelectlistTransformer)->transformSelectlist($departments);
}
/**
* Update the specified resource in storage.
*
* @author [Godfrey Martinez] [<gmartinez@grokability.com>]
* @since [v4.0]
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
$this->authorize('update', Department::class);
$departments = Department::findOrFail($id);
$departments->fill($request->all());
if ($departments->save()) {
return response()
->json(Helper::formatStandardApiResponse('success', (new DepartmentsTransformer())->transformdepartment($departments), trans('admin/departments/message.update.success')));
}
return response()
->json(Helper::formatStandardApiResponse('error', null, $departments->getErrors()));
}
}

View File

@@ -28,13 +28,8 @@ class DepreciationsController extends Controller
$depreciations = $depreciations->TextSearch($request->input('search'));
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($depreciations) && ($request->get('offset') > $depreciations->count())) ? $depreciations->count() : $request->get('offset', 0);
// Check to make sure the limit is not higher than the max allowed
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
$offset = (($depreciations) && (request('offset') > $depreciations->count())) ? 0 : request('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
$depreciations->orderBy($sort, $order);

View File

@@ -28,13 +28,8 @@ class GroupsController extends Controller
$groups = $groups->TextSearch($request->input('search'));
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($groups) && ($request->get('offset') > $groups->count())) ? $groups->count() : $request->get('offset', 0);
// Check to make sure the limit is not higher than the max allowed
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
$offset = (($groups) && (request('offset') > $groups->count())) ? 0 : request('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
$groups->orderBy($sort, $order);

View File

@@ -119,14 +119,7 @@ class ImportController extends Controller
{
$this->authorize('import');
// Run a backup immediately before processing
if ($request->has('run-backup')) {
\Log::debug('Backup manually requested via importer');
Artisan::call('backup:run');
} else {
\Log::debug('NO BACKUP requested via importer');
}
Artisan::call('backup:run');
$errors = $request->import(Import::find($import_id));
$redirectTo = "hardware.index";
switch ($request->get('import-type')) {

View File

@@ -82,13 +82,8 @@ class LicensesController extends Controller
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($licenses) && ($request->get('offset') > $licenses->count())) ? $licenses->count() : $request->get('offset', 0);
// Check to make sure the limit is not higher than the max allowed
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
$offset = (($licenses) && (request('offset') > $licenses->count())) ? 0 : request('offset', 0);
$limit = request('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
@@ -230,21 +225,14 @@ class LicensesController extends Controller
$this->authorize('view', $license);
$seats = LicenseSeat::where('license_seats.license_id', $licenseId)
->with('license', 'user', 'asset', 'user.department');
$seats = LicenseSeat::where('license_id', $licenseId)->with('license', 'user', 'asset');
$offset = (($seats) && (request('offset') > $seats->count())) ? 0 : request('offset', 0);
$limit = request('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
if ($request->input('sort')=='department') {
$seats->OrderDepartments($order);
} else {
$seats->orderBy('id', $order);
}
$total = $seats->count();
$offset = (($seats) && (request('offset') > $total)) ? 0 : request('offset', 0);
$limit = request('limit', 50);
$seats = $seats->skip($offset)->take($limit)->get();
if ($seats) {

View File

@@ -8,8 +8,6 @@ use App\Helpers\Helper;
use App\Models\Location;
use App\Http\Transformers\LocationsTransformer;
use App\Http\Transformers\SelectlistTransformer;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
class LocationsController extends Controller
{
@@ -28,7 +26,7 @@ class LocationsController extends Controller
'updated_at','manager_id','image',
'assigned_assets_count','users_count','assets_count','currency'];
$locations = Location::with('parent', 'manager', 'children')->select([
$locations = Location::with('parent', 'manager', 'childLocations')->select([
'locations.id',
'locations.name',
'locations.address',
@@ -52,13 +50,9 @@ class LocationsController extends Controller
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($locations) && ($request->get('offset') > $locations->count())) ? $locations->count() : $request->get('offset', 0);
// Check to make sure the limit is not higher than the max allowed
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
$offset = (($locations) && (request('offset') > $locations->count())) ? 0 : request('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
@@ -112,7 +106,7 @@ class LocationsController extends Controller
public function show($id)
{
$this->authorize('view', Location::class);
$location = Location::with('parent', 'manager', 'children')
$location = Location::with('parent', 'manager', 'childLocations')
->select([
'locations.id',
'locations.name',
@@ -149,13 +143,6 @@ class LocationsController extends Controller
{
$this->authorize('update', Location::class);
$location = Location::findOrFail($id);
if ($request->input('parent_id') == $id) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'A location cannot be its own parent. Please select a different parent ID.'));
}
$location->fill($request->all());
if ($location->save()) {
@@ -191,27 +178,6 @@ class LocationsController extends Controller
/**
* Gets a paginated collection for the select2 menus
*
* This is handled slightly differently as of ~4.7.8-pre, as
* we have to do some recursive magic to get the hierarchy to display
* properly when looking at the parent/child relationship in the
* rich menus.
*
* This means we can't use the normal pagination that we use elsewhere
* in our selectlists, since we have to get the full set before we can
* determine which location is parent/child/grandchild, etc.
*
* This also means that hierarchy display gets a little funky when people
* use the Select2 search functionality, but there's not much we can do about
* that right now.
*
* As a result, instead of paginating as part of the query, we have to grab
* the entire data set, and then invoke a paginator manually and pass that
* through to the SelectListTransformer.
*
* Many thanks to @uberbrady for the help getting this working better.
* Recursion still sucks, but I guess he doesn't have to get in the
* sea... this time.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
@@ -223,44 +189,25 @@ class LocationsController extends Controller
$locations = Location::select([
'locations.id',
'locations.name',
'locations.parent_id',
'locations.image',
]);
$page = 1;
if ($request->filled('page')) {
$page = $request->input('page');
}
if ($request->filled('search')) {
$locations = $locations->where('locations.name', 'LIKE', '%'.$request->input('search').'%');
$locations = $locations->where('locations.name', 'LIKE', '%'.$request->get('search').'%');
}
$locations = $locations->orderBy('name', 'ASC')->get();
$locations_with_children = [];
$locations = $locations->orderBy('name', 'ASC')->paginate(50);
// Loop through and set some custom properties for the transformer to use.
// This lets us have more flexibility in special cases like assets, where
// they may not have a ->name value but we want to display something anyway
foreach ($locations as $location) {
if (!array_key_exists($location->parent_id, $locations_with_children)) {
$locations_with_children[$location->parent_id] = [];
}
$locations_with_children[$location->parent_id][] = $location;
$location->use_text = $location->name;
$location->use_image = ($location->image) ? url('/').'/uploads/locations/'.$location->image : null;
}
if ($request->filled('search')) {
$locations_formatted = $locations;
} else {
$location_options = Location::indenter($locations_with_children);
$locations_formatted = new Collection($location_options);
}
$paginated_results = new LengthAwarePaginator($locations_formatted->forPage($page, 500), $locations_formatted->count(), 500, $page, []);
//return [];
return (new SelectlistTransformer)->transformSelectlist($paginated_results);
return (new SelectlistTransformer)->transformSelectlist($locations);
}
}

View File

@@ -37,13 +37,10 @@ class ManufacturersController extends Controller
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($manufacturers) && ($request->get('offset') > $manufacturers->count())) ? $manufacturers->count() : $request->get('offset', 0);
// Check to make sure the limit is not higher than the max allowed
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
$offset = (($manufacturers) && (request('offset') > $manufacturers->count())) ? 0 : request('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
$manufacturers->orderBy($sort, $order);

View File

@@ -20,8 +20,8 @@ class SettingsController extends Controller
{
if (Setting::getSettings()->ldap_enabled!='1') {
\Log::debug('LDAP is not enabled so cannot test.');
return response()->json(['message' => 'LDAP is not enabled, so we cannot test LDAP connections.'], 400);
\Log::debug('LDAP is not enabled cannot test.');
return response()->json(['message' => 'LDAP is not enabled, cannot test.'], 400);
}
\Log::debug('Preparing to test LDAP connection');
@@ -33,13 +33,13 @@ class SettingsController extends Controller
Ldap::bindAdminToLdap($connection);
return response()->json(['message' => 'It worked!'], 200);
} catch (\Exception $e) {
\Log::debug('LDAP connected but Bind failed. Please check your LDAP settings and try again.');
\Log::debug('Bind failed');
return response()->json(['message' => $e->getMessage()], 400);
//return response()->json(['message' => $e->getMessage()], 500);
}
} catch (\Exception $e) {
\Log::info('LDAP connection failed but we cannot debug it any further on our end.');
return response()->json(['message' => 'The LDAP connection failed but we cannot debug it any further on our end. The error from the server is: '.$e->getMessage()], 500);
\Log::debug('Connection failed but we cannot debug it any further on our end.');
return response()->json(['message' => $e->getMessage()], 600);
}

View File

@@ -30,13 +30,8 @@ class StatuslabelsController extends Controller
$statuslabels = $statuslabels->TextSearch($request->input('search'));
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($statuslabels) && ($request->get('offset') > $statuslabels->count())) ? $statuslabels->count() : $request->get('offset', 0);
// Check to make sure the limit is not higher than the max allowed
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
$offset = (($statuslabels) && (request('offset') > $statuslabels->count())) ? 0 : request('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
$statuslabels->orderBy($sort, $order);

View File

@@ -33,13 +33,8 @@ class SuppliersController extends Controller
$suppliers = $suppliers->TextSearch($request->input('search'));
}
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($suppliers) && ($request->get('offset') > $suppliers->count())) ? $suppliers->count() : $request->get('offset', 0);
// Check to make sure the limit is not higher than the max allowed
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
$offset = (($suppliers) && (request('offset') > $suppliers->count())) ? 0 : request('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
$suppliers->orderBy($sort, $order);

View File

@@ -13,8 +13,6 @@ use App\Models\Asset;
use App\Http\Transformers\AssetsTransformer;
use App\Http\Transformers\SelectlistTransformer;
use App\Http\Transformers\AccessoriesTransformer;
use App\Http\Transformers\LicensesTransformer;
use Auth;
class UsersController extends Controller
{
@@ -76,14 +74,6 @@ class UsersController extends Controller
$users = $users->where('users.location_id', '=', $request->input('location_id'));
}
if ($request->filled('email')) {
$users = $users->where('users.email', '=', $request->input('email'));
}
if ($request->filled('username')) {
$users = $users->where('users.username', '=', $request->input('username'));
}
if ($request->filled('group_id')) {
$users = $users->ByGroup($request->get('group_id'));
}
@@ -97,14 +87,8 @@ class UsersController extends Controller
}
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (($users) && ($request->get('offset') > $users->count())) ? $users->count() : $request->get('offset', 0);
// Check to make sure the limit is not higher than the max allowed
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
$offset = (($users) && (request('offset') > $users->count())) ? 0 : request('offset', 0);
$limit = request('limit', 20);
switch ($request->input('sort')) {
case 'manager':
@@ -216,17 +200,6 @@ class UsersController extends Controller
$user = new User;
$user->fill($request->all());
if ($request->has('permissions')) {
$permissions_array = $request->input('permissions');
// Strip out the superuser permission if the API user isn't a superadmin
if (!Auth::user()->isSuperUser()) {
unset($permissions_array['superuser']);
}
$user->permissions = $permissions_array;
}
$tmp_pass = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 20);
$user->password = bcrypt($request->get('password', $tmp_pass));
@@ -252,7 +225,7 @@ class UsersController extends Controller
public function show($id)
{
$this->authorize('view', User::class);
$user = User::withCount('assets as assets_count','licenses as licenses_count','accessories as accessories_count','consumables as consumables_count')->findOrFail($id);
$user = User::findOrFail($id);
return (new UsersTransformer)->transformUser($user);
}
@@ -281,23 +254,6 @@ class UsersController extends Controller
$user->password = bcrypt($request->input('password'));
}
// We need to use has() instead of filled()
// here because we need to overwrite permissions
// if someone needs to null them out
if ($request->has('permissions')) {
$permissions_array = $request->input('permissions');
// Strip out the superuser permission if the API user isn't a superadmin
if (!Auth::user()->isSuperUser()) {
unset($permissions_array['superuser']);
}
$user->permissions = $permissions_array;
}
// Update the location of any assets checked out to this user
Asset::where('assigned_type', User::class)
->where('assigned_to', $user->id)->update(['location_id' => $request->input('location_id', null)]);
@@ -396,23 +352,6 @@ class UsersController extends Controller
return (new AccessoriesTransformer)->transformAccessories($accessories, $accessories->count());
}
/**
* Return JSON containing a list of licenses assigned to a user.
*
* @author [N. Mathar] [<snipe@snipe.net>]
* @since [v5.0]
* @param $userId
* @return string JSON
*/
public function licenses($id)
{
$this->authorize('view', User::class);
$this->authorize('view', License::class);
$user = User::where('id', $id)->withTrashed()->first();
$licenses = $user->licenses()->get();
return (new LicensesTransformer())->transformLicenses($licenses, $licenses->count());
}
/**
* Reset the user's two-factor status
*
@@ -451,6 +390,6 @@ class UsersController extends Controller
*/
public function getCurrentUserInfo(Request $request)
{
return (new UsersTransformer)->transformUser($request->user());
return response()->json($request->user());
}
}

View File

@@ -90,7 +90,23 @@ class AssetModelsController extends Controller
$model->fieldset_id = e($request->input('custom_fieldset'));
}
$model = $request->handleImages($model,600, public_path().'/uploads/models');
if (Input::file('image')) {
$image = Input::file('image');
$file_name = str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
$path = app('models_upload_path');
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path.'/'.$file_name);
} else {
$image->move($path, $file_name);
}
$model->image = $file_name;
}
// Was it created?
if ($model->save()) {
@@ -166,7 +182,37 @@ class AssetModelsController extends Controller
}
}
$model = $request->handleImages($model,600, public_path().'/uploads/models');
$old_image = $model->image;
// Set the model's image property to null if the image is being deleted
if ($request->input('image_delete') == 1) {
$model->image = null;
}
if ($request->file('image')) {
$image = $request->file('image');
$file_name = $model->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save(app('models_upload_path').$file_name);
} else {
$image->move(app('models_upload_path'), $file_name);
}
$model->image = $file_name;
}
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
try {
unlink(app('models_upload_path').$old_image);
} catch (\Exception $e) {
\Log::info($e);
}
}
if ($model->save()) {
return redirect()->route("models.index")->with('success', trans('admin/models/message.update.success'));
@@ -259,8 +305,11 @@ class AssetModelsController extends Controller
if (isset($model->id)) {
return view('models/view', compact('model'));
}
// Prepare the error message
$error = trans('admin/models/message.does_not_exist', compact('id'));
return redirect()->route('models.index')->with('error', trans('admin/models/message.does_not_exist'));
// Redirect to the user management page
return redirect()->route('models.index')->with('error', $error);
}
/**

View File

@@ -137,7 +137,6 @@ class AssetsController extends Controller
$asset->supplier_id = request('supplier_id', 0);
$asset->requestable = request('requestable', 0);
$asset->rtd_location_id = request('rtd_location_id', null);
if ($asset->assigned_to=='') {
$asset->location_id = $request->input('rtd_location_id', null);
@@ -327,7 +326,7 @@ class AssetsController extends Controller
unlink(public_path().'/uploads/assets/'.$asset->image);
$asset->image = '';
} catch (\Exception $e) {
\Log::debug($e);
\Log::info($e);
}
}
@@ -395,12 +394,6 @@ class AssetsController extends Controller
if ($asset->save()) {
// Update any assigned assets with the new location_id from the parent asset
Asset::where('assigned_type', '\\App\\Models\\Asset')->where('assigned_to', $asset->id)
->update(['location_id' => $asset->location_id]);
// Redirect to the new asset page
\Session::flash('success', trans('admin/hardware/message.update.success'));
return response()->json(['redirect_url' => route("hardware.show", $assetId)]);
@@ -440,63 +433,22 @@ class AssetsController extends Controller
/**
* Searches the assets table by tag, and redirects if it finds one.
*
* This is used by the top search box in Snipe-IT, but as of 4.9.x
* can also be used as a url segment.
*
* https://yoursnipe.com/hardware/bytag/?assetTag=foo
*
* OR
*
* https://yoursnipe.com/hardware/bytag/foo
*
* The latter is useful if you're doing home-grown barcodes, or
* some other automation where you don't always know the internal ID of
* an asset and don't want to query for it.
* Searches the assets table by asset tag, and redirects if it finds one
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param string $tag
* @since [v3.0]
* @return Redirect
*/
public function getAssetByTag(Request $request, $tag = null)
public function getAssetByTag(Request $request)
{
$topsearch = ($request->get('topsearch')=="true");
// We need this part to determine whether a url query parameter has been passed, OR
// whether it's the url fragment we need to look at
$tag = ($request->get('assetTag')) ? $request->get('assetTag') : $tag;
if (!$asset = Asset::where('asset_tag', '=', $tag)->first()) {
if (!$asset = Asset::where('asset_tag', '=', $request->get('assetTag'))->first()) {
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
}
$this->authorize('view', $asset);
return redirect()->route('hardware.show', $asset->id)->with('topsearch', $topsearch);
}
/**
* Searches the assets table by serial, and redirects if it finds one
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param string $serial
* @since [v4.9.1]
* @return Redirect
*/
public function getAssetBySerial(Request $request, $serial = null)
{
$serial = ($request->get('serial')) ? $request->get('serial') : $serial;
if (!$asset = Asset::where('serial', '=', $serial)->first()) {
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
}
$this->authorize('view', $asset);
return redirect()->route('hardware.show', $asset->id);
}
/**
* Return a QR code for the asset
*
@@ -547,7 +499,6 @@ class AssetsController extends Controller
$barcode_file = public_path().'/uploads/barcodes/'.str_slug($settings->alt_barcode).'-'.str_slug($asset->asset_tag).'.png';
if (isset($asset->id, $asset->asset_tag)) {
if (file_exists($barcode_file)) {
$header = ['Content-type' => 'image/png'];
return response()->file($barcode_file, $header);
@@ -556,22 +507,10 @@ class AssetsController extends Controller
$barcode_width = ($settings->labels_width - $settings->labels_display_sgutter) * 96.000000000001;
$barcode = new \Com\Tecnick\Barcode\Barcode();
$barcode_obj = $barcode->getBarcodeObj($settings->alt_barcode,$asset->asset_tag,($barcode_width < 300 ? $barcode_width : 300),50);
try {
$barcode_obj = $barcode->getBarcodeObj($settings->alt_barcode,$asset->asset_tag,($barcode_width < 300 ? $barcode_width : 300),50);
file_put_contents($barcode_file, $barcode_obj->getPngData());
return response($barcode_obj->getPngData())->header('Content-type', 'image/png');
} catch (\Exception $e) {
\Log::debug('Error creating barcode: '.$e->getMessage());
\Log::debug('This usually happens because the asset tags are of a format that is not compatible with the selected barcode type.');
$img = file_get_contents(public_path().'/uploads/barcodes/invalid_barcode.gif');
return response($img)->header('Content-type', 'image/gif');
}
file_put_contents($barcode_file, $barcode_obj->getPngData());
return response($barcode_obj->getPngData())->header('Content-type', 'image/png');
}
}
}
@@ -631,17 +570,15 @@ class AssetsController extends Controller
*/
public function postImportHistory(Request $request)
{
if (!$request->hasFile('user_import_csv')) {
return back()->with('error', 'No file provided. Please select a file for import and try again. ');
}
if (!ini_get("auto_detect_line_endings")) {
ini_set("auto_detect_line_endings", '1');
}
$csv = Reader::createFromPath(Input::file('user_import_csv'));
$csv->setHeaderOffset(0);
$csv->setNewline("\r\n");
//get the first row, usually the CSV header
//$headers = $csv->fetchOne();
$results = $csv->getRecords();
$item = array();
$status = array();
@@ -658,9 +595,7 @@ class AssetsController extends Controller
}
$batch_counter = count($item[$asset_tag]);
$item[$asset_tag][$batch_counter]['checkout_date'] = Carbon::parse(Helper::array_smart_fetch($row, "checkout date"))->format('Y-m-d H:i:s');
$item[$asset_tag][$batch_counter]['checkin_date'] = Carbon::parse(Helper::array_smart_fetch($row, "checkin date"))->format('Y-m-d H:i:s');
\Log::debug($item[$asset_tag][$batch_counter]['checkin_date']);
$item[$asset_tag][$batch_counter]['checkout_date'] = Carbon::parse(Helper::array_smart_fetch($row, "date"))->format('Y-m-d H:i:s');
$item[$asset_tag][$batch_counter]['asset_tag'] = Helper::array_smart_fetch($row, "asset tag");
$item[$asset_tag][$batch_counter]['name'] = Helper::array_smart_fetch($row, "name");
@@ -743,11 +678,9 @@ class AssetsController extends Controller
// Only do this if a matching user was found
if ((array_key_exists('checkedout_to', $asset_batch[$x])) && ($asset_batch[$x]['checkedout_to']!='')) {
if (($total_in_batch > 1) && ($x < $total_in_batch) && (array_key_exists($next, $asset_batch))) {
$checkin_date = Carbon::parse($asset_batch[$next]['checkin_date'])->format('Y-m-d H:i:s');
$checkin_date = Carbon::parse($asset_batch[$next]['checkout_date'])->subDay(1)->format('Y-m-d H:i:s');
$asset_batch[$x]['real_checkin'] = $checkin_date;
\Log::debug($asset_batch[$next]['checkin_date']);
\Log::debug($checkin_date);
Actionlog::firstOrCreate(array(
'item_id' => $asset_batch[$x]['asset_id'],
'item_type' => Asset::class,

View File

@@ -5,7 +5,6 @@ namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class ForgotPasswordController extends Controller
{
@@ -42,8 +41,6 @@ class ForgotPasswordController extends Controller
return property_exists($this, 'subject') ? $this->subject : \Lang::get('mail.reset_link');
}
/**
* Send a reset link to the given user.
*
@@ -52,21 +49,11 @@ class ForgotPasswordController extends Controller
*/
public function sendResetLinkEmail(Request $request)
{
$this->validate($request, ['email' => 'required|email']);
/**
* Let's set a max character count here to prevent potential
* buffer overflow issues with attackers sending very large
* payloads through.
*/
$this->validate($request, ['email' => 'required|email|max:250']);
/**
* If we find a matching email with an activated user, we will
* send the password reset link to the user.
*
* Once we have attempted to send the link, we will examine the response
* then see the message we need to show to the user. Finally, we'll send out a proper response.
*/
// We will send the password reset link to this user. Once we have attempted
// to send the link, we will examine the response then see the message we
// need to show to the user. Finally, we'll send out a proper response.
$response = $this->broker()->sendResetLink(
array_merge(
$request->only('email'),
@@ -78,25 +65,9 @@ class ForgotPasswordController extends Controller
return redirect()->route('login')->with('status', trans($response));
}
/**
* If an error was returned by the password broker, we will get this message
* translated so we can notify a user of the problem. We'll redirect back
* to where the users came from so they can attempt this process again.
*
* HOWEVER, we do not want to translate the message if the user isn't found
* or isn't active, since that would allow an attacker to walk through
* a dictionary attack and figure out registered user email addresses.
*
* Instead we tell the user we've sent an email even though we haven't.
* It's bad UX, but better security. The compromises we sometimes have to make.
*/
if ($response == 'passwords.user') {
\Log::debug('User with email '.$request->input('email').' attempted a password reset request but was not found. No email was sent.');
return redirect()->route('login')->with('success', trans('passwords.user_inactive'));
}
// If an error was returned by the password broker, we will get this message
// translated so we can notify a user of the problem. We'll redirect back
// to where the users came from so they can attempt this process again.
return back()->withErrors(
['email' => trans($response)]
);

View File

@@ -303,8 +303,8 @@ class LoginController extends Controller
*/
public function logout(Request $request)
{
$request->session()->forget('2fa_authed');
$request->session()->regenerate(true);
Auth::logout();
$settings = Setting::getSettings();

View File

@@ -83,7 +83,17 @@ class CategoriesController extends Controller
$category->checkin_email = $request->input('checkin_email', '0');
$category->user_id = Auth::id();
$category = $request->handleImages($category,600, public_path().'/uploads/categories');
if ($request->file('image')) {
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/categories/'.$file_name);
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
$category->image = $file_name;
}
if ($category->save()) {
return redirect()->route('categories.index')->with('success', trans('admin/categories/message.create.success'));
@@ -142,12 +152,37 @@ class CategoriesController extends Controller
$category->require_acceptance = $request->input('require_acceptance', '0');
$category->checkin_email = $request->input('checkin_email', '0');
$old_image = $category->image;
// Set the model's image property to null if the image is being deleted
if ($request->input('image_delete') == 1) {
$category->image = null;
}
$category = $request->handleImages($category,600, public_path().'/uploads/categories');
if ($request->file('image')) {
$image = $request->file('image');
$file_name = $category->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save(app('categories_upload_path').$file_name);
} else {
$image->move(app('categories_upload_path'), $file_name);
}
$category->image = $file_name;
}
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
try {
unlink(app('categories_upload_path').$old_image);
} catch (\Exception $e) {
\Log::info($e);
}
}
if ($category->save()) {
// Redirect to the new category page
@@ -219,7 +254,10 @@ class CategoriesController extends Controller
->with('category_type_route',$category_type_route);
}
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.does_not_exist'));
// Prepare the error message
$error = trans('admin/categories/message.does_not_exist', compact('id'));
// Redirect to the user management page
return redirect()->route('categories.index')->with('error', $error);
}

View File

@@ -63,7 +63,16 @@ final class CompaniesController extends Controller
$company = new Company;
$company->name = $request->input('name');
$company = $request->handleImages($company,600, public_path().'/uploads/companies');
if ($request->file('image')) {
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/companies/'.$file_name);
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
$company->image = $file_name;
}
if ($company->save()) {
return redirect()->route('companies.index')
@@ -112,12 +121,36 @@ final class CompaniesController extends Controller
$company->name = $request->input('name');
$old_image = $company->image;
// Set the model's image property to null if the image is being deleted
if ($request->input('image_delete') == 1) {
$company->image = null;
}
$company = $request->handleImages($company,600, public_path().'/uploads/companies');
if ($request->file('image')) {
$image = $request->file('image');
$file_name = $company->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save(app('companies_upload_path').$file_name);
} else {
$image->move(app('companies_upload_path'), $file_name);
}
$company->image = $file_name;
}
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
try {
unlink(app('companies_upload_path').$old_image);
} catch (\Exception $e) {
\Log::info($e);
}
}
if ($company->save()) {

View File

@@ -91,7 +91,16 @@ class ComponentsController extends Controller
$component->user_id = Auth::id();
$component = $request->handleImages($component,600, public_path().'/uploads/components');
if ($request->file('image')) {
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/components/'.$file_name);
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
$component->image = $file_name;
}
if ($component->save()) {
return redirect()->route('components.index')->with('success', trans('admin/components/message.create.success'));
@@ -155,7 +164,18 @@ class ComponentsController extends Controller
$component->purchase_cost = request('purchase_cost');
$component->qty = Input::get('qty');
$component = $request->handleImages($component,600, public_path().'/uploads/components');
if ($request->file('image')) {
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/components/'.$file_name);
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
$component->image = $file_name;
} elseif ($request->input('image_delete')=='1') {
$component->image = null;
}
if ($component->save()) {
return redirect()->route('components.index')->with('success', trans('admin/components/message.update.success'));
@@ -199,8 +219,10 @@ class ComponentsController extends Controller
$this->authorize('view', $component);
return view('components/view', compact('component'));
}
return redirect()->route('components.index')->with('error', trans('admin/components/message.does_not_exist'));
// Prepare the error message
$error = trans('admin/components/message.does_not_exist', compact('id'));
// Redirect to the user management page
return redirect()->route('components.index')->with('error', $error);
}
/**

View File

@@ -87,8 +87,16 @@ class ConsumablesController extends Controller
$consumable->user_id = Auth::id();
$consumable = $request->handleImages($consumable,600, public_path().'/uploads/components');
if ($request->file('image')) {
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/consumables/'.$file_name);
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
$consumable->image = $file_name;
}
if ($consumable->save()) {
return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.create.success'));
@@ -204,7 +212,7 @@ class ConsumablesController extends Controller
if (isset($consumable->id)) {
return view('consumables/view', compact('consumable'));
}
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist'));
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist', compact('id')));
}
/**

View File

@@ -179,59 +179,14 @@ class CustomFieldsetsController extends Controller
$this->authorize('update', $set);
if ($request->filled('field_id')) {
foreach ($set->fields as $field) {
if ($field->id == $request->input('field_id')) {
return redirect()->route("fieldsets.show", [$id])->withInput()->withErrors(['field_id' => trans('admin/custom_fields/message.field.already_added')]);
}
foreach ($set->fields as $field) {
if ($field->id == $request->input('field_id')) {
return redirect()->route("fieldsets.show", [$id])->withInput()->withErrors(['field_id' => trans('admin/custom_fields/message.field.already_added')]);
}
$results = $set->fields()->attach(Input::get('field_id'), ["required" => ($request->input('required') == "on"),"order" => $request->input('order', 1)]);
return redirect()->route("fieldsets.show", [$id])->with("success", trans('admin/custom_fields/message.field.create.assoc_success'));
}
return redirect()->route("fieldsets.show", [$id])->with("error", 'No field selected.');
$results = $set->fields()->attach(Input::get('field_id'), ["required" => ($request->input('required') == "on"),"order" => $request->input('order', 1)]);
return redirect()->route("fieldsets.show", [$id])->with("success", trans('admin/custom_fields/message.field.create.assoc_success'));
}
/**
* Set the field in a fieldset to required
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v5.0]
*/
public function makeFieldRequired($fieldset_id, $field_id)
{
$this->authorize('update', CustomFieldset::class);
$field = CustomField::findOrFail($field_id);
$fieldset = CustomFieldset::findOrFail($fieldset_id);
$fields[$field->id] = ['required' => 1];
$fieldset->fields()->syncWithoutDetaching($fields);
return redirect()->route('fieldsets.show', ['fieldset' => $fieldset_id])
->with("success", trans('Field successfully set to required'));
}
/**
* Set the field in a fieldset to optional
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v5.0]
*/
public function makeFieldOptional($fieldset_id, $field_id)
{
$this->authorize('update', CustomFieldset::class);
$field = CustomField::findOrFail($field_id);
$fieldset = CustomFieldset::findOrFail($fieldset_id);
$fields[$field->id] = ['required' => 0];
$fieldset->fields()->syncWithoutDetaching($fields);
return redirect()->route('fieldsets.show', ['fieldset' => $fieldset_id])
->with("success", trans('Field successfully set to optional'));
}
}

View File

@@ -53,7 +53,16 @@ class DepartmentsController extends Controller
$department->user_id = Auth::user()->id;
$department->manager_id = ($request->filled('manager_id' ) ? $request->input('manager_id') : null);
$department = $request->handleImages($department,600, public_path().'/uploads/departments');
if ($request->file('image')) {
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/departments/'.$file_name);
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
$department->image = $file_name;
}
if ($department->save()) {
return redirect()->route("departments.index")->with('success', trans('admin/departments/message.create.success'));
@@ -79,7 +88,7 @@ class DepartmentsController extends Controller
if (isset($department->id)) {
return view('departments/view', compact('department'));
}
return redirect()->route('departments.index')->with('error', trans('admin/departments/message.does_not_exist'));
return redirect()->route('departments.index')->with('error', trans('admin/departments/message.does_not_exist', compact('id')));
}
@@ -155,7 +164,36 @@ class DepartmentsController extends Controller
$department->fill($request->all());
$department->manager_id = ($request->filled('manager_id' ) ? $request->input('manager_id') : null);
$department = $request->handleImages($department,600, public_path().'/uploads/departments');
$old_image = $department->image;
// Set the model's image property to null if the image is being deleted
if ($request->input('image_delete') == 1) {
$department->image = null;
}
if ($request->file('image')) {
$image = $request->file('image');
$file_name = $department->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save(app('departments_upload_path').$file_name);
} else {
$image->move(app('departments_upload_path'), $file_name);
}
$department->image = $file_name;
}
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
try {
unlink(app('departments_upload_path').$old_image);
} catch (\Exception $e) {
\Log::info($e);
}
}
if ($department->save()) {
return redirect()->route("departments.index")->with('success', trans('admin/departments/message.update.success'));

View File

@@ -246,23 +246,17 @@ class LicensesController extends Controller
*/
public function getCheckout($licenceId)
{
// Check that the license is valid
if ($license = License::where('id',$licenceId)->first()) {
$this->authorize('checkout', $license);
// If the license is valid, check that there is an available seat
if ($license->getAvailSeatsCountAttribute() < 1) {
return redirect()->route('licenses.index')->with('error', 'There are no available seats for this license');
}
return view('licenses/checkout', compact('license'));
}
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist'));
$this->authorize('checkout', $license);
return view('licenses/checkout', compact('license'));
}
@@ -461,7 +455,7 @@ class LicensesController extends Controller
$this->authorize('view', $license);
return view('licenses/view', compact('license'));
}
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist'));
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist', compact('id')));
}
@@ -530,8 +524,9 @@ class LicensesController extends Controller
}
return redirect()->route('licenses.show', $license->id)->with('error', trans('admin/licenses/message.upload.nofiles'));
}
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist'));
// Prepare the error message
$error = trans('admin/licenses/message.does_not_exist', compact('id'));
return redirect()->route('licenses.index')->with('error', $error);
}
@@ -567,7 +562,7 @@ class LicensesController extends Controller
}
// Redirect to the licence management page
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist'));
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist', compact('id')));
}
@@ -618,7 +613,7 @@ class LicensesController extends Controller
}
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist'));
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist', compact('id')));
}

View File

@@ -41,6 +41,8 @@ class LocationsController extends Controller
{
// Grab all the locations
$this->authorize('view', Location::class);
$locations = Location::orderBy('created_at', 'DESC')->with('parent', 'assets', 'assignedassets')->get();
// Show the page
return view('locations/index');
}
@@ -57,7 +59,14 @@ class LocationsController extends Controller
public function create()
{
$this->authorize('create', Location::class);
$locations = Location::orderBy('name', 'ASC')->get();
$location_options_array = Location::getLocationHierarchy($locations);
$location_options = Location::flattenLocationsArray($location_options_array);
$location_options = array('' => 'Top Level') + $location_options;
return view('locations/edit')
->with('location_options', $location_options)
->with('item', new Location);
}
@@ -88,7 +97,16 @@ class LocationsController extends Controller
$location->manager_id = $request->input('manager_id');
$location->user_id = Auth::id();
$location = $request->handleImages($location,600, public_path().'/uploads/locations');
if ($request->file('image')) {
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/locations/'.$file_name);
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
$location->image = $file_name;
}
if ($location->save()) {
return redirect()->route("locations.index")->with('success', trans('admin/locations/message.create.success'));
@@ -114,8 +132,14 @@ class LocationsController extends Controller
return redirect()->route('locations.index')->with('error', trans('admin/locations/message.does_not_exist'));
}
// Show the page
$locations = Location::orderBy('name', 'ASC')->get();
$location_options_array = Location::getLocationHierarchy($locations);
$location_options = Location::flattenLocationsArray($location_options_array);
$location_options = array('' => 'Top Level') + $location_options;
return view('locations/edit', compact('item'));
return view('locations/edit', compact('item'))
->with('location_options', $location_options);
}
@@ -136,11 +160,6 @@ class LocationsController extends Controller
return redirect()->route('locations.index')->with('error', trans('admin/locations/message.does_not_exist'));
}
if ($request->input('parent_id') == $locationId) {
return redirect()->back()->withInput()->with('error', 'A location cannot be its own parent. Please select a different parent location.');
}
// Update the location data
$location->name = $request->input('name');
$location->parent_id = $request->input('parent_id', null);
@@ -153,7 +172,37 @@ class LocationsController extends Controller
$location->zip = $request->input('zip');
$location->ldap_ou = $request->input('ldap_ou');
$location->manager_id = $request->input('manager_id');
$location = $request->handleImages($location,600, public_path().'/uploads/locations');
$old_image = $location->image;
// Set the model's image property to null if the image is being deleted
if ($request->input('image_delete') == 1) {
$location->image = null;
}
if ($request->file('image')) {
$image = $request->file('image');
$file_name = $location->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save(app('locations_upload_path').$file_name);
} else {
$image->move(app('locations_upload_path'), $file_name);
}
$location->image = $file_name;
}
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
try {
unlink(app('locations_upload_path').$old_image);
} catch (\Exception $e) {
\Log::info($e);
}
}
if ($location->save()) {
@@ -180,7 +229,7 @@ class LocationsController extends Controller
if ($location->users->count() > 0) {
return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.assoc_users'));
} elseif ($location->children->count() > 0) {
} elseif ($location->childLocations->count() > 0) {
return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.assoc_child_loc'));
} elseif ($location->assets->count() > 0) {
@@ -213,7 +262,7 @@ class LocationsController extends Controller
return view('locations/view', compact('location'));
}
return redirect()->route('locations.index')->with('error', trans('admin/locations/message.does_not_exist'));
return redirect()->route('locations.index')->with('error', trans('admin/locations/message.does_not_exist', compact('id')));
}
}

View File

@@ -75,7 +75,18 @@ class ManufacturersController extends Controller
$manufacturer->support_url = $request->input('support_url');
$manufacturer->support_phone = $request->input('support_phone');
$manufacturer->support_email = $request->input('support_email');
$manufacturer = $request->handleImages($manufacturer,600, public_path().'/uploads/manufacturers');
if ($request->file('image')) {
$image = $request->file('image');
$file_name = str_slug($image->getClientOriginalName()).".".$image->getClientOriginalExtension();
$path = public_path('uploads/manufacturers/'.$file_name);
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
$manufacturer->image = $file_name;
}
@@ -96,14 +107,11 @@ class ManufacturersController extends Controller
*/
public function edit($id = null)
{
// Handles manufacturer checks and permissions.
$this->authorize('update', Manufacturer::class);
$this->authorize('edit', Manufacturer::class);
// Check if the manufacturer exists
if (!$item = Manufacturer::find($id)) {
if (is_null($item = Manufacturer::find($id))) {
return redirect()->route('manufacturers.index')->with('error', trans('admin/manufacturers/message.does_not_exist'));
}
// Show the page
return view('manufacturers/edit', compact('item'));
}
@@ -121,7 +129,7 @@ class ManufacturersController extends Controller
*/
public function update(ImageUploadRequest $request, $manufacturerId = null)
{
$this->authorize('update', Manufacturer::class);
$this->authorize('edit', Manufacturer::class);
// Check if the manufacturer exists
if (is_null($manufacturer = Manufacturer::find($manufacturerId))) {
// Redirect to the manufacturer page
@@ -134,14 +142,37 @@ class ManufacturersController extends Controller
$manufacturer->support_url = $request->input('support_url');
$manufacturer->support_phone = $request->input('support_phone');
$manufacturer->support_email = $request->input('support_email');
$old_image = $manufacturer->image;
// Set the model's image property to null if the image is being deleted
if ($request->input('image_delete') == 1) {
$manufacturer->image = null;
}
$manufacturer = $request->handleImages($manufacturer,600, public_path().'/uploads/manufacturers');
if ($request->file('image')) {
$image = $request->file('image');
$file_name = $manufacturer->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save(app('manufacturers_upload_path').$file_name);
} else {
$image->move(app('manufacturers_upload_path'), $file_name);
}
$manufacturer->image = $file_name;
}
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
try {
unlink(app('manufacturers_upload_path').$old_image);
} catch (\Exception $e) {
\Log::info($e);
}
}
if ($manufacturer->save()) {

View File

@@ -307,18 +307,12 @@ class ReportsController extends Controller
public function postCustom(Request $request)
{
ini_set('max_execution_time', 12000);
\Debugbar::disable();
$customfields = CustomField::get();
$response = new StreamedResponse(function () use ($customfields, $request) {
\Log::debug('Starting streamed response');
// Open output stream
$handle = fopen('php://output', 'w');
stream_set_timeout($handle, 2000);
if ($request->filled('use_bom')) {
fprintf($handle, chr(0xEF) . chr(0xBB) . chr(0xBF));
@@ -470,12 +464,8 @@ class ReportsController extends Controller
}
}
$executionTime = microtime(true) - $_SERVER["REQUEST_TIME_FLOAT"];
\Log::debug('Starting headers: '.$executionTime);
fputcsv($handle, $header);
$executionTime = microtime(true) - $_SERVER["REQUEST_TIME_FLOAT"];
\Log::debug('Added headers: '.$executionTime);
fputcsv($handle, $header);
$assets = \App\Models\Company::scopeCompanyables(Asset::select('assets.*'))->with(
'location', 'assetstatus', 'assetlog', 'company', 'defaultLoc','assignedTo',
@@ -530,13 +520,9 @@ class ReportsController extends Controller
$assets->whereBetween('assets.expected_checkin', [$request->input('expected_checkin_start'), $request->input('expected_checkin_end')]);
}
$assets->orderBy('assets.created_at', 'ASC')->chunk(20, function($assets) use($handle, $customfields, $request) {
$assets->orderBy('assets.created_at', 'ASC')->chunk(500, function($assets) use($handle, $customfields, $request) {
$executionTime = microtime(true) - $_SERVER["REQUEST_TIME_FLOAT"];
\Log::debug('Walking results: '.$executionTime);
$count = 0;
foreach ($assets as $asset) {
$count++;
$row = [];
if ($request->filled('company')) {
@@ -709,24 +695,17 @@ class ReportsController extends Controller
}
}
fputcsv($handle, $row);
$executionTime = microtime(true) - $_SERVER["REQUEST_TIME_FLOAT"];
\Log::debug('-- Record '.$count.' Asset ID:' .$asset->id. ' in '. $executionTime);
}
});
// Close the output stream
fclose($handle);
$executionTime = microtime(true) - $_SERVER["REQUEST_TIME_FLOAT"];
\Log::debug('-- SCRIPT COMPLETED IN '. $executionTime);
}, 200, [
'Content-Type' => 'text/csv',
'Content-Disposition'
=> 'attachment; filename="custom-assets-report-'.date('Y-m-d-his').'.csv"',
]);
return $response;

View File

@@ -1,7 +1,6 @@
<?php
namespace App\Http\Controllers;
use enshrined\svgSanitize\Sanitizer;
use Input;
use Lang;
use Illuminate\Http\Request;
@@ -427,23 +426,12 @@ class SettingsController extends Controller
$file_name = "logo.".$image->getClientOriginalExtension();
$path = public_path('uploads');
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(null, 150, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path.'/'.$file_name);
} else {
// This is kinda copypasta from the ImageUploadRequest - should refactor the ImageUploadRequest to better handle maybe
$sanitizer = new Sanitizer();
$dirtySVG = file_get_contents($image->getRealPath());
$cleanSVG = $sanitizer->sanitize($dirtySVG);
try {
file_put_contents($path.'/'.$file_name, $cleanSVG);
} catch (\Exception $e) {
\Log::debug($e);
}
$image->move($path, $file_name);
}
$setting->logo = $file_name;
}
@@ -645,24 +633,14 @@ class SettingsController extends Controller
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
}
$validatedData = $request->validate([
'slack_endpoint' => 'url|required_with:slack_channel|nullable',
'slack_channel' => 'regex:/(?<!\w)#\w+/|required_with:slack_endpoint|nullable',
'slack_botname' => 'string|nullable',
]);
$setting->slack_endpoint = $request->input('slack_endpoint');
$setting->slack_channel = $request->input('slack_channel');
$setting->slack_botname = $request->input('slack_botname');
if ($validatedData) {
$setting->slack_endpoint = $request->input('slack_endpoint');
$setting->slack_channel = $request->input('slack_channel');
$setting->slack_botname = $request->input('slack_botname');
$setting->save();
if ($setting->save()) {
return redirect()->route('settings.index')
->with('success', trans('admin/settings/message.update.success'));
}
return redirect()->back()->withInput()->withErrors($setting->getErrors());
}

View File

@@ -43,7 +43,7 @@ class StatuslabelsController extends Controller
return view('statuslabels.view')->with('statuslabel', $statuslabel);
}
return redirect()->route('statuslabels.index')->with('error', trans('admin/statuslabels/message.does_not_exist'));
return redirect()->route('statuslabels.index')->with('error', trans('admin/statuslabels/message.does_not_exist', compact('id')));
}

View File

@@ -78,8 +78,17 @@ class SuppliersController extends Controller
$supplier->notes = request('notes');
$supplier->url = $supplier->addhttp(request('url'));
$supplier->user_id = Auth::id();
$supplier = $request->handleImages($supplier,600, public_path().'/uploads/suppliers');
if ($request->file('image')) {
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/suppliers/'.$file_name);
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
$supplier->image = $file_name;
}
if ($supplier->save()) {
return redirect()->route('suppliers.index')->with('success', trans('admin/suppliers/message.create.success'));
@@ -136,7 +145,39 @@ class SuppliersController extends Controller
$supplier->email = request('email');
$supplier->url = $supplier->addhttp(request('url'));
$supplier->notes = request('notes');
$supplier = $request->handleImages($supplier,600, public_path().'/uploads/suppliers');
$old_image = $supplier->image;
// Set the model's image property to null if the image is being deleted
if ($request->input('image_delete') == 1) {
$supplier->image = null;
}
if ($request->file('image')) {
$image = $request->file('image');
$file_name = $supplier->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save(app('suppliers_upload_path').$file_name);
} else {
$image->move(app('suppliers_upload_path'), $file_name);
}
$supplier->image = $file_name;
}
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
try {
unlink(app('suppliers_upload_path').$old_image);
} catch (\Exception $e) {
\Log::info($e);
}
}
if ($supplier->save()) {
return redirect()->route('suppliers.index')->with('success', trans('admin/suppliers/message.update.success'));
@@ -195,8 +236,11 @@ class SuppliersController extends Controller
if (isset($supplier->id)) {
return view('suppliers/view', compact('supplier'));
}
// Prepare the error message
$error = trans('admin/suppliers/message.does_not_exist', compact('id'));
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.does_not_exist'));
// Redirect to the user management page
return redirect()->route('suppliers.index')->with('error', $error);
}
}

View File

@@ -240,12 +240,6 @@ class UsersController extends Controller
if ($user->id == $request->input('manager_id')) {
return redirect()->back()->withInput()->with('error', 'You cannot be your own manager.');
}
// If the user isn't a superuser, don't let them edit their own permissions
if ((!Auth::user()->isSuperUser()) && ($user->id == Auth::user()->id)) {
return redirect()->back()->withInput()->with('error', 'You cannot edit your own permissions. Please contact an administrator.');
}
$this->authorize('update', $user);
// Figure out of this user was an admin before this edit
$orig_permissions_array = $user->decodePermissions();
@@ -612,12 +606,10 @@ class UsersController extends Controller
*/
public function show($userId = null)
{
if (!$user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')
->withTrashed()
->find($userId))
{
return redirect()->route('users.index')->with('error', trans('admin/users/message.user_not_found', ['id' => $userId]));
if(!$user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find($userId)) {
$error = trans('admin/users/message.user_not_found', compact('id'));
// Redirect to the user management page
return redirect()->route('users.index')->with('error', $error);
}
$userlog = $user->userlog->load('item');
@@ -714,8 +706,10 @@ class UsersController extends Controller
->with('userGroups', $userGroups)
->with('clone_user', $user_to_clone);
} catch (UserNotFoundException $e) {
return redirect()->route('users.index')->with('error', trans('admin/users/message.user_not_found'));
// Prepare the error message
$error = trans('admin/users/message.user_not_found', compact('id'));
// Redirect to the user management page
return redirect()->route('users.index')->with('error', $error);
}
}
@@ -737,38 +731,30 @@ class UsersController extends Controller
if (isset($user->id)) {
$this->authorize('update', $user);
if (!$request->has('file')) {
\Log::debug('No file selected: ');
\Log::debug(print_r($request, true));
return redirect()->back()->with('error', 'No file submitted.');
foreach (Input::file('file') as $file) {
} else {
foreach ($request->file('file') as $file) {
$extension = $file->getClientOriginalExtension();
$filename = 'user-' . $user->id . '-' . str_random(8);
$filename .= '-' . str_slug($file->getClientOriginalName()) . '.' . $extension;
$upload_success = $file->move($destinationPath, $filename);
$extension = $file->getClientOriginalExtension();
$filename = 'user-' . $user->id . '-' . str_random(8);
$filename .= '-' . str_slug($file->getClientOriginalName()) . '.' . $extension;
$upload_success = $file->move($destinationPath, $filename);
//Log the uploaded file to the log
$logAction = new Actionlog();
$logAction->item_id = $user->id;
$logAction->item_type = User::class;
$logAction->user_id = Auth::user()->id;
$logAction->note = e(Input::get('notes'));
$logAction->target_id = null;
$logAction->created_at = date("Y-m-d H:i:s");
$logAction->filename = $filename;
$logAction->action_type = 'uploaded';
$logAction->save();
//Log the uploaded file to the log
$logAction = new Actionlog();
$logAction->item_id = $user->id;
$logAction->item_type = User::class;
$logAction->target_type = User::class;
$logAction->target_id = $user->id;
$logAction->user_id = Auth::user()->id;
$logAction->note = $request->input('notes');
$logAction->created_at = date("Y-m-d H:i:s");
$logAction->filename = $filename;
$logAction->action_type = 'uploaded';
$logAction->save();
}
return redirect()->back()->with('success', 'File uploaded');
}
return JsonResponse::create($logAction);
}
return redirect()->route('users.index')->with('error', 'Error uploading files');
return JsonResponse::create(["error" => "Failed validation: ".print_r($logAction->getErrors(), true)], 500);
}
@@ -796,8 +782,10 @@ class UsersController extends Controller
$log->delete();
return redirect()->back()->with('success', trans('admin/users/message.deletefile.success'));
}
return redirect()->route('users.index')->with('error', trans('admin/users/message.does_not_exist'));
// Prepare the error message
$error = trans('admin/users/message.does_not_exist', compact('id'));
// Redirect to the licence management page
return redirect()->route('users.index')->with('error', $error);
}

View File

@@ -17,12 +17,15 @@ class Kernel extends HttpKernel
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\FrameGuard::class,
\App\Http\Middleware\XssProtectHeader::class,
\App\Http\Middleware\ReferrerPolicyHeader::class,
\App\Http\Middleware\ContentSecurityPolicyHeader::class,
\App\Http\Middleware\NosniffGuard::class,
\Fideloper\Proxy\TrustProxies::class,
\App\Http\Middleware\CheckForSetup::class,
\App\Http\Middleware\CheckForDebug::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\App\Http\Middleware\SecurityHeaders::class,
];
/**

View File

@@ -0,0 +1,35 @@
<?php
namespace App\Http\Middleware;
use Closure;
class ContentSecurityPolicyHeader
{
/**
* Handle the given request and get the response.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return \Illuminate\Http\Response
*/
public function handle($request, Closure $next)
{
if ((config('app.debug')=='true') || (config('app.enable_csp')!='true')) {
$response = $next($request);
return $response;
}
$policy[] = "default-src 'self'";
$policy[] = "style-src 'self' 'unsafe-inline' oss.maxcdn.com";
$policy[] = "script-src 'self' 'unsafe-inline' oss.mafxcdn.com cdnjs.cloudflare.com'";
$policy[] = "connect-src 'self'";
$policy[] = "object-src 'none'";
$policy[] = "font-src 'self' data:";
$policy[] = "img-src 'self' data: gravatar.com";
$policy = join(';', $policy);
$response = $next($request);
$response->headers->set('Content-Security-Policy', $policy);
return $response;
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace App\Http\Middleware;
use Closure;
class FrameGuard
{
/**
* Handle the given request and get the response.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return \Illuminate\Http\Response
*/
public function handle($request, Closure $next)
{
$response = $next($request);
if (config('app.allow_iframing') == false) {
$response->headers->set('X-Frame-Options', 'SAMEORIGIN', false);
}
return $response;
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace App\Http\Middleware;
use Closure;
class NosniffGuard
{
/**
* Handle the given request and get the response.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return \Illuminate\Http\Response
*/
public function handle($request, Closure $next)
{
$response = $next($request);
$response->headers->set('X-Content-Type-Options', 'nosniff', false);
return $response;
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace App\Http\Middleware;
use Closure;
class ReferrerPolicyHeader
{
/**
* Handle the given request and get the response.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return \Illuminate\Http\Response
*/
public function handle($request, Closure $next)
{
$response = $next($request);
$response->headers->set('Referrer-Policy', config('app.referrer_policy'));
return $response;
}
}

View File

@@ -1,122 +0,0 @@
<?php
namespace App\Http\Middleware;
use Closure;
class SecurityHeaders
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
// See https://securityheaders.com/
private $unwantedHeaderList = [
'X-Powered-By',
'Server',
];
public function handle($request, Closure $next)
{
$this->removeUnwantedHeaders($this->unwantedHeaderList);
$response = $next($request);
$response->headers->set('X-Content-Type-Options', 'nosniff');
$response->headers->set('X-XSS-Protection', '1; mode=block');
// Ugh. Feature-Policy is dumb and clumsy and mostly irrelevant for Snipe-IT,
// since we don't provide any way to IFRAME anything in in the first place.
// There is currently no easy way to default ALL THE THINGS to 'none', but
// security audits will still ding you if you don't have this header, even
// though we don't allow IFRAMING in the first place.
//
// So for security and compliance sake, here we are. Sigh.
//
// See also:
// - https://developers.google.com/web/updates/2018/06/feature-policy
// - https://scotthelme.co.uk/a-new-security-header-feature-policy/
// - https://github.com/w3c/webappsec-feature-policy/issues/189
$feature_policy[] = "accelerometer 'none'";
$feature_policy[] = "ambient-light-sensor 'none'";
$feature_policy[] = "animations 'none'";
$feature_policy[] = "autoplay 'none'";
$feature_policy[] = "battery 'none'";
$feature_policy[] = "camera 'none'";
$feature_policy[] = "display-capture 'none'";
$feature_policy[] = "document-domain 'none'";
$feature_policy[] = "encrypted-media 'none'";
$feature_policy[] = "fullscreen 'none'";
$feature_policy[] = "geolocation 'none'";
$feature_policy[] = "gyroscope 'none'";
$feature_policy[] = "legacy-image-formats 'none'";
$feature_policy[] = "magnetometer 'none'";
$feature_policy[] = "microphone 'none'";
$feature_policy[] = "midi 'none'";
$feature_policy[] = "oversized-images 'none'";
$feature_policy[] = "payment 'none'";
$feature_policy[] = "picture-in-picture 'none'";
$feature_policy[] = "publickey-credentials 'none'";
$feature_policy[] = "sync-xhr 'none'";
$feature_policy[] = "unsized-media 'none'";
$feature_policy[] = "usb 'none'";
$feature_policy[] = "vibrate 'none'";
$feature_policy[] = "wake-lock 'none'";
$feature_policy[] = "xr-spatial-tracking 'none'";
$feature_policy = join(';', $feature_policy);
$response->headers->set('Feature-Policy', $feature_policy);
// Defaults to same-origin if REFERRER_POLICY is not set in the .env
$response->headers->set('Referrer-Policy', config('app.referrer_policy'));
// The .env var ALLOW_IFRAMING defaults to false (which disallows IFRAMING)
// if not present, but some unique cases require this to be enabled.
// For example, some IT depts have IFRAMED Snipe-IT into their IT portal
// for convenience so while it is normally disallowed, there is
// an override that exists.
if (config('app.allow_iframing') == false) {
$response->headers->set('X-Frame-Options', 'DENY');
}
// This defaults to false to maintain backwards compatibility for
// people who are not running Snipe-IT over TLS (shame, shame, shame!)
// Seriously though, please run Snipe-IT over TLS. Let's Encrypt is free.
// https://letsencrypt.org
if (config('app.enable_hsts') === true) {
$response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
}
// We have to exclude debug mode here because debugbar pulls from a CDN or two
// and it will break things.
if ((config('app.debug')!='true') || (config('app.enable_csp')=='true')) {
$csp_policy[] = "default-src 'self'";
$csp_policy[] = "style-src 'self' 'unsafe-inline'";
$csp_policy[] = "script-src 'self' 'unsafe-inline' 'unsafe-eval'";
$csp_policy[] = "connect-src 'self'";
$csp_policy[] = "object-src 'none'";
$csp_policy[] = "font-src 'self' data:";
$csp_policy[] = "img-src 'self' data: gravatar.com";
$csp_policy = join(';', $csp_policy);
$response->headers->set('Content-Security-Policy', $csp_policy);
}
return $response;
}
private function removeUnwantedHeaders($headerList)
{
foreach ($headerList as $header)
header_remove($header);
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace App\Http\Middleware;
use Closure;
class XssProtectHeader
{
/**
* Handle the given request and get the response.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return \Illuminate\Http\Response
*/
public function handle($request, Closure $next)
{
$mode = '1;mode=block';
$response = $next($request);
$response->headers->set('X-XSS-Protection', $mode);
return $response;
}
}

View File

@@ -51,7 +51,7 @@ class AssetRequest extends Request
if ($this->request->get('model_id') != '') {
$model = AssetModel::find($this->request->get('model_id'));
if (($model) && (isset($model->fieldset)) && ($model->fieldset)) {
if (($model) && ($model->fieldset)) {
$rules += $model->fieldset->validation_rules();
}
}

View File

@@ -2,9 +2,7 @@
namespace App\Http\Requests;
use App\Models\SnipeModel;
use Intervention\Image\Facades\Image;
use enshrined\svgSanitize\Sanitizer;
use App\Http\Requests\Request;
class ImageUploadRequest extends Request
{
@@ -35,83 +33,4 @@ class ImageUploadRequest extends Request
{
return $this->redirector->back()->withInput()->withErrors($errors, $this->errorBag);
}
/**
* Handle and store any images attached to request
* @param SnipeModel $item Item the image is associated with
* @param String $path location for uploaded images, defaults to uploads/plural of item type.
* @return SnipeModel Target asset is being checked out to.
*/
public function handleImages($item, $w = 600, $path = null)
{
$type = strtolower(class_basename(get_class($item)));
if (is_null($path)) {
$path = str_plural($type);
}
\Log::debug('Trying to upload to '. $path);
if ($this->hasFile('image')) {
if (!config('app.lock_passwords')) {
if (!is_dir($path)) {
\Log::debug($path.' does not exist');
mkdir($path);
}
$image = $this->file('image');
$ext = $image->getClientOriginalExtension();
$file_name = $type.'-'.str_random(18).'.'.$ext;
\Log::debug('File name will be: '.$file_name);
if ($image->getClientOriginalExtension()!=='svg') {
\Log::debug('Not an SVG - resize');
\Log::debug('Trying to upload to: '.$path.'/'.$file_name);
$upload = Image::make($image->getRealPath())->resize(null, $w, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path.'/'.$file_name);
} else {
\Log::debug('This is an SVG');
$sanitizer = new Sanitizer();
$dirtySVG = file_get_contents($image->getRealPath());
$cleanSVG = $sanitizer->sanitize($dirtySVG);
try {
\Log::debug('Trying to upload to: '.$path.'/'.$file_name);
file_put_contents($path.'/'.$file_name, $cleanSVG);
} catch (\Exception $e) {
\Log::debug($e);
}
}
// Remove Current image if exists
if (($item->image) && (file_exists($path.'/'.$item->image))) {
try {
unlink($path.'/'.$item->image);
} catch (\Exception $e) {
\Log::debug($e);
}
}
$item->image = $file_name;
}
} elseif ($this->input('image_delete')=='1') {
try {
unlink($path.'/'.$item->image);
} catch (\Exception $e) {
\Log::debug($e);
}
$item->image = null;
}
return $item;
}
}
}

View File

@@ -30,49 +30,10 @@ class ActionlogsTransformer
// This is necessary since we can't escape special characters within a JSON object
if (($actionlog->log_meta) && ($actionlog->log_meta!='')) {
$meta_array = json_decode($actionlog->log_meta);
if ($meta_array) {
foreach ($meta_array as $key => $value) {
foreach ($value as $meta_key => $meta_value) {
if (is_array($meta_value)) {
foreach ($meta_value as $meta_value_key => $meta_value_value) {
$clean_meta[$key][$meta_value_key] = e($meta_value_value);
}
} else {
// This object stuff is weird, and is used to make up for the fact that
// older data can get strangely formatted if an asset existed,
// then a new custom field is added, and the asset is saved again.
// It can result in funnily-formatted strings like:
//
// {"_snipeit_right_sized_fault_tolerant_localareanetwo_1":
// {"old":null,"new":{"value":"1579490695972","_snipeit_new_field_2":2,"_snipeit_new_field_3":"Monday, 20 January 2020 2:24:55 PM"}}
// so we have to walk down that next level
if (is_object($meta_value)) {
foreach ($meta_value as $meta_value_key => $meta_value_value) {
if ($meta_value_key == 'value') {
$clean_meta[$key]['old'] = null;
$clean_meta[$key]['new'] = e($meta_value->value);
} else {
$clean_meta[$meta_value_key]['old'] = null;
$clean_meta[$meta_value_key]['new'] = e($meta_value_value);
}
}
} else {
$clean_meta[$key][$meta_key] = e($meta_value);
}
}
}
foreach ($meta_array as $key => $value) {
foreach ($value as $meta_key => $meta_value) {
$clean_meta[$key][$meta_key] = e($meta_value);
}
}
}
@@ -89,7 +50,7 @@ class ActionlogsTransformer
'item' => ($actionlog->item) ? [
'id' => (int) $actionlog->item->id,
'name' => ($actionlog->itemType()=='user') ? $actionlog->filename : e($actionlog->item->getDisplayNameAttribute()),
'name' => e($actionlog->item->getDisplayNameAttribute()),
'type' => e($actionlog->itemType()),
] : null,
'location' => ($actionlog->location) ? [

View File

@@ -5,7 +5,6 @@ use App\Models\AssetMaintenance;
use Gate;
use Illuminate\Database\Eloquent\Collection;
use App\Helpers\Helper;
use App\Models\Asset;
class AssetMaintenancesTransformer
{

View File

@@ -29,14 +29,7 @@ class LicenseSeatsTransformer
'name' => 'Seat '.$seat_count,
'assigned_user' => ($seat->user) ? [
'id' => (int) $seat->user->id,
'name'=> e($seat->user->present()->fullName),
'department'=>
($seat->user->department) ?
[
"id" => (int) $seat->user->department->id,
"name" => e($seat->user->department->name)
] : null
'name'=> e($seat->user->present()->fullName)
] : null,
'assigned_asset' => ($seat->asset) ? [
'id' => (int) $seat->asset->id,

View File

@@ -23,7 +23,7 @@ class LocationsTransformer
if ($location) {
$children_arr = [];
foreach($location->children as $child) {
foreach($location->childLocations as $child) {
$children_arr[] = [
'id' => (int) $child->id,
'name' => $child->name

View File

@@ -27,17 +27,9 @@ class AssetImporter extends ItemImporter
foreach ($this->customFields as $customField) {
$customFieldValue = $this->array_smart_custom_field_fetch($row, $customField);
if ($customFieldValue) {
if ($customField->field_encrypted == 1) {
$this->item['custom_fields'][$customField->db_column_name()] = \Crypt::encrypt($customFieldValue);
$this->log('Custom Field '. $customField->name.': '.\Crypt::encrypt($customFieldValue));
} else {
$this->item['custom_fields'][$customField->db_column_name()] = $customFieldValue;
$this->log('Custom Field '. $customField->name.': '.$customFieldValue);
}
$this->item['custom_fields'][$customField->db_column_name()] = $customFieldValue;
$this->log('Custom Field '. $customField->name.': '.$customFieldValue);
} else {
// Clear out previous data.
$this->item['custom_fields'][$customField->db_column_name()] = null;
@@ -76,8 +68,6 @@ class AssetImporter extends ItemImporter
}
$this->item['image'] = $this->findCsvMatch($row, "image");
$this->item['requestable'] = $this->fetchHumanBoolean($this->findCsvMatch($row, "requestable"));;
$asset->requestable = $this->fetchHumanBoolean($this->findCsvMatch($row, "requestable"));
$this->item['warranty_months'] = intval($this->findCsvMatch($row, "warranty_months"));
$this->item['model_id'] = $this->createOrFetchAssetModel($row);

View File

@@ -443,7 +443,11 @@ abstract class Importer
public function fetchHumanBoolean($value)
{
return (int) filter_var($value, FILTER_VALIDATE_BOOLEAN);
if (($value =='1') || (strtolower($value) =='true') || (strtolower($value) =='yes'))
{
return '1';
}
return '0';
}
/**

View File

@@ -111,7 +111,6 @@ class Asset extends Depreciable
'status_id',
'supplier_id',
'warranty_months',
'requestable',
];
use Searchable;
@@ -226,10 +225,10 @@ class Asset extends Depreciable
if ($location != null) {
$this->location_id = $location;
} else {
if (isset($target->location)) {
if($target->location) {
$this->location_id = $target->location->id;
}
if ($target instanceof Location) {
if($target instanceof Location) {
$this->location_id = $target->id;
}
}
@@ -605,26 +604,20 @@ class Asset extends Depreciable
public function requireAcceptance()
{
if (($this->model) && ($this->model->category)) {
return $this->model->category->require_acceptance;
}
return $this->model->category->require_acceptance;
}
public function getEula()
{
$Parsedown = new \Parsedown();
if (($this->model) && ($this->model->category)) {
if ($this->model->category->eula_text) {
return $Parsedown->text(e($this->model->category->eula_text));
} elseif ($this->model->category->use_default_eula == '1') {
return $Parsedown->text(e(Setting::getSettings()->default_eula_text));
} else {
return false;
}
if ($this->model->category->eula_text) {
return $Parsedown->text(e($this->model->category->eula_text));
} elseif ($this->model->category->use_default_eula == '1') {
return $Parsedown->text(e(Setting::getSettings()->default_eula_text));
} else {
return false;
}
return false;
}
/**
@@ -828,11 +821,9 @@ class Asset extends Depreciable
public function scopeDueForAudit($query, $settings)
{
$interval = $settings->audit_warning_days ?? 0;
return $query->whereNotNull('assets.next_audit_date')
->where('assets.next_audit_date', '>=', Carbon::now())
->whereRaw("DATE_SUB(assets.next_audit_date, INTERVAL $interval DAY) <= '".Carbon::now()."'")
->whereRaw("DATE_SUB(assets.next_audit_date, INTERVAL $settings->audit_warning_days DAY) <= '".Carbon::now()."'")
->where('assets.archived', '=', 0)
->NotArchived();
}
@@ -878,7 +869,7 @@ class Asset extends Depreciable
$interval = $settings->audit_warning_days ?? 0;
return $query->whereNotNull('assets.next_audit_date')
->whereRaw("DATE_SUB(".DB::getTablePrefix()."assets.next_audit_date, INTERVAL $interval DAY) <= '".Carbon::now()."'")
->whereRaw("DATE_SUB(assets.next_audit_date, INTERVAL $interval DAY) <= '".Carbon::now()."'")
->where('assets.archived', '=', 0)
->NotArchived();
}
@@ -1176,29 +1167,7 @@ class Asset extends Depreciable
}
}
/**
* THIS CLUNKY BIT IS VERY IMPORTANT
*
* Although inelegant, this section matters a lot when querying against fields that do not
* exist on the asset table. There's probably a better way to do this moving forward, for
* example using the Schema:: methods to determine whether or not a column actually exists,
* or even just using the $searchableRelations variable earlier in this file.
*
* In short, this set of statements tells the query builder to ONLY query against an
* actual field that's being passed if it doesn't meet known relational fields. This
* allows us to query custom fields directly in the assetsv table
* (regardless of their name) and *skip* any fields that we already know can only be
* searched through relational searches that we do earlier in this method.
*
* For example, we do not store "location" as a field on the assets table, we store
* that relationship through location_id on the assets table, therefore querying
* assets.location would fail, as that field doesn't exist -- plus we're already searching
* against those relationships earlier in this method.
*
* - snipe
*
*/
if (($fieldname!='category') && ($fieldname!='model_number') && ($fieldname!='rtd_location') && ($fieldname!='location') && ($fieldname!='supplier')
if (($fieldname!='category') && ($fieldname!='model_number') && ($fieldname!='location') && ($fieldname!='supplier')
&& ($fieldname!='status_label') && ($fieldname!='model') && ($fieldname!='company') && ($fieldname!='manufacturer')) {
$query->orWhere('assets.'.$fieldname, 'LIKE', '%' . $search_val . '%');
}
@@ -1398,7 +1367,8 @@ class Asset extends Depreciable
/**
* Query builder scope to search on depreciation name
* Query builder scope to search on location ID
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $search Search term
*

View File

@@ -73,8 +73,7 @@ class AssetMaintenance extends Model implements ICompanyableChild
trans('admin/asset_maintenances/general.upgrade') => trans('admin/asset_maintenances/general.upgrade'),
'PAT test' => 'PAT test',
trans('admin/asset_maintenances/general.calibration') => trans('admin/asset_maintenances/general.calibration'),
'Software Support' => trans('admin/asset_maintenances/general.software_support'),
'Hardware Support' => trans('admin/asset_maintenances/general.hardware_support'),
'PAT test' => 'PAT test',
];
}

View File

@@ -128,12 +128,9 @@ final class Company extends SnipeModel
} elseif (!static::isFullMultipleCompanySupportEnabled()) {
return true;
} else {
if (Auth::user()) {
$current_user_company_id = Auth::user()->company_id;
$companyable_company_id = $companyable->company_id;
return ($current_user_company_id == null || $current_user_company_id == $companyable_company_id || Auth::user()->isSuperUser());
}
$current_user_company_id = Auth::user()->company_id;
$companyable_company_id = $companyable->company_id;
return ($current_user_company_id == null || $current_user_company_id == $companyable_company_id || Auth::user()->isSuperUser());
}
}

View File

@@ -48,7 +48,7 @@ class License extends Depreciable
protected $table = 'licenses';
protected $rules = array(
'name' => 'required|string|min:3|max:255',
'seats' => 'required|min:1|max:999|integer',
'seats' => 'required|min:1|max:1000000|integer',
'license_email' => 'email|nullable|max:120',
'license_name' => 'string|nullable|max:100',
'notes' => 'string|nullable',

View File

@@ -55,23 +55,4 @@ class LicenseSeat extends Model implements ICompanyableChild
return false;
}
/**
* Query builder scope to order on department
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeOrderDepartments($query, $order)
{
return $query->leftJoin('users as license_seat_users', 'license_seats.assigned_to', '=', 'license_seat_users.id')
->leftJoin('departments as license_user_dept', 'license_user_dept.id', '=', 'license_seat_users.department_id')
->orderBy('license_user_dept.name', $order);
}
}

View File

@@ -113,8 +113,7 @@ class Location extends SnipeModel
public function parent()
{
return $this->belongsTo('\App\Models\Location', 'parent_id','id')
->with('parent');
return $this->belongsTo('\App\Models\Location', 'parent_id','id');
}
public function manager()
@@ -122,9 +121,9 @@ class Location extends SnipeModel
return $this->belongsTo('\App\Models\User', 'manager_id');
}
public function children() {
return $this->hasMany('\App\Models\Location','parent_id')
->with('children');
public function childLocations()
{
return $this->hasMany('\App\Models\Location', 'parent_id');
}
// I don't think we need this anymore since we de-normed location_id in assets?
@@ -138,39 +137,59 @@ class Location extends SnipeModel
return $this->attributes['ldap_ou'] = empty($ldap_ou) ? null : $ldap_ou;
}
/**
* Query builder scope to order on parent
*
* @param Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return Illuminate\Database\Query\Builder Modified query builder
*/
public static function indenter($locations_with_children, $parent_id = null, $prefix = '') {
$results = Array();
if (!array_key_exists($parent_id, $locations_with_children)) {
return [];
}
public static function getLocationHierarchy($locations, $parent_id = null)
{
foreach ($locations_with_children[$parent_id] as $location) {
$location->use_text = $prefix.' '.$location->name;
$location->use_image = ($location->image) ? url('/').'/uploads/locations/'.$location->image : null;
$results[] = $location;
//now append the children. (if we have any)
if (array_key_exists($location->id, $locations_with_children)) {
$results = array_merge($results, Location::indenter($locations_with_children, $location->id,$prefix.'--'));
$op = array();
foreach ($locations as $location) {
if ($location['parent_id'] == $parent_id) {
$op[$location['id']] =
array(
'name' => $location['name'],
'parent_id' => $location['parent_id']
);
// Using recursion
$children = Location::getLocationHierarchy($locations, $location['id']);
if ($children) {
$op[$location['id']]['children'] = $children;
}
}
}
return $results;
return $op;
}
public static function flattenLocationsArray($location_options_array = null)
{
$location_options = array();
foreach ($location_options_array as $id => $value) {
// get the top level key value
$location_options[$id] = $value['name'];
// If there is a key named children, it has child locations and we have to walk it
if (array_key_exists('children', $value)) {
foreach ($value['children'] as $child_id => $child_location_array) {
$child_location_options = Location::flattenLocationsArray($value['children']);
foreach ($child_location_options as $child_id => $child_name) {
$location_options[$child_id] = '--'.$child_name;
}
}
}
}
return $location_options;
}
/**
* Query builder scope to order on parent

View File

@@ -45,15 +45,9 @@ trait Loggable
$log->user_id = Auth::user()->id;
if (!isset($target)) {
throw new \Exception('All checkout logs require a target.');
throw new Exception('All checkout logs require a target');
return;
}
if (!isset($target->id)) {
throw new \Exception('That target seems invalid (no target ID available).');
return;
}
$log->target_type = get_class($target);
$log->target_id = $target->id;

View File

@@ -20,7 +20,10 @@ class Setting extends Model
'admin_cc_email' => 'email|nullable',
'default_currency' => 'required',
'locale' => 'required',
'labels_per_page' => 'numeric|min:1',
'slack_endpoint' => 'url|required_with:slack_channel|nullable',
'slack_channel' => 'regex:/(?<!\w)#\w+/|required_with:slack_endpoint|nullable',
'slack_botname' => 'string|nullable',
'labels_per_page' => 'numeric',
'labels_width' => 'numeric',
'labels_height' => 'numeric',
'labels_pmargin_left' => 'numeric|nullable',

View File

@@ -237,7 +237,7 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo
*/
public function userlog()
{
return $this->hasMany('\App\Models\Actionlog', 'target_id')->where('target_type', '=', 'App\Models\User')->orderBy('created_at', 'DESC')->withTrashed();
return $this->hasMany('\App\Models\Actionlog', 'target_id')->orderBy('created_at', 'DESC')->withTrashed();
}
/**

View File

@@ -67,7 +67,7 @@ class AssetModelPresenter extends Presenter
public function imageUrl()
{
if (!empty($this->image)) {
return '<img src="' . url('/') . '/uploads/models/' . $this->image . '" alt="'.$this->name.'" height="50" width="50">';
return '<img src="' . url('/') . '/uploads/models/' . $this->image . '" height=50 width=50>';
}
return '';
}

View File

@@ -258,21 +258,14 @@ class AssetPresenter extends Presenter
$query->whereHas('models');
})->get();
// Note: We do not need to e() escape the field names here, as they are already escaped when
// they are presented in the blade view. If we escape them here, custom fields with quotes in their
// name can break the listings page. - snipe
foreach ($fields as $field) {
$layout[] = [
"field" => 'custom_fields.'.$field->convertUnicodeDbSlug(),
"searchable" => true,
"sortable" => true,
"switchable" => true,
"title" => $field->name,
"formatter"=> 'customFieldsFormatter',
"escape" => true,
"class" => ($field->field_encrypted=='1') ? 'css-padlock' : '',
"visible" => true,
"title" => ($field->field_encrypted=='1') ?'<i class="fa fa-lock"></i> '.e($field->name) : e($field->name),
"formatter" => "customFieldsFormatter"
];
}
@@ -327,14 +320,12 @@ class AssetPresenter extends Presenter
$imagePath = '';
if ($this->image && !empty($this->image)) {
$imagePath = $this->image;
$imageAlt = $this->name;
} elseif ($this->model && !empty($this->model->image)) {
$imagePath = $this->model->image;
$imageAlt = $this->model->name;
}
$url = config('app.url');
if (!empty($imagePath)) {
$imagePath = '<img src="'.$url.'/uploads/assets/'.$imagePath.' height="50" width="50" alt="'.$imageAlt.'">';
$imagePath = "<img src='{$url}/uploads/assets/{$imagePath}' height=50 width=50>";
}
return $imagePath;
}
@@ -400,7 +391,7 @@ class AssetPresenter extends Presenter
public function eol_date()
{
if (( $this->purchase_date ) && ( $this->model->model ) && ($this->model->model->eol) ) {
if (( $this->purchase_date ) && ( $this->model ) && ($this->model->model->eol) ) {
$date = date_create($this->purchase_date);
date_add($date, date_interval_create_from_date_string($this->model->model->eol . ' months'));
return date_format($date, 'Y-m-d');
@@ -521,6 +512,6 @@ class AssetPresenter extends Presenter
public function glyph()
{
return '<i class="fa fa-barcode" aria-hidden="true"></i>';
return '<i class="fa fa-barcode"></i>';
}
}

View File

@@ -49,7 +49,7 @@ class CompanyPresenter extends Presenter
"field" => "assets_count",
"searchable" => false,
"sortable" => true,
"title" => '<span class="hidden-xs"><i class="fa fa-barcode" aria-hidden="true"></i></span><span class="hidden-md hidden-lg">'.trans('general.assets').'</span>',
"title" => '<span class="hidden-xs"><i class="fa fa-barcode"></i></span><span class="hidden-md hidden-lg">'.trans('general.assets').'</span>',
"visible" => true,
],[

View File

@@ -176,15 +176,6 @@ class LicensePresenter extends Presenter
"visible" => true,
"formatter" => "usersLinkObjFormatter"
], [
"field" => "department",
"searchable" => false,
"sortable" => true,
"switchable" => true,
"title" => trans('general.department'),
"visible" => false,
"formatter" => "departmentNameLinkFormatter"
],
[
"field" => "assigned_asset",
"searchable" => false,
"sortable" => false,
@@ -200,8 +191,7 @@ class LicensePresenter extends Presenter
"title" => trans('general.location'),
"visible" => true,
"formatter" => "locationsLinkObjFormatter"
],
[
], [
"field" => "checkincheckout",
"searchable" => false,
"sortable" => false,

View File

@@ -190,7 +190,7 @@ class LocationPresenter extends Presenter
public function glyph()
{
return '<i class="fa fa-map-marker" aria-hidden="true"></i>';
return '<i class="fa fa-map-marker"></i>';
}
public function fullName() {

View File

@@ -171,22 +171,21 @@ class UserPresenter extends Presenter
"formatter" => "usersLinkObjFormatter"
],
[
'field' => 'assets_count',
'searchable' => false,
'sortable' => true,
'switchable' => true,
'escape' => true,
'class' => 'css-barcode',
'title' => 'Assets',
'visible' => true,
"field" => "assets_count",
"searchable" => false,
"sortable" => true,
"switchable" => true,
"title" => ' <span class="hidden-md hidden-lg">Assets</span>'
.'<span class="hidden-xs"><i class="fa fa-barcode fa-lg"></i></span>',
"visible" => true,
],
[
"field" => "licenses_count",
"searchable" => false,
"sortable" => true,
"switchable" => true,
'class' => 'css-license',
"title" => 'License',
"title" => ' <span class="hidden-md hidden-lg">Licenses</span>'
.'<span class="hidden-xs"><i class="fa fa-floppy-o fa-lg"></i></span>',
"visible" => true,
],
[
@@ -194,8 +193,8 @@ class UserPresenter extends Presenter
"searchable" => false,
"sortable" => true,
"switchable" => true,
'class' => 'css-consumable',
"title" => 'Consumables',
"title" => ' <span class="hidden-md hidden-lg">Consumables</span>'
.'<span class="hidden-xs"><i class="fa fa-tint fa-lg"></i></span>',
"visible" => true,
],
[
@@ -203,8 +202,8 @@ class UserPresenter extends Presenter
"searchable" => false,
"sortable" => true,
"switchable" => true,
'class' => 'css-accessory',
"title" => 'Accessories',
"title" => ' <span class="hidden-md hidden-lg">Accessories</span>'
.'<span class="hidden-xs"><i class="fa fa-keyboard-o fa-lg"></i></span>',
"visible" => true,
],
[
@@ -324,14 +323,9 @@ class UserPresenter extends Presenter
return config('app.url').'/uploads/avatars/'.$this->avatar;
}
if (Setting::getSettings()->load_remote=='1') {
if ($this->model->gravatar!='') {
$gravatar = md5(strtolower(trim($this->model->gravatar)));
return "//gravatar.com/avatar/".$gravatar;
} elseif ($this->email!='') {
$gravatar = md5(strtolower(trim($this->email)));
return "//gravatar.com/avatar/".$gravatar;
}
if ((Setting::getSettings()->load_remote=='1') && ($this->email!='')) {
$gravatar = md5(strtolower(trim($this->email)));
return "//gravatar.com/avatar/".$gravatar;
}
// Set a fun, gender-neutral default icon
@@ -359,6 +353,6 @@ class UserPresenter extends Presenter
public function glyph()
{
return '<i class="fa fa-user" aria-hidden="true"></i>';
return '<i class="fa fa-user"></i>';
}
}

View File

@@ -14,7 +14,6 @@
"doctrine/inflector": "^1.3",
"doctrine/instantiator": "^1.2",
"eduardokum/laravel-mail-auto-embed": "^1.0",
"enshrined/svg-sanitize": "^0.13.3",
"erusev/parsedown": "^1.7",
"fideloper/proxy": "^4.1",
"guzzlehttp/guzzle": "^6.3",
@@ -25,10 +24,10 @@
"laravel/tinker": "^1.0",
"laravelcollective/html": "^5.5",
"league/csv": "^9.2",
"alek13/slack": "^1.7",
"maknz/slack": "^1.7",
"neitanod/forceutf8": "^2.0",
"patchwork/utf8": "^1.3",
"phpdocumentor/reflection-docblock": "^4.0",
"phpdocumentor/reflection-docblock": "3.2.2",
"phpspec/prophecy": "^1.8",
"pragmarx/google2fa": "^5.0",
"pragmarx/google2fa-laravel": "^1.0",
@@ -44,7 +43,7 @@
"require-dev": {
"codeception/codeception": "2.3.6",
"filp/whoops": "~2.0",
"fzaninotto/faker": "1.9.1",
"fzaninotto/faker": "~1.4",
"phpunit/php-token-stream": "1.4.11",
"phpunit/phpunit": "~6.0",
"roave/security-advisories": "dev-master",

2101
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -36,19 +36,6 @@ return [
'env' => env('APP_ENV', 'production'),
/*
|--------------------------------------------------------------------------
| Result Limit
|--------------------------------------------------------------------------
|
| This value determines the max number of results to return, even if a higher limit
| is passed in the API request. This is done to prevent server timeouts when
| custom scripts are requesting 100k assets at a time.
|
*/
'max_results' => env('MAX_RESULTS', 500),
/*
|--------------------------------------------------------------------------
| Application Debug Mode
@@ -196,33 +183,19 @@ return [
'private_uploads' => storage_path().'/private_uploads',
/*
|--------------------------------------------------------------------------
| ALLOW I-FRAMING
|--------------------------------------------------------------------------
|
| Normal users will never need to edit this. This option lets you run
| Snipe-IT within an I-Frame, which is normally disabled by default for
| security reasons, to prevent clickjacking. It should normally be set to false.
|
*/
'allow_iframing' => env('ALLOW_IFRAMING', false),
/*
|--------------------------------------------------------------------------
| ENABLE HTTP Strict Transport Security (HSTS)
| ALLOW I-FRAMING
|--------------------------------------------------------------------------
|
| This is set to default false for backwards compatibilty but should be
| set to true if the hosting environment allows it.
|
| See https://scotthelme.co.uk/hsts-the-missing-link-in-tls/
| Normal users will never need to edit this. This option lets you run
| Snipe-IT within an I-Frame, which is normally disabled by default for
| security reasons, to prevent clickjacking. It should normally be set to false.
|
*/
'enable_hsts' => env('ENABLE_HSTS', false),
'allow_iframing' => env('ALLOW_IFRAMING', false),
/*
|--------------------------------------------------------------------------

View File

@@ -87,14 +87,12 @@ return [
//'exclude_tables' => ['table1', 'table2'],
//'add_extra_option' => '--optionname=optionvalue',
],
'options' => (env('DB_SSL')) ? ((env('DB_SSL_IS_PAAS')) ? [
PDO::MYSQL_ATTR_SSL_CA => env('DB_SSL_CA_PATH'), // /path/to/ca.pem
] : [
PDO::MYSQL_ATTR_SSL_KEY => env('DB_SSL_KEY_PATH'), // /path/to/key.pem
PDO::MYSQL_ATTR_SSL_CERT => env('DB_SSL_CERT_PATH'), // /path/to/cert.pem
PDO::MYSQL_ATTR_SSL_CA => env('DB_SSL_CA_PATH'), // /path/to/ca.pem
PDO::MYSQL_ATTR_SSL_CIPHER => env('DB_SSL_CIPHER')
]) : []
'options' => (env('DB_SSL')) ? [
PDO::MYSQL_ATTR_SSL_KEY => env('DB_SSL_KEY_PATH'), // /path/to/key.pem
PDO::MYSQL_ATTR_SSL_CERT => env('DB_SSL_CERT_PATH'), // /path/to/cert.pem
PDO::MYSQL_ATTR_SSL_CA => env('DB_SSL_CA_PATH'), // /path/to/ca.pem
PDO::MYSQL_ATTR_SSL_CIPHER => env('DB_SSL_CIPHER')
] : []
],
'pgsql' => [

View File

@@ -1,10 +1,10 @@
<?php
return array (
'app_version' => 'v4.9.4',
'full_app_version' => 'v4.9.4 - build 4437-g799a93c46',
'build_version' => '4437',
'app_version' => 'v4.7.5',
'full_app_version' => 'v4.7.5 - build 4137-g55ee90b25',
'build_version' => '4137',
'prerelease_version' => '',
'hash_version' => 'g799a93c46',
'full_hash' => 'v4.9.4-41-g799a93c46',
'hash_version' => 'g55ee90b25',
'full_hash' => 'v4.7.5-18-g55ee90b25',
'branch' => 'master',
);
);

View File

@@ -1,4 +1,4 @@
#!/bin/bash
#!/bin/sh
# fix key if needed
if [ -z "$APP_KEY" ]
@@ -41,14 +41,6 @@ chown -R docker:root /var/lib/snipeit/data/*
chown -R docker:root /var/lib/snipeit/dumps
chown -R docker:root /var/lib/snipeit/keys
# Fix php settings
if [ -v "PHP_UPLOAD_LIMIT" ]
then
echo "Changing upload limit to ${PHP_UPLOAD_LIMIT}"
sed -i "s/^upload_max_filesize.*/upload_max_filesize = ${PHP_UPLOAD_LIMIT}M/" /etc/php/*/apache2/php.ini
fi
# If the Oauth DB files are not present copy the vendor files over to the db migrations
if [ ! -f "/var/www/html/database/migrations/*create_oauth*" ]
then

5190
npm-shrinkwrap.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -10,7 +10,7 @@
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js "
},
"devDependencies": {
"axios": ">=0.18.1",
"axios": "^0.16.2",
"babel-preset-latest": "^6.24.1",
"cross-env": "^5.0.5",
"jquery": "^3.1.1",
@@ -35,9 +35,8 @@
"jquery.iframe-transport": "^1.0.0",
"less": "less/less.js#efa6eb5306f28a7ef7e235d79ce854b780345591",
"less-loader": "^4.1.0",
"list.js": "^1.5.0",
"papaparse": "^4.3.3",
"select2": "4.0.13",
"select2": "^4.0.3",
"tether": "^1.4.0",
"vue-resource": "^1.3.3"
}

View File

@@ -35,7 +35,7 @@ a, a:link, a:visited, .btn-primary.hover {
background-color: var(--back-sub);
color: var(--header);
}
.btn-primary, .btn-primary.hover, .btn-primary:active, .btn-primary:hover, .text-green {
.btn-primary, .btn-primary.hover, .btn-primary:active, .btn-primary:hover, .text-blue {
color: var(--text-main)!important;
}
#componentsTable>tbody>tr>td>nobr>a>i.fa {
@@ -130,10 +130,10 @@ input[type=text], input[type=search] {
background-color: var(--back-main);
color: var(--text-main);
}
.skin-green .main-header .navbar .dropdown-menu li a {
.skin-blue .main-header .navbar .dropdown-menu li a {
color: var(--header);
}
.skin-green .sidebar-menu>li.active>a, .skin-green .sidebar-menu>li:hover>a, .sidebar-toggle:hover {
.skin-blue .sidebar-menu>li.active>a, .skin-blue .sidebar-menu>li:hover>a, .sidebar-toggle:hover {
background-color: var(--header)!important;
}
.tab-content, .tab-pane {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
.skin-black-light .main-header .navbar{background-color:#111}.skin-black-light .main-header .navbar .nav>li>a{color:#fff}.skin-black-light .main-header .navbar .nav .open>a,.skin-black-light .main-header .navbar .nav .open>a:focus,.skin-black-light .main-header .navbar .nav .open>a:hover,.skin-black-light .main-header .navbar .nav>.active>a,.skin-black-light .main-header .navbar .nav>li>a:active,.skin-black-light .main-header .navbar .nav>li>a:focus,.skin-black-light .main-header .navbar .nav>li>a:hover,.skin-black-light .main-header .navbar .sidebar-toggle:hover{background:rgba(0,0,0,.1);color:#f6f6f6}.skin-black-light .main-header .navbar .sidebar-toggle{color:#fff}.skin-black-light .main-header .navbar .sidebar-toggle:hover{background-color:#040404}@media (max-width:767px){.skin-black-light .main-header .navbar .dropdown-menu li.divider{background-color:hsla(0,0%,100%,.1)}.skin-black-light .main-header .navbar .dropdown-menu li a{color:#fff}.skin-black-light .main-header .navbar .dropdown-menu li a:hover{background:#040404}}.skin-black-light .main-header .logo{background-color:#111;color:#fff;border-bottom:0 solid transparent}.skin-black-light .main-header .logo:hover{background-color:#0e0e0e}.skin-black-light .main-header li.user-header{background-color:#111}.skin-black-light .content-header{background:transparent}.skin-black-light .left-side,.skin-black-light .main-sidebar,.skin-black-light .wrapper{background-color:#f9fafc}.skin-black-light .content-wrapper,.skin-black-light .main-footer{border-left:1px solid #d2d6de}.skin-black-light .user-panel>.info,.skin-black-light .user-panel>.info>a{color:#444}.skin-black-light .sidebar-menu>li{-webkit-transition:border-left-color .3s ease;transition:border-left-color .3s ease}.skin-black-light .sidebar-menu>li.header{color:#848484;background:#f9fafc}.skin-black-light .sidebar-menu>li>a{border-left:3px solid transparent;font-weight:600}.skin-black-light .sidebar-menu>li.active>a,.skin-black-light .sidebar-menu>li:hover>a{color:#000;background:#f4f4f5}.skin-black-light .sidebar-menu>li.active{border-left-color:#111}.skin-black-light .sidebar-menu>li.active>a{font-weight:600}.skin-black-light .sidebar-menu>li>.treeview-menu{background:#f4f4f5}.skin-black-light .sidebar a{color:#444}.skin-black-light .sidebar a:hover{text-decoration:none}.skin-black-light .treeview-menu>li>a{color:#777}.skin-black-light .treeview-menu>li.active>a,.skin-black-light .treeview-menu>li>a:hover{color:#000}.skin-black-light .treeview-menu>li.active>a{font-weight:600}.skin-black-light .sidebar-form{border-radius:3px;border:1px solid #d2d6de;margin:10px}.skin-black-light .sidebar-form .btn,.skin-black-light .sidebar-form input[type=text]{-webkit-box-shadow:none;box-shadow:none;background-color:#fff;border:1px solid transparent;height:35px;-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}.skin-black-light .sidebar-form input[type=text]{color:#666;border-top-left-radius:2px;border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:2px}.skin-black-light .sidebar-form input[type=text]:focus,.skin-black-light .sidebar-form input[type=text]:focus+.input-group-btn .btn{background-color:#fff;color:#666}.skin-black-light .sidebar-form input[type=text]:focus+.input-group-btn .btn{border-left-color:#fff}.skin-black-light .sidebar-form .btn{color:#999;border-top-left-radius:0;border-top-right-radius:2px;border-bottom-right-radius:2px;border-bottom-left-radius:0}@media (min-width:768px){.skin-black-light.sidebar-mini.sidebar-collapse .sidebar-menu>li>.treeview-menu{border-left:1px solid #d2d6de}}

File diff suppressed because one or more lines are too long

View File

@@ -1,2 +0,0 @@
.skin-black .main-header .navbar{background-color:#111}.skin-black .main-header .navbar .nav>li>a{color:#fff}.skin-black .main-header .navbar .nav .open>a,.skin-black .main-header .navbar .nav .open>a:focus,.skin-black .main-header .navbar .nav .open>a:hover,.skin-black .main-header .navbar .nav>.active>a,.skin-black .main-header .navbar .nav>li>a:active,.skin-black .main-header .navbar .nav>li>a:focus,.skin-black .main-header .navbar .nav>li>a:hover,.skin-black .main-header .navbar .sidebar-toggle:hover{background:rgba(0,0,0,.1);color:#f6f6f6}.skin-black .main-header .navbar .sidebar-toggle{color:#fff}.skin-black .main-header .navbar .sidebar-toggle:hover{background-color:#040404}@media (max-width:767px){.skin-black .main-header .navbar .dropdown-menu li.divider{background-color:hsla(0,0%,100%,.1)}.skin-black .main-header .navbar .dropdown-menu li a{color:#fff}.skin-black .main-header .navbar .dropdown-menu li a:hover{background:#040404}}.skin-black .main-header li.user-header{background-color:#111}.skin-black .content-header{background:transparent}.skin-black .left-side,.skin-black .main-sidebar,.skin-black .wrapper{background-color:#222d32}.skin-black .user-panel>.info,.skin-black .user-panel>.info>a{color:#fff}.skin-black .sidebar-menu>li.header{color:#4b646f;background:#1a2226}.skin-black .sidebar-menu>li>a{border-left:3px solid transparent}.skin-black .sidebar-menu>li.active>a,.skin-black .sidebar-menu>li:hover>a{color:#fff;background:#1e282c;border-left-color:#111}.skin-black .sidebar-menu>li>.treeview-menu{margin:0 1px;background:#2c3b41}.skin-black .sidebar a{color:#b8c7ce}.skin-black .sidebar a:hover{text-decoration:none}.skin-black .treeview-menu>li>a{color:#8aa4af}.skin-black .treeview-menu>li.active>a,.skin-black .treeview-menu>li>a:hover{color:#fff}.skin-black .sidebar-form{border-radius:3px;border:1px solid #374850;margin:10px}.skin-black .sidebar-form .btn,.skin-black .sidebar-form input[type=text]{-webkit-box-shadow:none;box-shadow:none;background-color:#374850;border:1px solid transparent;height:35px;-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}.skin-black .sidebar-form input[type=text]{color:#666;border-top-left-radius:2px;border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:2px}.skin-black .sidebar-form input[type=text]:focus,.skin-black .sidebar-form input[type=text]:focus+.input-group-btn .btn{background-color:#fff;color:#666}.skin-black .sidebar-form input[type=text]:focus+.input-group-btn .btn{border-left-color:#fff}.skin-black .sidebar-form .btn{color:#999;border-top-left-radius:0;border-top-right-radius:2px;border-bottom-right-radius:2px;border-bottom-left-radius:0}.skin-black.layout-top-nav .main-header>.logo .logo-variant{background-color:none}.btn,.btn:hover{text-decoration:none}.btn.btn-primary,.btn .btn-primary:link,.btn:hover.btn-primary,.btn:hover .btn-primary:link{background-color:#505156;border-color:#b5bbc8;color:#fff}.btn:hovera.btn-primary:hover,.btna.btn-primary:hover{background-color:#111;border-color:#1f1f21;color:#fff}.btn.btn-white:hover,.btn.btn-white:link,.btn.btn-white:visited,.btn:hover.btn-white:hover,.btn:hover.btn-white:link,.btn:hover.btn-white:visited{color:#fff}a{color:#111;text-decoration:underline}a:hover{color:#000}a:visited{color:#111}.text-primary{color:#000}.skin-black .main-header .navbar .nav>li>a{text-decoration:none}
/*# sourceMappingURL=skin-black.css.map*/

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