mirror of
https://github.com/snipe/snipe-it.git
synced 2025-03-05 20:52:15 -08:00
fixing ff error
This commit is contained in:
commit
690970b4aa
.env.dusk.example.gitignoreTESTING.mdcomposer.jsoncomposer.lockgeneral.phplocalizations.phpmail.phpvalidation.phpgeneral.phplocalizations.phpmail.phpvalidation.php
app
Console/Commands
Exceptions
Http
Controllers
Accessories
Account
Api
AccessoriesController.phpAssetsController.phpCustomFieldsetsController.phpImportController.phpSettingsController.phpUsersController.php
CustomFieldsController.phpCustomFieldsetsController.phpModalController.phpReportsController.phpSettingsController.phpLivewire
Middleware
Requests
Transformers
Importer
Models
Accessory.phpAsset.phpCheckoutAcceptance.phpComponent.phpConsumable.phpCustomField.phpLdap.phpLicense.phpSetting.phpSnipeSCIMConfig.php
Traits
User.phpNotifications
AcceptanceAssetAcceptedNotification.phpAcceptanceAssetDeclinedNotification.phpCurrentInventory.phpInventoryAlert.phpSendUpcomingAuditNotification.phpWelcomeNotification.php
Presenters
Services
config
database/migrations
2012_12_06_225929_migration_cartalyst_sentry_install_groups.php2013_11_17_054526_add_physical_to_assets.php2013_11_25_013244_recreate_licenses_table.php2013_11_25_031458_create_license_seats_table.php2013_11_25_104343_alter_warranty_column_on_assets.php2013_12_10_084038_add_eol_on_models_table.php2015_07_29_230054_add_thread_id_to_asset_logs_table.php2015_09_22_003413_migrate_mac_address.php2016_08_23_145619_add_show_in_nav_to_status_labels.php2017_01_25_063357_fix_utf8_custom_field_column_names.php2017_03_10_210807_add_fields_to_manufacturer.php2023_02_12_224353_fix_unescaped_customfields_format.php
phpstan.neon.distphpstan.neon.examplepsalm.xmlpublic/img
resources/lang
af
admin
categories
components
custom_fields
hardware
models
settings
users
am
admin
categories
components
custom_fields
hardware
models
settings
users
ar/admin
|
@ -20,13 +20,13 @@ PUBLIC_FILESYSTEM_DISK=local_public
|
||||||
# REQUIRED: DATABASE SETTINGS
|
# REQUIRED: DATABASE SETTINGS
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
DB_CONNECTION=mysql
|
DB_CONNECTION=mysql
|
||||||
DB_HOST=localhost
|
DB_HOST=127.0.0.1
|
||||||
DB_PORT=3306
|
DB_PORT=3306
|
||||||
DB_DATABASE=snipeit-local
|
DB_DATABASE=null
|
||||||
DB_USERNAME=snipeit-local
|
DB_USERNAME=null
|
||||||
DB_PASSWORD=snipeit-local
|
DB_PASSWORD=null
|
||||||
DB_PREFIX=null
|
DB_PREFIX=null
|
||||||
DB_DUMP_PATH='/Applications/MAMP/Library/bin'
|
#DB_DUMP_PATH=
|
||||||
|
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
# OPTIONAL: SSL DATABASE SETTINGS
|
# OPTIONAL: SSL DATABASE SETTINGS
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,6 +1,9 @@
|
||||||
.couscous
|
.couscous
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.env
|
.env
|
||||||
|
.env.dusk.*
|
||||||
|
!.env.dusk.example
|
||||||
|
phpstan.neon
|
||||||
.idea
|
.idea
|
||||||
/bin/
|
/bin/
|
||||||
/bootstrap/compiled.php
|
/bootstrap/compiled.php
|
||||||
|
|
24
TESTING.md
24
TESTING.md
|
@ -43,23 +43,33 @@ you want to run.
|
||||||
|
|
||||||
## Browser Tests
|
## Browser Tests
|
||||||
|
|
||||||
The browser tests use [Dusk](https://laravel.com/docs/8.x/dusk) to run them.
|
Browser tests are run via [Laravel Dusk](https://laravel.com/docs/8.x/dusk) and require Google Chrome to be installed.
|
||||||
When troubleshooting any problems, make sure that your `.env` file is configured
|
|
||||||
correctly to run the existing application.
|
Before attempting to run Dusk tests copy the example environment file for Dusk and update the values to match your environment:
|
||||||
|
|
||||||
|
`cp .env.dusk.example .env.dusk.local`
|
||||||
|
> `local` refers to the value of `APP_ENV` in your `.env` so if you have it set to `dev` then the file should be named `.env.dusk.dev`.
|
||||||
|
|
||||||
|
**Important**: Dusk tests cannot be run using an in-memory SQLite database. Additionally, the Dusk test suite uses the `DatabaseMigrations` trait which will leave the database in a fresh state after running. Therefore, it is recommended that you create a test database and point `DB_DATABASE` in `.env.dusk.local` to it.
|
||||||
|
|
||||||
### Test Setup
|
### Test Setup
|
||||||
|
|
||||||
Your application needs to be configued and up and running in order for the browser
|
Your application needs to be configured and up and running in order for the browser
|
||||||
tests to actually run. When running the tests locally, you can start the application
|
tests to actually run. When running the tests locally, you can start the application
|
||||||
using the following command:
|
using the following command:
|
||||||
|
|
||||||
`php artisan serve`
|
`php artisan serve`
|
||||||
|
|
||||||
|
Now you are ready to run the test suite. Use the following command from another terminal tab or window:
|
||||||
To run the test suite use the following command from another terminal tab or window:
|
|
||||||
|
|
||||||
`php artisan dusk`
|
`php artisan dusk`
|
||||||
|
|
||||||
To run individual test files, you can pass the path to the test that you want to run.
|
To run individual test files, you can pass the path to the test that you want to run:
|
||||||
|
|
||||||
`php artisan dusk tests/Browser/LoginTest.php`
|
`php artisan dusk tests/Browser/LoginTest.php`
|
||||||
|
|
||||||
|
If you get an error when attempting to run Dusk tests that says `Couldn't connect to server` run:
|
||||||
|
|
||||||
|
`php artisan dusk:chrome-driver --detect`
|
||||||
|
|
||||||
|
This command will install the specific ChromeDriver Dusk needs for your operating system and Chrome version.
|
||||||
|
|
|
@ -3,14 +3,29 @@
|
||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
|
use \App\Models\User;
|
||||||
|
|
||||||
|
|
||||||
class CreateAdmin extends Command
|
class CreateAdmin extends Command
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/** @mixin User **/
|
||||||
/**
|
/**
|
||||||
* The name and signature of the console command.
|
* App\Console\CreateAdmin
|
||||||
*
|
* @property mixed $first_name
|
||||||
* @var string
|
* @property string $last_name
|
||||||
|
* @property string $username
|
||||||
|
* @property string $email
|
||||||
|
* @property string $permissions
|
||||||
|
* @property string $password
|
||||||
|
* @property boolean $activated
|
||||||
|
* @property boolean $show_in_list
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property mixed $created_by
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected $signature = 'snipeit:create-admin {--first_name=} {--last_name=} {--email=} {--username=} {--password=} {show_in_list?}';
|
protected $signature = 'snipeit:create-admin {--first_name=} {--last_name=} {--email=} {--username=} {--password=} {show_in_list?}';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,11 +45,7 @@ class CreateAdmin extends Command
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute the console command.
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$first_name = $this->option('first_name');
|
$first_name = $this->option('first_name');
|
||||||
|
@ -47,7 +58,7 @@ class CreateAdmin extends Command
|
||||||
if (($first_name == '') || ($last_name == '') || ($username == '') || ($email == '') || ($password == '')) {
|
if (($first_name == '') || ($last_name == '') || ($username == '') || ($email == '') || ($password == '')) {
|
||||||
$this->info('ERROR: All fields are required.');
|
$this->info('ERROR: All fields are required.');
|
||||||
} else {
|
} else {
|
||||||
$user = new \App\Models\User;
|
$user = new User;
|
||||||
$user->first_name = $first_name;
|
$user->first_name = $first_name;
|
||||||
$user->last_name = $last_name;
|
$user->last_name = $last_name;
|
||||||
$user->username = $username;
|
$user->username = $username;
|
||||||
|
|
|
@ -44,12 +44,18 @@ class LdapSync extends Command
|
||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// If LDAP enabled isn't set to 1 (ldap_enabled!=1) then we should cut this short immediately without going any further
|
||||||
|
if (Setting::getSettings()->ldap_enabled!='1') {
|
||||||
|
$this->error('LDAP is not enabled. Aborting. See Settings > LDAP to enable it.');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
ini_set('max_execution_time', env('LDAP_TIME_LIM', 600)); //600 seconds = 10 minutes
|
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('memory_limit', env('LDAP_MEM_LIM', '500M'));
|
||||||
$ldap_result_username = Setting::getSettings()->ldap_username_field;
|
$ldap_result_username = Setting::getSettings()->ldap_username_field;
|
||||||
$ldap_result_last_name = Setting::getSettings()->ldap_lname_field;
|
$ldap_result_last_name = Setting::getSettings()->ldap_lname_field;
|
||||||
$ldap_result_first_name = Setting::getSettings()->ldap_fname_field;
|
$ldap_result_first_name = Setting::getSettings()->ldap_fname_field;
|
||||||
|
|
||||||
$ldap_result_active_flag = Setting::getSettings()->ldap_active_flag;
|
$ldap_result_active_flag = Setting::getSettings()->ldap_active_flag;
|
||||||
$ldap_result_emp_num = Setting::getSettings()->ldap_emp_num;
|
$ldap_result_emp_num = Setting::getSettings()->ldap_emp_num;
|
||||||
$ldap_result_email = Setting::getSettings()->ldap_email;
|
$ldap_result_email = Setting::getSettings()->ldap_email;
|
||||||
|
@ -68,7 +74,7 @@ class LdapSync extends Command
|
||||||
$json_summary = ['error' => true, 'error_message' => $e->getMessage(), 'summary' => []];
|
$json_summary = ['error' => true, 'error_message' => $e->getMessage(), 'summary' => []];
|
||||||
$this->info(json_encode($json_summary));
|
$this->info(json_encode($json_summary));
|
||||||
}
|
}
|
||||||
LOG::info($e);
|
Log::info($e);
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
@ -78,7 +84,7 @@ class LdapSync extends Command
|
||||||
try {
|
try {
|
||||||
if ($this->option('base_dn') != '') {
|
if ($this->option('base_dn') != '') {
|
||||||
$search_base = $this->option('base_dn');
|
$search_base = $this->option('base_dn');
|
||||||
LOG::debug('Importing users from specified base DN: \"'.$search_base.'\".');
|
Log::debug('Importing users from specified base DN: \"'.$search_base.'\".');
|
||||||
} else {
|
} else {
|
||||||
$search_base = null;
|
$search_base = null;
|
||||||
}
|
}
|
||||||
|
@ -92,7 +98,7 @@ class LdapSync extends Command
|
||||||
$json_summary = ['error' => true, 'error_message' => $e->getMessage(), 'summary' => []];
|
$json_summary = ['error' => true, 'error_message' => $e->getMessage(), 'summary' => []];
|
||||||
$this->info(json_encode($json_summary));
|
$this->info(json_encode($json_summary));
|
||||||
}
|
}
|
||||||
LOG::info($e);
|
Log::info($e);
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
@ -102,16 +108,16 @@ class LdapSync extends Command
|
||||||
|
|
||||||
if ($this->option('location') != '') {
|
if ($this->option('location') != '') {
|
||||||
$location = Location::where('name', '=', $this->option('location'))->first();
|
$location = Location::where('name', '=', $this->option('location'))->first();
|
||||||
LOG::debug('Location name '.$this->option('location').' passed');
|
Log::debug('Location name '.$this->option('location').' passed');
|
||||||
LOG::debug('Importing to '.$location->name.' ('.$location->id.')');
|
Log::debug('Importing to '.$location->name.' ('.$location->id.')');
|
||||||
} elseif ($this->option('location_id') != '') {
|
} elseif ($this->option('location_id') != '') {
|
||||||
$location = Location::where('id', '=', $this->option('location_id'))->first();
|
$location = Location::where('id', '=', $this->option('location_id'))->first();
|
||||||
LOG::debug('Location ID '.$this->option('location_id').' passed');
|
Log::debug('Location ID '.$this->option('location_id').' passed');
|
||||||
LOG::debug('Importing to '.$location->name.' ('.$location->id.')');
|
Log::debug('Importing to '.$location->name.' ('.$location->id.')');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! isset($location)) {
|
if (! isset($location)) {
|
||||||
LOG::debug('That location is invalid or a location was not provided, so no location will be assigned by default.');
|
Log::debug('That location is invalid or a location was not provided, so no location will be assigned by default.');
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process locations with explicitly defined OUs, if doing a full import. */
|
/* Process locations with explicitly defined OUs, if doing a full import. */
|
||||||
|
@ -127,7 +133,7 @@ class LdapSync extends Command
|
||||||
array_multisort($ldap_ou_lengths, SORT_ASC, $ldap_ou_locations);
|
array_multisort($ldap_ou_lengths, SORT_ASC, $ldap_ou_locations);
|
||||||
|
|
||||||
if (count($ldap_ou_locations) > 0) {
|
if (count($ldap_ou_locations) > 0) {
|
||||||
LOG::debug('Some locations have special OUs set. Locations will be automatically set for users in those OUs.');
|
Log::debug('Some locations have special OUs set. Locations will be automatically set for users in those OUs.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inject location information fields
|
// Inject location information fields
|
||||||
|
@ -145,7 +151,7 @@ class LdapSync extends Command
|
||||||
$json_summary = ['error' => true, 'error_message' => trans('admin/users/message.error.ldap_could_not_search').' Location: '.$ldap_loc['name'].' (ID: '.$ldap_loc['id'].') cannot connect to "'.$ldap_loc['ldap_ou'].'" - '.$e->getMessage(), 'summary' => []];
|
$json_summary = ['error' => true, 'error_message' => trans('admin/users/message.error.ldap_could_not_search').' Location: '.$ldap_loc['name'].' (ID: '.$ldap_loc['id'].') cannot connect to "'.$ldap_loc['ldap_ou'].'" - '.$e->getMessage(), 'summary' => []];
|
||||||
$this->info(json_encode($json_summary));
|
$this->info(json_encode($json_summary));
|
||||||
}
|
}
|
||||||
LOG::info($e);
|
Log::info($e);
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
@ -191,18 +197,18 @@ class LdapSync extends Command
|
||||||
|
|
||||||
for ($i = 0; $i < $results['count']; $i++) {
|
for ($i = 0; $i < $results['count']; $i++) {
|
||||||
$item = [];
|
$item = [];
|
||||||
$item['username'] = isset($results[$i][$ldap_result_username][0]) ? $results[$i][$ldap_result_username][0] : '';
|
$item['username'] = $results[$i][$ldap_result_username][0] ?? '';
|
||||||
$item['employee_number'] = isset($results[$i][$ldap_result_emp_num][0]) ? $results[$i][$ldap_result_emp_num][0] : '';
|
$item['employee_number'] = $results[$i][$ldap_result_emp_num][0] ?? '';
|
||||||
$item['lastname'] = isset($results[$i][$ldap_result_last_name][0]) ? $results[$i][$ldap_result_last_name][0] : '';
|
$item['lastname'] = $results[$i][$ldap_result_last_name][0] ?? '';
|
||||||
$item['firstname'] = isset($results[$i][$ldap_result_first_name][0]) ? $results[$i][$ldap_result_first_name][0] : '';
|
$item['firstname'] = $results[$i][$ldap_result_first_name][0] ?? '';
|
||||||
$item['email'] = isset($results[$i][$ldap_result_email][0]) ? $results[$i][$ldap_result_email][0] : '';
|
$item['email'] = $results[$i][$ldap_result_email][0] ?? '';
|
||||||
$item['ldap_location_override'] = isset($results[$i]['ldap_location_override']) ? $results[$i]['ldap_location_override'] : '';
|
$item['ldap_location_override'] = $results[$i]['ldap_location_override'] ?? '';
|
||||||
$item['location_id'] = isset($results[$i]['location_id']) ? $results[$i]['location_id'] : '';
|
$item['location_id'] = $results[$i]['location_id'] ?? '';
|
||||||
$item['telephone'] = isset($results[$i][$ldap_result_phone][0]) ? $results[$i][$ldap_result_phone][0] : '';
|
$item['telephone'] = $results[$i][$ldap_result_phone][0] ?? '';
|
||||||
$item['jobtitle'] = isset($results[$i][$ldap_result_jobtitle][0]) ? $results[$i][$ldap_result_jobtitle][0] : '';
|
$item['jobtitle'] = $results[$i][$ldap_result_jobtitle][0] ?? '';
|
||||||
$item['country'] = isset($results[$i][$ldap_result_country][0]) ? $results[$i][$ldap_result_country][0] : '';
|
$item['country'] = $results[$i][$ldap_result_country][0] ?? '';
|
||||||
$item['department'] = isset($results[$i][$ldap_result_dept][0]) ? $results[$i][$ldap_result_dept][0] : '';
|
$item['department'] = $results[$i][$ldap_result_dept][0] ?? '';
|
||||||
$item['manager'] = isset($results[$i][$ldap_result_manager][0]) ? $results[$i][$ldap_result_manager][0] : '';
|
$item['manager'] = $results[$i][$ldap_result_manager][0] ?? '';
|
||||||
|
|
||||||
|
|
||||||
$department = Department::firstOrCreate([
|
$department = Department::firstOrCreate([
|
||||||
|
@ -303,17 +309,18 @@ class LdapSync extends Command
|
||||||
$user->activated = 0;
|
$user->activated = 0;
|
||||||
} */
|
} */
|
||||||
$enabled_accounts = [
|
$enabled_accounts = [
|
||||||
'512', // 0x200 NORMAL_ACCOUNT
|
'512', // 0x200 NORMAL_ACCOUNT
|
||||||
'544', // 0x220 NORMAL_ACCOUNT, PASSWD_NOTREQD
|
'544', // 0x220 NORMAL_ACCOUNT, PASSWD_NOTREQD
|
||||||
'66048', // 0x10200 NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD
|
'66048', // 0x10200 NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD
|
||||||
'66080', // 0x10220 NORMAL_ACCOUNT, PASSWD_NOTREQD, DONT_EXPIRE_PASSWORD
|
'66080', // 0x10220 NORMAL_ACCOUNT, PASSWD_NOTREQD, DONT_EXPIRE_PASSWORD
|
||||||
'262656', // 0x40200 NORMAL_ACCOUNT, SMARTCARD_REQUIRED
|
'262656', // 0x40200 NORMAL_ACCOUNT, SMARTCARD_REQUIRED
|
||||||
'262688', // 0x40220 NORMAL_ACCOUNT, PASSWD_NOTREQD, SMARTCARD_REQUIRED
|
'262688', // 0x40220 NORMAL_ACCOUNT, PASSWD_NOTREQD, SMARTCARD_REQUIRED
|
||||||
'328192', // 0x50200 NORMAL_ACCOUNT, SMARTCARD_REQUIRED, DONT_EXPIRE_PASSWORD
|
'328192', // 0x50200 NORMAL_ACCOUNT, SMARTCARD_REQUIRED, DONT_EXPIRE_PASSWORD
|
||||||
'328224', // 0x50220 NORMAL_ACCOUNT, PASSWD_NOT_REQD, SMARTCARD_REQUIRED, DONT_EXPIRE_PASSWORD
|
'328224', // 0x50220 NORMAL_ACCOUNT, PASSWD_NOT_REQD, SMARTCARD_REQUIRED, DONT_EXPIRE_PASSWORD
|
||||||
'4194816',// 0x400200 NORMAL_ACCOUNT, DONT_REQ_PREAUTH
|
'4194816',// 0x400200 NORMAL_ACCOUNT, DONT_REQ_PREAUTH
|
||||||
'4260352', // 0x410200 NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD, DONT_REQ_PREAUTH
|
'4260352', // 0x410200 NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD, DONT_REQ_PREAUTH
|
||||||
'1049088', // 0x100200 NORMAL_ACCOUNT, NOT_DELEGATED
|
'1049088', // 0x100200 NORMAL_ACCOUNT, NOT_DELEGATED
|
||||||
|
'1114624', // 0x110200 NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD, NOT_DELEGATED,
|
||||||
];
|
];
|
||||||
$user->activated = (in_array($results[$i]['useraccountcontrol'][0], $enabled_accounts)) ? 1 : 0;
|
$user->activated = (in_array($results[$i]['useraccountcontrol'][0], $enabled_accounts)) ? 1 : 0;
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,9 @@ class Handler extends ExceptionHandler
|
||||||
public function report(Throwable $exception)
|
public function report(Throwable $exception)
|
||||||
{
|
{
|
||||||
if ($this->shouldReport($exception)) {
|
if ($this->shouldReport($exception)) {
|
||||||
\Log::error($exception);
|
if (class_exists(\Log::class)) {
|
||||||
|
\Log::error($exception);
|
||||||
|
}
|
||||||
return parent::report($exception);
|
return parent::report($exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,7 @@ class AccessoriesController extends Controller
|
||||||
public function store(ImageUploadRequest $request)
|
public function store(ImageUploadRequest $request)
|
||||||
{
|
{
|
||||||
$this->authorize(Accessory::class);
|
$this->authorize(Accessory::class);
|
||||||
|
|
||||||
// create a new model instance
|
// create a new model instance
|
||||||
$accessory = new Accessory();
|
$accessory = new Accessory();
|
||||||
|
|
||||||
|
@ -82,7 +83,6 @@ class AccessoriesController extends Controller
|
||||||
$accessory->supplier_id = request('supplier_id');
|
$accessory->supplier_id = request('supplier_id');
|
||||||
$accessory->notes = request('notes');
|
$accessory->notes = request('notes');
|
||||||
|
|
||||||
|
|
||||||
$accessory = $request->handleImages($accessory);
|
$accessory = $request->handleImages($accessory);
|
||||||
|
|
||||||
// Was the accessory created?
|
// Was the accessory created?
|
||||||
|
@ -127,45 +127,47 @@ class AccessoriesController extends Controller
|
||||||
*/
|
*/
|
||||||
public function update(ImageUploadRequest $request, $accessoryId = null)
|
public function update(ImageUploadRequest $request, $accessoryId = null)
|
||||||
{
|
{
|
||||||
if (is_null($accessory = Accessory::find($accessoryId))) {
|
if ($accessory = Accessory::withCount('users as users_count')->find($accessoryId)) {
|
||||||
|
|
||||||
|
$this->authorize($accessory);
|
||||||
|
|
||||||
|
$validator = Validator::make($request->all(), [
|
||||||
|
"qty" => "required|numeric|min:$accessory->users_count"
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($validator->fails()) {
|
||||||
|
return redirect()->back()
|
||||||
|
->withErrors($validator)
|
||||||
|
->withInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Update the accessory data
|
||||||
|
$accessory->name = request('name');
|
||||||
|
$accessory->location_id = request('location_id');
|
||||||
|
$accessory->min_amt = request('min_amt');
|
||||||
|
$accessory->category_id = request('category_id');
|
||||||
|
$accessory->company_id = Company::getIdForCurrentUser(request('company_id'));
|
||||||
|
$accessory->manufacturer_id = request('manufacturer_id');
|
||||||
|
$accessory->order_number = request('order_number');
|
||||||
|
$accessory->model_number = request('model_number');
|
||||||
|
$accessory->purchase_date = request('purchase_date');
|
||||||
|
$accessory->purchase_cost = Helper::ParseCurrency(request('purchase_cost'));
|
||||||
|
$accessory->qty = request('qty');
|
||||||
|
$accessory->supplier_id = request('supplier_id');
|
||||||
|
$accessory->notes = request('notes');
|
||||||
|
|
||||||
|
$accessory = $request->handleImages($accessory);
|
||||||
|
|
||||||
|
// Was the accessory updated?
|
||||||
|
if ($accessory->save()) {
|
||||||
|
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.update.success'));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
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'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$min = $accessory->numCheckedOut();
|
|
||||||
$validator = Validator::make($request->all(), [
|
|
||||||
"qty" => "required|numeric|min:$min"
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($validator->fails()) {
|
|
||||||
return redirect()->back()
|
|
||||||
->withErrors($validator)
|
|
||||||
->withInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->authorize($accessory);
|
|
||||||
|
|
||||||
// Update the accessory data
|
|
||||||
$accessory->name = request('name');
|
|
||||||
$accessory->location_id = request('location_id');
|
|
||||||
$accessory->min_amt = request('min_amt');
|
|
||||||
$accessory->category_id = request('category_id');
|
|
||||||
$accessory->company_id = Company::getIdForCurrentUser(request('company_id'));
|
|
||||||
$accessory->manufacturer_id = request('manufacturer_id');
|
|
||||||
$accessory->order_number = request('order_number');
|
|
||||||
$accessory->model_number = request('model_number');
|
|
||||||
$accessory->purchase_date = request('purchase_date');
|
|
||||||
$accessory->purchase_cost = Helper::ParseCurrency(request('purchase_cost'));
|
|
||||||
$accessory->qty = request('qty');
|
|
||||||
$accessory->supplier_id = request('supplier_id');
|
|
||||||
$accessory->notes = request('notes');
|
|
||||||
|
|
||||||
$accessory = $request->handleImages($accessory);
|
|
||||||
|
|
||||||
// Was the accessory updated?
|
|
||||||
if ($accessory->save()) {
|
|
||||||
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.update.success'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return redirect()->back()->withInput()->withErrors($accessory->getErrors());
|
return redirect()->back()->withInput()->withErrors($accessory->getErrors());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,7 +219,7 @@ class AccessoriesController extends Controller
|
||||||
*/
|
*/
|
||||||
public function show($accessoryID = null)
|
public function show($accessoryID = null)
|
||||||
{
|
{
|
||||||
$accessory = Accessory::find($accessoryID);
|
$accessory = Accessory::withCount('users as users_count')->find($accessoryID);
|
||||||
$this->authorize('view', $accessory);
|
$this->authorize('view', $accessory);
|
||||||
if (isset($accessory->id)) {
|
if (isset($accessory->id)) {
|
||||||
return view('accessories/view', compact('accessory'));
|
return view('accessories/view', compact('accessory'));
|
||||||
|
|
|
@ -222,8 +222,8 @@ class AcceptanceController extends Controller
|
||||||
'item_model' => $display_model,
|
'item_model' => $display_model,
|
||||||
'item_serial' => $item->serial,
|
'item_serial' => $item->serial,
|
||||||
'eula' => $item->getEula(),
|
'eula' => $item->getEula(),
|
||||||
'check_out_date' => Carbon::parse($acceptance->created_at)->format($branding_settings->date_display_format),
|
'check_out_date' => Carbon::parse($acceptance->created_at)->format('Y-m-d'),
|
||||||
'accepted_date' => Carbon::parse($acceptance->accepted_at)->format($branding_settings->date_display_format),
|
'accepted_date' => Carbon::parse($acceptance->accepted_at)->format('Y-m-d'),
|
||||||
'assigned_to' => $assigned_to,
|
'assigned_to' => $assigned_to,
|
||||||
'company_name' => $branding_settings->site_name,
|
'company_name' => $branding_settings->site_name,
|
||||||
'signature' => ($sig_filename) ? storage_path() . '/private_uploads/signatures/' . $sig_filename : null,
|
'signature' => ($sig_filename) ? storage_path() . '/private_uploads/signatures/' . $sig_filename : null,
|
||||||
|
@ -273,7 +273,7 @@ class AcceptanceController extends Controller
|
||||||
'item_tag' => $item->asset_tag,
|
'item_tag' => $item->asset_tag,
|
||||||
'item_model' => $display_model,
|
'item_model' => $display_model,
|
||||||
'item_serial' => $item->serial,
|
'item_serial' => $item->serial,
|
||||||
'declined_date' => Carbon::parse($acceptance->accepted_at)->format($branding_settings->date_display_format),
|
'declined_date' => Carbon::parse($acceptance->declined_at)->format('Y-m-d'),
|
||||||
'assigned_to' => $assigned_to,
|
'assigned_to' => $assigned_to,
|
||||||
'company_name' => $branding_settings->site_name,
|
'company_name' => $branding_settings->site_name,
|
||||||
'date_settings' => $branding_settings->date_display_format,
|
'date_settings' => $branding_settings->date_display_format,
|
||||||
|
|
|
@ -41,10 +41,13 @@ class AccessoriesController extends Controller
|
||||||
'min_amt',
|
'min_amt',
|
||||||
'company_id',
|
'company_id',
|
||||||
'notes',
|
'notes',
|
||||||
|
'users_count',
|
||||||
|
'qty',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
$accessories = Accessory::select('accessories.*')->with('category', 'company', 'manufacturer', 'users', 'location', 'supplier');
|
$accessories = Accessory::select('accessories.*')->with('category', 'company', 'manufacturer', 'users', 'location', 'supplier')
|
||||||
|
->withCount('users as users_count');
|
||||||
|
|
||||||
if ($request->filled('search')) {
|
if ($request->filled('search')) {
|
||||||
$accessories = $accessories->TextSearch($request->input('search'));
|
$accessories = $accessories->TextSearch($request->input('search'));
|
||||||
|
|
|
@ -857,7 +857,8 @@ class AssetsController extends Controller
|
||||||
$checkout_at = request('checkout_at', date('Y-m-d H:i:s'));
|
$checkout_at = request('checkout_at', date('Y-m-d H:i:s'));
|
||||||
$expected_checkin = request('expected_checkin', null);
|
$expected_checkin = request('expected_checkin', null);
|
||||||
$note = request('note', null);
|
$note = request('note', null);
|
||||||
$asset_name = request('name', null);
|
// Using `->has` preserves the asset name if the name parameter was not included in request.
|
||||||
|
$asset_name = request()->has('name') ? request('name') : $asset->name;
|
||||||
|
|
||||||
// Set the location ID to the RTD location id if there is one
|
// 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.
|
// Wait, why are we doing this? This overrides the stuff we set further up, which makes no sense.
|
||||||
|
|
|
@ -33,7 +33,7 @@ class CustomFieldsetsController extends Controller
|
||||||
*/
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$this->authorize('index', CustomFieldset::class);
|
$this->authorize('index', CustomField::class);
|
||||||
$fieldsets = CustomFieldset::withCount('fields as fields_count', 'models as models_count')->get();
|
$fieldsets = CustomFieldset::withCount('fields as fields_count', 'models as models_count')->get();
|
||||||
|
|
||||||
return (new CustomFieldsetsTransformer)->transformCustomFieldsets($fieldsets, $fieldsets->count());
|
return (new CustomFieldsetsTransformer)->transformCustomFieldsets($fieldsets, $fieldsets->count());
|
||||||
|
@ -49,7 +49,7 @@ class CustomFieldsetsController extends Controller
|
||||||
*/
|
*/
|
||||||
public function show($id)
|
public function show($id)
|
||||||
{
|
{
|
||||||
$this->authorize('view', CustomFieldset::class);
|
$this->authorize('view', CustomField::class);
|
||||||
if ($fieldset = CustomFieldset::find($id)) {
|
if ($fieldset = CustomFieldset::find($id)) {
|
||||||
return (new CustomFieldsetsTransformer)->transformCustomFieldset($fieldset);
|
return (new CustomFieldsetsTransformer)->transformCustomFieldset($fieldset);
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ class CustomFieldsetsController extends Controller
|
||||||
*/
|
*/
|
||||||
public function update(Request $request, $id)
|
public function update(Request $request, $id)
|
||||||
{
|
{
|
||||||
$this->authorize('update', CustomFieldset::class);
|
$this->authorize('update', CustomField::class);
|
||||||
$fieldset = CustomFieldset::findOrFail($id);
|
$fieldset = CustomFieldset::findOrFail($id);
|
||||||
$fieldset->fill($request->all());
|
$fieldset->fill($request->all());
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ class CustomFieldsetsController extends Controller
|
||||||
*/
|
*/
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
$this->authorize('create', CustomFieldset::class);
|
$this->authorize('create', CustomField::class);
|
||||||
$fieldset = new CustomFieldset;
|
$fieldset = new CustomFieldset;
|
||||||
$fieldset->fill($request->all());
|
$fieldset->fill($request->all());
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ class CustomFieldsetsController extends Controller
|
||||||
*/
|
*/
|
||||||
public function destroy($id)
|
public function destroy($id)
|
||||||
{
|
{
|
||||||
$this->authorize('delete', CustomFieldset::class);
|
$this->authorize('delete', CustomField::class);
|
||||||
$fieldset = CustomFieldset::findOrFail($id);
|
$fieldset = CustomFieldset::findOrFail($id);
|
||||||
|
|
||||||
$modelsCount = $fieldset->models->count();
|
$modelsCount = $fieldset->models->count();
|
||||||
|
@ -136,7 +136,7 @@ class CustomFieldsetsController extends Controller
|
||||||
*/
|
*/
|
||||||
public function fields($id)
|
public function fields($id)
|
||||||
{
|
{
|
||||||
$this->authorize('view', CustomFieldset::class);
|
$this->authorize('view', CustomField::class);
|
||||||
$set = CustomFieldset::findOrFail($id);
|
$set = CustomFieldset::findOrFail($id);
|
||||||
$fields = $set->fields;
|
$fields = $set->fields;
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ class CustomFieldsetsController extends Controller
|
||||||
*/
|
*/
|
||||||
public function fieldsWithDefaultValues($fieldsetId, $modelId)
|
public function fieldsWithDefaultValues($fieldsetId, $modelId)
|
||||||
{
|
{
|
||||||
$this->authorize('view', CustomFieldset::class);
|
$this->authorize('view', CustomField::class);
|
||||||
|
|
||||||
$set = CustomFieldset::findOrFail($fieldsetId);
|
$set = CustomFieldset::findOrFail($fieldsetId);
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ use App\Models\Asset;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
use App\Models\Import;
|
use App\Models\Import;
|
||||||
use Artisan;
|
use Artisan;
|
||||||
|
use Illuminate\Database\Eloquent\JsonEncodingException;
|
||||||
use Illuminate\Support\Facades\Request;
|
use Illuminate\Support\Facades\Request;
|
||||||
use Illuminate\Support\Facades\Session;
|
use Illuminate\Support\Facades\Session;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
@ -35,7 +36,7 @@ class ImportController extends Controller
|
||||||
* Process and store a CSV upload file.
|
* Process and store a CSV upload file.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @return \Illuminate\Http\Response
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function store()
|
public function store()
|
||||||
{
|
{
|
||||||
|
@ -56,7 +57,7 @@ class ImportController extends Controller
|
||||||
'text/tsv', ])) {
|
'text/tsv', ])) {
|
||||||
$results['error'] = 'File type must be CSV. Uploaded file is '.$file->getMimeType();
|
$results['error'] = 'File type must be CSV. Uploaded file is '.$file->getMimeType();
|
||||||
|
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', null, $results['error']), 500);
|
return response()->json(Helper::formatStandardApiResponse('error', null, $results['error']), 422);
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: is there a lighter way to do this?
|
//TODO: is there a lighter way to do this?
|
||||||
|
@ -64,7 +65,19 @@ class ImportController extends Controller
|
||||||
ini_set('auto_detect_line_endings', '1');
|
ini_set('auto_detect_line_endings', '1');
|
||||||
}
|
}
|
||||||
$reader = Reader::createFromFileObject($file->openFile('r')); //file pointer leak?
|
$reader = Reader::createFromFileObject($file->openFile('r')); //file pointer leak?
|
||||||
$import->header_row = $reader->fetchOne(0);
|
|
||||||
|
try {
|
||||||
|
$import->header_row = $reader->fetchOne(0);
|
||||||
|
} catch (JsonEncodingException $e) {
|
||||||
|
return response()->json(
|
||||||
|
Helper::formatStandardApiResponse(
|
||||||
|
'error',
|
||||||
|
null,
|
||||||
|
trans('admin/hardware/message.import.header_row_has_malformed_characters')
|
||||||
|
),
|
||||||
|
422
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
//duplicate headers check
|
//duplicate headers check
|
||||||
$duplicate_headers = [];
|
$duplicate_headers = [];
|
||||||
|
@ -82,11 +95,22 @@ class ImportController extends Controller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (count($duplicate_headers) > 0) {
|
if (count($duplicate_headers) > 0) {
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', null, implode('; ', $duplicate_headers)), 500); //should this be '4xx'?
|
return response()->json(Helper::formatStandardApiResponse('error', null, implode('; ', $duplicate_headers)),422);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grab the first row to display via ajax as the user picks fields
|
try {
|
||||||
$import->first_row = $reader->fetchOne(1);
|
// Grab the first row to display via ajax as the user picks fields
|
||||||
|
$import->first_row = $reader->fetchOne(1);
|
||||||
|
} catch (JsonEncodingException $e) {
|
||||||
|
return response()->json(
|
||||||
|
Helper::formatStandardApiResponse(
|
||||||
|
'error',
|
||||||
|
null,
|
||||||
|
trans('admin/hardware/message.import.content_row_has_malformed_characters')
|
||||||
|
),
|
||||||
|
422
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
$date = date('Y-m-d-his');
|
$date = date('Y-m-d-his');
|
||||||
$fixed_filename = str_slug($file->getClientOriginalName());
|
$fixed_filename = str_slug($file->getClientOriginalName());
|
||||||
|
@ -108,12 +132,12 @@ class ImportController extends Controller
|
||||||
}
|
}
|
||||||
$results = (new ImportsTransformer)->transformImports($results);
|
$results = (new ImportsTransformer)->transformImports($results);
|
||||||
|
|
||||||
return [
|
return response()->json([
|
||||||
'files' => $results,
|
'files' => $results,
|
||||||
];
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.feature_disabled')), 500);
|
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.feature_disabled')), 422);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -143,47 +143,6 @@ class SettingsController extends Controller
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function slacktest(SlackSettingsRequest $request)
|
|
||||||
{
|
|
||||||
|
|
||||||
$validator = Validator::make($request->all(), [
|
|
||||||
'slack_endpoint' => 'url|required_with:slack_channel|starts_with:https://hooks.slack.com/|nullable',
|
|
||||||
'slack_channel' => 'required_with:slack_endpoint|starts_with:#|nullable',
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($validator->fails()) {
|
|
||||||
return response()->json(['message' => 'Validation failed', 'errors' => $validator->errors()], 422);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If validation passes, continue to the curl request
|
|
||||||
$slack = new Client([
|
|
||||||
'base_url' => e($request->input('slack_endpoint')),
|
|
||||||
'defaults' => [
|
|
||||||
'exceptions' => false,
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$payload = json_encode(
|
|
||||||
[
|
|
||||||
'channel' => e($request->input('slack_channel')),
|
|
||||||
'text' => trans('general.slack_test_msg'),
|
|
||||||
'username' => e($request->input('slack_botname')),
|
|
||||||
'icon_emoji' => ':heart:',
|
|
||||||
]);
|
|
||||||
|
|
||||||
try {
|
|
||||||
$slack->post($request->input('slack_endpoint'), ['body' => $payload]);
|
|
||||||
return response()->json(['message' => 'Success'], 200);
|
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
return response()->json(['message' => 'Please check the channel name and webhook endpoint URL ('.e($request->input('slack_endpoint')).'). Slack responded with: '.$e->getMessage()], 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
//}
|
|
||||||
return response()->json(['message' => 'Something went wrong :( '], 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test the email configuration
|
* Test the email configuration
|
||||||
*
|
*
|
||||||
|
|
|
@ -543,9 +543,10 @@ class UsersController extends Controller
|
||||||
if (empty($user->email)) {
|
if (empty($user->email)) {
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.inventorynotification.error')));
|
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.inventorynotification.error')));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$user->notify((new CurrentInventory($user)));
|
||||||
|
|
||||||
return response()->Helper::formatStandardApiResponse('success', null, trans('admin/users/message.inventorynotification.success'));
|
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.inventorynotification.success')));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -109,9 +109,9 @@ class CustomFieldsController extends Controller
|
||||||
|
|
||||||
|
|
||||||
if ($request->filled('custom_format')) {
|
if ($request->filled('custom_format')) {
|
||||||
$field->format = e($request->get('custom_format'));
|
$field->format = $request->get('custom_format');
|
||||||
} else {
|
} else {
|
||||||
$field->format = e($request->get('format'));
|
$field->format = $request->get('format');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($field->save()) {
|
if ($field->save()) {
|
||||||
|
|
|
@ -75,9 +75,9 @@ class CustomFieldsetsController extends Controller
|
||||||
*/
|
*/
|
||||||
public function create()
|
public function create()
|
||||||
{
|
{
|
||||||
$this->authorize('create', CustomFieldset::class);
|
$this->authorize('create', CustomField::class);
|
||||||
|
|
||||||
return view('custom_fields.fieldsets.edit');
|
return view('custom_fields.fieldsets.edit')->with('item', new CustomFieldset());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -91,7 +91,7 @@ class CustomFieldsetsController extends Controller
|
||||||
*/
|
*/
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
$this->authorize('create', CustomFieldset::class);
|
$this->authorize('create', CustomField::class);
|
||||||
|
|
||||||
$cfset = new CustomFieldset([
|
$cfset = new CustomFieldset([
|
||||||
'name' => e($request->get('name')),
|
'name' => e($request->get('name')),
|
||||||
|
@ -110,31 +110,52 @@ class CustomFieldsetsController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* What the actual fuck, Brady?
|
* Presents edit form for fieldset
|
||||||
*
|
*
|
||||||
* @todo Uhh, build this?
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
|
||||||
* @param int $id
|
* @param int $id
|
||||||
* @since [v1.8]
|
* @since [v6.0.14]
|
||||||
* @return Fuckall
|
* @return Redirect
|
||||||
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
*/
|
*/
|
||||||
public function edit($id)
|
public function edit($id)
|
||||||
{
|
{
|
||||||
//
|
$this->authorize('create', CustomField::class);
|
||||||
|
|
||||||
|
if ($fieldset = CustomFieldset::find($id)) {
|
||||||
|
return view('custom_fields.fieldsets.edit')->with('item', $fieldset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->route('fields.index')->with('error', trans('admin/custom_fields/general.fieldset_does_not_exist', ['id' => $id]));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GET IN THE SEA BRADY.
|
* Saves updated fieldset data
|
||||||
*
|
*
|
||||||
* @todo Uhh, build this too?
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
|
||||||
* @param int $id
|
* @param int $id
|
||||||
* @since [v1.8]
|
* @since [v6.0.14]
|
||||||
* @return Fuckall
|
* @return Redirect
|
||||||
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
*/
|
*/
|
||||||
public function update($id)
|
public function update(Request $request, $id)
|
||||||
{
|
{
|
||||||
//
|
$this->authorize('create', CustomField::class);
|
||||||
|
|
||||||
|
if ($fieldset = CustomFieldset::find($id)) {
|
||||||
|
|
||||||
|
$fieldset->name = $request->input('name');
|
||||||
|
|
||||||
|
if ($fieldset->save()) {
|
||||||
|
return redirect()->route('fields.index')->with('success', trans('admin/custom_fields/general.fieldset_updated'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->back()->withInput()->withErrors($fieldset->getErrors());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->route('fields.index')->with('error', trans('admin/custom_fields/general.fieldset_does_not_exist', ['id' => $id]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -202,7 +223,7 @@ class CustomFieldsetsController extends Controller
|
||||||
*/
|
*/
|
||||||
public function makeFieldRequired($fieldset_id, $field_id)
|
public function makeFieldRequired($fieldset_id, $field_id)
|
||||||
{
|
{
|
||||||
$this->authorize('update', CustomFieldset::class);
|
$this->authorize('update', CustomField::class);
|
||||||
$field = CustomField::findOrFail($field_id);
|
$field = CustomField::findOrFail($field_id);
|
||||||
$fieldset = CustomFieldset::findOrFail($fieldset_id);
|
$fieldset = CustomFieldset::findOrFail($fieldset_id);
|
||||||
$fields[$field->id] = ['required' => 1];
|
$fields[$field->id] = ['required' => 1];
|
||||||
|
@ -220,7 +241,7 @@ class CustomFieldsetsController extends Controller
|
||||||
*/
|
*/
|
||||||
public function makeFieldOptional($fieldset_id, $field_id)
|
public function makeFieldOptional($fieldset_id, $field_id)
|
||||||
{
|
{
|
||||||
$this->authorize('update', CustomFieldset::class);
|
$this->authorize('update', CustomField::class);
|
||||||
$field = CustomField::findOrFail($field_id);
|
$field = CustomField::findOrFail($field_id);
|
||||||
$fieldset = CustomFieldset::findOrFail($fieldset_id);
|
$fieldset = CustomFieldset::findOrFail($fieldset_id);
|
||||||
$fields[$field->id] = ['required' => 0];
|
$fields[$field->id] = ['required' => 0];
|
||||||
|
|
|
@ -17,7 +17,7 @@ class ModalController extends Controller
|
||||||
* @author [A. Gianotto] [<snipe@snipe.net]
|
* @author [A. Gianotto] [<snipe@snipe.net]
|
||||||
* @return View
|
* @return View
|
||||||
*/
|
*/
|
||||||
function show ($type, $itemId = null) {
|
public function show ($type, $itemId = null) {
|
||||||
|
|
||||||
// These values should correspond to a file in resources/views/modals/
|
// These values should correspond to a file in resources/views/modals/
|
||||||
$allowed_types = [
|
$allowed_types = [
|
||||||
|
|
|
@ -1120,8 +1120,6 @@ class ReportsController extends Controller
|
||||||
$row[] = str_replace(',', '', e($item['assetItem']->asset_tag));
|
$row[] = str_replace(',', '', e($item['assetItem']->asset_tag));
|
||||||
$row[] = str_replace(',', '', e(($item['acceptance']->assignedTo) ? $item['acceptance']->assignedTo->present()->name() : trans('admin/reports/general.deleted_user')));
|
$row[] = str_replace(',', '', e(($item['acceptance']->assignedTo) ? $item['acceptance']->assignedTo->present()->name() : trans('admin/reports/general.deleted_user')));
|
||||||
$rows[] = implode(',', $row);
|
$rows[] = implode(',', $row);
|
||||||
} else {
|
|
||||||
// Log the error maybe?
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -679,33 +679,6 @@ class SettingsController extends Controller
|
||||||
return view('settings.slack', compact('setting'));
|
return view('settings.slack', compact('setting'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a form to allow a super admin to update settings.
|
|
||||||
*
|
|
||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
|
||||||
*
|
|
||||||
* @since [v1.0]
|
|
||||||
*
|
|
||||||
* @return View
|
|
||||||
*/
|
|
||||||
public function postSlack(SlackSettingsRequest $request)
|
|
||||||
{
|
|
||||||
if (is_null($setting = Setting::getSettings())) {
|
|
||||||
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$setting->slack_endpoint = $request->input('slack_endpoint');
|
|
||||||
$setting->slack_channel = $request->input('slack_channel');
|
|
||||||
$setting->slack_botname = $request->input('slack_botname');
|
|
||||||
|
|
||||||
if ($setting->save()) {
|
|
||||||
return redirect()->route('settings.index')
|
|
||||||
->with('success', trans('admin/settings/message.update.success'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return redirect()->back()->withInput()->withErrors($setting->getErrors());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a form to allow a super admin to update settings.
|
* Return a form to allow a super admin to update settings.
|
||||||
*
|
*
|
||||||
|
@ -807,7 +780,7 @@ class SettingsController extends Controller
|
||||||
*/
|
*/
|
||||||
public function getPhpInfo()
|
public function getPhpInfo()
|
||||||
{
|
{
|
||||||
if (true === config('app.debug')) {
|
if (config('app.debug') === true) {
|
||||||
return view('settings.phpinfo');
|
return view('settings.phpinfo');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
95
app/Http/Livewire/SlackSettingsForm.php
Normal file
95
app/Http/Livewire/SlackSettingsForm.php
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Livewire;
|
||||||
|
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
use Livewire\Component;
|
||||||
|
use App\Models\Setting;
|
||||||
|
|
||||||
|
class SlackSettingsForm extends Component
|
||||||
|
{
|
||||||
|
public $slack_endpoint;
|
||||||
|
public $slack_channel;
|
||||||
|
public $slack_botname;
|
||||||
|
public $isDisabled ='disabled' ;
|
||||||
|
|
||||||
|
public Setting $setting;
|
||||||
|
|
||||||
|
protected $rules = [
|
||||||
|
'slack_endpoint' => 'url|required_with:slack_channel|starts_with:https://hooks.slack.com/|nullable',
|
||||||
|
'slack_channel' => 'required_with:slack_endpoint|starts_with:#|nullable',
|
||||||
|
'slack_botname' => 'string|nullable',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function mount(){
|
||||||
|
|
||||||
|
$this->setting = Setting::getSettings();
|
||||||
|
$this->slack_endpoint = $this->setting->slack_endpoint;
|
||||||
|
$this->slack_channel = $this->setting->slack_channel;
|
||||||
|
$this->slack_botname = $this->setting->slack_botname;
|
||||||
|
|
||||||
|
}
|
||||||
|
public function updated($field){
|
||||||
|
|
||||||
|
$this->validateOnly($field ,$this->rules);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
if(empty($this->slack_channel || $this->slack_endpoint)){
|
||||||
|
$this->isDisabled= 'disabled';
|
||||||
|
}
|
||||||
|
if(empty($this->slack_endpoint && $this->slack_channel)){
|
||||||
|
$this->isDisabled= '';
|
||||||
|
}
|
||||||
|
return view('livewire.slack-settings-form');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSlack(){
|
||||||
|
|
||||||
|
$slack = new Client([
|
||||||
|
'base_url' => e($this->slack_endpoint),
|
||||||
|
'defaults' => [
|
||||||
|
'exceptions' => false,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$payload = json_encode(
|
||||||
|
[
|
||||||
|
'channel' => e($this->slack_channel),
|
||||||
|
'text' => trans('general.slack_test_msg'),
|
||||||
|
'username' => e($this->slack_botname),
|
||||||
|
'icon_emoji' => ':heart:',
|
||||||
|
]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$slack->post($this->slack_endpoint, ['body' => $payload]);
|
||||||
|
$this->isDisabled='';
|
||||||
|
return session()->flash('success' , 'Your Slack Integration works!');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->isDisabled= 'disabled';
|
||||||
|
return session()->flash('error' , trans('admin/settings/message.slack.error', ['error_message' => $e->getMessage()]));
|
||||||
|
}
|
||||||
|
|
||||||
|
//}
|
||||||
|
return session()->flash('message' , trans('admin/settings/message.slack.error_misc'));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
public function submit()
|
||||||
|
{
|
||||||
|
$this->validate($this->rules);
|
||||||
|
|
||||||
|
$this->setting->slack_endpoint = $this->slack_endpoint;
|
||||||
|
$this->setting->slack_channel = $this->slack_channel;
|
||||||
|
$this->setting->slack_botname = $this->slack_botname;
|
||||||
|
|
||||||
|
$this->setting->save();
|
||||||
|
|
||||||
|
session()->flash('save',trans('admin/settings/message.update.success'));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,7 +11,7 @@ class CheckForTwoFactor
|
||||||
/**
|
/**
|
||||||
* Routes to ignore for Two Factor Auth
|
* Routes to ignore for Two Factor Auth
|
||||||
*/
|
*/
|
||||||
const IGNORE_ROUTES = ['two-factor', 'two-factor-enroll', 'setup', 'logout'];
|
public const IGNORE_ROUTES = ['two-factor', 'two-factor-enroll', 'setup', 'logout'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle an incoming request.
|
* Handle an incoming request.
|
||||||
|
|
|
@ -39,14 +39,12 @@ class SaveUserRequest extends FormRequest
|
||||||
|
|
||||||
// Brand new user
|
// Brand new user
|
||||||
case 'POST':
|
case 'POST':
|
||||||
{
|
|
||||||
$rules['first_name'] = 'required|string|min:1';
|
$rules['first_name'] = 'required|string|min:1';
|
||||||
$rules['username'] = 'required_unless:ldap_import,1|string|min:1';
|
$rules['username'] = 'required_unless:ldap_import,1|string|min:1';
|
||||||
if ($this->request->get('ldap_import') == false) {
|
if ($this->request->get('ldap_import') == false) {
|
||||||
$rules['password'] = Setting::passwordComplexityRulesSaving('store').'|confirmed';
|
$rules['password'] = Setting::passwordComplexityRulesSaving('store').'|confirmed';
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
// Save all fields
|
// Save all fields
|
||||||
case 'PUT':
|
case 'PUT':
|
||||||
|
@ -57,12 +55,11 @@ class SaveUserRequest extends FormRequest
|
||||||
|
|
||||||
// Save only what's passed
|
// Save only what's passed
|
||||||
case 'PATCH':
|
case 'PATCH':
|
||||||
{
|
|
||||||
$rules['password'] = Setting::passwordComplexityRulesSaving('update');
|
$rules['password'] = Setting::passwordComplexityRulesSaving('update');
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
default:break;
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $rules;
|
return $rules;
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Requests;
|
|
||||||
|
|
||||||
class SlackSettingsRequest extends Request
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Determine if the user is authorized to make this request.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function authorize()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the validation rules that apply to the request.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function rules()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'slack_endpoint' => 'url|required_with:slack_channel|starts_with:"https://hooks.slack.com"|nullable',
|
|
||||||
'slack_channel' => 'required_with:slack_endpoint|starts_with:#|nullable',
|
|
||||||
'slack_botname' => 'string|nullable',
|
|
||||||
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -38,7 +38,8 @@ class AccessoriesTransformer
|
||||||
'purchase_cost' => Helper::formatCurrencyOutput($accessory->purchase_cost),
|
'purchase_cost' => Helper::formatCurrencyOutput($accessory->purchase_cost),
|
||||||
'order_number' => ($accessory->order_number) ? e($accessory->order_number) : null,
|
'order_number' => ($accessory->order_number) ? e($accessory->order_number) : null,
|
||||||
'min_qty' => ($accessory->min_amt) ? (int) $accessory->min_amt : null,
|
'min_qty' => ($accessory->min_amt) ? (int) $accessory->min_amt : null,
|
||||||
'remaining_qty' => $accessory->numRemaining(),
|
'remaining_qty' => (int) $accessory->numRemaining(),
|
||||||
|
'users_count' => $accessory->users_count,
|
||||||
|
|
||||||
'created_at' => Helper::getFormattedDateObject($accessory->created_at, 'datetime'),
|
'created_at' => Helper::getFormattedDateObject($accessory->created_at, 'datetime'),
|
||||||
'updated_at' => Helper::getFormattedDateObject($accessory->updated_at, 'datetime'),
|
'updated_at' => Helper::getFormattedDateObject($accessory->updated_at, 'datetime'),
|
||||||
|
|
|
@ -60,12 +60,14 @@ class ActionlogsTransformer
|
||||||
if ($actionlog->action_type == 'accepted') {
|
if ($actionlog->action_type == 'accepted') {
|
||||||
$file_url = route('log.storedeula.download', ['filename' => $actionlog->filename]);
|
$file_url = route('log.storedeula.download', ['filename' => $actionlog->filename]);
|
||||||
} else {
|
} else {
|
||||||
if ($actionlog->itemType() == 'asset') {
|
if ($actionlog->item) {
|
||||||
$file_url = route('show/assetfile', ['assetId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
|
if ($actionlog->itemType() == 'asset') {
|
||||||
} elseif ($actionlog->itemType() == 'license') {
|
$file_url = route('show/assetfile', ['assetId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
|
||||||
$file_url = route('show.licensefile', ['licenseId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
|
} elseif ($actionlog->itemType() == 'license') {
|
||||||
} elseif ($actionlog->itemType() == 'user') {
|
$file_url = route('show.licensefile', ['licenseId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
|
||||||
$file_url = route('show/userfile', ['userId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
|
} elseif ($actionlog->itemType() == 'user') {
|
||||||
|
$file_url = route('show/userfile', ['userId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace App\Http\Transformers;
|
||||||
|
|
||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
use App\Models\AssetModel;
|
use App\Models\AssetModel;
|
||||||
use Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,11 @@ class LicenseImporter extends ItemImporter
|
||||||
$checkout_target = $this->item['checkout_target'];
|
$checkout_target = $this->item['checkout_target'];
|
||||||
$asset = Asset::where('asset_tag', $asset_tag)->first();
|
$asset = Asset::where('asset_tag', $asset_tag)->first();
|
||||||
$targetLicense = $license->freeSeat();
|
$targetLicense = $license->freeSeat();
|
||||||
|
|
||||||
|
if (is_null($targetLicense)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ($checkout_target) {
|
if ($checkout_target) {
|
||||||
$targetLicense->assigned_to = $checkout_target->id;
|
$targetLicense->assigned_to = $checkout_target->id;
|
||||||
$targetLicense->user_id = Auth::id();
|
$targetLicense->user_id = Auth::id();
|
||||||
|
|
|
@ -63,6 +63,7 @@ class Accessory extends SnipeModel
|
||||||
'company_id' => 'integer|nullable',
|
'company_id' => 'integer|nullable',
|
||||||
'min_amt' => 'integer|min:0|nullable',
|
'min_amt' => 'integer|min:0|nullable',
|
||||||
'purchase_cost' => 'numeric|nullable|gte:0',
|
'purchase_cost' => 'numeric|nullable|gte:0',
|
||||||
|
'purchase_date' => 'date_format:Y-m-d|nullable',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
@ -327,20 +328,6 @@ class Accessory extends SnipeModel
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check how many items within an accessory are checked out
|
|
||||||
*
|
|
||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
|
||||||
* @since [v5.0]
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function numCheckedOut()
|
|
||||||
{
|
|
||||||
$checkedout = 0;
|
|
||||||
$checkedout = $this->users->count();
|
|
||||||
|
|
||||||
return $checkedout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check how many items of an accessory remain
|
* Check how many items of an accessory remain
|
||||||
|
@ -351,11 +338,11 @@ class Accessory extends SnipeModel
|
||||||
*/
|
*/
|
||||||
public function numRemaining()
|
public function numRemaining()
|
||||||
{
|
{
|
||||||
$checkedout = $this->users->count();
|
$checkedout = $this->users_count;
|
||||||
$total = $this->qty;
|
$total = $this->qty;
|
||||||
$remaining = $total - $checkedout;
|
$remaining = $total - $checkedout;
|
||||||
|
|
||||||
return $remaining;
|
return (int) $remaining;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -34,9 +34,9 @@ class Asset extends Depreciable
|
||||||
use CompanyableTrait;
|
use CompanyableTrait;
|
||||||
use HasFactory, Loggable, Requestable, Presentable, SoftDeletes, ValidatingTrait, UniqueUndeletedTrait, UniqueSerialTrait;
|
use HasFactory, Loggable, Requestable, Presentable, SoftDeletes, ValidatingTrait, UniqueUndeletedTrait, UniqueSerialTrait;
|
||||||
|
|
||||||
const LOCATION = 'location';
|
public const LOCATION = 'location';
|
||||||
const ASSET = 'asset';
|
public const ASSET = 'asset';
|
||||||
const USER = 'user';
|
public const USER = 'user';
|
||||||
|
|
||||||
use Acceptable;
|
use Acceptable;
|
||||||
|
|
||||||
|
@ -84,11 +84,11 @@ class Asset extends Depreciable
|
||||||
|
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'purchase_date' => 'datetime',
|
'purchase_date' => 'date',
|
||||||
'last_checkout' => 'datetime',
|
'last_checkout' => 'datetime',
|
||||||
'expected_checkin' => 'datetime',
|
'expected_checkin' => 'date',
|
||||||
'last_audit_date' => 'datetime',
|
'last_audit_date' => 'datetime',
|
||||||
'next_audit_date' => 'datetime',
|
'next_audit_date' => 'date',
|
||||||
'model_id' => 'integer',
|
'model_id' => 'integer',
|
||||||
'status_id' => 'integer',
|
'status_id' => 'integer',
|
||||||
'company_id' => 'integer',
|
'company_id' => 'integer',
|
||||||
|
@ -105,16 +105,14 @@ class Asset extends Depreciable
|
||||||
'company_id' => 'integer|nullable',
|
'company_id' => 'integer|nullable',
|
||||||
'warranty_months' => 'numeric|nullable|digits_between:0,240',
|
'warranty_months' => 'numeric|nullable|digits_between:0,240',
|
||||||
'physical' => 'numeric|max:1|nullable',
|
'physical' => 'numeric|max:1|nullable',
|
||||||
'checkout_date' => 'date|max:10|min:10|nullable',
|
'last_checkout' => 'date_format:Y-m-d H:i:s|nullable',
|
||||||
'checkin_date' => 'date|max:10|min:10|nullable',
|
'expected_checkin' => 'date|nullable',
|
||||||
'location_id' => 'exists:locations,id|nullable',
|
'location_id' => 'exists:locations,id|nullable',
|
||||||
'rtd_location_id' => 'exists:locations,id|nullable',
|
'rtd_location_id' => 'exists:locations,id|nullable',
|
||||||
'asset_tag' => 'required|min:1|max:255|unique_undeleted',
|
'asset_tag' => 'required|min:1|max:255|unique_undeleted',
|
||||||
'status' => 'integer',
|
'purchase_date' => 'date|date_format:Y-m-d|nullable',
|
||||||
'serial' => 'unique_serial|nullable',
|
'serial' => 'unique_serial|nullable',
|
||||||
'purchase_cost' => 'numeric|nullable|gte:0',
|
'purchase_cost' => 'numeric|nullable|gte:0',
|
||||||
'next_audit_date' => 'date|nullable',
|
|
||||||
'last_audit_date' => 'date|nullable',
|
|
||||||
'supplier_id' => 'exists:suppliers,id|nullable',
|
'supplier_id' => 'exists:suppliers,id|nullable',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -145,6 +143,9 @@ class Asset extends Depreciable
|
||||||
'last_checkout',
|
'last_checkout',
|
||||||
'expected_checkin',
|
'expected_checkin',
|
||||||
'byod',
|
'byod',
|
||||||
|
'last_audit_date',
|
||||||
|
'next_audit_date',
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
use Searchable;
|
use Searchable;
|
||||||
|
|
|
@ -16,12 +16,16 @@ class CheckoutAcceptance extends Model
|
||||||
'declined_at' => 'datetime',
|
'declined_at' => 'datetime',
|
||||||
];
|
];
|
||||||
|
|
||||||
// Get the mail recipient from the config
|
/**
|
||||||
public function routeNotificationForMail(): string
|
* Get the mail recipient from the config
|
||||||
|
*
|
||||||
|
* @return mixed|string|null
|
||||||
|
*/
|
||||||
|
public function routeNotificationForMail()
|
||||||
{
|
{
|
||||||
// At this point the endpoint is the same for everything.
|
// At this point the endpoint is the same for everything.
|
||||||
// In the future this may want to be adapted for individual notifications.
|
// In the future this may want to be adapted for individual notifications.
|
||||||
return (config('mail.reply_to.address')) ? config('mail.reply_to.address') : '' ;
|
return Setting::getSettings()->alert_email;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -35,7 +35,7 @@ class Component extends SnipeModel
|
||||||
'category_id' => 'required|integer|exists:categories,id',
|
'category_id' => 'required|integer|exists:categories,id',
|
||||||
'company_id' => 'integer|nullable',
|
'company_id' => 'integer|nullable',
|
||||||
'min_amt' => 'integer|min:0|nullable',
|
'min_amt' => 'integer|min:0|nullable',
|
||||||
'purchase_date' => 'date|nullable',
|
'purchase_date' => 'date_format:Y-m-d|nullable',
|
||||||
'purchase_cost' => 'numeric|nullable|gte:0',
|
'purchase_cost' => 'numeric|nullable|gte:0',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@ class Consumable extends SnipeModel
|
||||||
'company_id' => 'integer|nullable',
|
'company_id' => 'integer|nullable',
|
||||||
'min_amt' => 'integer|min:0|nullable',
|
'min_amt' => 'integer|min:0|nullable',
|
||||||
'purchase_cost' => 'numeric|nullable|gte:0',
|
'purchase_cost' => 'numeric|nullable|gte:0',
|
||||||
|
'purchase_date' => 'date_format:Y-m-d|nullable',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -21,7 +21,7 @@ class CustomField extends Model
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
const PREDEFINED_FORMATS = [
|
public const PREDEFINED_FORMATS = [
|
||||||
'ANY' => '',
|
'ANY' => '',
|
||||||
'CUSTOM REGEX' => '',
|
'CUSTOM REGEX' => '',
|
||||||
'ALPHA' => 'alpha',
|
'ALPHA' => 'alpha',
|
||||||
|
|
|
@ -217,16 +217,16 @@ class Ldap extends Model
|
||||||
$ldap_result_manager = Setting::getSettings()->ldap_manager;
|
$ldap_result_manager = Setting::getSettings()->ldap_manager;
|
||||||
// Get LDAP user data
|
// Get LDAP user data
|
||||||
$item = [];
|
$item = [];
|
||||||
$item['username'] = isset($ldapattributes[$ldap_result_username][0]) ? $ldapattributes[$ldap_result_username][0] : '';
|
$item['username'] = $ldapattributes[$ldap_result_username][0] ?? '';
|
||||||
$item['employee_number'] = isset($ldapattributes[$ldap_result_emp_num][0]) ? $ldapattributes[$ldap_result_emp_num][0] : '';
|
$item['employee_number'] = $ldapattributes[$ldap_result_emp_num][0] ?? '';
|
||||||
$item['lastname'] = isset($ldapattributes[$ldap_result_last_name][0]) ? $ldapattributes[$ldap_result_last_name][0] : '';
|
$item['lastname'] = $ldapattributes[$ldap_result_last_name][0] ?? '';
|
||||||
$item['firstname'] = isset($ldapattributes[$ldap_result_first_name][0]) ? $ldapattributes[$ldap_result_first_name][0] : '';
|
$item['firstname'] = $ldapattributes[$ldap_result_first_name][0] ?? '';
|
||||||
$item['email'] = isset($ldapattributes[$ldap_result_email][0]) ? $ldapattributes[$ldap_result_email][0] : '';
|
$item['email'] = $ldapattributes[$ldap_result_email][0] ?? '';
|
||||||
$item['telephone'] = isset($ldapattributes[$ldap_result_phone][0]) ? $ldapattributes[$ldap_result_phone][0] : '';
|
$item['telephone'] = $ldapattributes[$ldap_result_phone][0] ?? '';
|
||||||
$item['jobtitle'] = isset($ldapattributes[$ldap_result_jobtitle][0]) ? $ldapattributes[$ldap_result_jobtitle][0] : '';
|
$item['jobtitle'] = $ldapattributes[$ldap_result_jobtitle][0] ?? '';
|
||||||
$item['country'] = isset($ldapattributes[$ldap_result_country][0]) ? $ldapattributes[$ldap_result_country][0] : '';
|
$item['country'] = $ldapattributes[$ldap_result_country][0] ?? '';
|
||||||
$item['department'] = isset($ldapattributes[$ldap_result_dept][0]) ? $ldapattributes[$ldap_result_dept][0] : '';
|
$item['department'] = $ldapattributes[$ldap_result_dept][0] ?? '';
|
||||||
$item['manager'] = isset($ldapattributes[$ldap_result_manager][0]) ? $ldapattributes[$ldap_result_manager][0] : '';
|
$item['manager'] = $ldapattributes[$ldap_result_manager][0] ?? '';
|
||||||
|
|
||||||
return $item;
|
return $item;
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,9 @@ class License extends Depreciable
|
||||||
'category_id' => 'required|exists:categories,id',
|
'category_id' => 'required|exists:categories,id',
|
||||||
'company_id' => 'integer|nullable',
|
'company_id' => 'integer|nullable',
|
||||||
'purchase_cost'=> 'numeric|nullable|gte:0',
|
'purchase_cost'=> 'numeric|nullable|gte:0',
|
||||||
|
'purchase_date' => 'date_format:Y-m-d|nullable',
|
||||||
|
'expiration_date' => 'date_format:Y-m-d|nullable',
|
||||||
|
'termination_date' => 'date_format:Y-m-d|nullable',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -31,7 +31,7 @@ class Setting extends Model
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
const SETUP_CHECK_KEY = 'snipeit_setup_check';
|
public const SETUP_CHECK_KEY = 'snipeit_setup_check';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the model should inject it's identifier to the unique
|
* Whether the model should inject it's identifier to the unique
|
||||||
|
@ -83,6 +83,9 @@ class Setting extends Model
|
||||||
'email_domain',
|
'email_domain',
|
||||||
'email_format',
|
'email_format',
|
||||||
'username_format',
|
'username_format',
|
||||||
|
'slack_endpoint',
|
||||||
|
'slack_channel',
|
||||||
|
'slack_botname',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -12,94 +12,9 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig
|
||||||
{
|
{
|
||||||
public function getUserConfig()
|
public function getUserConfig()
|
||||||
{
|
{
|
||||||
$config = parent::getUserConfig();
|
|
||||||
|
|
||||||
// Much of this is copied verbatim from the library, then adjusted for our needs
|
// Much of this is copied verbatim from the library, then adjusted for our needs
|
||||||
$config['class'] = SCIMUser::class;
|
|
||||||
|
|
||||||
unset($config['mapping']['example:name:space']);
|
/*
|
||||||
|
|
||||||
$config['map_unmapped'] = false; // anything we don't explicitly map will _not_ show up.
|
|
||||||
|
|
||||||
$core_namespace = 'urn:ietf:params:scim:schemas:core:2.0:User';
|
|
||||||
$core = $core_namespace.':';
|
|
||||||
$mappings =& $config['mapping'][$core_namespace]; //grab this entire key, we don't want to be repeating ourselves
|
|
||||||
|
|
||||||
//username - *REQUIRED*
|
|
||||||
$config['validations'][$core.'userName'] = 'required';
|
|
||||||
$mappings['userName'] = AttributeMapping::eloquent('username');
|
|
||||||
|
|
||||||
//human name - *FIRST NAME REQUIRED*
|
|
||||||
$config['validations'][$core.'name.givenName'] = 'required';
|
|
||||||
$config['validations'][$core.'name.familyName'] = 'string'; //not required
|
|
||||||
|
|
||||||
$mappings['name']['familyName'] = AttributeMapping::eloquent("last_name");
|
|
||||||
$mappings['name']['givenName'] = AttributeMapping::eloquent("first_name");
|
|
||||||
$mappings['name']['formatted'] = (new AttributeMapping())->ignoreWrite()->setRead(
|
|
||||||
function (&$object) {
|
|
||||||
return $object->getFullNameAttribute();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// externalId support
|
|
||||||
$config['validations'][$core.'externalId'] = 'string|nullable'; // not required, but supported mostly just for Okta
|
|
||||||
// note that the mapping is *not* namespaced like the other $mappings
|
|
||||||
$config['mapping']['externalId'] = AttributeMapping::eloquent('scim_externalid');
|
|
||||||
|
|
||||||
$config['validations'][$core.'emails'] = 'nullable|array'; // emails are not required in Snipe-IT...
|
|
||||||
$config['validations'][$core.'emails.*.value'] = 'email'; // ...(had to remove the recommended 'required' here)
|
|
||||||
|
|
||||||
$mappings['emails'] = [[
|
|
||||||
"value" => AttributeMapping::eloquent("email"),
|
|
||||||
"display" => null,
|
|
||||||
"type" => AttributeMapping::constant("work")->ignoreWrite(),
|
|
||||||
"primary" => AttributeMapping::constant(true)->ignoreWrite()
|
|
||||||
]];
|
|
||||||
|
|
||||||
//active
|
|
||||||
$config['validations'][$core.'active'] = 'boolean';
|
|
||||||
|
|
||||||
$mappings['active'] = AttributeMapping::eloquent('activated');
|
|
||||||
|
|
||||||
//phone
|
|
||||||
$config['validations'][$core.'phoneNumbers'] = 'nullable|array';
|
|
||||||
$config['validations'][$core.'phoneNumbers.*.value'] = 'string'; // another one where want to say 'we don't _need_ a phone number, but if you have one it better have a value.
|
|
||||||
|
|
||||||
$mappings['phoneNumbers'] = [[
|
|
||||||
"value" => AttributeMapping::eloquent("phone"),
|
|
||||||
"display" => null,
|
|
||||||
"type" => AttributeMapping::constant("work")->ignoreWrite(),
|
|
||||||
"primary" => AttributeMapping::constant(true)->ignoreWrite()
|
|
||||||
]];
|
|
||||||
|
|
||||||
//address
|
|
||||||
$config['validations'][$core.'addresses'] = 'nullable|array';
|
|
||||||
$config['validations'][$core.'addresses.*.streetAddress'] = 'string';
|
|
||||||
$config['validations'][$core.'addresses.*.locality'] = 'string';
|
|
||||||
$config['validations'][$core.'addresses.*.region'] = 'nullable|string';
|
|
||||||
$config['validations'][$core.'addresses.*.postalCode'] = 'nullable|string';
|
|
||||||
$config['validations'][$core.'addresses.*.country'] = 'string';
|
|
||||||
|
|
||||||
$mappings['addresses'] = [[
|
|
||||||
'type' => AttributeMapping::constant("work")->ignoreWrite(),
|
|
||||||
'formatted' => AttributeMapping::constant("n/a")->ignoreWrite(), // TODO - is this right? This doesn't look right.
|
|
||||||
'streetAddress' => AttributeMapping::eloquent("address"),
|
|
||||||
'locality' => AttributeMapping::eloquent("city"),
|
|
||||||
'region' => AttributeMapping::eloquent("state"),
|
|
||||||
'postalCode' => AttributeMapping::eloquent("zip"),
|
|
||||||
'country' => AttributeMapping::eloquent("country"),
|
|
||||||
'primary' => AttributeMapping::constant(true)->ignoreWrite() //this isn't in the example?
|
|
||||||
]];
|
|
||||||
|
|
||||||
//title
|
|
||||||
$config['validations'][$core.'title'] = 'string';
|
|
||||||
$mappings['title'] = AttributeMapping::eloquent('jobtitle');
|
|
||||||
|
|
||||||
//Preferred Language
|
|
||||||
$config['validations'][$core.'preferredLanguage'] = 'string';
|
|
||||||
$mappings['preferredLanguage'] = AttributeMapping::eloquent('locale');
|
|
||||||
|
|
||||||
/*
|
|
||||||
more snipe-it attributes I'd like to check out (to map to 'enterprise' maybe?):
|
more snipe-it attributes I'd like to check out (to map to 'enterprise' maybe?):
|
||||||
- website
|
- website
|
||||||
- notes?
|
- notes?
|
||||||
|
@ -108,66 +23,213 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig
|
||||||
- company_id to "organization?"
|
- company_id to "organization?"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$enterprise_namespace = 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User';
|
|
||||||
$ent = $enterprise_namespace.':';
|
|
||||||
|
|
||||||
// we remove the 'example' namespace and add the Enterprise one
|
$user_prefix = 'urn:ietf:params:scim:schemas:core:2.0:User:';
|
||||||
$config['mapping']['schemas'] = AttributeMapping::constant( [$core_namespace, $enterprise_namespace] )->ignoreWrite();
|
$enterprise_prefix = 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:';
|
||||||
|
|
||||||
$config['validations'][$ent.'employeeNumber'] = 'string';
|
return [
|
||||||
$config['validations'][$ent.'department'] = 'string';
|
|
||||||
$config['validations'][$ent.'manager'] = 'nullable';
|
|
||||||
$config['validations'][$ent.'manager.value'] = 'string';
|
|
||||||
|
|
||||||
$config['mapping'][$enterprise_namespace] = [
|
// Set to 'null' to make use of auth.providers.users.model (App\User::class)
|
||||||
'employeeNumber' => AttributeMapping::eloquent('employee_num'),
|
'class' => SCIMUser::class,
|
||||||
'department' =>(new AttributeMapping())->setAdd( // FIXME parent?
|
|
||||||
function ($value, &$object) {
|
'validations' => [
|
||||||
$department = Department::where("name", $value)->first();
|
$user_prefix . 'userName' => 'required',
|
||||||
if ($department) {
|
$user_prefix . 'name.givenName' => 'required',
|
||||||
$object->department_id = $department->id;
|
$user_prefix . 'name.familyName' => 'nullable|string',
|
||||||
}
|
$user_prefix . 'externalId' => 'nullable|string',
|
||||||
}
|
$user_prefix . 'emails' => 'nullable|array',
|
||||||
)->setReplace(
|
$user_prefix . 'emails.*.value' => 'nullable|email',
|
||||||
function ($value, &$object) {
|
$user_prefix . 'active' => 'boolean',
|
||||||
$department = Department::where("name", $value)->first();
|
$user_prefix . 'phoneNumbers' => 'nullable|array',
|
||||||
if ($department) {
|
$user_prefix . 'phoneNumbers.*.value' => 'nullable|string',
|
||||||
$object->department_id = $department->id;
|
$user_prefix . 'addresses' => 'nullable|array',
|
||||||
|
$user_prefix . 'addresses.*.streetAddress' => 'nullable|string',
|
||||||
|
$user_prefix . 'addresses.*.locality' => 'nullable|string',
|
||||||
|
$user_prefix . 'addresses.*.region' => 'nullable|string',
|
||||||
|
$user_prefix . 'addresses.*.postalCode' => 'nullable|string',
|
||||||
|
$user_prefix . 'addresses.*.country' => 'nullable|string',
|
||||||
|
$user_prefix . 'title' => 'nullable|string',
|
||||||
|
$user_prefix . 'preferredLanguage' => 'nullable|string',
|
||||||
|
|
||||||
|
// Enterprise validations:
|
||||||
|
$enterprise_prefix . 'employeeNumber' => 'nullable|string',
|
||||||
|
$enterprise_prefix . 'department' => 'nullable|string',
|
||||||
|
$enterprise_prefix . 'manager' => 'nullable',
|
||||||
|
$enterprise_prefix . 'manager.value' => 'nullable|string'
|
||||||
|
],
|
||||||
|
|
||||||
|
'singular' => 'User',
|
||||||
|
'schema' => [Schema::SCHEMA_USER],
|
||||||
|
|
||||||
|
//eager loading
|
||||||
|
'withRelations' => [],
|
||||||
|
'map_unmapped' => false,
|
||||||
|
// 'unmapped_namespace' => 'urn:ietf:params:scim:schemas:laravel:unmapped',
|
||||||
|
'description' => 'User Account',
|
||||||
|
|
||||||
|
// Map a SCIM attribute to an attribute of the object.
|
||||||
|
'mapping' => [
|
||||||
|
|
||||||
|
'id' => AttributeMapping::eloquent("id")->disableWrite(),
|
||||||
|
|
||||||
|
'externalId' => AttributeMapping::eloquent('scim_externalid'), // FIXME - I have a PR that changes a lot of this.
|
||||||
|
|
||||||
|
'meta' => [
|
||||||
|
'created' => AttributeMapping::eloquent("created_at")->disableWrite(),
|
||||||
|
'lastModified' => AttributeMapping::eloquent("updated_at")->disableWrite(),
|
||||||
|
|
||||||
|
'location' => (new AttributeMapping())->setRead(
|
||||||
|
function ($object) {
|
||||||
|
return route(
|
||||||
|
'scim.resource',
|
||||||
|
[
|
||||||
|
'resourceType' => 'Users',
|
||||||
|
'resourceObject' => $object->id
|
||||||
|
]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
)->disableWrite(),
|
||||||
)->setRead(
|
|
||||||
function (&$object) {
|
'resourceType' => AttributeMapping::constant("User")
|
||||||
return $object->department ? $object->department->name : null;
|
],
|
||||||
}
|
|
||||||
),
|
'schemas' => AttributeMapping::constant(
|
||||||
'manager' => [
|
[
|
||||||
// FIXME - manager writes are disabled. This kinda works but it leaks errors all over the place. Not cool.
|
'urn:ietf:params:scim:schemas:core:2.0:User',
|
||||||
// '$ref' => (new AttributeMapping())->ignoreWrite()->ignoreRead(),
|
'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User'
|
||||||
// 'displayName' => (new AttributeMapping())->ignoreWrite()->ignoreRead(),
|
]
|
||||||
// NOTE: you could probably do a 'plain' Eloquent mapping here, but we don't for future-proofing
|
)->ignoreWrite(),
|
||||||
'value' => (new AttributeMapping())->setAdd(
|
|
||||||
function ($value, &$object) {
|
'urn:ietf:params:scim:schemas:core:2.0:User' => [
|
||||||
$manager = User::find($value);
|
|
||||||
if ($manager) {
|
'userName' => AttributeMapping::eloquent("username"),
|
||||||
$object->manager_id = $manager->id;
|
|
||||||
|
'name' => [
|
||||||
|
'formatted' => (new AttributeMapping())->ignoreWrite()->setRead(
|
||||||
|
function (&$object) {
|
||||||
|
return $object->getFullNameAttribute();
|
||||||
|
}
|
||||||
|
),
|
||||||
|
'familyName' => AttributeMapping::eloquent("last_name"),
|
||||||
|
'givenName' => AttributeMapping::eloquent("first_name"),
|
||||||
|
'middleName' => null,
|
||||||
|
'honorificPrefix' => null,
|
||||||
|
'honorificSuffix' => null
|
||||||
|
],
|
||||||
|
|
||||||
|
'displayName' => null,
|
||||||
|
'nickName' => null,
|
||||||
|
'profileUrl' => null,
|
||||||
|
'title' => AttributeMapping::eloquent('jobtitle'),
|
||||||
|
'userType' => null,
|
||||||
|
'preferredLanguage' => AttributeMapping::eloquent('locale'), // Section 5.3.5 of [RFC7231]
|
||||||
|
'locale' => null, // see RFC5646
|
||||||
|
'timezone' => null, // see RFC6557
|
||||||
|
'active' => AttributeMapping::eloquent('activated'),
|
||||||
|
|
||||||
|
'password' => AttributeMapping::eloquent('password')->disableRead(),
|
||||||
|
|
||||||
|
// Multi-Valued Attributes
|
||||||
|
'emails' => [[
|
||||||
|
"value" => AttributeMapping::eloquent("email"),
|
||||||
|
"display" => null,
|
||||||
|
"type" => AttributeMapping::constant("work")->ignoreWrite(),
|
||||||
|
"primary" => AttributeMapping::constant(true)->ignoreWrite()
|
||||||
|
]],
|
||||||
|
|
||||||
|
'phoneNumbers' => [[
|
||||||
|
"value" => AttributeMapping::eloquent("phone"),
|
||||||
|
"display" => null,
|
||||||
|
"type" => AttributeMapping::constant("work")->ignoreWrite(),
|
||||||
|
"primary" => AttributeMapping::constant(true)->ignoreWrite()
|
||||||
|
]],
|
||||||
|
|
||||||
|
'ims' => [[
|
||||||
|
"value" => null,
|
||||||
|
"display" => null,
|
||||||
|
"type" => null,
|
||||||
|
"primary" => null
|
||||||
|
]], // Instant messaging addresses for the User
|
||||||
|
|
||||||
|
'photos' => [[
|
||||||
|
"value" => null,
|
||||||
|
"display" => null,
|
||||||
|
"type" => null,
|
||||||
|
"primary" => null
|
||||||
|
]],
|
||||||
|
|
||||||
|
'addresses' => [[
|
||||||
|
'type' => AttributeMapping::constant("work")->ignoreWrite(),
|
||||||
|
'formatted' => AttributeMapping::constant("n/a")->ignoreWrite(), // TODO - is this right? This doesn't look right.
|
||||||
|
'streetAddress' => AttributeMapping::eloquent("address"),
|
||||||
|
'locality' => AttributeMapping::eloquent("city"),
|
||||||
|
'region' => AttributeMapping::eloquent("state"),
|
||||||
|
'postalCode' => AttributeMapping::eloquent("zip"),
|
||||||
|
'country' => AttributeMapping::eloquent("country"),
|
||||||
|
'primary' => AttributeMapping::constant(true)->ignoreWrite() //this isn't in the example?
|
||||||
|
]],
|
||||||
|
|
||||||
|
'groups' => [[
|
||||||
|
'value' => null,
|
||||||
|
'$ref' => null,
|
||||||
|
'display' => null,
|
||||||
|
'type' => null,
|
||||||
|
'type' => null
|
||||||
|
]],
|
||||||
|
|
||||||
|
'entitlements' => null,
|
||||||
|
'roles' => null,
|
||||||
|
'x509Certificates' => null
|
||||||
|
],
|
||||||
|
|
||||||
|
'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User' => [
|
||||||
|
'employeeNumber' => AttributeMapping::eloquent('employee_num'),
|
||||||
|
'department' => (new AttributeMapping())->setAdd( // FIXME parent?
|
||||||
|
function ($value, &$object) {
|
||||||
|
$department = Department::where("name", $value)->first();
|
||||||
|
if ($department) {
|
||||||
|
$object->department_id = $department->id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
)->setReplace(
|
)->setReplace(
|
||||||
function ($value, &$object) {
|
function ($value, &$object) {
|
||||||
$manager = User::find($value);
|
$department = Department::where("name", $value)->first();
|
||||||
if ($manager) {
|
if ($department) {
|
||||||
$object->manager_id = $manager->id;
|
$object->department_id = $department->id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)->setRead(
|
)->setRead(
|
||||||
function (&$object) {
|
function (&$object) {
|
||||||
return $object->manager_id;
|
return $object->department ? $object->department->name : null;
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
'manager' => [
|
||||||
|
// FIXME - manager writes are disabled. This kinda works but it leaks errors all over the place. Not cool.
|
||||||
|
// '$ref' => (new AttributeMapping())->ignoreWrite()->ignoreRead(),
|
||||||
|
// 'displayName' => (new AttributeMapping())->ignoreWrite()->ignoreRead(),
|
||||||
|
// NOTE: you could probably do a 'plain' Eloquent mapping here, but we don't for future-proofing
|
||||||
|
'value' => (new AttributeMapping())->setAdd(
|
||||||
|
function ($value, &$object) {
|
||||||
|
$manager = User::find($value);
|
||||||
|
if ($manager) {
|
||||||
|
$object->manager_id = $manager->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)->setReplace(
|
||||||
|
function ($value, &$object) {
|
||||||
|
$manager = User::find($value);
|
||||||
|
if ($manager) {
|
||||||
|
$object->manager_id = $manager->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)->setRead(
|
||||||
|
function (&$object) {
|
||||||
|
return $object->manager_id;
|
||||||
|
}
|
||||||
|
),
|
||||||
|
]
|
||||||
|
]
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
return $config;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,7 +164,7 @@ trait Searchable
|
||||||
}
|
}
|
||||||
// I put this here because I only want to add the concat one time in the end of the user relation search
|
// I put this here because I only want to add the concat one time in the end of the user relation search
|
||||||
if($relation == 'user') {
|
if($relation == 'user') {
|
||||||
$query->orWhereRaw('CONCAT (users.first_name, " ", users.last_name) LIKE ?', ["%$term%"]);
|
$query->orWhereRaw('CONCAT (users.first_name, " ", users.last_name) LIKE ?', ["%{$term}%"]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -195,7 +195,7 @@ trait Searchable
|
||||||
*/
|
*/
|
||||||
private function getSearchableAttributes()
|
private function getSearchableAttributes()
|
||||||
{
|
{
|
||||||
return isset($this->searchableAttributes) ? $this->searchableAttributes : [];
|
return $this->searchableAttributes ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -205,7 +205,7 @@ trait Searchable
|
||||||
*/
|
*/
|
||||||
private function getSearchableRelations()
|
private function getSearchableRelations()
|
||||||
{
|
{
|
||||||
return isset($this->searchableRelations) ? $this->searchableRelations : [];
|
return $this->searchableRelations ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -100,8 +100,8 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||||
'website' => 'url|nullable|max:191',
|
'website' => 'url|nullable|max:191',
|
||||||
'manager_id' => 'nullable|exists:users,id|cant_manage_self',
|
'manager_id' => 'nullable|exists:users,id|cant_manage_self',
|
||||||
'location_id' => 'exists:locations,id|nullable',
|
'location_id' => 'exists:locations,id|nullable',
|
||||||
'start_date' => 'nullable|date',
|
'start_date' => 'nullable|date_format:Y-m-d',
|
||||||
'end_date' => 'nullable|date|after_or_equal:start_date',
|
'end_date' => 'nullable|date_format:Y-m-d|after_or_equal:start_date',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -659,7 +659,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||||
{
|
{
|
||||||
$query = $query->where('first_name', 'LIKE', '%'.$search.'%')
|
$query = $query->where('first_name', 'LIKE', '%'.$search.'%')
|
||||||
->orWhere('last_name', 'LIKE', '%'.$search.'%')
|
->orWhere('last_name', 'LIKE', '%'.$search.'%')
|
||||||
->orWhereRaw('CONCAT('.DB::getTablePrefix().'users.first_name," ",'.DB::getTablePrefix().'users.last_name) LIKE ?', ["%$search%"]);
|
->orWhereRaw('CONCAT('.DB::getTablePrefix().'users.first_name," ",'.DB::getTablePrefix().'users.last_name) LIKE ?', ["%{$search}%"]);
|
||||||
|
|
||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
@ -675,7 +675,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||||
public function advancedTextSearch(Builder $query, array $terms) {
|
public function advancedTextSearch(Builder $query, array $terms) {
|
||||||
|
|
||||||
foreach($terms as $term) {
|
foreach($terms as $term) {
|
||||||
$query = $query->orWhereRaw('CONCAT('.DB::getTablePrefix().'users.first_name," ",'.DB::getTablePrefix().'users.last_name) LIKE ?', ["%$term%"]);
|
$query = $query->orWhereRaw('CONCAT('.DB::getTablePrefix().'users.first_name," ",'.DB::getTablePrefix().'users.last_name) LIKE ?', ["%{$term}%"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $query;
|
return $query;
|
||||||
|
|
|
@ -40,12 +40,17 @@ class AcceptanceAssetAcceptedNotification extends Notification
|
||||||
public function via()
|
public function via()
|
||||||
{
|
{
|
||||||
|
|
||||||
$notifyBy[] = 'mail';
|
$notifyBy = ['mail'];
|
||||||
|
|
||||||
return $notifyBy;
|
return $notifyBy;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function shouldSend($notifiable, $channel)
|
||||||
|
{
|
||||||
|
return $this->settings->alerts_enabled && ! empty($this->settings->alert_email);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the mail representation of the notification.
|
* Get the mail representation of the notification.
|
||||||
*
|
*
|
||||||
|
|
|
@ -38,12 +38,17 @@ class AcceptanceAssetDeclinedNotification extends Notification
|
||||||
*/
|
*/
|
||||||
public function via($notifiable)
|
public function via($notifiable)
|
||||||
{
|
{
|
||||||
$notifyBy[] = 'mail';
|
$notifyBy = ['mail'];
|
||||||
|
|
||||||
return $notifyBy;
|
return $notifyBy;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function shouldSend($notifiable, $channel)
|
||||||
|
{
|
||||||
|
return $this->settings->alerts_enabled && ! empty($this->settings->alert_email);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the mail representation of the notification.
|
* Get the mail representation of the notification.
|
||||||
*
|
*
|
||||||
|
|
|
@ -44,7 +44,7 @@ class CurrentInventory extends Notification
|
||||||
'accessories' => $this->user->accessories,
|
'accessories' => $this->user->accessories,
|
||||||
'licenses' => $this->user->licenses,
|
'licenses' => $this->user->licenses,
|
||||||
])
|
])
|
||||||
->subject('Inventory Report');
|
->subject(trans('mail.inventory_report'));
|
||||||
|
|
||||||
return $message;
|
return $message;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ class InventoryAlert extends Notification
|
||||||
*/
|
*/
|
||||||
public function via()
|
public function via()
|
||||||
{
|
{
|
||||||
$notifyBy[] = 'mail';
|
$notifyBy = ['mail'];
|
||||||
|
|
||||||
return $notifyBy;
|
return $notifyBy;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ class SendUpcomingAuditNotification extends Notification
|
||||||
*/
|
*/
|
||||||
public function toMail()
|
public function toMail()
|
||||||
{
|
{
|
||||||
$message = (new MailMessage)->markdown('notifications.markdown.upcoming-audits',
|
$message = (new MailMessage())->markdown('notifications.markdown.upcoming-audits',
|
||||||
[
|
[
|
||||||
'assets' => $this->assets,
|
'assets' => $this->assets,
|
||||||
'threshold' => $this->threshold,
|
'threshold' => $this->threshold,
|
||||||
|
|
|
@ -44,7 +44,7 @@ class WelcomeNotification extends Notification
|
||||||
*/
|
*/
|
||||||
public function toMail()
|
public function toMail()
|
||||||
{
|
{
|
||||||
return (new MailMessage)
|
return (new MailMessage())
|
||||||
->subject(trans('mail.welcome', ['name' => $this->_data['first_name'].' '.$this->_data['last_name']]))
|
->subject(trans('mail.welcome', ['name' => $this->_data['first_name'].' '.$this->_data['last_name']]))
|
||||||
->markdown('notifications.Welcome', $this->_data);
|
->markdown('notifications.Welcome', $this->_data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,19 +80,25 @@ class AccessoryPresenter extends Presenter
|
||||||
], [
|
], [
|
||||||
'field' => 'qty',
|
'field' => 'qty',
|
||||||
'searchable' => false,
|
'searchable' => false,
|
||||||
'sortable' => false,
|
|
||||||
'title' => trans('admin/accessories/general.total'),
|
|
||||||
], [
|
|
||||||
'field' => 'min_qty',
|
|
||||||
'searchable' => false,
|
|
||||||
'sortable' => true,
|
'sortable' => true,
|
||||||
'title' => trans('general.min_amt'),
|
'title' => trans('admin/accessories/general.total'),
|
||||||
], [
|
], [
|
||||||
'field' => 'remaining_qty',
|
'field' => 'remaining_qty',
|
||||||
'searchable' => false,
|
'searchable' => false,
|
||||||
'sortable' => false,
|
'sortable' => false,
|
||||||
'visible' => false,
|
'visible' => false,
|
||||||
'title' => trans('admin/accessories/general.remaining'),
|
'title' => trans('admin/accessories/general.remaining'),
|
||||||
|
],[
|
||||||
|
'field' => 'users_count',
|
||||||
|
'searchable' => false,
|
||||||
|
'sortable' => true,
|
||||||
|
'visible' => true,
|
||||||
|
'title' => trans('general.checked_out'),
|
||||||
|
], [
|
||||||
|
'field' => 'min_qty',
|
||||||
|
'searchable' => false,
|
||||||
|
'sortable' => true,
|
||||||
|
'title' => trans('general.min_amt'),
|
||||||
], [
|
], [
|
||||||
'field' => 'purchase_date',
|
'field' => 'purchase_date',
|
||||||
'searchable' => true,
|
'searchable' => true,
|
||||||
|
|
|
@ -355,8 +355,7 @@ class UserPresenter extends Presenter
|
||||||
public function emailLink()
|
public function emailLink()
|
||||||
{
|
{
|
||||||
if ($this->email) {
|
if ($this->email) {
|
||||||
return '<a href="mailto:'.$this->email.'">'.$this->email.'</a>'
|
return '<a href="mailto:'.$this->email.'">'.$this->email.'</a><a href="mailto:'.$this->email.'" class="hidden-xs hidden-sm"><i class="far fa-envelope"></i></a>';
|
||||||
.'<a href="mailto:'.$this->email.'" class="hidden-xs hidden-sm"><i class="far fa-envelope"></i></a>';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return '';
|
return '';
|
||||||
|
|
|
@ -22,7 +22,7 @@ use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||||
*/
|
*/
|
||||||
class Saml
|
class Saml
|
||||||
{
|
{
|
||||||
const DATA_SESSION_KEY = '_samlData';
|
public const DATA_SESSION_KEY = '_samlData';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OneLogin_Saml2_Auth instance.
|
* OneLogin_Saml2_Auth instance.
|
||||||
|
@ -308,12 +308,9 @@ class Saml
|
||||||
*/
|
*/
|
||||||
public function samlLogin($data)
|
public function samlLogin($data)
|
||||||
{
|
{
|
||||||
$setting = Setting::getSettings();
|
|
||||||
$this->saveDataToSession($data);
|
$this->saveDataToSession($data);
|
||||||
$this->loadDataFromSession();
|
$this->loadDataFromSession();
|
||||||
|
|
||||||
$username = $this->getUsername();
|
$username = $this->getUsername();
|
||||||
|
|
||||||
return User::where('username', '=', $username)->whereNull('deleted_at')->where('activated', '=', '1')->first();
|
return User::where('username', '=', $username)->whereNull('deleted_at')->where('activated', '=', '1')->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,25 +61,29 @@
|
||||||
"nunomaduro/collision": "^5.4",
|
"nunomaduro/collision": "^5.4",
|
||||||
"onelogin/php-saml": "^3.4",
|
"onelogin/php-saml": "^3.4",
|
||||||
"paragonie/constant_time_encoding": "^2.3",
|
"paragonie/constant_time_encoding": "^2.3",
|
||||||
"symfony/polyfill-mbstring": "^1.22",
|
"paragonie/sodium_compat": "^1.19",
|
||||||
"phpdocumentor/reflection-docblock": "^5.1",
|
"phpdocumentor/reflection-docblock": "^5.1",
|
||||||
"phpspec/prophecy": "^1.10",
|
"phpspec/prophecy": "^1.10",
|
||||||
"pragmarx/google2fa-laravel": "^1.3",
|
"pragmarx/google2fa-laravel": "^1.3",
|
||||||
"rollbar/rollbar-laravel": "^7.0",
|
"rollbar/rollbar-laravel": "^7.0",
|
||||||
"spatie/laravel-backup": "^6.16",
|
"spatie/laravel-backup": "^6.16",
|
||||||
|
"symfony/polyfill-mbstring": "^1.22",
|
||||||
"tecnickcom/tc-lib-barcode": "^1.15",
|
"tecnickcom/tc-lib-barcode": "^1.15",
|
||||||
"unicodeveloper/laravel-password": "^1.0",
|
"unicodeveloper/laravel-password": "^1.0",
|
||||||
"watson/validating": "^6.1"
|
"watson/validating": "^6.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"fakerphp/faker": "^1.16",
|
"fakerphp/faker": "^1.16",
|
||||||
"laravel/dusk": "^6.19",
|
"laravel/dusk": "^6.25",
|
||||||
"mockery/mockery": "^1.4",
|
"mockery/mockery": "^1.4",
|
||||||
|
"nunomaduro/larastan": "^1.0",
|
||||||
|
"nunomaduro/phpinsights": "^2.7",
|
||||||
"phpunit/php-token-stream": "^3.1",
|
"phpunit/php-token-stream": "^3.1",
|
||||||
"phpunit/phpunit": "^9.0",
|
"phpunit/phpunit": "^9.0",
|
||||||
"squizlabs/php_codesniffer": "^3.5",
|
"squizlabs/php_codesniffer": "^3.5",
|
||||||
"symfony/css-selector": "^4.4",
|
"symfony/css-selector": "^4.4",
|
||||||
"symfony/dom-crawler": "^4.4"
|
"symfony/dom-crawler": "^4.4",
|
||||||
|
"vimeo/psalm": "^5.6"
|
||||||
},
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
"laravel": {
|
"laravel": {
|
||||||
|
|
2923
composer.lock
generated
2923
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -102,6 +102,7 @@ return [
|
||||||
'pgsql' => [
|
'pgsql' => [
|
||||||
'driver' => 'pgsql',
|
'driver' => 'pgsql',
|
||||||
'host' => env('DB_HOST', 'localhost'),
|
'host' => env('DB_HOST', 'localhost'),
|
||||||
|
'port' => env('DB_PORT', '5432'),
|
||||||
'database' => env('DB_DATABASE', 'forge'),
|
'database' => env('DB_DATABASE', 'forge'),
|
||||||
'username' => env('DB_USERNAME', 'forge'),
|
'username' => env('DB_USERNAME', 'forge'),
|
||||||
'password' => env('DB_PASSWORD', ''),
|
'password' => env('DB_PASSWORD', ''),
|
||||||
|
|
128
config/insights.php
Normal file
128
config/insights.php
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use NunoMaduro\PhpInsights\Domain\Insights\ForbiddenDefineFunctions;
|
||||||
|
use NunoMaduro\PhpInsights\Domain\Insights\ForbiddenFinalClasses;
|
||||||
|
use NunoMaduro\PhpInsights\Domain\Insights\ForbiddenNormalClasses;
|
||||||
|
use NunoMaduro\PhpInsights\Domain\Insights\ForbiddenPrivateMethods;
|
||||||
|
use NunoMaduro\PhpInsights\Domain\Insights\ForbiddenTraits;
|
||||||
|
use NunoMaduro\PhpInsights\Domain\Metrics\Architecture\Classes;
|
||||||
|
use SlevomatCodingStandard\Sniffs\Commenting\UselessFunctionDocCommentSniff;
|
||||||
|
use SlevomatCodingStandard\Sniffs\Namespaces\AlphabeticallySortedUsesSniff;
|
||||||
|
use SlevomatCodingStandard\Sniffs\TypeHints\DeclareStrictTypesSniff;
|
||||||
|
use SlevomatCodingStandard\Sniffs\TypeHints\DisallowMixedTypeHintSniff;
|
||||||
|
use SlevomatCodingStandard\Sniffs\TypeHints\ParameterTypeHintSniff;
|
||||||
|
use SlevomatCodingStandard\Sniffs\TypeHints\PropertyTypeHintSniff;
|
||||||
|
use SlevomatCodingStandard\Sniffs\TypeHints\ReturnTypeHintSniff;
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Default Preset
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This option controls the default preset that will be used by PHP Insights
|
||||||
|
| to make your code reliable, simple, and clean. However, you can always
|
||||||
|
| adjust the `Metrics` and `Insights` below in this configuration file.
|
||||||
|
|
|
||||||
|
| Supported: "default", "laravel", "symfony", "magento2", "drupal"
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'preset' => 'laravel',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| IDE
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This options allow to add hyperlinks in your terminal to quickly open
|
||||||
|
| files in your favorite IDE while browsing your PhpInsights report.
|
||||||
|
|
|
||||||
|
| Supported: "textmate", "macvim", "emacs", "sublime", "phpstorm",
|
||||||
|
| "atom", "vscode".
|
||||||
|
|
|
||||||
|
| If you have another IDE that is not in this list but which provide an
|
||||||
|
| url-handler, you could fill this config with a pattern like this:
|
||||||
|
|
|
||||||
|
| myide://open?url=file://%f&line=%l
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'ide' => null,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Configuration
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may adjust all the various `Insights` that will be used by PHP
|
||||||
|
| Insights. You can either add, remove or configure `Insights`. Keep in
|
||||||
|
| mind that all added `Insights` must belong to a specific `Metric`.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'exclude' => [
|
||||||
|
// 'path/to/directory-or-file'
|
||||||
|
],
|
||||||
|
|
||||||
|
'add' => [
|
||||||
|
Classes::class => [
|
||||||
|
ForbiddenFinalClasses::class,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
'remove' => [
|
||||||
|
AlphabeticallySortedUsesSniff::class,
|
||||||
|
DeclareStrictTypesSniff::class,
|
||||||
|
DisallowMixedTypeHintSniff::class,
|
||||||
|
ForbiddenDefineFunctions::class,
|
||||||
|
ForbiddenNormalClasses::class,
|
||||||
|
ForbiddenTraits::class,
|
||||||
|
ParameterTypeHintSniff::class,
|
||||||
|
PropertyTypeHintSniff::class,
|
||||||
|
ReturnTypeHintSniff::class,
|
||||||
|
UselessFunctionDocCommentSniff::class,
|
||||||
|
],
|
||||||
|
|
||||||
|
'config' => [
|
||||||
|
ForbiddenPrivateMethods::class => [
|
||||||
|
'title' => 'The usage of private methods is not idiomatic in Laravel.',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Requirements
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may define a level you want to reach per `Insights` category.
|
||||||
|
| When a score is lower than the minimum level defined, then an error
|
||||||
|
| code will be returned. This is optional and individually defined.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'requirements' => [
|
||||||
|
// 'min-quality' => 0,
|
||||||
|
// 'min-complexity' => 0,
|
||||||
|
// 'min-architecture' => 0,
|
||||||
|
// 'min-style' => 0,
|
||||||
|
// 'disable-security-check' => false,
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Threads
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may adjust how many threads (core) PHPInsights can use to perform
|
||||||
|
| the analyse. This is optional, don't provide it and the tool will guess
|
||||||
|
| the max core number available. It accepts null value or integer > 0.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'threads' => null,
|
||||||
|
|
||||||
|
];
|
|
@ -1,5 +1,4 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Monolog\Handler\NullHandler;
|
use Monolog\Handler\NullHandler;
|
||||||
use Monolog\Handler\StreamHandler;
|
use Monolog\Handler\StreamHandler;
|
||||||
use Monolog\Handler\SyslogUdpHandler;
|
use Monolog\Handler\SyslogUdpHandler;
|
||||||
|
@ -113,6 +112,13 @@ $config = [
|
||||||
'handler' => \Rollbar\Laravel\MonologHandler::class,
|
'handler' => \Rollbar\Laravel\MonologHandler::class,
|
||||||
'access_token' => env('ROLLBAR_TOKEN'),
|
'access_token' => env('ROLLBAR_TOKEN'),
|
||||||
'level' => env('ROLLBAR_LEVEL', 'error'),
|
'level' => env('ROLLBAR_LEVEL', 'error'),
|
||||||
|
'check_ignore' => function($isUncaught, $args, $payload) {
|
||||||
|
if (App::environment('production') && is_object($args) && get_class($args) == Rollbar\ErrorWrapper::class && $args->errorLevel == E_WARNING ) {
|
||||||
|
\Log::info("IGNORING E_WARNING in production mode: ".$args->getMessage());
|
||||||
|
return true; // "TRUE - you should ignore it!"
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,6 @@
|
||||||
return [
|
return [
|
||||||
"trace" => env("SCIM_TRACE",false),
|
"trace" => env("SCIM_TRACE",false),
|
||||||
// below, if we ever get 'sure' that we can change this default to 'true' we should
|
// below, if we ever get 'sure' that we can change this default to 'true' we should
|
||||||
"omit_main_schema_in_return" => env('SCIM_STANDARDS_COMPLIANCE', false),
|
"omit_main_schema_in_return" => env('SCIM_STANDARDS_COMPLIANCE', true),
|
||||||
"publish_routes" => false,
|
"publish_routes" => false,
|
||||||
];
|
];
|
||||||
|
|
|
@ -44,6 +44,8 @@ class MigrationCartalystSentryInstallGroups extends Migration
|
||||||
*/
|
*/
|
||||||
public function down()
|
public function down()
|
||||||
{
|
{
|
||||||
Schema::drop('permission_groups');
|
// See 2014_11_04_231416_update_group_field_for_reporting.php and 2019_06_12_184327_rename_groups_table.php
|
||||||
|
Schema::dropIfExists('permission_groups');
|
||||||
|
Schema::dropIfExists('groups');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,6 @@ class AddPhysicalToAssets extends Migration
|
||||||
*/
|
*/
|
||||||
public function down()
|
public function down()
|
||||||
{
|
{
|
||||||
$table->dropColumn('physical');
|
// $table->dropColumn('physical');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ class ReCreateLicensesTable extends Migration
|
||||||
*/
|
*/
|
||||||
public function down()
|
public function down()
|
||||||
{
|
{
|
||||||
//
|
// This was most likely handled in 2013_11_17_054359_drop_licenses_table.php
|
||||||
Schema::drop('licenses');
|
Schema::dropIfExists('licenses');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,6 @@ class CreateLicenseSeatsTable extends Migration
|
||||||
*/
|
*/
|
||||||
public function down()
|
public function down()
|
||||||
{
|
{
|
||||||
//
|
Schema::dropIfExists('license_seats');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,8 @@ class AlterWarrantyColumnOnAssets extends Migration
|
||||||
*/
|
*/
|
||||||
public function down()
|
public function down()
|
||||||
{
|
{
|
||||||
//
|
Schema::table('assets', function ($table) {
|
||||||
|
$table->renameColumn('warranty_months', 'warrantee_months');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ class AddEolOnModelsTable extends Migration
|
||||||
public function down()
|
public function down()
|
||||||
{
|
{
|
||||||
Schema::table('models', function ($table) {
|
Schema::table('models', function ($table) {
|
||||||
$table->dropColumn('old');
|
$table->dropColumn('eol');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,10 +105,10 @@
|
||||||
*/
|
*/
|
||||||
public function down()
|
public function down()
|
||||||
{
|
{
|
||||||
Schema::table('asset_logs', function (Blueprint $table) {
|
// Schema::table('asset_logs', function (Blueprint $table) {
|
||||||
$table->dropIndex('thread_id');
|
// $table->dropIndex('thread_id');
|
||||||
$table->dropColumn('thread_id');
|
// $table->dropColumn('thread_id');
|
||||||
});
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -48,13 +48,19 @@ class MigrateMacAddress extends Migration
|
||||||
*/
|
*/
|
||||||
public function down()
|
public function down()
|
||||||
{
|
{
|
||||||
//
|
|
||||||
$f = \App\Models\CustomFieldset::where(['name' => 'Asset with MAC Address'])->first();
|
$f = \App\Models\CustomFieldset::where(['name' => 'Asset with MAC Address'])->first();
|
||||||
$f->fields()->delete();
|
|
||||||
$f->delete();
|
if ($f) {
|
||||||
|
$f->fields()->delete();
|
||||||
|
$f->delete();
|
||||||
|
}
|
||||||
|
|
||||||
Schema::table('models', function (Blueprint $table) {
|
Schema::table('models', function (Blueprint $table) {
|
||||||
$table->renameColumn('deprecated_mac_address', 'show_mac_address');
|
$table->renameColumn('deprecated_mac_address', 'show_mac_address');
|
||||||
});
|
});
|
||||||
DB::statement('ALTER TABLE assets CHANGE _snipeit_mac_address mac_address varchar(255)');
|
|
||||||
|
if (Schema::hasColumn('assets', '_snipeit_mac_address')) {
|
||||||
|
DB::statement('ALTER TABLE assets CHANGE _snipeit_mac_address mac_address varchar(255)');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ class AddShowInNavToStatusLabels extends Migration
|
||||||
public function down()
|
public function down()
|
||||||
{
|
{
|
||||||
Schema::table('status_labels', function (Blueprint $table) {
|
Schema::table('status_labels', function (Blueprint $table) {
|
||||||
$table->dropColumn('show_in_nav', 'field_encrypted');
|
$table->dropColumn('show_in_nav');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ use App\Models\CustomField;
|
||||||
use Illuminate\Database\Migrations\Migration;
|
use Illuminate\Database\Migrations\Migration;
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
use Illuminate\Support\Facades\Schema;
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fixes issue #2551 where columns got donked if the field name in non-ascii
|
* Fixes issue #2551 where columns got donked if the field name in non-ascii
|
||||||
|
@ -71,6 +72,25 @@ class FixUtf8CustomFieldColumnNames extends Migration
|
||||||
*/
|
*/
|
||||||
public function down()
|
public function down()
|
||||||
{
|
{
|
||||||
|
// In the up method above, updateLegacyColumnName is called and custom fields in the assets table are prefixed
|
||||||
|
// with "_snipe_it_", suffixed with "_{id of the CustomField}", and stored in custom_fields.db_column.
|
||||||
|
// The following reverses those changes.
|
||||||
|
foreach (CustomField::all() as $field) {
|
||||||
|
$currentColumnName = $field->db_column;
|
||||||
|
|
||||||
|
// "_snipeit_imei_1" becomes "_snipeit_imei"
|
||||||
|
$legacyColumnName = (string) Str::of($currentColumnName)->replaceMatches('/_(\d)+$/', '');
|
||||||
|
|
||||||
|
if (Schema::hasColumn(CustomField::$table_name, $currentColumnName)) {
|
||||||
|
Schema::table(CustomField::$table_name, function (Blueprint $table) use ($currentColumnName, $legacyColumnName) {
|
||||||
|
$table->renameColumn(
|
||||||
|
$currentColumnName,
|
||||||
|
$legacyColumnName
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Schema::table('custom_fields', function ($table) {
|
Schema::table('custom_fields', function ($table) {
|
||||||
$table->dropColumn('db_column');
|
$table->dropColumn('db_column');
|
||||||
$table->dropColumn('help_text');
|
$table->dropColumn('help_text');
|
||||||
|
|
|
@ -28,7 +28,7 @@ class AddFieldsToManufacturer extends Migration
|
||||||
*/
|
*/
|
||||||
public function down()
|
public function down()
|
||||||
{
|
{
|
||||||
Schema::table('settings', function ($table) {
|
Schema::table('manufacturers', function ($table) {
|
||||||
$table->dropColumn('url');
|
$table->dropColumn('url');
|
||||||
$table->dropColumn('support_url');
|
$table->dropColumn('support_url');
|
||||||
$table->dropColumn('support_phone');
|
$table->dropColumn('support_phone');
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use App\Models\CustomField;
|
||||||
|
|
||||||
|
class FixUnescapedCustomfieldsFormat extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
$customfields = CustomField::where('format', 'LIKE', '%&%')->get();
|
||||||
|
|
||||||
|
foreach($customfields as $customfield){
|
||||||
|
$customfield->update(['format' => html_entity_decode($customfield->format)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
12
phpstan.neon.dist
Normal file
12
phpstan.neon.dist
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
includes:
|
||||||
|
- ./vendor/nunomaduro/larastan/extension.neon
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
paths:
|
||||||
|
- app
|
||||||
|
- config
|
||||||
|
- database/migrations
|
||||||
|
- resources/lang
|
||||||
|
- resources/views
|
||||||
|
|
||||||
|
level: 4
|
8
phpstan.neon.example
Normal file
8
phpstan.neon.example
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Copy this file to "phpstan.neon" and update the parameters section as needed
|
||||||
|
|
||||||
|
includes:
|
||||||
|
- phpstan.neon.dist
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
# https://phpstan.org/user-guide/output-format#opening-file-in-an-editor
|
||||||
|
editorUrl: 'phpstorm://open?file=%%file%%&line=%%line%%'
|
18
psalm.xml
Normal file
18
psalm.xml
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<psalm
|
||||||
|
errorLevel="7"
|
||||||
|
resolveFromConfigFile="true"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="https://getpsalm.org/schema/config"
|
||||||
|
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
||||||
|
findUnusedBaselineEntry="true"
|
||||||
|
>
|
||||||
|
<projectFiles>
|
||||||
|
<directory name="app" />
|
||||||
|
<directory name="database/factories" />
|
||||||
|
<directory name="database/seeders" />
|
||||||
|
<ignoreFiles>
|
||||||
|
<directory name="vendor" />
|
||||||
|
</ignoreFiles>
|
||||||
|
</projectFiles>
|
||||||
|
</psalm>
|
BIN
public/img/snipe-logo-bug.png
Normal file
BIN
public/img/snipe-logo-bug.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 22 KiB |
|
@ -13,7 +13,8 @@ return array(
|
||||||
|
|
||||||
'update' => array(
|
'update' => array(
|
||||||
'error' => 'Kategorie is nie opgedateer nie, probeer asseblief weer',
|
'error' => 'Kategorie is nie opgedateer nie, probeer asseblief weer',
|
||||||
'success' => 'Kategorie suksesvol opgedateer.'
|
'success' => 'Kategorie suksesvol opgedateer.',
|
||||||
|
'cannot_change_category_type' => 'You cannot change the category type once it has been created',
|
||||||
),
|
),
|
||||||
|
|
||||||
'delete' => array(
|
'delete' => array(
|
||||||
|
|
|
@ -12,4 +12,5 @@ return array(
|
||||||
'remaining' => 'oorblywende',
|
'remaining' => 'oorblywende',
|
||||||
'total' => 'totale',
|
'total' => 'totale',
|
||||||
'update' => 'Opdateer komponent',
|
'update' => 'Opdateer komponent',
|
||||||
|
'checkin_limit' => 'Amount checked in must be equal to or less than :assigned_qty'
|
||||||
);
|
);
|
||||||
|
|
|
@ -27,6 +27,9 @@ return [
|
||||||
'used_by_models' => 'Gebruik deur modelle',
|
'used_by_models' => 'Gebruik deur modelle',
|
||||||
'order' => 'Orde',
|
'order' => 'Orde',
|
||||||
'create_fieldset' => 'Nuwe Fieldset',
|
'create_fieldset' => 'Nuwe Fieldset',
|
||||||
|
'update_fieldset' => 'Update Fieldset',
|
||||||
|
'fieldset_does_not_exist' => 'Fieldset :id does not exist',
|
||||||
|
'fieldset_updated' => 'Fieldset updated',
|
||||||
'create_fieldset_title' => 'Create a new fieldset',
|
'create_fieldset_title' => 'Create a new fieldset',
|
||||||
'create_field' => 'Nuwe aangepaste veld',
|
'create_field' => 'Nuwe aangepaste veld',
|
||||||
'create_field_title' => 'Create a new custom field',
|
'create_field_title' => 'Create a new custom field',
|
||||||
|
|
|
@ -14,6 +14,8 @@ return [
|
||||||
'deleted' => 'This asset has been deleted.',
|
'deleted' => 'This asset has been deleted.',
|
||||||
'edit' => 'Wysig bate',
|
'edit' => 'Wysig bate',
|
||||||
'model_deleted' => 'This Assets model has been deleted. You must restore the model before you can restore the Asset.',
|
'model_deleted' => 'This Assets model has been deleted. You must restore the model before you can restore the Asset.',
|
||||||
|
'model_invalid' => 'The Model of this Asset is invalid.',
|
||||||
|
'model_invalid_fix' => 'The Asset should be edited to correct this before attempting to check it in or out.',
|
||||||
'requestable' => 'Requestable',
|
'requestable' => 'Requestable',
|
||||||
'requested' => 'versoek',
|
'requested' => 'versoek',
|
||||||
'not_requestable' => 'Not Requestable',
|
'not_requestable' => 'Not Requestable',
|
||||||
|
|
|
@ -48,6 +48,8 @@ return [
|
||||||
'success' => 'Jou lêer is ingevoer',
|
'success' => 'Jou lêer is ingevoer',
|
||||||
'file_delete_success' => 'Jou lêer is suksesvol verwyder',
|
'file_delete_success' => 'Jou lêer is suksesvol verwyder',
|
||||||
'file_delete_error' => 'Die lêer kon nie uitgevee word nie',
|
'file_delete_error' => 'Die lêer kon nie uitgevee word nie',
|
||||||
|
'header_row_has_malformed_characters' => 'One or more attributes in the header row contain malformed UTF-8 characters',
|
||||||
|
'content_row_has_malformed_characters' => 'One or more attributes in the first row of content contain malformed UTF-8 characters',
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
return array(
|
return array(
|
||||||
|
|
||||||
'does_not_exist' => 'Model bestaan nie.',
|
'does_not_exist' => 'Model bestaan nie.',
|
||||||
|
'no_association' => 'NO MODEL ASSOCIATED.',
|
||||||
|
'no_association_fix' => 'This will break things in weird and horrible ways. Edit this asset now to assign it a model.',
|
||||||
'assoc_users' => 'Hierdie model word tans geassosieer met een of meer bates en kan nie verwyder word nie. Verwyder asseblief die bates en probeer dan weer uitvee.',
|
'assoc_users' => 'Hierdie model word tans geassosieer met een of meer bates en kan nie verwyder word nie. Verwyder asseblief die bates en probeer dan weer uitvee.',
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,7 @@ return [
|
||||||
'ldap' => 'LDAP',
|
'ldap' => 'LDAP',
|
||||||
'ldap_default_group' => 'Default Permissions Group',
|
'ldap_default_group' => 'Default Permissions Group',
|
||||||
'ldap_default_group_info' => 'Select a group to assign to newly synced users. Remember that a user takes on the permissions of the group they are assigned.',
|
'ldap_default_group_info' => 'Select a group to assign to newly synced users. Remember that a user takes on the permissions of the group they are assigned.',
|
||||||
|
'no_default_group' => 'No Default Group',
|
||||||
'ldap_help' => 'LDAP/Active Directory',
|
'ldap_help' => 'LDAP/Active Directory',
|
||||||
'ldap_client_tls_key' => 'LDAP Client TLS Key',
|
'ldap_client_tls_key' => 'LDAP Client TLS Key',
|
||||||
'ldap_client_tls_cert' => 'LDAP Client-Side TLS Certificate',
|
'ldap_client_tls_cert' => 'LDAP Client-Side TLS Certificate',
|
||||||
|
|
|
@ -38,6 +38,7 @@ return [
|
||||||
'success_pt1' => 'Success! Check the ',
|
'success_pt1' => 'Success! Check the ',
|
||||||
'success_pt2' => ' channel for your test message, and be sure to click SAVE below to store your settings.',
|
'success_pt2' => ' channel for your test message, and be sure to click SAVE below to store your settings.',
|
||||||
'500' => '500 Server Error.',
|
'500' => '500 Server Error.',
|
||||||
'error' => 'Something went wrong.',
|
'error' => 'Something went wrong. Slack responded with: :error_message',
|
||||||
|
'error_misc' => 'Something went wrong. :( ',
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
|
@ -41,4 +41,4 @@ return [
|
||||||
'remote' => 'Remote',
|
'remote' => 'Remote',
|
||||||
'remote_help' => 'This can be useful if you need to filter by remote users who never or rarely come into your physical locations.',
|
'remote_help' => 'This can be useful if you need to filter by remote users who never or rarely come into your physical locations.',
|
||||||
'not_remote_label' => 'This is not a remote user',
|
'not_remote_label' => 'This is not a remote user',
|
||||||
];
|
];
|
|
@ -3,6 +3,7 @@
|
||||||
return [
|
return [
|
||||||
'accessories' => 'bykomstighede',
|
'accessories' => 'bykomstighede',
|
||||||
'activated' => 'geaktiveer',
|
'activated' => 'geaktiveer',
|
||||||
|
'accepted_date' => 'Date Accepted',
|
||||||
'accessory' => 'Bykomstigheid',
|
'accessory' => 'Bykomstigheid',
|
||||||
'accessory_report' => 'Toebehoreverslag',
|
'accessory_report' => 'Toebehoreverslag',
|
||||||
'action' => 'aksie',
|
'action' => 'aksie',
|
||||||
|
@ -27,7 +28,13 @@ return [
|
||||||
'audit' => 'oudit',
|
'audit' => 'oudit',
|
||||||
'audit_report' => 'Ouditlogboek',
|
'audit_report' => 'Ouditlogboek',
|
||||||
'assets' => 'bates',
|
'assets' => 'bates',
|
||||||
|
'assets_audited' => 'assets audited',
|
||||||
|
'assets_checked_in_count' => 'assets checked in',
|
||||||
|
'assets_checked_out_count' => 'assets checked out',
|
||||||
|
'asset_deleted_warning' => 'This asset has been deleted. You must restore it before you can assign it to someone.',
|
||||||
|
'assigned_date' => 'Date Assigned',
|
||||||
'assigned_to' => 'Assigned to :name',
|
'assigned_to' => 'Assigned to :name',
|
||||||
|
'assignee' => 'Assigned to',
|
||||||
'avatar_delete' => 'Verwyder Avatar',
|
'avatar_delete' => 'Verwyder Avatar',
|
||||||
'avatar_upload' => 'Laai avatar op',
|
'avatar_upload' => 'Laai avatar op',
|
||||||
'back' => 'terug',
|
'back' => 'terug',
|
||||||
|
@ -39,6 +46,8 @@ return [
|
||||||
'bulk_delete' => 'Bulk Delete',
|
'bulk_delete' => 'Bulk Delete',
|
||||||
'bulk_actions' => 'Bulk Actions',
|
'bulk_actions' => 'Bulk Actions',
|
||||||
'bulk_checkin_delete' => 'Bulk Checkin Items from Users',
|
'bulk_checkin_delete' => 'Bulk Checkin Items from Users',
|
||||||
|
'byod' => 'BYOD',
|
||||||
|
'byod_help' => 'This device is owned by the user',
|
||||||
'bystatus' => 'by Status',
|
'bystatus' => 'by Status',
|
||||||
'cancel' => 'kanselleer',
|
'cancel' => 'kanselleer',
|
||||||
'categories' => 'kategorieë',
|
'categories' => 'kategorieë',
|
||||||
|
@ -385,7 +394,15 @@ return [
|
||||||
'start_date' => 'Start Date',
|
'start_date' => 'Start Date',
|
||||||
'end_date' => 'End Date',
|
'end_date' => 'End Date',
|
||||||
'alt_uploaded_image_thumbnail' => 'Uploaded thumbnail',
|
'alt_uploaded_image_thumbnail' => 'Uploaded thumbnail',
|
||||||
'placeholder_kit' => 'Select a kit'
|
'placeholder_kit' => 'Select a kit',
|
||||||
|
'file_not_found' => 'File not found',
|
||||||
|
'preview_not_available' => '(no preview)',
|
||||||
|
'setup' => 'Setup',
|
||||||
|
'pre_flight' => 'Pre-Flight',
|
||||||
|
'skip_to_main_content' => 'Skip to main content',
|
||||||
|
'toggle_navigation' => 'Toggle navigation',
|
||||||
|
'alerts' => 'Alerts',
|
||||||
|
'tasks_view_all' => 'View all tasks',
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -256,6 +256,7 @@ return [
|
||||||
'UK'=>'Scotland',
|
'UK'=>'Scotland',
|
||||||
'SB'=>'Solomon Islands',
|
'SB'=>'Solomon Islands',
|
||||||
'SC'=>'Seychelles',
|
'SC'=>'Seychelles',
|
||||||
|
'SS'=>'South Sudan',
|
||||||
'SD'=>'Sudan',
|
'SD'=>'Sudan',
|
||||||
'SE'=>'Sweden',
|
'SE'=>'Sweden',
|
||||||
'SG'=>'Singapore',
|
'SG'=>'Singapore',
|
||||||
|
|
|
@ -43,6 +43,7 @@ return [
|
||||||
'login_first_admin' => 'Teken in op jou nuwe Snipe-IT-installasie deur die volgende inligting te gebruik:',
|
'login_first_admin' => 'Teken in op jou nuwe Snipe-IT-installasie deur die volgende inligting te gebruik:',
|
||||||
'login' => 'Teken aan:',
|
'login' => 'Teken aan:',
|
||||||
'Low_Inventory_Report' => 'Lae voorraadverslag',
|
'Low_Inventory_Report' => 'Lae voorraadverslag',
|
||||||
|
'inventory_report' => 'Inventory Report',
|
||||||
'min_QTY' => 'Min QTY',
|
'min_QTY' => 'Min QTY',
|
||||||
'name' => 'naam',
|
'name' => 'naam',
|
||||||
'new_item_checked' => '\'N Nuwe item is onder u naam nagegaan, besonderhede is hieronder.',
|
'new_item_checked' => '\'N Nuwe item is onder u naam nagegaan, besonderhede is hieronder.',
|
||||||
|
@ -78,4 +79,5 @@ return [
|
||||||
'Expected_Checkin_Notification' => 'Reminder: :name checkin deadline approaching',
|
'Expected_Checkin_Notification' => 'Reminder: :name checkin deadline approaching',
|
||||||
'Expected_Checkin_Date' => 'An asset checked out to you is due to be checked back in on :date',
|
'Expected_Checkin_Date' => 'An asset checked out to you is due to be checked back in on :date',
|
||||||
'your_assets' => 'View Your Assets',
|
'your_assets' => 'View Your Assets',
|
||||||
|
'rights_reserved' => 'All rights reserved.',
|
||||||
];
|
];
|
||||||
|
|
|
@ -103,17 +103,6 @@ return [
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Custom Validation Language Lines
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| Here you may specify custom validation messages for attributes using the
|
|
||||||
| convention "attribute.rule" to name the lines. This makes it quick to
|
|
||||||
| specify a specific custom language line for a given attribute rule.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
| Custom Validation Language Lines
|
| Custom Validation Language Lines
|
||||||
|
@ -131,6 +120,18 @@ return [
|
||||||
'hashed_pass' => 'Jou huidige wagwoord is verkeerd',
|
'hashed_pass' => 'Jou huidige wagwoord is verkeerd',
|
||||||
'dumbpwd' => 'Daardie wagwoord is te algemeen.',
|
'dumbpwd' => 'Daardie wagwoord is te algemeen.',
|
||||||
'statuslabel_type' => 'U moet \'n geldige statusetiket tipe kies',
|
'statuslabel_type' => 'U moet \'n geldige statusetiket tipe kies',
|
||||||
|
|
||||||
|
// date_format validation with slightly less stupid messages. It duplicates a lot, but it gets the job done :(
|
||||||
|
// We use this because the default error message for date_format is reflects php Y-m-d, which non-PHP
|
||||||
|
// people won't know how to format.
|
||||||
|
'purchase_date.date_format' => 'The :attribute must be a valid date in YYYY-MM-DD format',
|
||||||
|
'last_audit_date.date_format' => 'The :attribute must be a valid date in YYYY-MM-DD hh:mm:ss format',
|
||||||
|
'expiration_date.date_format' => 'The :attribute must be a valid date in YYYY-MM-DD format',
|
||||||
|
'termination_date.date_format' => 'The :attribute must be a valid date in YYYY-MM-DD format',
|
||||||
|
'expected_checkin.date_format' => 'The :attribute must be a valid date in YYYY-MM-DD format',
|
||||||
|
'start_date.date_format' => 'The :attribute must be a valid date in YYYY-MM-DD format',
|
||||||
|
'end_date.date_format' => 'The :attribute must be a valid date in YYYY-MM-DD format',
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -13,7 +13,8 @@ return array(
|
||||||
|
|
||||||
'update' => array(
|
'update' => array(
|
||||||
'error' => 'Category was not updated, please try again',
|
'error' => 'Category was not updated, please try again',
|
||||||
'success' => 'Category updated successfully.'
|
'success' => 'Category updated successfully.',
|
||||||
|
'cannot_change_category_type' => 'You cannot change the category type once it has been created',
|
||||||
),
|
),
|
||||||
|
|
||||||
'delete' => array(
|
'delete' => array(
|
||||||
|
|
|
@ -12,4 +12,5 @@ return array(
|
||||||
'remaining' => 'Remaining',
|
'remaining' => 'Remaining',
|
||||||
'total' => 'Total',
|
'total' => 'Total',
|
||||||
'update' => 'Update Component',
|
'update' => 'Update Component',
|
||||||
|
'checkin_limit' => 'Amount checked in must be equal to or less than :assigned_qty'
|
||||||
);
|
);
|
||||||
|
|
|
@ -27,6 +27,9 @@ return [
|
||||||
'used_by_models' => 'Used By Models',
|
'used_by_models' => 'Used By Models',
|
||||||
'order' => 'Order',
|
'order' => 'Order',
|
||||||
'create_fieldset' => 'New Fieldset',
|
'create_fieldset' => 'New Fieldset',
|
||||||
|
'update_fieldset' => 'Update Fieldset',
|
||||||
|
'fieldset_does_not_exist' => 'Fieldset :id does not exist',
|
||||||
|
'fieldset_updated' => 'Fieldset updated',
|
||||||
'create_fieldset_title' => 'Create a new fieldset',
|
'create_fieldset_title' => 'Create a new fieldset',
|
||||||
'create_field' => 'New Custom Field',
|
'create_field' => 'New Custom Field',
|
||||||
'create_field_title' => 'Create a new custom field',
|
'create_field_title' => 'Create a new custom field',
|
||||||
|
|
|
@ -14,6 +14,8 @@ return [
|
||||||
'deleted' => 'This asset has been deleted.',
|
'deleted' => 'This asset has been deleted.',
|
||||||
'edit' => 'Edit Asset',
|
'edit' => 'Edit Asset',
|
||||||
'model_deleted' => 'This Assets model has been deleted. You must restore the model before you can restore the Asset.',
|
'model_deleted' => 'This Assets model has been deleted. You must restore the model before you can restore the Asset.',
|
||||||
|
'model_invalid' => 'The Model of this Asset is invalid.',
|
||||||
|
'model_invalid_fix' => 'The Asset should be edited to correct this before attempting to check it in or out.',
|
||||||
'requestable' => 'Requestable',
|
'requestable' => 'Requestable',
|
||||||
'requested' => 'Requested',
|
'requested' => 'Requested',
|
||||||
'not_requestable' => 'Not Requestable',
|
'not_requestable' => 'Not Requestable',
|
||||||
|
|
|
@ -49,6 +49,8 @@ return [
|
||||||
'success' => 'Your file has been imported',
|
'success' => 'Your file has been imported',
|
||||||
'file_delete_success' => 'Your file has been been successfully deleted',
|
'file_delete_success' => 'Your file has been been successfully deleted',
|
||||||
'file_delete_error' => 'The file was unable to be deleted',
|
'file_delete_error' => 'The file was unable to be deleted',
|
||||||
|
'header_row_has_malformed_characters' => 'One or more attributes in the header row contain malformed UTF-8 characters',
|
||||||
|
'content_row_has_malformed_characters' => 'One or more attributes in the first row of content contain malformed UTF-8 characters',
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
return array(
|
return array(
|
||||||
|
|
||||||
'does_not_exist' => 'Model does not exist.',
|
'does_not_exist' => 'Model does not exist.',
|
||||||
|
'no_association' => 'NO MODEL ASSOCIATED.',
|
||||||
|
'no_association_fix' => 'This will break things in weird and horrible ways. Edit this asset now to assign it a model.',
|
||||||
'assoc_users' => 'This model is currently associated with one or more assets and cannot be deleted. Please delete the assets, and then try deleting again. ',
|
'assoc_users' => 'This model is currently associated with one or more assets and cannot be deleted. Please delete the assets, and then try deleting again. ',
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,7 @@ return [
|
||||||
'ldap' => 'LDAP',
|
'ldap' => 'LDAP',
|
||||||
'ldap_default_group' => 'Default Permissions Group',
|
'ldap_default_group' => 'Default Permissions Group',
|
||||||
'ldap_default_group_info' => 'Select a group to assign to newly synced users. Remember that a user takes on the permissions of the group they are assigned.',
|
'ldap_default_group_info' => 'Select a group to assign to newly synced users. Remember that a user takes on the permissions of the group they are assigned.',
|
||||||
|
'no_default_group' => 'No Default Group',
|
||||||
'ldap_help' => 'LDAP/Active Directory',
|
'ldap_help' => 'LDAP/Active Directory',
|
||||||
'ldap_client_tls_key' => 'LDAP Client TLS Key',
|
'ldap_client_tls_key' => 'LDAP Client TLS Key',
|
||||||
'ldap_client_tls_cert' => 'LDAP Client-Side TLS Certificate',
|
'ldap_client_tls_cert' => 'LDAP Client-Side TLS Certificate',
|
||||||
|
|
|
@ -38,6 +38,7 @@ return [
|
||||||
'success_pt1' => 'Success! Check the ',
|
'success_pt1' => 'Success! Check the ',
|
||||||
'success_pt2' => ' channel for your test message, and be sure to click SAVE below to store your settings.',
|
'success_pt2' => ' channel for your test message, and be sure to click SAVE below to store your settings.',
|
||||||
'500' => '500 Server Error.',
|
'500' => '500 Server Error.',
|
||||||
'error' => 'Something went wrong.',
|
'error' => 'Something went wrong. Slack responded with: :error_message',
|
||||||
|
'error_misc' => 'Something went wrong. :( ',
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
|
@ -41,4 +41,4 @@ return [
|
||||||
'remote' => 'Remote',
|
'remote' => 'Remote',
|
||||||
'remote_help' => 'This can be useful if you need to filter by remote users who never or rarely come into your physical locations.',
|
'remote_help' => 'This can be useful if you need to filter by remote users who never or rarely come into your physical locations.',
|
||||||
'not_remote_label' => 'This is not a remote user',
|
'not_remote_label' => 'This is not a remote user',
|
||||||
];
|
];
|
|
@ -3,6 +3,7 @@
|
||||||
return [
|
return [
|
||||||
'accessories' => 'Accessories',
|
'accessories' => 'Accessories',
|
||||||
'activated' => 'Activated',
|
'activated' => 'Activated',
|
||||||
|
'accepted_date' => 'Date Accepted',
|
||||||
'accessory' => 'Accessory',
|
'accessory' => 'Accessory',
|
||||||
'accessory_report' => 'Accessory Report',
|
'accessory_report' => 'Accessory Report',
|
||||||
'action' => 'Action',
|
'action' => 'Action',
|
||||||
|
@ -27,7 +28,13 @@ return [
|
||||||
'audit' => 'Audit',
|
'audit' => 'Audit',
|
||||||
'audit_report' => 'Audit Log',
|
'audit_report' => 'Audit Log',
|
||||||
'assets' => 'Assets',
|
'assets' => 'Assets',
|
||||||
|
'assets_audited' => 'assets audited',
|
||||||
|
'assets_checked_in_count' => 'assets checked in',
|
||||||
|
'assets_checked_out_count' => 'assets checked out',
|
||||||
|
'asset_deleted_warning' => 'This asset has been deleted. You must restore it before you can assign it to someone.',
|
||||||
|
'assigned_date' => 'Date Assigned',
|
||||||
'assigned_to' => 'Assigned to :name',
|
'assigned_to' => 'Assigned to :name',
|
||||||
|
'assignee' => 'Assigned to',
|
||||||
'avatar_delete' => 'Delete Avatar',
|
'avatar_delete' => 'Delete Avatar',
|
||||||
'avatar_upload' => 'Upload Avatar',
|
'avatar_upload' => 'Upload Avatar',
|
||||||
'back' => 'Back',
|
'back' => 'Back',
|
||||||
|
@ -39,6 +46,8 @@ return [
|
||||||
'bulk_delete' => 'Bulk Delete',
|
'bulk_delete' => 'Bulk Delete',
|
||||||
'bulk_actions' => 'Bulk Actions',
|
'bulk_actions' => 'Bulk Actions',
|
||||||
'bulk_checkin_delete' => 'Bulk Checkin Items from Users',
|
'bulk_checkin_delete' => 'Bulk Checkin Items from Users',
|
||||||
|
'byod' => 'BYOD',
|
||||||
|
'byod_help' => 'This device is owned by the user',
|
||||||
'bystatus' => 'by Status',
|
'bystatus' => 'by Status',
|
||||||
'cancel' => 'Cancel',
|
'cancel' => 'Cancel',
|
||||||
'categories' => 'Categories',
|
'categories' => 'Categories',
|
||||||
|
@ -385,7 +394,15 @@ return [
|
||||||
'start_date' => 'Start Date',
|
'start_date' => 'Start Date',
|
||||||
'end_date' => 'End Date',
|
'end_date' => 'End Date',
|
||||||
'alt_uploaded_image_thumbnail' => 'Uploaded thumbnail',
|
'alt_uploaded_image_thumbnail' => 'Uploaded thumbnail',
|
||||||
'placeholder_kit' => 'Select a kit'
|
'placeholder_kit' => 'Select a kit',
|
||||||
|
'file_not_found' => 'File not found',
|
||||||
|
'preview_not_available' => '(no preview)',
|
||||||
|
'setup' => 'Setup',
|
||||||
|
'pre_flight' => 'Pre-Flight',
|
||||||
|
'skip_to_main_content' => 'Skip to main content',
|
||||||
|
'toggle_navigation' => 'Toggle navigation',
|
||||||
|
'alerts' => 'Alerts',
|
||||||
|
'tasks_view_all' => 'View all tasks',
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -256,6 +256,7 @@ return [
|
||||||
'UK'=>'Scotland',
|
'UK'=>'Scotland',
|
||||||
'SB'=>'Solomon Islands',
|
'SB'=>'Solomon Islands',
|
||||||
'SC'=>'Seychelles',
|
'SC'=>'Seychelles',
|
||||||
|
'SS'=>'South Sudan',
|
||||||
'SD'=>'Sudan',
|
'SD'=>'Sudan',
|
||||||
'SE'=>'Sweden',
|
'SE'=>'Sweden',
|
||||||
'SG'=>'Singapore',
|
'SG'=>'Singapore',
|
||||||
|
|
|
@ -43,6 +43,7 @@ return [
|
||||||
'login_first_admin' => 'Login to your new Snipe-IT installation using the credentials below:',
|
'login_first_admin' => 'Login to your new Snipe-IT installation using the credentials below:',
|
||||||
'login' => 'Login:',
|
'login' => 'Login:',
|
||||||
'Low_Inventory_Report' => 'Low Inventory Report',
|
'Low_Inventory_Report' => 'Low Inventory Report',
|
||||||
|
'inventory_report' => 'Inventory Report',
|
||||||
'min_QTY' => 'Min QTY',
|
'min_QTY' => 'Min QTY',
|
||||||
'name' => 'Name',
|
'name' => 'Name',
|
||||||
'new_item_checked' => 'A new item has been checked out under your name, details are below.',
|
'new_item_checked' => 'A new item has been checked out under your name, details are below.',
|
||||||
|
@ -79,4 +80,5 @@ return [
|
||||||
'Expected_Checkin_Notification' => 'Reminder: :name checkin deadline approaching',
|
'Expected_Checkin_Notification' => 'Reminder: :name checkin deadline approaching',
|
||||||
'Expected_Checkin_Date' => 'An asset checked out to you is due to be checked back in on :date',
|
'Expected_Checkin_Date' => 'An asset checked out to you is due to be checked back in on :date',
|
||||||
'your_assets' => 'View Your Assets',
|
'your_assets' => 'View Your Assets',
|
||||||
|
'rights_reserved' => 'All rights reserved.',
|
||||||
];
|
];
|
||||||
|
|
|
@ -103,17 +103,6 @@ return [
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Custom Validation Language Lines
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| Here you may specify custom validation messages for attributes using the
|
|
||||||
| convention "attribute.rule" to name the lines. This makes it quick to
|
|
||||||
| specify a specific custom language line for a given attribute rule.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
| Custom Validation Language Lines
|
| Custom Validation Language Lines
|
||||||
|
@ -131,6 +120,18 @@ return [
|
||||||
'hashed_pass' => 'Your current password is incorrect',
|
'hashed_pass' => 'Your current password is incorrect',
|
||||||
'dumbpwd' => 'That password is too common.',
|
'dumbpwd' => 'That password is too common.',
|
||||||
'statuslabel_type' => 'You must select a valid status label type',
|
'statuslabel_type' => 'You must select a valid status label type',
|
||||||
|
|
||||||
|
// date_format validation with slightly less stupid messages. It duplicates a lot, but it gets the job done :(
|
||||||
|
// We use this because the default error message for date_format is reflects php Y-m-d, which non-PHP
|
||||||
|
// people won't know how to format.
|
||||||
|
'purchase_date.date_format' => 'The :attribute must be a valid date in YYYY-MM-DD format',
|
||||||
|
'last_audit_date.date_format' => 'The :attribute must be a valid date in YYYY-MM-DD hh:mm:ss format',
|
||||||
|
'expiration_date.date_format' => 'The :attribute must be a valid date in YYYY-MM-DD format',
|
||||||
|
'termination_date.date_format' => 'The :attribute must be a valid date in YYYY-MM-DD format',
|
||||||
|
'expected_checkin.date_format' => 'The :attribute must be a valid date in YYYY-MM-DD format',
|
||||||
|
'start_date.date_format' => 'The :attribute must be a valid date in YYYY-MM-DD format',
|
||||||
|
'end_date.date_format' => 'The :attribute must be a valid date in YYYY-MM-DD format',
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -13,7 +13,8 @@ return array(
|
||||||
|
|
||||||
'update' => array(
|
'update' => array(
|
||||||
'error' => 'لقد فشل تحديث التصنيف، الرجاء المحاولة مرة أخرى',
|
'error' => 'لقد فشل تحديث التصنيف، الرجاء المحاولة مرة أخرى',
|
||||||
'success' => 'تم تحديث التصنيف بنجاح.'
|
'success' => 'تم تحديث التصنيف بنجاح.',
|
||||||
|
'cannot_change_category_type' => 'You cannot change the category type once it has been created',
|
||||||
),
|
),
|
||||||
|
|
||||||
'delete' => array(
|
'delete' => array(
|
||||||
|
|
|
@ -12,4 +12,5 @@ return array(
|
||||||
'remaining' => 'المتبقية',
|
'remaining' => 'المتبقية',
|
||||||
'total' => 'المجموع',
|
'total' => 'المجموع',
|
||||||
'update' => 'تحديث مكون',
|
'update' => 'تحديث مكون',
|
||||||
|
'checkin_limit' => 'Amount checked in must be equal to or less than :assigned_qty'
|
||||||
);
|
);
|
||||||
|
|
|
@ -27,6 +27,9 @@ return [
|
||||||
'used_by_models' => 'مستخدم في الموديلات',
|
'used_by_models' => 'مستخدم في الموديلات',
|
||||||
'order' => 'طلب',
|
'order' => 'طلب',
|
||||||
'create_fieldset' => 'مجموعة حقول جديدة',
|
'create_fieldset' => 'مجموعة حقول جديدة',
|
||||||
|
'update_fieldset' => 'Update Fieldset',
|
||||||
|
'fieldset_does_not_exist' => 'Fieldset :id does not exist',
|
||||||
|
'fieldset_updated' => 'Fieldset updated',
|
||||||
'create_fieldset_title' => 'Create a new fieldset',
|
'create_fieldset_title' => 'Create a new fieldset',
|
||||||
'create_field' => 'حقل جديد مخصص',
|
'create_field' => 'حقل جديد مخصص',
|
||||||
'create_field_title' => 'Create a new custom field',
|
'create_field_title' => 'Create a new custom field',
|
||||||
|
|
|
@ -14,6 +14,8 @@ return [
|
||||||
'deleted' => 'تم حذف هذا الأصل.',
|
'deleted' => 'تم حذف هذا الأصل.',
|
||||||
'edit' => 'تعديل الأصل',
|
'edit' => 'تعديل الأصل',
|
||||||
'model_deleted' => 'تم حذف موديل الأصول هذا. يجب استعادة الموديل قبل أن تتمكن من استعادة الأصل.',
|
'model_deleted' => 'تم حذف موديل الأصول هذا. يجب استعادة الموديل قبل أن تتمكن من استعادة الأصل.',
|
||||||
|
'model_invalid' => 'The Model of this Asset is invalid.',
|
||||||
|
'model_invalid_fix' => 'The Asset should be edited to correct this before attempting to check it in or out.',
|
||||||
'requestable' => 'قابل للطلب',
|
'requestable' => 'قابل للطلب',
|
||||||
'requested' => 'تم الطلب',
|
'requested' => 'تم الطلب',
|
||||||
'not_requestable' => 'Not Requestable',
|
'not_requestable' => 'Not Requestable',
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue