Compare commits
93 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 943cf40247 | |||
| ff57f10e9f | |||
| 91bb76fd8a | |||
| 893454dca7 | |||
| de0b5a6149 | |||
| 8fd4e35244 | |||
| e71e57f16a | |||
| 3f5840d390 | |||
| d3f4205f09 | |||
| 5b946087c4 | |||
| ff8d98c97c | |||
| 2fbbe430b5 | |||
| f0af750b0a | |||
| 88cf456386 | |||
| d8049209ca | |||
| dd40ddf5a5 | |||
| a73fd24695 | |||
| 70c8ad9797 | |||
| 0290257734 | |||
| 4fe689dc5d | |||
| 0769f585ea | |||
| 04562e6d4a | |||
| 22d2ad9248 | |||
| 6deb26fafe | |||
| 6c1de7ff05 | |||
| 7f5f4a1297 | |||
| c68c0e1208 | |||
| c256536d21 | |||
| 4159a0effa | |||
| b8f7cd81eb | |||
| b381528668 | |||
| 6d66d7e215 | |||
| b5bf8e9a37 | |||
| ba197c8857 | |||
| 124b249df4 | |||
| 2a6919c438 | |||
| 8b4a9aa382 | |||
| 99cd552d5c | |||
| 6c7e5cb9cf | |||
| 6ebb01a081 | |||
| 5591c861b9 | |||
| d37280567d | |||
| e7b0ee2539 | |||
| c593b3645c | |||
| 28ae90fa8a | |||
| c7be25078e | |||
| 3dc2cc9f22 | |||
| ab86e42b2e | |||
| 9af9ed9eb9 | |||
| 250a797339 | |||
| a0f3fc6d76 | |||
| 74e647fea7 | |||
| 55ee90b25d | |||
| eec445fcf5 | |||
| cef22c3158 | |||
| 61fb38087e | |||
| 0e93495ca2 | |||
| 444e250609 | |||
| 77a6f6f400 | |||
| 15bfd07f30 | |||
| fecf8015a1 | |||
| 79ab0d8dc2 | |||
| b4b6d6b571 | |||
| 8c73a47afb | |||
| f82ffe378c | |||
| 984c2a8fd4 | |||
| 6736b1c4e7 | |||
| d409be6d43 | |||
| e1b33f3087 | |||
| 740d5a6846 | |||
| d19df4ded8 | |||
| 03a4512406 | |||
| de992e4df3 | |||
| a85251aa83 | |||
| 26a1181765 | |||
| cef030cf55 | |||
| 2bfa05fd2d | |||
| 30904dd019 | |||
| 1d0d25db37 | |||
| cbff66c9db | |||
| 27231d49ea | |||
| 765417c0be | |||
| 49a255c8fb | |||
| 925d3a23c6 | |||
| 6966c132d0 | |||
| c29ab90029 | |||
| d2bbc09892 | |||
| 74a2c29bc2 | |||
| 2c64739e8f | |||
| 37f950ab42 | |||
| b07a254e60 | |||
| 087cdd859e | |||
| 829d44bd27 |
@@ -1659,6 +1659,15 @@
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "mskrip",
|
||||
"name": "Marián Skrip",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/17459600?v=4",
|
||||
"profile": "https://github.com/mskrip",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+5
-2
@@ -7,6 +7,7 @@ APP_KEY=ChangeMe
|
||||
APP_URL=null
|
||||
APP_TIMEZONE='UTC'
|
||||
APP_LOCALE=en
|
||||
MAX_RESULTS=500
|
||||
|
||||
# --------------------------------------------
|
||||
# REQUIRED: DATABASE SETTINGS
|
||||
@@ -43,6 +44,7 @@ MAIL_FROM_ADDR=you@example.com
|
||||
MAIL_FROM_NAME='Snipe-IT'
|
||||
MAIL_REPLYTO_ADDR=you@example.com
|
||||
MAIL_REPLYTO_NAME='Snipe-IT'
|
||||
MAIL_BACKUP_NOTIFICATION_ADDRESS=you@example.com
|
||||
|
||||
# --------------------------------------------
|
||||
# REQUIRED: IMAGE LIBRARY
|
||||
@@ -63,8 +65,11 @@ SECURE_COOKIES=false
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: SECURITY HEADER SETTINGS
|
||||
# --------------------------------------------
|
||||
APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1
|
||||
ALLOW_IFRAMING=false
|
||||
REFERRER_POLICY=same-origin
|
||||
ENABLE_CSP=false
|
||||
CORS_ALLOWED_ORIGINS=null
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: CACHE SETTINGS
|
||||
@@ -108,8 +113,6 @@ APP_LOG=single
|
||||
APP_LOG_MAX_FILES=10
|
||||
APP_LOCKED=false
|
||||
FILESYSTEM_DISK=local
|
||||
APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1
|
||||
ALLOW_IFRAMING=false
|
||||
APP_CIPHER=AES-256-CBC
|
||||
GOOGLE_MAPS_API=
|
||||
BACKUP_ENV=true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[](https://travis-ci.org/snipe/snipe-it) [](https://crowdin.com/project/snipe-it) [](https://gitter.im/snipe/snipe-it?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [](https://hub.docker.com/r/snipe/snipe-it/) [](https://twitter.com/snipeitapp) [](https://www.codacy.com/app/snipe/snipe-it?utm_source=github.com&utm_medium=referral&utm_content=snipe/snipe-it&utm_campaign=Badge_Grade)
|
||||
[](#contributors) [](https://www.codetriage.com/snipe/snipe-it)
|
||||
[](#contributors) [](https://www.codetriage.com/snipe/snipe-it)
|
||||
|
||||
|
||||
## Snipe-IT - Open Source Asset Management System
|
||||
@@ -61,6 +61,8 @@ Since the release of the JSON REST API, several third-party developers have been
|
||||
- [jamf2snipe](https://github.com/ParadoxGuitarist/jamf2snipe) by [@ParadoxGuitarist](https://github.com/ParadoxGuitarist) - Python script to sync assets between a JAMFPro instance and a Snipe-IT instance
|
||||
- [Marksman](https://github.com/Scope-IT/marksman) - A Windows agent for Snipe-IT
|
||||
- [Snipe-IT plugin for Jira Service Desk (beta)](https://marketplace.atlassian.com/apps/1220379/snipe-it-for-jira-service-desk-beta?hosting=cloud&tab=overview) - for the upcoming Snipe-IT v5 only
|
||||
- [Python 3 CSV importer](https://github.com/gastamper/snipeit-csvimporter) - allows importing assets into Snipe-IT based on Item Name rather than Asset Tag.
|
||||
- [Snipe-IT Kubernetes Helm Chart](https://github.com/t3n/helm-charts/tree/master/snipeit) - For more information, [click here](https://hub.helm.sh/charts/t3n/snipeit).
|
||||
|
||||
As these were created by third-parties, Snipe-IT cannot provide support for these project, and you should contact the developers directly if you need assistance. Additionally, Snipe-IT makes no guarantees as to the reliability, accuracy or maintainability of these libraries. Use at your own risk. :)
|
||||
|
||||
@@ -103,7 +105,7 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
|
||||
| [<img src="https://avatars2.githubusercontent.com/u/982885?v=4" width="110px;"/><br /><sub>Martin Stub</sub>](http://martinstub.dk)<br />[🌍](#translation-stubben "Translation") | [<img src="https://avatars2.githubusercontent.com/u/28959963?v=4" width="110px;"/><br /><sub>Meyer Flavio</sub>](https://github.com/meyerf99)<br />[🌍](#translation-meyerf99 "Translation") | [<img src="https://avatars3.githubusercontent.com/u/796443?v=4" width="110px;"/><br /><sub>Micael Rodrigues</sub>](https://github.com/MicaelRodrigues)<br />[🌍](#translation-MicaelRodrigues "Translation") | [<img src="https://avatars0.githubusercontent.com/u/10481331?v=4" width="110px;"/><br /><sub>Mikael Rasmussen</sub>](http://rubixy.com/)<br />[🌍](#translation-mikaelssen "Translation") | [<img src="https://avatars1.githubusercontent.com/u/1544552?v=4" width="110px;"/><br /><sub>IxFail</sub>](https://github.com/IxFail)<br />[🌍](#translation-IxFail "Translation") | [<img src="https://avatars3.githubusercontent.com/u/18483118?v=4" width="110px;"/><br /><sub>Mohammed Fota</sub>](http://www.mohammedfota.com)<br />[🌍](#translation-MohammedFota "Translation") | [<img src="https://avatars0.githubusercontent.com/u/227080?v=4" width="110px;"/><br /><sub>Moayad Alserihi</sub>](https://github.com/omego)<br />[🌍](#translation-omego "Translation") |
|
||||
| [<img src="https://avatars0.githubusercontent.com/u/1680266?v=4" width="110px;"/><br /><sub>saymd</sub>](https://github.com/saymd)<br />[🌍](#translation-saymd "Translation") | [<img src="https://avatars0.githubusercontent.com/u/1826808?v=4" width="110px;"/><br /><sub>Patrik Larsson</sub>](https://nordsken.se)<br />[🌍](#translation-pooot "Translation") | [<img src="https://avatars1.githubusercontent.com/u/20584746?v=4" width="110px;"/><br /><sub>drcryo</sub>](https://github.com/drcryo)<br />[🌍](#translation-drcryo "Translation") | [<img src="https://avatars1.githubusercontent.com/u/19408004?v=4" width="110px;"/><br /><sub>pawel1615</sub>](https://github.com/pawel1615)<br />[🌍](#translation-pawel1615 "Translation") | [<img src="https://avatars2.githubusercontent.com/u/23340468?v=4" width="110px;"/><br /><sub>bodrovics</sub>](https://github.com/bodrovics)<br />[🌍](#translation-bodrovics "Translation") | [<img src="https://avatars0.githubusercontent.com/u/3257654?v=4" width="110px;"/><br /><sub>priatna</sub>](https://github.com/priatna)<br />[🌍](#translation-priatna "Translation") | [<img src="https://avatars1.githubusercontent.com/u/5358374?v=4" width="110px;"/><br /><sub>Fan Jiang</sub>](https://amayume.net)<br />[🌍](#translation-ProfFan "Translation") |
|
||||
| [<img src="https://avatars1.githubusercontent.com/u/22555451?v=4" width="110px;"/><br /><sub>ragnarcx</sub>](https://github.com/ragnarcx)<br />[🌍](#translation-ragnarcx "Translation") | [<img src="https://avatars2.githubusercontent.com/u/18654582?v=4" width="110px;"/><br /><sub>Rein van Haaren</sub>](http://www.reinvanhaaren.nl/)<br />[🌍](#translation-reinvanhaaren "Translation") | [<img src="https://avatars1.githubusercontent.com/u/386672?v=4" width="110px;"/><br /><sub>Teguh Dwicaksana</sub>](http://dheche.songolimo.net)<br />[🌍](#translation-dheche "Translation") | [<img src="https://avatars2.githubusercontent.com/u/2572552?v=4" width="110px;"/><br /><sub>fraccie</sub>](https://github.com/FRaccie)<br />[🌍](#translation-FRaccie "Translation") | [<img src="https://avatars0.githubusercontent.com/u/35182720?v=4" width="110px;"/><br /><sub>vinzruzell</sub>](https://github.com/vinzruzell)<br />[🌍](#translation-vinzruzell "Translation") | [<img src="https://avatars1.githubusercontent.com/u/7883603?v=4" width="110px;"/><br /><sub>Kevin Austin</sub>](http://kevinaustin.com)<br />[🌍](#translation-vipsystem "Translation") | [<img src="https://avatars3.githubusercontent.com/u/3861828?v=4" width="110px;"/><br /><sub>Wira Sandy</sub>](http://azuraweb.xyz)<br />[🌍](#translation-wira-sandy "Translation") |
|
||||
| [<img src="https://avatars2.githubusercontent.com/u/8663789?v=4" width="110px;"/><br /><sub>Илья</sub>](https://github.com/GrayHoax)<br />[🌍](#translation-GrayHoax "Translation") | [<img src="https://avatars3.githubusercontent.com/u/30119111?v=4" width="110px;"/><br /><sub>GodUseVPN</sub>](https://github.com/godusevpn)<br />[🌍](#translation-godusevpn "Translation") | [<img src="https://avatars1.githubusercontent.com/u/745576?v=4" width="110px;"/><br /><sub>周周</sub>](https://github.com/EngrZhou)<br />[🌍](#translation-EngrZhou "Translation") | [<img src="https://avatars3.githubusercontent.com/u/1631095?v=4" width="110px;"/><br /><sub>Sam</sub>](https://github.com/takuy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=takuy "Code") | [<img src="https://avatars1.githubusercontent.com/u/264022?v=4" width="110px;"/><br /><sub>Azerothian</sub>](https://www.illisian.com.au)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Azerothian "Code") | [<img src="https://avatars1.githubusercontent.com/u/7632599?v=4" width="110px;"/><br /><sub>Tim Farmer</sub>](https://github.com/timothyfarmer)<br />[💻](https://github.com/snipe/snipe-it/commits?author=timothyfarmer "Code") |
|
||||
| [<img src="https://avatars2.githubusercontent.com/u/8663789?v=4" width="110px;"/><br /><sub>Илья</sub>](https://github.com/GrayHoax)<br />[🌍](#translation-GrayHoax "Translation") | [<img src="https://avatars3.githubusercontent.com/u/30119111?v=4" width="110px;"/><br /><sub>GodUseVPN</sub>](https://github.com/godusevpn)<br />[🌍](#translation-godusevpn "Translation") | [<img src="https://avatars1.githubusercontent.com/u/745576?v=4" width="110px;"/><br /><sub>周周</sub>](https://github.com/EngrZhou)<br />[🌍](#translation-EngrZhou "Translation") | [<img src="https://avatars3.githubusercontent.com/u/1631095?v=4" width="110px;"/><br /><sub>Sam</sub>](https://github.com/takuy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=takuy "Code") | [<img src="https://avatars1.githubusercontent.com/u/264022?v=4" width="110px;"/><br /><sub>Azerothian</sub>](https://www.illisian.com.au)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Azerothian "Code") | [<img src="https://avatars1.githubusercontent.com/u/7632599?v=4" width="110px;"/><br /><sub>Tim Farmer</sub>](https://github.com/timothyfarmer)<br />[💻](https://github.com/snipe/snipe-it/commits?author=timothyfarmer "Code") | [<img src="https://avatars0.githubusercontent.com/u/17459600?v=4" width="110px;"/><br /><sub>Marián Skrip</sub>](https://github.com/mskrip)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mskrip "Code") |
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
|
||||
|
||||
@@ -48,60 +48,90 @@ class ImportLocations extends Command
|
||||
$filename = $this->argument('filename');
|
||||
$csv = Reader::createFromPath(storage_path('private_uploads/imports/').$filename, 'r');
|
||||
$this->info('Attempting to process: '.storage_path('private_uploads/imports/').$filename);
|
||||
$csv->setOffset(1); //because we don't want to insert the header
|
||||
$csv->setHeaderOffset(0); //because we don't want to insert the header
|
||||
$results = $csv->getRecords();
|
||||
|
||||
// Import parent location names first if they don't exist
|
||||
foreach ($results as $parent_index => $parent_row) {
|
||||
|
||||
$parent_name = trim($parent_row['Parent Name']);
|
||||
// First create any parents if they don't exist
|
||||
|
||||
if ($parent_name!='') {
|
||||
if (array_key_exists('Parent Name', $parent_row)) {
|
||||
$parent_name = trim($parent_row['Parent Name']);
|
||||
if (array_key_exists('Name', $parent_row)) {
|
||||
$this->info('- Parent: ' . $parent_name . ' in row as: ' . trim($parent_row['Parent Name']));
|
||||
}
|
||||
|
||||
// Save parent location name
|
||||
// This creates a sort of name-stub that we'll update later on in this script
|
||||
$parent_location = Location::firstOrCreate(array('name' => $parent_name));
|
||||
$this->info('Parent for '.$parent_row['Name'].' is '.$parent_name.'. Attempting to save '.$parent_name.'.');
|
||||
if (array_key_exists('Name', $parent_row)) {
|
||||
$this->info('Parent for ' . $parent_row['Name'] . ' is ' . $parent_name . '. Attempting to save ' . $parent_name . '.');
|
||||
}
|
||||
|
||||
// Check if the record was updated or created.
|
||||
// This is mostly for clearer debugging.
|
||||
if ($parent_location->exists) {
|
||||
$this->info('- Parent location '.$parent_name.' already exists.');
|
||||
$this->info('- Parent location '.$parent_name.' already exists.');
|
||||
} else {
|
||||
$this->info('- Parent location '.$parent_name.' was created.');
|
||||
}
|
||||
|
||||
} else {
|
||||
$this->info('- No parent location for '.$parent_row['Name'].' provided.');
|
||||
$this->info('- No Parent Name provided, so no parent location will be created.');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$this->info('----- Parents Created.... backfilling additional details... --------');
|
||||
// Loop through ALL records and add/update them if there are additional fields
|
||||
// besides name
|
||||
foreach ($results as $index => $row) {
|
||||
|
||||
if (array_key_exists('Parent Name', $row)) {
|
||||
$parent_name = trim($row['Parent Name']);
|
||||
}
|
||||
|
||||
// Set the location attributes to save
|
||||
$location = Location::firstOrNew(array('name' => trim($row['Name'])));
|
||||
$location->name = trim($row['Name']);
|
||||
$location->currency = trim($row['Currency']);
|
||||
$location->address = trim($row['Address 1']);
|
||||
$location->address2 = trim($row['Address 2']);
|
||||
$location->city = trim($row['City']);
|
||||
$location->state = trim($row['State']);
|
||||
$location->zip = trim($row['Zip']);
|
||||
$location->country = trim($row['Country']);
|
||||
$location->ldap_ou = trim($row['OU']);
|
||||
if (array_key_exists('Name', $row)) {
|
||||
$location = Location::firstOrNew(array('name' => trim($row['Name'])));
|
||||
$location->name = trim($row['Name']);
|
||||
$this->info('Checking location: '.$location->name);
|
||||
} else {
|
||||
$this->error('Location name is required and is missing from at least one row in this dataset. Check your CSV for extra trailing rows and try again.');
|
||||
return false;
|
||||
}
|
||||
if (array_key_exists('Currency', $row)) {
|
||||
$location->currency = trim($row['Currency']);
|
||||
}
|
||||
if (array_key_exists('Address 1', $row)) {
|
||||
$location->address = trim($row['Address 1']);
|
||||
}
|
||||
if (array_key_exists('Address 2', $row)) {
|
||||
$location->address2 = trim($row['Address 2']);
|
||||
}
|
||||
if (array_key_exists('City', $row)) {
|
||||
$location->city = trim($row['City']);
|
||||
}
|
||||
if (array_key_exists('State', $row)) {
|
||||
$location->state = trim($row['State']);
|
||||
}
|
||||
if (array_key_exists('Zip', $row)) {
|
||||
$location->zip = trim($row['Zip']);
|
||||
}
|
||||
if (array_key_exists('Country', $row)) {
|
||||
$location->country = trim($row['Country']);
|
||||
}
|
||||
if (array_key_exists('Country', $row)) {
|
||||
$location->ldap_ou = trim($row['OU']);
|
||||
}
|
||||
|
||||
$this->info('Checking location: '.$location->name);
|
||||
|
||||
// If a parent name nis provided, we created it earlier in the script,
|
||||
// If a parent name is provided, we created it earlier in the script,
|
||||
// so let's grab that ID
|
||||
if ($parent_name) {
|
||||
$this->info('-- Searching for Parent Name: '.$parent_name);
|
||||
$parent = Location::where('name', '=', $parent_name)->first();
|
||||
$location->parent_id = $parent->id;
|
||||
$this->info('Parent ID: '.$parent->id);
|
||||
$this->info('Parent: '.$parent_name.' - ID: '.$parent->id);
|
||||
}
|
||||
|
||||
// Make sure the more advanced (non-name) fields pass validation
|
||||
|
||||
@@ -189,7 +189,7 @@ class LdapSync extends Command
|
||||
// Sync activated state for Active Directory.
|
||||
if ( array_key_exists('useraccountcontrol', $results[$i]) ) {
|
||||
$enabled_accounts = [
|
||||
'512', '544', '66048', '66080', '262656', '262688', '328192', '328224'
|
||||
'512', '544', '66048', '66080', '262656', '262688', '328192', '328224', '4260352'
|
||||
];
|
||||
$user->activated = ( in_array($results[$i]['useraccountcontrol'][0], $enabled_accounts) ) ? 1 : 0;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ class Purge extends Command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Purge all soft-deleted deleted records in the database. This will rewrite history for items that have been edited, or checked in or out. It will also reqrite history for users associated with deleted items.';
|
||||
protected $description = 'Purge all soft-deleted deleted records in the database. This will rewrite history for items that have been edited, or checked in or out. It will also rewrite history for users associated with deleted items.';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\CustomField;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class ReEncodeCustomFieldNames extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'snipeit:regenerate-fieldnames';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'This utility will regenerate the column names for custom fields. It should typically only be needed when a PHP upgrade changed the behavior of the unicode conversion between versions.';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* All three of these things must match for the custom fields system to work as expected:
|
||||
*
|
||||
* - what the system thinks the output of $field->convertUnicodeDbSlug() is
|
||||
* - the actual db_column name in the customfields table
|
||||
* - the physical column name that was created on the assets table
|
||||
*
|
||||
* For some people who upgraded their version of PHP, the unicode converter now behaves
|
||||
* differently in than it did when their custom fields were first created, specifically as it
|
||||
* relates to handling slashes, ampersands, etc. This can result in the field names no longer
|
||||
* matching up, as an older version of the PHP extension simply dropped slashes, etc, while the
|
||||
* newer version of the PHP extension will convert them to underscores.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
if ($this->confirm('This will regenerate all of the custom field database fieldnames in your database. THIS WILL CHANGE YOUR SCHEMA AND SHOULD NOT BE DONE WITHOUT MAKING A BACKUP FIRST. Do you wish to continue?'))
|
||||
{
|
||||
|
||||
/** Get all of the custom fields */
|
||||
$fields = CustomField::get();
|
||||
|
||||
$asset_columns = \DB::getSchemaBuilder()->getColumnListing('assets');
|
||||
$custom_field_columns = array();
|
||||
|
||||
/** Loop through the columns on the assets table */
|
||||
foreach ($asset_columns as $asset_column) {
|
||||
|
||||
/** Add ones that start with _snipeit_ to an array for handling */
|
||||
if (strpos($asset_column, '_snipeit_') === 0) {
|
||||
|
||||
/**
|
||||
* Get the ID of the custom field based on the fieldname.
|
||||
* For example, in _snipeit_mac_address_1, we grab the 1 because we know
|
||||
* that's the ID of the custom field that created the column.
|
||||
* Then use that ID as the array key for use comparing the actual assets field name
|
||||
* and the db_column value from the custom fields table.
|
||||
*/
|
||||
$last_part = substr(strrchr($asset_column, "_snipeit_"), 1);
|
||||
$custom_field_columns[$last_part] = $asset_column;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($fields as $field) {
|
||||
|
||||
$this->info($field->name .' ('.$field->id.') column should be '. $field->convertUnicodeDbSlug().'');
|
||||
|
||||
/** The assets table has the column it should have, all is well */
|
||||
if (\Schema::hasColumn('assets', $field->convertUnicodeDbSlug()))
|
||||
{
|
||||
$this->info('-- ✓ This field exists - all good');
|
||||
|
||||
/**
|
||||
* There is a mismatch between the fieldname on the assets table and
|
||||
* what $field->convertUnicodeDbSlug() is *now* expecting.
|
||||
*/
|
||||
} else {
|
||||
$this->warn('-- X Field mismatch: updating... ');
|
||||
|
||||
/** Make sure the custom_field_columns array has the ID */
|
||||
if (array_key_exists($field->id, $custom_field_columns)) {
|
||||
|
||||
/**
|
||||
* Update the asset schema to the corrected fieldname that will be recognized by the
|
||||
* system elsewhere that we use $field->convertUnicodeDbSlug()
|
||||
*/
|
||||
\Schema::table('assets', function($table) use ($custom_field_columns, $field) {
|
||||
$table->renameColumn($custom_field_columns[$field->id], $field->convertUnicodeDbSlug());
|
||||
});
|
||||
|
||||
$this->warn('-- ✓ Field updated from '.$custom_field_columns[$field->id].' to '.$field->convertUnicodeDbSlug());
|
||||
|
||||
} else {
|
||||
$this->warn('-- X WARNING: There is no field on the assets table ending in '.$field->id.'. This may require more in-depth investigation and may mean the schema was altered manually.');
|
||||
}
|
||||
}
|
||||
|
||||
/** Update the db_column property in the custom fields table, just in case it doesn't match the other
|
||||
* things.
|
||||
*/
|
||||
$field->db_column = $field->convertUnicodeDbSlug();
|
||||
$field->save();
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Artisan;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Setting;
|
||||
use \Illuminate\Encryption\Encrypter;
|
||||
|
||||
class RotateAppKey extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'snipeit:rotate-key';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Command description';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if ($this->confirm("\n****************************************************\nTHIS WILL MODIFY YOUR APP_KEY AND DE-CRYPT YOUR ENCRYPTED CUSTOM FIELDS AND \nRE-ENCRYPT THEM WITH A NEWLY GENERATED KEY. \n\nThere is NO undo. \n\nMake SURE you have a database backup and a backup of your .env generated BEFORE running this command. \n\nIf you do not save the newly generated APP_KEY to your .env in this process, \nyour encrypted data will no longer be decryptable. \n\nAre you SURE you wish to continue, and have confirmed you have a database backup and an .env backup? ")) {
|
||||
|
||||
|
||||
|
||||
// Get the existing app_key and ciphers
|
||||
// We put them in a variable since we clear the cache partway through here.
|
||||
$old_app_key = config('app.key');
|
||||
$cipher = config('app.cipher');
|
||||
|
||||
// Generate a new one
|
||||
Artisan::call('key:generate', ['--show' => true]);
|
||||
$new_app_key = Artisan::output();
|
||||
|
||||
// Clear the config cache
|
||||
Artisan::call('config:clear');
|
||||
|
||||
$this->warn('Your app cipher is: '.$cipher);
|
||||
$this->warn('Your old APP_KEY is: '.$old_app_key);
|
||||
$this->warn('Your new APP_KEY is: '.$new_app_key);
|
||||
|
||||
// Write the new app key to the .env file
|
||||
$this->writeNewEnvironmentFileWith($new_app_key);
|
||||
|
||||
// Manually create an old encrypter instance using the old app key
|
||||
// and also create a new encrypter instance so we can re-crypt the field
|
||||
// using the newly generated app key
|
||||
$oldEncrypter = new Encrypter(base64_decode(substr($old_app_key, 7)), $cipher);
|
||||
$newEncrypter = new Encrypter(base64_decode(substr($new_app_key, 7)), $cipher);
|
||||
|
||||
$fields = CustomField::where('field_encrypted', '1')->get();
|
||||
|
||||
|
||||
foreach ($fields as $field) {
|
||||
|
||||
$assets = Asset::whereNotNull($field->db_column)->get();
|
||||
|
||||
foreach ($assets as $asset) {
|
||||
|
||||
$asset->{$field->db_column} = $oldEncrypter->decrypt($asset->{$field->db_column});
|
||||
$this->line('DECRYPTED: '. $field->db_column);
|
||||
$asset->{$field->db_column} = $newEncrypter->encrypt($asset->{$field->db_column});
|
||||
$this->line('ENCRYPTED: '.$field->db_column);
|
||||
$asset->save();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Handle the LDAP password if one is provided
|
||||
$setting = Setting::first();
|
||||
if ($setting->ldap_pword!='') {
|
||||
$setting->ldap_pword = $oldEncrypter->decrypt($setting->ldap_pword);
|
||||
$setting->ldap_pword = $newEncrypter->encrypt($setting->ldap_pword);
|
||||
$setting->save();
|
||||
$this->warn('LDAP password has been re-encrypted.');
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
$this->info('This operation has been canceled. No changes have been made.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a new environment file with the given key.
|
||||
*
|
||||
* @param string $key
|
||||
* @return void
|
||||
*/
|
||||
protected function writeNewEnvironmentFileWith($key)
|
||||
{
|
||||
|
||||
file_put_contents($this->laravel->environmentFilePath(), preg_replace(
|
||||
$this->keyReplacementPattern(),
|
||||
'APP_KEY='.$key,
|
||||
file_get_contents($this->laravel->environmentFilePath())
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a regex pattern that will match env APP_KEY with any random key.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function keyReplacementPattern()
|
||||
{
|
||||
$escaped = preg_quote('='.$this->laravel['config']['app.key'], '/');
|
||||
return "/^APP_KEY{$escaped}/m";
|
||||
}
|
||||
|
||||
}
|
||||
+2
-27
@@ -2,39 +2,14 @@
|
||||
|
||||
namespace App\Console;
|
||||
|
||||
use App\Console\Commands\ImportLocations;
|
||||
use App\Console\Commands\ReEncodeCustomFieldNames;
|
||||
use App\Console\Commands\RestoreDeletedUsers;
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
|
||||
class Kernel extends ConsoleKernel
|
||||
{
|
||||
/**
|
||||
* The Artisan commands provided by your application.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $commands = [
|
||||
Commands\PaveIt::class,
|
||||
Commands\CreateAdmin::class,
|
||||
Commands\SendExpirationAlerts::class,
|
||||
Commands\SendInventoryAlerts::class,
|
||||
Commands\SendExpectedCheckinAlerts::class,
|
||||
Commands\ObjectImportCommand::class,
|
||||
Commands\Version::class,
|
||||
Commands\SystemBackup::class,
|
||||
Commands\DisableLDAP::class,
|
||||
Commands\Purge::class,
|
||||
Commands\LdapSync::class,
|
||||
Commands\FixDoubleEscape::class,
|
||||
Commands\RecryptFromMcrypt::class,
|
||||
Commands\ResetDemoSettings::class,
|
||||
Commands\SyncAssetLocations::class,
|
||||
Commands\RegenerateAssetTags::class,
|
||||
Commands\SyncAssetCounters::class,
|
||||
Commands\RestoreDeletedUsers::class,
|
||||
Commands\SendUpcomingAuditReport::class,
|
||||
Commands\ImportLocations::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* Define the application's command schedule.
|
||||
|
||||
@@ -67,10 +67,6 @@ class Handler extends ExceptionHandler
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $className . ' not found'), 200);
|
||||
}
|
||||
|
||||
if ($e instanceof \Illuminate\Validation\ValidationException) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $e->response['messages'], 400));
|
||||
}
|
||||
|
||||
if ($this->isHttpException($e)) {
|
||||
|
||||
$statusCode = $e->getStatusCode();
|
||||
@@ -85,11 +81,6 @@ class Handler extends ExceptionHandler
|
||||
|
||||
}
|
||||
}
|
||||
// Try to parse 500 Errors in a bit nicer way when debug is enabled.
|
||||
if (config('app.debug')) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, "An Error has occured! " . $e->getMessage()), 500);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -128,6 +119,6 @@ class Handler extends ExceptionHandler
|
||||
*/
|
||||
protected function invalidJson($request, ValidationException $exception)
|
||||
{
|
||||
return response()->json($exception->errors(), $exception->status);
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $exception->errors(), 400));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,26 +85,7 @@ class AccessoriesController extends Controller
|
||||
$accessory->qty = request('qty');
|
||||
$accessory->user_id = Auth::user()->id;
|
||||
$accessory->supplier_id = request('supplier_id');
|
||||
|
||||
if ($request->hasFile('image')) {
|
||||
|
||||
if (!config('app.lock_passwords')) {
|
||||
$image = $request->file('image');
|
||||
$ext = $image->getClientOriginalExtension();
|
||||
$file_name = "accessory-".str_random(18).'.'.$ext;
|
||||
$path = public_path('/uploads/accessories');
|
||||
if ($image->getClientOriginalExtension()!='svg') {
|
||||
Image::make($image->getRealPath())->resize(null, 800, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path.'/'.$file_name);
|
||||
} else {
|
||||
$image->move($path, $file_name);
|
||||
}
|
||||
$accessory->image = $file_name;
|
||||
}
|
||||
}
|
||||
|
||||
$accessory = $request->handleImages($accessory,600, public_path().'/uploads/accessories');
|
||||
|
||||
|
||||
// Was the accessory created?
|
||||
@@ -165,28 +146,7 @@ class AccessoriesController extends Controller
|
||||
$accessory->qty = request('qty');
|
||||
$accessory->supplier_id = request('supplier_id');
|
||||
|
||||
if ($request->hasFile('image')) {
|
||||
|
||||
if (!config('app.lock_passwords')) {
|
||||
$image = $request->file('image');
|
||||
$ext = $image->getClientOriginalExtension();
|
||||
$file_name = "accessory-".str_random(18).'.'.$ext;
|
||||
$path = public_path('/uploads/accessories');
|
||||
if ($image->getClientOriginalExtension()!='svg') {
|
||||
Image::make($image->getRealPath())->resize(null, 800, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path.'/'.$file_name);
|
||||
} else {
|
||||
$image->move($path, $file_name);
|
||||
}
|
||||
if (($accessory->image) && (file_exists($path.'/'.$accessory->image))) {
|
||||
unlink($path.'/'.$accessory->image);
|
||||
}
|
||||
|
||||
$accessory->image = $file_name;
|
||||
}
|
||||
}
|
||||
$accessory = $request->handleImages($accessory,600, public_path().'/uploads/accessories');
|
||||
|
||||
|
||||
// Was the accessory updated?
|
||||
|
||||
@@ -8,7 +8,10 @@ use App\Helpers\Helper;
|
||||
use App\Models\Accessory;
|
||||
use App\Http\Transformers\AccessoriesTransformer;
|
||||
use App\Models\Company;
|
||||
|
||||
use App\Models\User;
|
||||
use Carbon\Carbon;
|
||||
use Auth;
|
||||
use DB;
|
||||
|
||||
class AccessoriesController extends Controller
|
||||
{
|
||||
@@ -47,7 +50,11 @@ class AccessoriesController extends Controller
|
||||
}
|
||||
|
||||
$offset = (($accessories) && (request('offset') > $accessories->count())) ? 0 : request('offset', 0);
|
||||
$limit = $request->input('limit', 50);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
|
||||
@@ -191,4 +198,94 @@ class AccessoriesController extends Controller
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/accessories/message.delete.success')));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save the Accessory checkout information.
|
||||
*
|
||||
* If Slack is enabled and/or asset acceptance is enabled, it will also
|
||||
* trigger a Slack message and send an email.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $accessoryId
|
||||
* @return Redirect
|
||||
*/
|
||||
public function checkout(Request $request, $accessoryId)
|
||||
{
|
||||
// Check if the accessory exists
|
||||
if (is_null($accessory = Accessory::find($accessoryId))) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/accessories/message.does_not_exist')));
|
||||
}
|
||||
|
||||
$this->authorize('checkout', $accessory);
|
||||
|
||||
|
||||
if ($accessory->numRemaining() > 0) {
|
||||
|
||||
if (!$user = User::find($request->input('assigned_to'))) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/accessories/message.checkout.user_does_not_exist')));
|
||||
}
|
||||
|
||||
// Update the accessory data
|
||||
$accessory->assigned_to = $request->input('assigned_to');
|
||||
|
||||
$accessory->users()->attach($accessory->id, [
|
||||
'accessory_id' => $accessory->id,
|
||||
'created_at' => Carbon::now(),
|
||||
'user_id' => Auth::id(),
|
||||
'assigned_to' => $request->get('assigned_to')
|
||||
]);
|
||||
|
||||
$accessory->logCheckout($request->input('note'), $user);
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/accessories/message.checkout.success')));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'No accessories remaining'));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check in the item so that it can be checked out again to someone else
|
||||
*
|
||||
* @uses Accessory::checkin_email() to determine if an email can and should be sent
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param Request $request
|
||||
* @param integer $accessoryUserId
|
||||
* @param string $backto
|
||||
* @return Redirect
|
||||
* @internal param int $accessoryId
|
||||
*/
|
||||
public function checkin(Request $request, $accessoryUserId = null)
|
||||
{
|
||||
if (is_null($accessory_user = DB::table('accessories_users')->find($accessoryUserId))) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/accessories/message.does_not_exist')));
|
||||
}
|
||||
|
||||
$accessory = Accessory::find($accessory_user->accessory_id);
|
||||
$this->authorize('checkin', $accessory);
|
||||
|
||||
$logaction = $accessory->logCheckin(User::find($accessoryUserId), $request->input('note'));
|
||||
|
||||
// Was the accessory updated?
|
||||
if (DB::table('accessories_users')->where('id', '=', $accessory_user->id)->delete()) {
|
||||
if (!is_null($accessory_user->assigned_to)) {
|
||||
$user = User::find($accessory_user->assigned_to);
|
||||
}
|
||||
|
||||
$data['log_id'] = $logaction->id;
|
||||
$data['first_name'] = $user->first_name;
|
||||
$data['last_name'] = $user->last_name;
|
||||
$data['item_name'] = $accessory->name;
|
||||
$data['checkin_date'] = $logaction->created_at;
|
||||
$data['item_tag'] = '';
|
||||
$data['note'] = $logaction->note;
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/accessories/message.checkin.success')));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/accessories/message.checkin.error')));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -45,7 +45,10 @@ class AssetMaintenancesController extends Controller
|
||||
}
|
||||
|
||||
$offset = (($maintenances) && (request('offset') > $maintenances->count())) ? 0 : request('offset', 0);
|
||||
$limit = request('limit', 50);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
|
||||
$allowed_columns = [
|
||||
'id',
|
||||
|
||||
@@ -61,7 +61,10 @@ class AssetModelsController extends Controller
|
||||
}
|
||||
|
||||
$offset = (($assetmodels) && (request('offset') > $assetmodels->count())) ? 0 : request('offset', 0);
|
||||
$limit = $request->input('limit', 50);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'models.created_at';
|
||||
|
||||
|
||||
@@ -145,7 +145,10 @@ class AssetsController extends Controller
|
||||
$request->filled('order_number') ? $assets = $assets->where('assets.order_number', '=', e($request->get('order_number'))) : '';
|
||||
|
||||
$offset = (($assets) && (request('offset') > $assets->count())) ? 0 : request('offset', 0);
|
||||
$limit = $request->input('limit', 50);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
|
||||
// This is used by the audit reporting routes
|
||||
@@ -522,6 +525,10 @@ class AssetsController extends Controller
|
||||
$location = $target->location_id;
|
||||
} elseif (($request->filled('assigned_asset')) && ($target = Asset::find($request->get('assigned_asset')))) {
|
||||
$location = $target->location_id;
|
||||
|
||||
Asset::where('assigned_type', '\\App\\Models\\Asset')->where('assigned_to', $id)
|
||||
->update(['location_id' => $target->location_id]);
|
||||
|
||||
} elseif (($request->filled('assigned_location')) && ($target = Location::find($request->get('assigned_location')))) {
|
||||
$location = $target->id;
|
||||
}
|
||||
@@ -645,7 +652,7 @@ class AssetsController extends Controller
|
||||
return response()->json(Helper::formatStandardApiResponse('success', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkout.success')));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkout.error')))->withErrors($asset->getErrors());
|
||||
return response()->json(Helper::formatStandardApiResponse('error', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkout.error')));
|
||||
}
|
||||
|
||||
|
||||
@@ -674,7 +681,11 @@ class AssetsController extends Controller
|
||||
$asset->assigned_to = null;
|
||||
$asset->assignedTo()->disassociate($asset);
|
||||
$asset->accepted = null;
|
||||
$asset->name = Input::get('name');
|
||||
|
||||
if ($request->filled('name')) {
|
||||
$asset->name = $request->input('name');
|
||||
}
|
||||
|
||||
$asset->location_id = $asset->rtd_location_id;
|
||||
|
||||
if ($request->filled('location_id')) {
|
||||
|
||||
@@ -31,7 +31,10 @@ class CategoriesController extends Controller
|
||||
}
|
||||
|
||||
$offset = (($categories) && (request('offset') > $categories->count())) ? 0 : request('offset', 0);
|
||||
$limit = $request->input('limit', 50);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'assets_count';
|
||||
$categories->orderBy($sort, $order);
|
||||
|
||||
@@ -42,7 +42,10 @@ class CompaniesController extends Controller
|
||||
}
|
||||
|
||||
$offset = (($companies) && (request('offset') > $companies->count())) ? 0 : request('offset', 0);
|
||||
$limit = $request->input('limit', 50);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
$companies->orderBy($sort, $order);
|
||||
|
||||
@@ -44,7 +44,9 @@ class ComponentsController extends Controller
|
||||
}
|
||||
|
||||
$offset = (($components) && (request('offset') > $components->count())) ? 0 : request('offset', 0);
|
||||
$limit = request('limit', 50);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$allowed_columns = ['id','name','min_amt','order_number','serial','purchase_date','purchase_cost','company','category','qty','location','image'];
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
|
||||
@@ -45,7 +45,10 @@ class ConsumablesController extends Controller
|
||||
|
||||
|
||||
$offset = (($consumables) && (request('offset') > $consumables->count())) ? 0 : request('offset', 0);
|
||||
$limit = request('limit', 50);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$allowed_columns = ['id','name','order_number','min_amt','purchase_date','purchase_cost','company','category','model_number', 'item_no', 'manufacturer','location','qty','image'];
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
@@ -165,7 +168,7 @@ class ConsumablesController extends Controller
|
||||
{
|
||||
$consumable = Consumable::with(array('consumableAssignments'=>
|
||||
function ($query) {
|
||||
$query->orderBy('created_at', 'DESC');
|
||||
$query->orderBy($query->getModel()->getTable().'.created_at', 'DESC');
|
||||
},
|
||||
'consumableAssignments.admin'=> function ($query) {
|
||||
},
|
||||
|
||||
@@ -24,7 +24,7 @@ class CustomFieldsController extends Controller
|
||||
|
||||
public function index()
|
||||
{
|
||||
$this->authorize('index', CustomFields::class);
|
||||
$this->authorize('index', CustomField::class);
|
||||
$fields = CustomField::get();
|
||||
return (new CustomFieldsTransformer)->transformCustomFields($fields, $fields->count());
|
||||
}
|
||||
@@ -38,7 +38,7 @@ class CustomFieldsController extends Controller
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
$this->authorize('show', CustomField::class);
|
||||
$this->authorize('view', CustomField::class);
|
||||
if ($field = CustomField::find($id)) {
|
||||
return (new CustomFieldsTransformer)->transformCustomField($field);
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ class CustomFieldsetsController extends Controller
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
$this->authorize('show', CustomFieldset::class);
|
||||
$this->authorize('view', CustomFieldset::class);
|
||||
if ($fieldset = CustomFieldset::find($id)) {
|
||||
return (new CustomFieldsetsTransformer)->transformCustomFieldset($fieldset);
|
||||
}
|
||||
|
||||
@@ -40,7 +40,10 @@ class DepartmentsController extends Controller
|
||||
}
|
||||
|
||||
$offset = (($departments) && (request('offset') > $departments->count())) ? 0 : request('offset', 0);
|
||||
$limit = $request->input('limit', 50);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
|
||||
|
||||
@@ -29,7 +29,10 @@ class DepreciationsController extends Controller
|
||||
}
|
||||
|
||||
$offset = (($depreciations) && (request('offset') > $depreciations->count())) ? 0 : request('offset', 0);
|
||||
$limit = $request->input('limit', 50);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
$depreciations->orderBy($sort, $order);
|
||||
|
||||
@@ -29,7 +29,10 @@ class GroupsController extends Controller
|
||||
}
|
||||
|
||||
$offset = (($groups) && (request('offset') > $groups->count())) ? 0 : request('offset', 0);
|
||||
$limit = $request->input('limit', 50);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
$groups->orderBy($sort, $order);
|
||||
|
||||
@@ -83,7 +83,10 @@ class LicensesController extends Controller
|
||||
|
||||
|
||||
$offset = (($licenses) && (request('offset') > $licenses->count())) ? 0 : request('offset', 0);
|
||||
$limit = request('limit', 50);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
|
||||
|
||||
@@ -225,14 +228,21 @@ class LicensesController extends Controller
|
||||
|
||||
$this->authorize('view', $license);
|
||||
|
||||
$seats = LicenseSeat::where('license_id', $licenseId)->with('license', 'user', 'asset');
|
||||
$seats = LicenseSeat::where('license_seats.license_id', $licenseId)
|
||||
->with('license', 'user', 'asset', 'user.department');
|
||||
|
||||
$offset = (($seats) && (request('offset') > $seats->count())) ? 0 : request('offset', 0);
|
||||
|
||||
$limit = request('limit', 50);
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
|
||||
if ($request->input('sort')=='department') {
|
||||
$seats->OrderDepartments($order);
|
||||
} else {
|
||||
$seats->orderBy('id', $order);
|
||||
}
|
||||
|
||||
$total = $seats->count();
|
||||
$offset = (($seats) && (request('offset') > $total)) ? 0 : request('offset', 0);
|
||||
$limit = request('limit', 50);
|
||||
|
||||
$seats = $seats->skip($offset)->take($limit)->get();
|
||||
|
||||
if ($seats) {
|
||||
|
||||
@@ -8,6 +8,8 @@ use App\Helpers\Helper;
|
||||
use App\Models\Location;
|
||||
use App\Http\Transformers\LocationsTransformer;
|
||||
use App\Http\Transformers\SelectlistTransformer;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class LocationsController extends Controller
|
||||
{
|
||||
@@ -26,7 +28,7 @@ class LocationsController extends Controller
|
||||
'updated_at','manager_id','image',
|
||||
'assigned_assets_count','users_count','assets_count','currency'];
|
||||
|
||||
$locations = Location::with('parent', 'manager', 'childLocations')->select([
|
||||
$locations = Location::with('parent', 'manager', 'children')->select([
|
||||
'locations.id',
|
||||
'locations.name',
|
||||
'locations.address',
|
||||
@@ -52,7 +54,10 @@ class LocationsController extends Controller
|
||||
|
||||
|
||||
$offset = (($locations) && (request('offset') > $locations->count())) ? 0 : request('offset', 0);
|
||||
$limit = $request->input('limit', 50);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
|
||||
@@ -106,7 +111,7 @@ class LocationsController extends Controller
|
||||
public function show($id)
|
||||
{
|
||||
$this->authorize('view', Location::class);
|
||||
$location = Location::with('parent', 'manager', 'childLocations')
|
||||
$location = Location::with('parent', 'manager', 'children')
|
||||
->select([
|
||||
'locations.id',
|
||||
'locations.name',
|
||||
@@ -143,6 +148,13 @@ class LocationsController extends Controller
|
||||
{
|
||||
$this->authorize('update', Location::class);
|
||||
$location = Location::findOrFail($id);
|
||||
|
||||
if ($request->input('parent_id') == $id) {
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'A location cannot be its own parent. Please select a different parent ID.'));
|
||||
}
|
||||
|
||||
|
||||
$location->fill($request->all());
|
||||
|
||||
if ($location->save()) {
|
||||
@@ -178,6 +190,27 @@ class LocationsController extends Controller
|
||||
/**
|
||||
* Gets a paginated collection for the select2 menus
|
||||
*
|
||||
* This is handled slightly differently as of ~4.7.8-pre, as
|
||||
* we have to do some recursive magic to get the hierarchy to display
|
||||
* properly when looking at the parent/child relationship in the
|
||||
* rich menus.
|
||||
*
|
||||
* This means we can't use the normal pagination that we use elsewhere
|
||||
* in our selectlists, since we have to get the full set before we can
|
||||
* determine which location is parent/child/grandchild, etc.
|
||||
*
|
||||
* This also means that hierarchy display gets a little funky when people
|
||||
* use the Select2 search functionality, but there's not much we can do about
|
||||
* that right now.
|
||||
*
|
||||
* As a result, instead of paginating as part of the query, we have to grab
|
||||
* the entire data set, and then invoke a paginator manually and pass that
|
||||
* through to the SelectListTransformer.
|
||||
*
|
||||
* Many thanks to @uberbrady for the help getting this working better.
|
||||
* Recursion still sucks, but I guess he doesn't have to get in the
|
||||
* sea... this time.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0.16]
|
||||
* @see \App\Http\Transformers\SelectlistTransformer
|
||||
@@ -189,25 +222,44 @@ class LocationsController extends Controller
|
||||
$locations = Location::select([
|
||||
'locations.id',
|
||||
'locations.name',
|
||||
'locations.parent_id',
|
||||
'locations.image',
|
||||
]);
|
||||
|
||||
$page = 1;
|
||||
if ($request->filled('page')) {
|
||||
$page = $request->input('page');
|
||||
}
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$locations = $locations->where('locations.name', 'LIKE', '%'.$request->get('search').'%');
|
||||
$locations = $locations->where('locations.name', 'LIKE', '%'.$request->input('search').'%');
|
||||
}
|
||||
|
||||
$locations = $locations->orderBy('name', 'ASC')->paginate(50);
|
||||
$locations = $locations->orderBy('name', 'ASC')->get();
|
||||
|
||||
$locations_with_children = [];
|
||||
|
||||
// Loop through and set some custom properties for the transformer to use.
|
||||
// This lets us have more flexibility in special cases like assets, where
|
||||
// they may not have a ->name value but we want to display something anyway
|
||||
foreach ($locations as $location) {
|
||||
$location->use_text = $location->name;
|
||||
$location->use_image = ($location->image) ? url('/').'/uploads/locations/'.$location->image : null;
|
||||
if (!array_key_exists($location->parent_id, $locations_with_children)) {
|
||||
$locations_with_children[$location->parent_id] = [];
|
||||
}
|
||||
$locations_with_children[$location->parent_id][] = $location;
|
||||
}
|
||||
|
||||
return (new SelectlistTransformer)->transformSelectlist($locations);
|
||||
if ($request->filled('search')) {
|
||||
$locations_formatted = $locations;
|
||||
} else {
|
||||
$location_options = Location::indenter($locations_with_children);
|
||||
$locations_formatted = new Collection($location_options);
|
||||
|
||||
}
|
||||
|
||||
$paginated_results = new LengthAwarePaginator($locations_formatted->forPage($page, 500), $locations_formatted->count(), 500, $page, []);
|
||||
|
||||
//return [];
|
||||
return (new SelectlistTransformer)->transformSelectlist($paginated_results);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -40,7 +40,10 @@ class ManufacturersController extends Controller
|
||||
|
||||
|
||||
$offset = (($manufacturers) && (request('offset') > $manufacturers->count())) ? 0 : request('offset', 0);
|
||||
$limit = $request->input('limit', 50);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
$manufacturers->orderBy($sort, $order);
|
||||
|
||||
@@ -38,7 +38,7 @@ class SettingsController extends Controller
|
||||
//return response()->json(['message' => $e->getMessage()], 500);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Connection failed');
|
||||
\Log::debug('Connection failed but we cannot debug it any further on our end.');
|
||||
return response()->json(['message' => $e->getMessage()], 600);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,10 @@ class StatuslabelsController extends Controller
|
||||
}
|
||||
|
||||
$offset = (($statuslabels) && (request('offset') > $statuslabels->count())) ? 0 : request('offset', 0);
|
||||
$limit = $request->input('limit', 50);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
$statuslabels->orderBy($sort, $order);
|
||||
|
||||
@@ -34,7 +34,10 @@ class SuppliersController extends Controller
|
||||
}
|
||||
|
||||
$offset = (($suppliers) && (request('offset') > $suppliers->count())) ? 0 : request('offset', 0);
|
||||
$limit = $request->input('limit', 50);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
$suppliers->orderBy($sort, $order);
|
||||
|
||||
@@ -88,7 +88,10 @@ class UsersController extends Controller
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$offset = (($users) && (request('offset') > $users->count())) ? 0 : request('offset', 0);
|
||||
$limit = request('limit', 20);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
|
||||
switch ($request->input('sort')) {
|
||||
case 'manager':
|
||||
@@ -260,12 +263,21 @@ class UsersController extends Controller
|
||||
|
||||
if ($user->save()) {
|
||||
|
||||
// Sync group memberships:
|
||||
// This was changed in Snipe-IT v4.6.x to 4.7, since we upgraded to Laravel 5.5
|
||||
// which changes the behavior of has vs filled.
|
||||
// The $request->has method will now return true even if the input value is an empty string or null.
|
||||
// A new $request->filled method has was added that provides the previous behavior of the has method.
|
||||
|
||||
// Check if the request has groups passed and has a value
|
||||
if ($request->filled('groups')) {
|
||||
$user->groups()->sync($request->input('groups'));
|
||||
} else {
|
||||
// The groups field has been passed but it is null, so we should blank it out
|
||||
} elseif ($request->has('groups')) {
|
||||
$user->groups()->sync(array());
|
||||
}
|
||||
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', (new UsersTransformer)->transformUser($user), trans('admin/users/message.success.update')));
|
||||
}
|
||||
|
||||
@@ -287,10 +299,23 @@ class UsersController extends Controller
|
||||
$this->authorize('delete', $user);
|
||||
|
||||
|
||||
if ($user->assets()->count() > 0) {
|
||||
if (($user->assets) && ($user->assets->count() > 0)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.error.delete_has_assets')));
|
||||
}
|
||||
|
||||
if (($user->licenses) && ($user->licenses->count() > 0)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'This user still has ' . $user->licenses->count() . ' license(s) associated with them and cannot be deleted.'));
|
||||
}
|
||||
|
||||
if (($user->accessories) && ($user->accessories->count() > 0)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'This user still has ' . $user->accessories->count() . ' accessories associated with them.'));
|
||||
}
|
||||
|
||||
if (($user->managedLocations()) && ($user->managedLocations()->count() > 0)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'This user still has ' . $user->managedLocations()->count() . ' locations that they manage.'));
|
||||
}
|
||||
|
||||
|
||||
if ($user->delete()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.success.delete')));
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ class AssetCheckinController extends Controller
|
||||
$data['model_name'] = $asset->model->name;
|
||||
$data['model_number'] = $asset->model->model_number;
|
||||
|
||||
if (($user) && ($backto =='user')) {
|
||||
if ((isset($user)) && ($backto =='user')) {
|
||||
return redirect()->route("users.show", $user->id)->with('success', trans('admin/hardware/message.checkin.success'));
|
||||
}
|
||||
return redirect()->route("hardware.index")->with('success', trans('admin/hardware/message.checkin.success'));
|
||||
|
||||
@@ -28,7 +28,6 @@ class AssetCheckoutController extends Controller
|
||||
{
|
||||
// Check if the asset exists
|
||||
if (is_null($asset = Asset::find(e($assetId)))) {
|
||||
// Redirect to the asset management page with error
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
}
|
||||
|
||||
@@ -39,7 +38,6 @@ class AssetCheckoutController extends Controller
|
||||
}
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkout.not_available'));
|
||||
|
||||
// Get the dropdown of users and then pass it to the checkout view
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -90,23 +90,7 @@ class AssetModelsController extends Controller
|
||||
$model->fieldset_id = e($request->input('custom_fieldset'));
|
||||
}
|
||||
|
||||
if (Input::file('image')) {
|
||||
|
||||
$image = Input::file('image');
|
||||
$file_name = str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
|
||||
$path = app('models_upload_path');
|
||||
|
||||
if ($image->getClientOriginalExtension()!='svg') {
|
||||
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path.'/'.$file_name);
|
||||
} else {
|
||||
$image->move($path, $file_name);
|
||||
}
|
||||
$model->image = $file_name;
|
||||
|
||||
}
|
||||
$model = $request->handleImages($model,600, public_path().'/uploads/models');
|
||||
|
||||
// Was it created?
|
||||
if ($model->save()) {
|
||||
@@ -182,37 +166,7 @@ class AssetModelsController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
$old_image = $model->image;
|
||||
|
||||
// Set the model's image property to null if the image is being deleted
|
||||
if ($request->input('image_delete') == 1) {
|
||||
$model->image = null;
|
||||
}
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = $model->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
|
||||
|
||||
if ($image->getClientOriginalExtension()!='svg') {
|
||||
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save(app('models_upload_path').$file_name);
|
||||
} else {
|
||||
$image->move(app('models_upload_path'), $file_name);
|
||||
}
|
||||
$model->image = $file_name;
|
||||
|
||||
}
|
||||
|
||||
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
|
||||
try {
|
||||
unlink(app('models_upload_path').$old_image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::info($e);
|
||||
}
|
||||
}
|
||||
|
||||
$model = $request->handleImages($model,600, public_path().'/uploads/models');
|
||||
|
||||
if ($model->save()) {
|
||||
return redirect()->route("models.index")->with('success', trans('admin/models/message.update.success'));
|
||||
|
||||
@@ -394,6 +394,12 @@ class AssetsController extends Controller
|
||||
|
||||
|
||||
if ($asset->save()) {
|
||||
|
||||
// Update any assigned assets with the new location_id from the parent asset
|
||||
|
||||
Asset::where('assigned_type', '\\App\\Models\\Asset')->where('assigned_to', $asset->id)
|
||||
->update(['location_id' => $asset->location_id]);
|
||||
|
||||
// Redirect to the new asset page
|
||||
\Session::flash('success', trans('admin/hardware/message.update.success'));
|
||||
return response()->json(['redirect_url' => route("hardware.show", $assetId)]);
|
||||
@@ -570,15 +576,17 @@ class AssetsController extends Controller
|
||||
*/
|
||||
public function postImportHistory(Request $request)
|
||||
{
|
||||
|
||||
if (!$request->hasFile('user_import_csv')) {
|
||||
return back()->with('error', 'No file provided. Please select a file for import and try again. ');
|
||||
}
|
||||
|
||||
if (!ini_get("auto_detect_line_endings")) {
|
||||
ini_set("auto_detect_line_endings", '1');
|
||||
}
|
||||
|
||||
$csv = Reader::createFromPath(Input::file('user_import_csv'));
|
||||
$csv->setNewline("\r\n");
|
||||
//get the first row, usually the CSV header
|
||||
//$headers = $csv->fetchOne();
|
||||
|
||||
$csv->setHeaderOffset(0);
|
||||
$results = $csv->getRecords();
|
||||
$item = array();
|
||||
$status = array();
|
||||
@@ -595,7 +603,9 @@ class AssetsController extends Controller
|
||||
}
|
||||
$batch_counter = count($item[$asset_tag]);
|
||||
|
||||
$item[$asset_tag][$batch_counter]['checkout_date'] = Carbon::parse(Helper::array_smart_fetch($row, "date"))->format('Y-m-d H:i:s');
|
||||
$item[$asset_tag][$batch_counter]['checkout_date'] = Carbon::parse(Helper::array_smart_fetch($row, "checkout date"))->format('Y-m-d H:i:s');
|
||||
$item[$asset_tag][$batch_counter]['checkin_date'] = Carbon::parse(Helper::array_smart_fetch($row, "checkin date"))->format('Y-m-d H:i:s');
|
||||
\Log::debug($item[$asset_tag][$batch_counter]['checkin_date']);
|
||||
|
||||
$item[$asset_tag][$batch_counter]['asset_tag'] = Helper::array_smart_fetch($row, "asset tag");
|
||||
$item[$asset_tag][$batch_counter]['name'] = Helper::array_smart_fetch($row, "name");
|
||||
@@ -678,9 +688,11 @@ class AssetsController extends Controller
|
||||
// Only do this if a matching user was found
|
||||
if ((array_key_exists('checkedout_to', $asset_batch[$x])) && ($asset_batch[$x]['checkedout_to']!='')) {
|
||||
if (($total_in_batch > 1) && ($x < $total_in_batch) && (array_key_exists($next, $asset_batch))) {
|
||||
$checkin_date = Carbon::parse($asset_batch[$next]['checkout_date'])->subDay(1)->format('Y-m-d H:i:s');
|
||||
$checkin_date = Carbon::parse($asset_batch[$next]['checkin_date'])->format('Y-m-d H:i:s');
|
||||
$asset_batch[$x]['real_checkin'] = $checkin_date;
|
||||
|
||||
\Log::debug($asset_batch[$next]['checkin_date']);
|
||||
\Log::debug($checkin_date);
|
||||
Actionlog::firstOrCreate(array(
|
||||
'item_id' => $asset_batch[$x]['asset_id'],
|
||||
'item_type' => Asset::class,
|
||||
|
||||
@@ -137,7 +137,7 @@ class BulkAssetsController extends Controller
|
||||
*/
|
||||
protected function conditionallyAddItem($field)
|
||||
{
|
||||
if(request()->has($field)) {
|
||||
if(request()->filled($field)) {
|
||||
$this->update_array[$field] = request()->input($field);
|
||||
}
|
||||
return $this;
|
||||
|
||||
@@ -83,17 +83,7 @@ class CategoriesController extends Controller
|
||||
$category->checkin_email = $request->input('checkin_email', '0');
|
||||
$category->user_id = Auth::id();
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = str_random(25).".".$image->getClientOriginalExtension();
|
||||
$path = public_path('uploads/categories/'.$file_name);
|
||||
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path);
|
||||
$category->image = $file_name;
|
||||
}
|
||||
|
||||
$category = $request->handleImages($category,600, public_path().'/uploads/categories');
|
||||
|
||||
if ($category->save()) {
|
||||
return redirect()->route('categories.index')->with('success', trans('admin/categories/message.create.success'));
|
||||
@@ -152,37 +142,12 @@ class CategoriesController extends Controller
|
||||
$category->require_acceptance = $request->input('require_acceptance', '0');
|
||||
$category->checkin_email = $request->input('checkin_email', '0');
|
||||
|
||||
$old_image = $category->image;
|
||||
|
||||
// Set the model's image property to null if the image is being deleted
|
||||
if ($request->input('image_delete') == 1) {
|
||||
$category->image = null;
|
||||
}
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = $category->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
|
||||
|
||||
if ($image->getClientOriginalExtension()!='svg') {
|
||||
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save(app('categories_upload_path').$file_name);
|
||||
} else {
|
||||
$image->move(app('categories_upload_path'), $file_name);
|
||||
}
|
||||
$category->image = $file_name;
|
||||
|
||||
}
|
||||
|
||||
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
|
||||
try {
|
||||
unlink(app('categories_upload_path').$old_image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::info($e);
|
||||
}
|
||||
}
|
||||
|
||||
$category = $request->handleImages($category,600, public_path().'/uploads/categories');
|
||||
|
||||
if ($category->save()) {
|
||||
// Redirect to the new category page
|
||||
|
||||
@@ -63,16 +63,7 @@ final class CompaniesController extends Controller
|
||||
$company = new Company;
|
||||
$company->name = $request->input('name');
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = str_random(25).".".$image->getClientOriginalExtension();
|
||||
$path = public_path('uploads/companies/'.$file_name);
|
||||
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path);
|
||||
$company->image = $file_name;
|
||||
}
|
||||
$company = $request->handleImages($company,600, public_path().'/uploads/companies');
|
||||
|
||||
if ($company->save()) {
|
||||
return redirect()->route('companies.index')
|
||||
@@ -121,36 +112,12 @@ final class CompaniesController extends Controller
|
||||
|
||||
$company->name = $request->input('name');
|
||||
|
||||
$old_image = $company->image;
|
||||
|
||||
// Set the model's image property to null if the image is being deleted
|
||||
if ($request->input('image_delete') == 1) {
|
||||
$company->image = null;
|
||||
}
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = $company->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
|
||||
|
||||
if ($image->getClientOriginalExtension()!='svg') {
|
||||
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save(app('companies_upload_path').$file_name);
|
||||
} else {
|
||||
$image->move(app('companies_upload_path'), $file_name);
|
||||
}
|
||||
$company->image = $file_name;
|
||||
|
||||
}
|
||||
|
||||
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
|
||||
try {
|
||||
unlink(app('companies_upload_path').$old_image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::info($e);
|
||||
}
|
||||
}
|
||||
$company = $request->handleImages($company,600, public_path().'/uploads/companies');
|
||||
|
||||
|
||||
if ($company->save()) {
|
||||
|
||||
@@ -91,16 +91,7 @@ class ComponentsController extends Controller
|
||||
$component->user_id = Auth::id();
|
||||
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = str_random(25).".".$image->getClientOriginalExtension();
|
||||
$path = public_path('uploads/components/'.$file_name);
|
||||
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path);
|
||||
$component->image = $file_name;
|
||||
}
|
||||
$component = $request->handleImages($component,600, public_path().'/uploads/components');
|
||||
|
||||
if ($component->save()) {
|
||||
return redirect()->route('components.index')->with('success', trans('admin/components/message.create.success'));
|
||||
@@ -164,18 +155,7 @@ class ComponentsController extends Controller
|
||||
$component->purchase_cost = request('purchase_cost');
|
||||
$component->qty = Input::get('qty');
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = str_random(25).".".$image->getClientOriginalExtension();
|
||||
$path = public_path('uploads/components/'.$file_name);
|
||||
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path);
|
||||
$component->image = $file_name;
|
||||
} elseif ($request->input('image_delete')=='1') {
|
||||
$component->image = null;
|
||||
}
|
||||
$component = $request->handleImages($component,600, public_path().'/uploads/components');
|
||||
|
||||
if ($component->save()) {
|
||||
return redirect()->route('components.index')->with('success', trans('admin/components/message.update.success'));
|
||||
|
||||
@@ -87,16 +87,8 @@ class ConsumablesController extends Controller
|
||||
$consumable->user_id = Auth::id();
|
||||
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = str_random(25).".".$image->getClientOriginalExtension();
|
||||
$path = public_path('uploads/consumables/'.$file_name);
|
||||
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path);
|
||||
$consumable->image = $file_name;
|
||||
}
|
||||
$consumable = $request->handleImages($consumable,600, public_path().'/uploads/components');
|
||||
|
||||
|
||||
if ($consumable->save()) {
|
||||
return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.create.success'));
|
||||
|
||||
@@ -53,16 +53,7 @@ class DepartmentsController extends Controller
|
||||
$department->user_id = Auth::user()->id;
|
||||
$department->manager_id = ($request->filled('manager_id' ) ? $request->input('manager_id') : null);
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = str_random(25).".".$image->getClientOriginalExtension();
|
||||
$path = public_path('uploads/departments/'.$file_name);
|
||||
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path);
|
||||
$department->image = $file_name;
|
||||
}
|
||||
$department = $request->handleImages($department,600, public_path().'/uploads/departments');
|
||||
|
||||
if ($department->save()) {
|
||||
return redirect()->route("departments.index")->with('success', trans('admin/departments/message.create.success'));
|
||||
@@ -164,36 +155,7 @@ class DepartmentsController extends Controller
|
||||
$department->fill($request->all());
|
||||
$department->manager_id = ($request->filled('manager_id' ) ? $request->input('manager_id') : null);
|
||||
|
||||
$old_image = $department->image;
|
||||
|
||||
// Set the model's image property to null if the image is being deleted
|
||||
if ($request->input('image_delete') == 1) {
|
||||
$department->image = null;
|
||||
}
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = $department->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
|
||||
|
||||
if ($image->getClientOriginalExtension()!='svg') {
|
||||
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save(app('departments_upload_path').$file_name);
|
||||
} else {
|
||||
$image->move(app('departments_upload_path'), $file_name);
|
||||
}
|
||||
$department->image = $file_name;
|
||||
|
||||
}
|
||||
|
||||
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
|
||||
try {
|
||||
unlink(app('departments_upload_path').$old_image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::info($e);
|
||||
}
|
||||
}
|
||||
$department = $request->handleImages($department,600, public_path().'/uploads/departments');
|
||||
|
||||
if ($department->save()) {
|
||||
return redirect()->route("departments.index")->with('success', trans('admin/departments/message.update.success'));
|
||||
|
||||
@@ -41,8 +41,6 @@ class LocationsController extends Controller
|
||||
{
|
||||
// Grab all the locations
|
||||
$this->authorize('view', Location::class);
|
||||
$locations = Location::orderBy('created_at', 'DESC')->with('parent', 'assets', 'assignedassets')->get();
|
||||
|
||||
// Show the page
|
||||
return view('locations/index');
|
||||
}
|
||||
@@ -59,14 +57,7 @@ class LocationsController extends Controller
|
||||
public function create()
|
||||
{
|
||||
$this->authorize('create', Location::class);
|
||||
$locations = Location::orderBy('name', 'ASC')->get();
|
||||
|
||||
$location_options_array = Location::getLocationHierarchy($locations);
|
||||
$location_options = Location::flattenLocationsArray($location_options_array);
|
||||
$location_options = array('' => 'Top Level') + $location_options;
|
||||
|
||||
return view('locations/edit')
|
||||
->with('location_options', $location_options)
|
||||
->with('item', new Location);
|
||||
}
|
||||
|
||||
@@ -97,16 +88,7 @@ class LocationsController extends Controller
|
||||
$location->manager_id = $request->input('manager_id');
|
||||
$location->user_id = Auth::id();
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = str_random(25).".".$image->getClientOriginalExtension();
|
||||
$path = public_path('uploads/locations/'.$file_name);
|
||||
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path);
|
||||
$location->image = $file_name;
|
||||
}
|
||||
$location = $request->handleImages($location,600, public_path().'/uploads/locations');
|
||||
|
||||
if ($location->save()) {
|
||||
return redirect()->route("locations.index")->with('success', trans('admin/locations/message.create.success'));
|
||||
@@ -132,14 +114,8 @@ class LocationsController extends Controller
|
||||
return redirect()->route('locations.index')->with('error', trans('admin/locations/message.does_not_exist'));
|
||||
}
|
||||
|
||||
// Show the page
|
||||
$locations = Location::orderBy('name', 'ASC')->get();
|
||||
$location_options_array = Location::getLocationHierarchy($locations);
|
||||
$location_options = Location::flattenLocationsArray($location_options_array);
|
||||
$location_options = array('' => 'Top Level') + $location_options;
|
||||
|
||||
return view('locations/edit', compact('item'))
|
||||
->with('location_options', $location_options);
|
||||
return view('locations/edit', compact('item'));
|
||||
}
|
||||
|
||||
|
||||
@@ -160,6 +136,11 @@ class LocationsController extends Controller
|
||||
return redirect()->route('locations.index')->with('error', trans('admin/locations/message.does_not_exist'));
|
||||
}
|
||||
|
||||
if ($request->input('parent_id') == $locationId) {
|
||||
return redirect()->back()->withInput()->with('error', 'A location cannot be its own parent. Please select a different parent location.');
|
||||
}
|
||||
|
||||
|
||||
// Update the location data
|
||||
$location->name = $request->input('name');
|
||||
$location->parent_id = $request->input('parent_id', null);
|
||||
@@ -172,37 +153,7 @@ class LocationsController extends Controller
|
||||
$location->zip = $request->input('zip');
|
||||
$location->ldap_ou = $request->input('ldap_ou');
|
||||
$location->manager_id = $request->input('manager_id');
|
||||
|
||||
$old_image = $location->image;
|
||||
|
||||
// Set the model's image property to null if the image is being deleted
|
||||
if ($request->input('image_delete') == 1) {
|
||||
$location->image = null;
|
||||
}
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = $location->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
|
||||
|
||||
if ($image->getClientOriginalExtension()!='svg') {
|
||||
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save(app('locations_upload_path').$file_name);
|
||||
} else {
|
||||
$image->move(app('locations_upload_path'), $file_name);
|
||||
}
|
||||
$location->image = $file_name;
|
||||
|
||||
}
|
||||
|
||||
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
|
||||
try {
|
||||
unlink(app('locations_upload_path').$old_image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::info($e);
|
||||
}
|
||||
}
|
||||
$location = $request->handleImages($location,600, public_path().'/uploads/locations');
|
||||
|
||||
|
||||
if ($location->save()) {
|
||||
@@ -229,7 +180,7 @@ class LocationsController extends Controller
|
||||
if ($location->users->count() > 0) {
|
||||
return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.assoc_users'));
|
||||
|
||||
} elseif ($location->childLocations->count() > 0) {
|
||||
} elseif ($location->children->count() > 0) {
|
||||
return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.assoc_child_loc'));
|
||||
|
||||
} elseif ($location->assets->count() > 0) {
|
||||
|
||||
@@ -75,18 +75,7 @@ class ManufacturersController extends Controller
|
||||
$manufacturer->support_url = $request->input('support_url');
|
||||
$manufacturer->support_phone = $request->input('support_phone');
|
||||
$manufacturer->support_email = $request->input('support_email');
|
||||
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = str_slug($image->getClientOriginalName()).".".$image->getClientOriginalExtension();
|
||||
$path = public_path('uploads/manufacturers/'.$file_name);
|
||||
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path);
|
||||
$manufacturer->image = $file_name;
|
||||
}
|
||||
$manufacturer = $request->handleImages($manufacturer,600, public_path().'/uploads/manufacturers');
|
||||
|
||||
|
||||
|
||||
@@ -142,37 +131,14 @@ class ManufacturersController extends Controller
|
||||
$manufacturer->support_url = $request->input('support_url');
|
||||
$manufacturer->support_phone = $request->input('support_phone');
|
||||
$manufacturer->support_email = $request->input('support_email');
|
||||
|
||||
$old_image = $manufacturer->image;
|
||||
|
||||
|
||||
// Set the model's image property to null if the image is being deleted
|
||||
if ($request->input('image_delete') == 1) {
|
||||
$manufacturer->image = null;
|
||||
}
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = $manufacturer->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
|
||||
$manufacturer = $request->handleImages($manufacturer,600, public_path().'/uploads/manufacturers');
|
||||
|
||||
if ($image->getClientOriginalExtension()!='svg') {
|
||||
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save(app('manufacturers_upload_path').$file_name);
|
||||
} else {
|
||||
$image->move(app('manufacturers_upload_path'), $file_name);
|
||||
}
|
||||
$manufacturer->image = $file_name;
|
||||
|
||||
}
|
||||
|
||||
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
|
||||
try {
|
||||
unlink(app('manufacturers_upload_path').$old_image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::info($e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($manufacturer->save()) {
|
||||
|
||||
@@ -307,12 +307,18 @@ class ReportsController extends Controller
|
||||
public function postCustom(Request $request)
|
||||
{
|
||||
|
||||
ini_set('max_execution_time', 12000);
|
||||
|
||||
|
||||
\Debugbar::disable();
|
||||
$customfields = CustomField::get();
|
||||
$response = new StreamedResponse(function () use ($customfields, $request) {
|
||||
|
||||
\Log::debug('Starting streamed response');
|
||||
|
||||
// Open output stream
|
||||
$handle = fopen('php://output', 'w');
|
||||
stream_set_timeout($handle, 2000);
|
||||
|
||||
if ($request->filled('use_bom')) {
|
||||
fprintf($handle, chr(0xEF) . chr(0xBB) . chr(0xBF));
|
||||
@@ -464,8 +470,12 @@ class ReportsController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$executionTime = microtime(true) - $_SERVER["REQUEST_TIME_FLOAT"];
|
||||
\Log::debug('Starting headers: '.$executionTime);
|
||||
fputcsv($handle, $header);
|
||||
$executionTime = microtime(true) - $_SERVER["REQUEST_TIME_FLOAT"];
|
||||
\Log::debug('Added headers: '.$executionTime);
|
||||
|
||||
|
||||
$assets = \App\Models\Company::scopeCompanyables(Asset::select('assets.*'))->with(
|
||||
'location', 'assetstatus', 'assetlog', 'company', 'defaultLoc','assignedTo',
|
||||
@@ -520,9 +530,13 @@ class ReportsController extends Controller
|
||||
$assets->whereBetween('assets.expected_checkin', [$request->input('expected_checkin_start'), $request->input('expected_checkin_end')]);
|
||||
}
|
||||
|
||||
$assets->orderBy('assets.created_at', 'ASC')->chunk(500, function($assets) use($handle, $customfields, $request) {
|
||||
$assets->orderBy('assets.created_at', 'ASC')->chunk(20, function($assets) use($handle, $customfields, $request) {
|
||||
|
||||
$executionTime = microtime(true) - $_SERVER["REQUEST_TIME_FLOAT"];
|
||||
\Log::debug('Walking results: '.$executionTime);
|
||||
$count = 0;
|
||||
foreach ($assets as $asset) {
|
||||
$count++;
|
||||
$row = [];
|
||||
|
||||
if ($request->filled('company')) {
|
||||
@@ -695,17 +709,24 @@ class ReportsController extends Controller
|
||||
}
|
||||
}
|
||||
fputcsv($handle, $row);
|
||||
$executionTime = microtime(true) - $_SERVER["REQUEST_TIME_FLOAT"];
|
||||
\Log::debug('-- Record '.$count.' Asset ID:' .$asset->id. ' in '. $executionTime);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
// Close the output stream
|
||||
fclose($handle);
|
||||
$executionTime = microtime(true) - $_SERVER["REQUEST_TIME_FLOAT"];
|
||||
\Log::debug('-- SCRIPT COMPLETED IN '. $executionTime);
|
||||
|
||||
}, 200, [
|
||||
'Content-Type' => 'text/csv',
|
||||
'Content-Disposition'
|
||||
=> 'attachment; filename="custom-assets-report-'.date('Y-m-d-his').'.csv"',
|
||||
]);
|
||||
|
||||
|
||||
return $response;
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use enshrined\svgSanitize\Sanitizer;
|
||||
use Input;
|
||||
use Lang;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -426,12 +427,23 @@ class SettingsController extends Controller
|
||||
$file_name = "logo.".$image->getClientOriginalExtension();
|
||||
$path = public_path('uploads');
|
||||
if ($image->getClientOriginalExtension()!='svg') {
|
||||
|
||||
Image::make($image->getRealPath())->resize(null, 150, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path.'/'.$file_name);
|
||||
} else {
|
||||
$image->move($path, $file_name);
|
||||
|
||||
// This is kinda copypasta from the ImageUploadRequest - should refactor the ImageUploadRequest to better handle maybe
|
||||
$sanitizer = new Sanitizer();
|
||||
$dirtySVG = file_get_contents($image->getRealPath());
|
||||
$cleanSVG = $sanitizer->sanitize($dirtySVG);
|
||||
|
||||
try {
|
||||
file_put_contents($path.'/'.$file_name, $cleanSVG);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
}
|
||||
$setting->logo = $file_name;
|
||||
}
|
||||
@@ -865,7 +877,7 @@ class SettingsController extends Controller
|
||||
$setting->ldap_server = $request->input('ldap_server');
|
||||
$setting->ldap_server_cert_ignore = $request->input('ldap_server_cert_ignore', false);
|
||||
$setting->ldap_uname = $request->input('ldap_uname');
|
||||
if (Input::has('ldap_pword')) {
|
||||
if (Input::filled('ldap_pword')) {
|
||||
$setting->ldap_pword = Crypt::encrypt($request->input('ldap_pword'));
|
||||
}
|
||||
$setting->ldap_basedn = $request->input('ldap_basedn');
|
||||
@@ -1012,7 +1024,7 @@ class SettingsController extends Controller
|
||||
|
||||
if (!config('app.lock_passwords')) {
|
||||
|
||||
$path = storage_path().'/app/'.config('laravel-backup.backup.name');
|
||||
$path = storage_path().'/app/'.config('backup.backup.name');
|
||||
$file = $path.'/'.$filename;
|
||||
if (file_exists($file)) {
|
||||
unlink($file);
|
||||
|
||||
@@ -78,17 +78,8 @@ class SuppliersController extends Controller
|
||||
$supplier->notes = request('notes');
|
||||
$supplier->url = $supplier->addhttp(request('url'));
|
||||
$supplier->user_id = Auth::id();
|
||||
$supplier = $request->handleImages($supplier,600, public_path().'/uploads/suppliers');
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = str_random(25).".".$image->getClientOriginalExtension();
|
||||
$path = public_path('uploads/suppliers/'.$file_name);
|
||||
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path);
|
||||
$supplier->image = $file_name;
|
||||
}
|
||||
|
||||
if ($supplier->save()) {
|
||||
return redirect()->route('suppliers.index')->with('success', trans('admin/suppliers/message.create.success'));
|
||||
@@ -145,39 +136,7 @@ class SuppliersController extends Controller
|
||||
$supplier->email = request('email');
|
||||
$supplier->url = $supplier->addhttp(request('url'));
|
||||
$supplier->notes = request('notes');
|
||||
|
||||
|
||||
$old_image = $supplier->image;
|
||||
|
||||
// Set the model's image property to null if the image is being deleted
|
||||
if ($request->input('image_delete') == 1) {
|
||||
$supplier->image = null;
|
||||
}
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = $supplier->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
|
||||
|
||||
if ($image->getClientOriginalExtension()!='svg') {
|
||||
Image::make($image->getRealPath())->resize(800, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save(app('suppliers_upload_path').$file_name);
|
||||
} else {
|
||||
$image->move(app('suppliers_upload_path'), $file_name);
|
||||
}
|
||||
$supplier->image = $file_name;
|
||||
|
||||
}
|
||||
|
||||
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
|
||||
try {
|
||||
unlink(app('suppliers_upload_path').$old_image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::info($e);
|
||||
}
|
||||
}
|
||||
|
||||
$supplier = $request->handleImages($supplier,600, public_path().'/uploads/suppliers');
|
||||
|
||||
if ($supplier->save()) {
|
||||
return redirect()->route('suppliers.index')->with('success', trans('admin/suppliers/message.update.success'));
|
||||
|
||||
@@ -340,25 +340,25 @@ class UsersController extends Controller
|
||||
// Check if we are not trying to delete ourselves
|
||||
if ($user->id === Auth::user()->id) {
|
||||
// Redirect to the user management page
|
||||
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->assets()->count() . ' assets associated with them.');
|
||||
return redirect()->route('users.index')->with('error', 'You cannot delete yourself.');
|
||||
}
|
||||
|
||||
if ($user->assets->count() > 0) {
|
||||
if (($user->assets) && ($user->assets->count() > 0)) {
|
||||
// Redirect to the user management page
|
||||
return redirect()->route('users.index')->with('error', 'This user still has ' . count($user->assets->count()) . ' assets associated with them.');
|
||||
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->assets->count() . ' assets associated with them. Use the Checkin and Delete button on the user profile to check these items back in and delete this user.');
|
||||
}
|
||||
|
||||
if ($user->licenses()->count() > 0) {
|
||||
if (($user->licenses) && ($user->licenses->count() > 0)) {
|
||||
// Redirect to the user management page
|
||||
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->assets()->count() . ' assets associated with them.');
|
||||
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->licenses->count() . ' license(s associated with them. Use the Checkin and Delete button on the user profile to check these items back in and delete this user.');
|
||||
}
|
||||
|
||||
if ($user->accessories()->count() > 0) {
|
||||
if (($user->accessories) && ($user->accessories->count() > 0)) {
|
||||
// Redirect to the user management page
|
||||
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->accessories()->count() . ' accessories associated with them.');
|
||||
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->accessories->count() . ' accessories associated with them. Use the Checkin and Delete button on the user profile to check these items back in and delete this user.');
|
||||
}
|
||||
|
||||
if ($user->managedLocations()->count() > 0) {
|
||||
if (($user->managedLocations()) && ($user->managedLocations()->count() > 0)) {
|
||||
// Redirect to the user management page
|
||||
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->managedLocations()->count() . ' locations that they manage.');
|
||||
}
|
||||
|
||||
+2
-1
@@ -44,7 +44,8 @@ class Kernel extends HttpKernel
|
||||
],
|
||||
|
||||
'api' => [
|
||||
'throttle:60,1',
|
||||
\Barryvdh\Cors\HandleCors::class,
|
||||
'throttle:120,1',
|
||||
'auth:api',
|
||||
],
|
||||
];
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace App\Http\Requests;
|
||||
|
||||
use App\Models\AssetModel;
|
||||
use Session;
|
||||
|
||||
use Illuminate\Http\Exceptions\HttpResponseException;
|
||||
|
||||
use Illuminate\Contracts\Validation\Validator;
|
||||
|
||||
@@ -32,7 +32,7 @@ class AssetRequest extends Request
|
||||
'model_id' => 'required|integer|exists:models,id',
|
||||
'status_id' => 'required|integer|exists:status_labels,id',
|
||||
'company_id' => 'integer|nullable',
|
||||
'warranty_months' => 'numeric|nullable',
|
||||
'warranty_months' => 'numeric|nullable|digits_between:0,240',
|
||||
'physical' => 'integer|nullable',
|
||||
'checkout_date' => 'date',
|
||||
'checkin_date' => 'date',
|
||||
@@ -48,7 +48,7 @@ class AssetRequest extends Request
|
||||
|
||||
$rules['asset_tag'] = ($settings->auto_increment_assets == '1') ? 'max:255' : 'required';
|
||||
|
||||
if($this->request->get('model_id') != '') {
|
||||
if ($this->request->get('model_id') != '') {
|
||||
$model = AssetModel::find($this->request->get('model_id'));
|
||||
|
||||
if (($model) && ($model->fieldset)) {
|
||||
@@ -60,13 +60,6 @@ class AssetRequest extends Request
|
||||
|
||||
}
|
||||
|
||||
public function response(array $errors)
|
||||
{
|
||||
$this->session()->flash('errors', Session::get('errors', new \Illuminate\Support\ViewErrorBag)
|
||||
->put('default', new \Illuminate\Support\MessageBag($errors)));
|
||||
\Input::flash();
|
||||
return parent::response($errors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a failed validation attempt.
|
||||
@@ -76,13 +69,17 @@ class AssetRequest extends Request
|
||||
* @param \Illuminate\Contracts\Validation\Validator $validator
|
||||
* @return void
|
||||
*
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
* @throws \Illuminate\Http\Exceptions\HttpResponseException
|
||||
*/
|
||||
protected function failedValidation(Validator $validator)
|
||||
{
|
||||
return response()->json([
|
||||
'message' => 'The given data is invalid',
|
||||
'errors' => $validator->errors()
|
||||
], 422);
|
||||
$this->session()->flash('errors', Session::get('errors', new \Illuminate\Support\ViewErrorBag)
|
||||
->put('default', new \Illuminate\Support\MessageBag($validator->errors()->toArray())));
|
||||
\Input::flash();
|
||||
throw new HttpResponseException(response()->json([
|
||||
'status' => 'error',
|
||||
'messages' => $validator->errors(),
|
||||
'payload' => null
|
||||
], 422));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Models\SnipeModel;
|
||||
use Intervention\Image\Facades\Image;
|
||||
use enshrined\svgSanitize\Sanitizer;
|
||||
|
||||
class ImageUploadRequest extends Request
|
||||
{
|
||||
@@ -33,4 +35,83 @@ class ImageUploadRequest extends Request
|
||||
{
|
||||
return $this->redirector->back()->withInput()->withErrors($errors, $this->errorBag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle and store any images attached to request
|
||||
* @param SnipeModel $item Item the image is associated with
|
||||
* @param String $path location for uploaded images, defaults to uploads/plural of item type.
|
||||
* @return SnipeModel Target asset is being checked out to.
|
||||
*/
|
||||
public function handleImages($item, $w = 600, $path = null)
|
||||
{
|
||||
|
||||
$type = strtolower(class_basename(get_class($item)));
|
||||
|
||||
if (is_null($path)) {
|
||||
$path = str_plural($type);
|
||||
}
|
||||
|
||||
\Log::debug('Trying to upload to '. $path);
|
||||
|
||||
if ($this->hasFile('image')) {
|
||||
|
||||
if (!config('app.lock_passwords')) {
|
||||
|
||||
|
||||
if (!is_dir($path)) {
|
||||
\Log::debug($path.' does not exist');
|
||||
mkdir($path);
|
||||
}
|
||||
|
||||
$image = $this->file('image');
|
||||
$ext = $image->getClientOriginalExtension();
|
||||
$file_name = $type.'-'.str_random(18).'.'.$ext;
|
||||
\Log::debug('File name will be: '.$file_name);
|
||||
|
||||
if ($image->getClientOriginalExtension()!=='svg') {
|
||||
\Log::debug('Not an SVG - resize');
|
||||
\Log::debug('Trying to upload to: '.$path.'/'.$file_name);
|
||||
$upload = Image::make($image->getRealPath())->resize(null, $w, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path.'/'.$file_name);
|
||||
} else {
|
||||
\Log::debug('This is an SVG');
|
||||
$sanitizer = new Sanitizer();
|
||||
$dirtySVG = file_get_contents($image->getRealPath());
|
||||
$cleanSVG = $sanitizer->sanitize($dirtySVG);
|
||||
|
||||
try {
|
||||
\Log::debug('Trying to upload to: '.$path.'/'.$file_name);
|
||||
file_put_contents($path.'/'.$file_name, $cleanSVG);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Remove Current image if exists
|
||||
if (($item->image) && (file_exists($path.'/'.$item->image))) {
|
||||
try {
|
||||
unlink($path.'/'.$item->image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
}
|
||||
|
||||
$item->image = $file_name;
|
||||
}
|
||||
|
||||
} elseif ($this->input('image_delete')=='1') {
|
||||
|
||||
try {
|
||||
unlink($path.'/'.$item->image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
|
||||
$item->image = null;
|
||||
}
|
||||
return $item;
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,12 @@
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Models\Setting;
|
||||
use Illuminate\Http\Exceptions\HttpResponseException;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Contracts\Validation\Validator;
|
||||
|
||||
class SaveUserRequest extends Request
|
||||
class SaveUserRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
@@ -62,4 +64,5 @@ class SaveUserRequest extends Request
|
||||
return $rules;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,7 +32,15 @@ class ActionlogsTransformer
|
||||
$meta_array = json_decode($actionlog->log_meta);
|
||||
foreach ($meta_array as $key => $value) {
|
||||
foreach ($value as $meta_key => $meta_value) {
|
||||
$clean_meta[$key][$meta_key] = e($meta_value);
|
||||
|
||||
if (is_array($meta_value)) {
|
||||
foreach ($meta_value as $meta_value_key => $meta_value_value) {
|
||||
$clean_meta[$key][$meta_value_key] = e($meta_value_value);
|
||||
}
|
||||
} else {
|
||||
$clean_meta[$key][$meta_key] = e($meta_value);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ use App\Models\AssetMaintenance;
|
||||
use Gate;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Asset;
|
||||
|
||||
class AssetMaintenancesTransformer
|
||||
{
|
||||
|
||||
@@ -29,7 +29,14 @@ class LicenseSeatsTransformer
|
||||
'name' => 'Seat '.$seat_count,
|
||||
'assigned_user' => ($seat->user) ? [
|
||||
'id' => (int) $seat->user->id,
|
||||
'name'=> e($seat->user->present()->fullName)
|
||||
'name'=> e($seat->user->present()->fullName),
|
||||
'department'=>
|
||||
($seat->user->department) ?
|
||||
[
|
||||
"id" => (int) $seat->user->department->id,
|
||||
"name" => e($seat->user->department->name)
|
||||
|
||||
] : null
|
||||
] : null,
|
||||
'assigned_asset' => ($seat->asset) ? [
|
||||
'id' => (int) $seat->asset->id,
|
||||
|
||||
@@ -23,7 +23,7 @@ class LocationsTransformer
|
||||
if ($location) {
|
||||
|
||||
$children_arr = [];
|
||||
foreach($location->childLocations as $child) {
|
||||
foreach($location->children as $child) {
|
||||
$children_arr[] = [
|
||||
'id' => (int) $child->id,
|
||||
'name' => $child->name
|
||||
|
||||
@@ -27,9 +27,17 @@ class AssetImporter extends ItemImporter
|
||||
|
||||
foreach ($this->customFields as $customField) {
|
||||
$customFieldValue = $this->array_smart_custom_field_fetch($row, $customField);
|
||||
|
||||
if ($customFieldValue) {
|
||||
$this->item['custom_fields'][$customField->db_column_name()] = $customFieldValue;
|
||||
$this->log('Custom Field '. $customField->name.': '.$customFieldValue);
|
||||
|
||||
if ($customField->field_encrypted == 1) {
|
||||
$this->item['custom_fields'][$customField->db_column_name()] = \Crypt::encrypt($customFieldValue);
|
||||
$this->log('Custom Field '. $customField->name.': '.\Crypt::encrypt($customFieldValue));
|
||||
} else {
|
||||
$this->item['custom_fields'][$customField->db_column_name()] = $customFieldValue;
|
||||
$this->log('Custom Field '. $customField->name.': '.$customFieldValue);
|
||||
}
|
||||
|
||||
} else {
|
||||
// Clear out previous data.
|
||||
$this->item['custom_fields'][$customField->db_column_name()] = null;
|
||||
|
||||
+31
-6
@@ -75,7 +75,7 @@ class Asset extends Depreciable
|
||||
'model_id' => 'required|integer|exists:models,id',
|
||||
'status_id' => 'required|integer|exists:status_labels,id',
|
||||
'company_id' => 'integer|nullable',
|
||||
'warranty_months' => 'numeric|nullable',
|
||||
'warranty_months' => 'numeric|nullable|digits_between:0,240',
|
||||
'physical' => 'numeric|max:1|nullable',
|
||||
'checkout_date' => 'date|max:10|min:10|nullable',
|
||||
'checkin_date' => 'date|max:10|min:10|nullable',
|
||||
@@ -821,9 +821,11 @@ class Asset extends Depreciable
|
||||
|
||||
public function scopeDueForAudit($query, $settings)
|
||||
{
|
||||
$interval = $settings->audit_warning_days ?? 0;
|
||||
|
||||
return $query->whereNotNull('assets.next_audit_date')
|
||||
->where('assets.next_audit_date', '>=', Carbon::now())
|
||||
->whereRaw("DATE_SUB(assets.next_audit_date, INTERVAL $settings->audit_warning_days DAY) <= '".Carbon::now()."'")
|
||||
->whereRaw("DATE_SUB(assets.next_audit_date, INTERVAL $interval DAY) <= '".Carbon::now()."'")
|
||||
->where('assets.archived', '=', 0)
|
||||
->NotArchived();
|
||||
}
|
||||
@@ -866,8 +868,10 @@ class Asset extends Depreciable
|
||||
|
||||
public function scopeDueOrOverdueForAudit($query, $settings)
|
||||
{
|
||||
$interval = $settings->audit_warning_days ?? 0;
|
||||
|
||||
return $query->whereNotNull('assets.next_audit_date')
|
||||
->whereRaw("DATE_SUB(assets.next_audit_date, INTERVAL $settings->audit_warning_days DAY) <= '".Carbon::now()."'")
|
||||
->whereRaw("DATE_SUB(assets.next_audit_date, INTERVAL $interval DAY) <= '".Carbon::now()."'")
|
||||
->where('assets.archived', '=', 0)
|
||||
->NotArchived();
|
||||
}
|
||||
@@ -1165,7 +1169,29 @@ class Asset extends Depreciable
|
||||
}
|
||||
}
|
||||
|
||||
if (($fieldname!='category') && ($fieldname!='model_number') && ($fieldname!='location') && ($fieldname!='supplier')
|
||||
/**
|
||||
* THIS CLUNKY BIT IS VERY IMPORTANT
|
||||
*
|
||||
* Although inelegant, this section matters a lot when querying against fields that do not
|
||||
* exist on the asset table. There's probably a better way to do this moving forward, for
|
||||
* example using the Schema:: methods to determine whether or not a column actually exists,
|
||||
* or even just using the $searchableRelations variable earlier in this file.
|
||||
*
|
||||
* In short, this set of statements tells the query builder to ONLY query against an
|
||||
* actual field that's being passed if it doesn't meet known relational fields. This
|
||||
* allows us to query custom fields directly in the assetsv table
|
||||
* (regardless of their name) and *skip* any fields that we already know can only be
|
||||
* searched through relational searches that we do earlier in this method.
|
||||
*
|
||||
* For example, we do not store "location" as a field on the assets table, we store
|
||||
* that relationship through location_id on the assets table, therefore querying
|
||||
* assets.location would fail, as that field doesn't exist -- plus we're already searching
|
||||
* against those relationships earlier in this method.
|
||||
*
|
||||
* - snipe
|
||||
*
|
||||
*/
|
||||
if (($fieldname!='category') && ($fieldname!='model_number') && ($fieldname!='rtd_location') && ($fieldname!='location') && ($fieldname!='supplier')
|
||||
&& ($fieldname!='status_label') && ($fieldname!='model') && ($fieldname!='company') && ($fieldname!='manufacturer')) {
|
||||
$query->orWhere('assets.'.$fieldname, 'LIKE', '%' . $search_val . '%');
|
||||
}
|
||||
@@ -1365,8 +1391,7 @@ class Asset extends Depreciable
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope to search on location ID
|
||||
*
|
||||
* Query builder scope to search on depreciation name
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $search Search term
|
||||
*
|
||||
|
||||
@@ -73,7 +73,8 @@ class AssetMaintenance extends Model implements ICompanyableChild
|
||||
trans('admin/asset_maintenances/general.upgrade') => trans('admin/asset_maintenances/general.upgrade'),
|
||||
'PAT test' => 'PAT test',
|
||||
trans('admin/asset_maintenances/general.calibration') => trans('admin/asset_maintenances/general.calibration'),
|
||||
'PAT test' => 'PAT test',
|
||||
'Software Support' => trans('admin/asset_maintenances/general.software_support'),
|
||||
'Hardware Support' => trans('admin/asset_maintenances/general.hardware_support'),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,13 @@ final class Company extends SnipeModel
|
||||
}
|
||||
|
||||
$table = ($table_name) ? DB::getTablePrefix().$table_name."." : '';
|
||||
return $query->where($table.$column, '=', $company_id);
|
||||
|
||||
if(\Schema::hasColumn($query->getModel()->getTable(), $column)){
|
||||
return $query->where($table.$column, '=', $company_id);
|
||||
} else {
|
||||
return $query->join('users as users_comp', 'users_comp.id', 'user_id')->where('users_comp.company_id', '=', $company_id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static function getIdFromInput($unescaped_input)
|
||||
|
||||
@@ -7,10 +7,10 @@ use Watson\Validating\ValidatingTrait;
|
||||
|
||||
class Group extends SnipeModel
|
||||
{
|
||||
protected $table = 'groups';
|
||||
protected $table = 'permission_groups';
|
||||
|
||||
public $rules = array(
|
||||
'name' => 'required|min:3|max:255',
|
||||
'name' => 'required|min:2|max:255',
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
@@ -48,7 +48,7 @@ class License extends Depreciable
|
||||
protected $table = 'licenses';
|
||||
protected $rules = array(
|
||||
'name' => 'required|string|min:3|max:255',
|
||||
'seats' => 'required|min:1|max:1000000|integer',
|
||||
'seats' => 'required|min:1|max:999|integer',
|
||||
'license_email' => 'email|nullable|max:120',
|
||||
'license_name' => 'string|nullable|max:100',
|
||||
'notes' => 'string|nullable',
|
||||
|
||||
@@ -55,4 +55,23 @@ class LicenseSeat extends Model implements ICompanyableChild
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to order on department
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeOrderDepartments($query, $order)
|
||||
{
|
||||
return $query->leftJoin('users as license_seat_users', 'license_seats.assigned_to', '=', 'license_seat_users.id')
|
||||
->leftJoin('departments as license_user_dept', 'license_user_dept.id', '=', 'license_seat_users.department_id')
|
||||
->orderBy('license_user_dept.name', $order);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+30
-49
@@ -113,7 +113,8 @@ class Location extends SnipeModel
|
||||
|
||||
public function parent()
|
||||
{
|
||||
return $this->belongsTo('\App\Models\Location', 'parent_id','id');
|
||||
return $this->belongsTo('\App\Models\Location', 'parent_id','id')
|
||||
->with('parent');
|
||||
}
|
||||
|
||||
public function manager()
|
||||
@@ -121,9 +122,9 @@ class Location extends SnipeModel
|
||||
return $this->belongsTo('\App\Models\User', 'manager_id');
|
||||
}
|
||||
|
||||
public function childLocations()
|
||||
{
|
||||
return $this->hasMany('\App\Models\Location', 'parent_id');
|
||||
public function children() {
|
||||
return $this->hasMany('\App\Models\Location','parent_id')
|
||||
->with('children');
|
||||
}
|
||||
|
||||
// I don't think we need this anymore since we de-normed location_id in assets?
|
||||
@@ -137,59 +138,39 @@ class Location extends SnipeModel
|
||||
return $this->attributes['ldap_ou'] = empty($ldap_ou) ? null : $ldap_ou;
|
||||
}
|
||||
|
||||
public static function getLocationHierarchy($locations, $parent_id = null)
|
||||
{
|
||||
|
||||
/**
|
||||
* Query builder scope to order on parent
|
||||
*
|
||||
* @param Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
|
||||
$op = array();
|
||||
|
||||
foreach ($locations as $location) {
|
||||
|
||||
if ($location['parent_id'] == $parent_id) {
|
||||
$op[$location['id']] =
|
||||
array(
|
||||
'name' => $location['name'],
|
||||
'parent_id' => $location['parent_id']
|
||||
);
|
||||
|
||||
// Using recursion
|
||||
$children = Location::getLocationHierarchy($locations, $location['id']);
|
||||
if ($children) {
|
||||
$op[$location['id']]['children'] = $children;
|
||||
}
|
||||
|
||||
}
|
||||
public static function indenter($locations_with_children, $parent_id = null, $prefix = '') {
|
||||
$results = Array();
|
||||
|
||||
|
||||
if (!array_key_exists($parent_id, $locations_with_children)) {
|
||||
return [];
|
||||
}
|
||||
return $op;
|
||||
|
||||
|
||||
foreach ($locations_with_children[$parent_id] as $location) {
|
||||
$location->use_text = $prefix.' '.$location->name;
|
||||
$location->use_image = ($location->image) ? url('/').'/uploads/locations/'.$location->image : null;
|
||||
$results[] = $location;
|
||||
//now append the children. (if we have any)
|
||||
if (array_key_exists($location->id, $locations_with_children)) {
|
||||
$results = array_merge($results, Location::indenter($locations_with_children, $location->id,$prefix.'--'));
|
||||
}
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
|
||||
public static function flattenLocationsArray($location_options_array = null)
|
||||
{
|
||||
$location_options = array();
|
||||
foreach ($location_options_array as $id => $value) {
|
||||
|
||||
// get the top level key value
|
||||
$location_options[$id] = $value['name'];
|
||||
|
||||
// If there is a key named children, it has child locations and we have to walk it
|
||||
if (array_key_exists('children', $value)) {
|
||||
|
||||
foreach ($value['children'] as $child_id => $child_location_array) {
|
||||
$child_location_options = Location::flattenLocationsArray($value['children']);
|
||||
|
||||
foreach ($child_location_options as $child_id => $child_name) {
|
||||
$location_options[$child_id] = '--'.$child_name;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $location_options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to order on parent
|
||||
|
||||
+1
-1
@@ -491,7 +491,7 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo
|
||||
|
||||
public function scopeByGroup($query, $id) {
|
||||
return $query->whereHas('groups', function ($query) use ($id) {
|
||||
$query->where('groups.id', '=', $id);
|
||||
$query->where('permission_groups.id', '=', $id);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -258,13 +258,17 @@ class AssetPresenter extends Presenter
|
||||
$query->whereHas('models');
|
||||
})->get();
|
||||
|
||||
|
||||
// Note: We do not need to e() escape the field names here, as they are already escaped when
|
||||
// they are presented in the blade view. If we escape them here, custom fields with quotes in their
|
||||
// name can break the listings page. - snipe
|
||||
foreach ($fields as $field) {
|
||||
$layout[] = [
|
||||
"field" => 'custom_fields.'.$field->convertUnicodeDbSlug(),
|
||||
"searchable" => true,
|
||||
"sortable" => true,
|
||||
"switchable" => true,
|
||||
"title" => ($field->field_encrypted=='1') ?'<i class="fa fa-lock"></i> '.e($field->name) : e($field->name),
|
||||
"title" => ($field->field_encrypted=='1') ?'<i class="fa fa-lock"></i> '.$field->name : $field->name,
|
||||
"formatter" => "customFieldsFormatter"
|
||||
];
|
||||
|
||||
|
||||
@@ -176,6 +176,15 @@ class LicensePresenter extends Presenter
|
||||
"visible" => true,
|
||||
"formatter" => "usersLinkObjFormatter"
|
||||
], [
|
||||
"field" => "department",
|
||||
"searchable" => false,
|
||||
"sortable" => true,
|
||||
"switchable" => true,
|
||||
"title" => trans('general.department'),
|
||||
"visible" => false,
|
||||
"formatter" => "departmentNameLinkFormatter"
|
||||
],
|
||||
[
|
||||
"field" => "assigned_asset",
|
||||
"searchable" => false,
|
||||
"sortable" => false,
|
||||
@@ -191,7 +200,8 @@ class LicensePresenter extends Presenter
|
||||
"title" => trans('general.location'),
|
||||
"visible" => true,
|
||||
"formatter" => "locationsLinkObjFormatter"
|
||||
], [
|
||||
],
|
||||
[
|
||||
"field" => "checkincheckout",
|
||||
"searchable" => false,
|
||||
"sortable" => false,
|
||||
|
||||
+4
-2
@@ -6,6 +6,7 @@
|
||||
"type": "project",
|
||||
"require": {
|
||||
"php": ">=7.1.2",
|
||||
"barryvdh/laravel-cors": "^0.11.3",
|
||||
"barryvdh/laravel-debugbar": "^3.2",
|
||||
"doctrine/cache": "^1.8",
|
||||
"doctrine/common": "^2.10",
|
||||
@@ -13,6 +14,7 @@
|
||||
"doctrine/inflector": "^1.3",
|
||||
"doctrine/instantiator": "^1.2",
|
||||
"eduardokum/laravel-mail-auto-embed": "^1.0",
|
||||
"enshrined/svg-sanitize": "^0.13.0",
|
||||
"erusev/parsedown": "^1.7",
|
||||
"fideloper/proxy": "^4.1",
|
||||
"guzzlehttp/guzzle": "^6.3",
|
||||
@@ -26,12 +28,12 @@
|
||||
"maknz/slack": "^1.7",
|
||||
"neitanod/forceutf8": "^2.0",
|
||||
"patchwork/utf8": "^1.3",
|
||||
"phpdocumentor/reflection-docblock": "3.2.2",
|
||||
"phpdocumentor/reflection-docblock": "^4.0",
|
||||
"phpspec/prophecy": "^1.8",
|
||||
"pragmarx/google2fa": "^5.0",
|
||||
"pragmarx/google2fa-laravel": "^1.0",
|
||||
"predis/predis": "^1.1",
|
||||
"rollbar/rollbar-laravel": "^4.0",
|
||||
"rollbar/rollbar-laravel": "2.*",
|
||||
"schuppo/password-strength": "~1.5",
|
||||
"spatie/laravel-backup": "^5.12",
|
||||
"tecnickcom/tc-lib-barcode": "^1.15",
|
||||
|
||||
Generated
+796
-552
File diff suppressed because it is too large
Load Diff
@@ -36,6 +36,19 @@ return [
|
||||
|
||||
'env' => env('APP_ENV', 'production'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Result Limit
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value determines the max number of results to return, even if a higher limit
|
||||
| is passed in the API request. This is done to prevent server timeouts when
|
||||
| custom scripts are requesting 100k assets at a time.
|
||||
|
|
||||
*/
|
||||
|
||||
'max_results' => env('MAX_RESULTS', 500),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Debug Mode
|
||||
|
||||
+1
-1
@@ -132,7 +132,7 @@ return [
|
||||
'notifiable' => \Spatie\Backup\Notifications\Notifiable::class,
|
||||
|
||||
'mail' => [
|
||||
'to' => 'your@example.com',
|
||||
'to' => env('MAIL_BACKUP_NOTIFICATION_ADDRESS', null),
|
||||
],
|
||||
|
||||
'slack' => [
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* ---------------------------------------------------------------------
|
||||
* THIS IS $allowed_origins code IS NOT PART OF THE ORIGINAL CORS PACKAGE.
|
||||
* IT IS A MODIFICATION BY SNIPE-IT TO ALLOW ADDING ALLOWED ORIGINS VIA THE ENV.
|
||||
* ---------------------------------------------------------------------
|
||||
*
|
||||
* Since we don't really want people editing config files (lest they get
|
||||
* overwritten later), this enables the person managing the Snipe-IT
|
||||
* installation to modify these values without modifying the code.
|
||||
*
|
||||
* If APP_CORS_ALLOWED_ORIGINS is not set in the .env (for example if no one added it
|
||||
* after an upgrade from a previous version that didn't include it in the .env.example) or is null,
|
||||
* set it to * to allow all. If there is a value, either a single url or a comma-delimited
|
||||
* list of urls, explode that out into an array to whitelist just those urls.
|
||||
*/
|
||||
|
||||
$allowed_origins = env('CORS_ALLOWED_ORIGINS') !== null ?
|
||||
explode(',', env('CORS_ALLOWED_ORIGINS')) : [];
|
||||
|
||||
/**
|
||||
* Original Laravel CORS package config file modifications end here
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Laravel CORS
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| allowedOrigins, allowedHeaders and allowedMethods can be set to array('*')
|
||||
| to accept any value.
|
||||
|
|
||||
*/
|
||||
|
||||
'supportsCredentials' => false,
|
||||
'allowedOrigins' => $allowed_origins,
|
||||
'allowedOriginsPatterns' => [],
|
||||
'allowedHeaders' => ['*'],
|
||||
'allowedMethods' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
|
||||
'exposedHeaders' => [],
|
||||
'maxAge' => 0,
|
||||
|
||||
];
|
||||
+6
-6
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
return array (
|
||||
'app_version' => 'v4.7.2',
|
||||
'full_app_version' => 'v4.7.2 - build 4037',
|
||||
'build_version' => '4037',
|
||||
'app_version' => 'v4.8.0',
|
||||
'full_app_version' => 'v4.8.0 - build 4186-g893454dca',
|
||||
'build_version' => '4186',
|
||||
'prerelease_version' => '',
|
||||
'hash_version' => '',
|
||||
'full_hash' => 'v4.7.2',
|
||||
'hash_version' => 'g893454dca',
|
||||
'full_hash' => 'v4.8.0-g893454dca',
|
||||
'branch' => 'master',
|
||||
);
|
||||
);
|
||||
@@ -29,7 +29,7 @@ class MigrationCartalystSentryInstallGroups extends Migration {
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('groups', function($table)
|
||||
Schema::create('permission_groups', function($table)
|
||||
{
|
||||
$table->increments('id');
|
||||
$table->string('name');
|
||||
@@ -46,7 +46,7 @@ class MigrationCartalystSentryInstallGroups extends Migration {
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::drop('groups');
|
||||
Schema::drop('permission_groups');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,39 +2,44 @@
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use App\Models\Group;
|
||||
|
||||
class UpdateGroupFieldForReporting extends Migration {
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
//
|
||||
// Schema::table('groups', function(Blueprint $table)
|
||||
// {
|
||||
// //
|
||||
// });
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
|
||||
DB::update('update '.DB::getTablePrefix().'groups set permissions = ? where id = ?', ['{"admin":1,"users":1,"reports":1}', 1]);
|
||||
// This is janky because we had to do a back in time change to handle a MySQL 8+
|
||||
// compatibility issue.
|
||||
|
||||
DB::update('update '.DB::getTablePrefix().'groups set permissions = ? where id = ?', ['{"users":1,"reports":1}', 2]);
|
||||
// Ideally we'd be using the model here, but since we can't really know whether this is an upgrade
|
||||
// or a fresh install, we have to check which table is being used.
|
||||
|
||||
if (Schema::hasTable('permission_groups')) {
|
||||
|
||||
// DB::statement('UPDATE '.$prefix.'groups SET permissions="{\"admin\":1,\"users\":1,\"reports\":1}" where id=1');
|
||||
// DB::statement('UPDATE '.$prefix.'groups SET permissions="{\"users\":1,\"reports\":1}" where id=2');
|
||||
Group::where('id', 1)->update(['permissions' => '{"users-poop":1,"reports":1}']);
|
||||
Group::where('id', 2)->update(['permissions' => '{"users-pop":1,"reports":1}']);
|
||||
|
||||
}
|
||||
} elseif (Schema::hasTable('groups')) {
|
||||
DB::update('update '.DB::getTablePrefix().'groups set permissions = ? where id = ?', ['{"admin-farts":1,"users":1,"reports":1}', 1]);
|
||||
DB::update('update '.DB::getTablePrefix().'groups set permissions = ? where id = ?', ['{"users-farts":1,"reports":1}', 2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class RenameGroupsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
// We check to see if this table exists before attempting the migration since
|
||||
// upgraded installs would have this table, but new installs wouldn't.
|
||||
// We had to change the name of the table in the older migrations
|
||||
// to handle a MySQl 8+ compatibility issue related to reserved words.
|
||||
// Without going back in time in migrations, this would fail since the groups table
|
||||
// would never be allowed to be created in the first place on MySql 8+.
|
||||
//
|
||||
// So... if an upgrade, let's rename that table.
|
||||
// If a new install, the migration was already changed, so the table isn't
|
||||
// called that anymore and we can skip this migration.
|
||||
|
||||
if (Schema::hasTable('groups')) {
|
||||
Schema::rename('groups', 'permission_groups');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
if (Schema::hasTable('permission_groups')) {
|
||||
Schema::rename('permission_groups', 'groups');
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js "
|
||||
},
|
||||
"devDependencies": {
|
||||
"axios": "^0.16.2",
|
||||
"axios": ">=0.18.1",
|
||||
"babel-preset-latest": "^6.24.1",
|
||||
"cross-env": "^5.0.5",
|
||||
"jquery": "^3.1.1",
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'about_accessories_title' => 'Amdan Ategolion',
|
||||
'about_accessories_text' => 'Mae ategolion yn unrhyw offer sydd yn cael eu ddosbarthu i defnyddwyr ond ddim hefo rhif cofrestru. (Neu nid oes angen tracio). Er enghraifft, llygod, ategolion.',
|
||||
'accessory_category' => 'Categori Ategolyn',
|
||||
'accessory_name' => 'Enw Ategolyn',
|
||||
'checkout' => 'Cofnodi ategolyn allan',
|
||||
'checkin' => 'Cofnodi ategolyn i fewn',
|
||||
'create' => 'Creu Ategolyn',
|
||||
'edit' => 'Golygu Ategolyn',
|
||||
'eula_text' => 'Categori CTDT',
|
||||
'eula_text_help' => 'Mae\'r blwch yma yn caniatau i chi addasu eich CTDTs ar gyfer mathau penodol o asedau. Os ydych yn defnyddio un CTDT ar gyfer eich asedau yna cewch ticio\'r blwch isod i defnyddio\'r fersiwn diofyn.',
|
||||
'require_acceptance' => 'Gorfodi defnyddwyr i cadarnhau derbyn asedau yn y categori yma.',
|
||||
'no_default_eula' => 'Wedi methu darganfod CTDT, Ychwanegwch un yn gosodiadau.',
|
||||
'total' => 'Cyfanswm',
|
||||
'remaining' => 'Yn weddill',
|
||||
'update' => 'Diweddaru Ategolyn',
|
||||
'use_default_eula' => 'Defnyddio\'r <a href="#" data-toggle="modal" data-target="#eulaModal">prif CTDT diofyn</a> yn lle.',
|
||||
'use_default_eula_disabled' => '<del>Defnyddio\'r CTDT diofn yn lle\'r un presennol.</del>Nid oes prif CTDT diofyn wedi gosod. Ychwanegwch un yn gosodiadau os gwelwch yn dda.',
|
||||
|
||||
);
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
|
||||
'does_not_exist' => 'Nid yw\'r ategolyn yn bodoli.',
|
||||
'assoc_users' => 'Mae\'r ategolyn yma hefo :count eitem wedi nodi allan i defnyddwyr. Nodwch yr ategolion yn ol i fewn ac yna ceisiwch eto. ',
|
||||
|
||||
'create' => array(
|
||||
'error' => 'Ni crewyd yr ategolyn, ceisiwch eto o.g.y.dd.',
|
||||
'success' => 'Ategolyn wedi creu yn llwyddiannus.'
|
||||
),
|
||||
|
||||
'update' => array(
|
||||
'error' => 'Ni diweddarwyd yr ategolyn, ceisiwch eto o.g.y.dd',
|
||||
'success' => 'Diweddarwyd yr ategolyn yn llwyddiannus.'
|
||||
),
|
||||
|
||||
'delete' => array(
|
||||
'confirm' => 'Ydych chi\'n sicr eich bod eisiau dileu\'r eitem hwn?',
|
||||
'error' => 'Nid oedd yn bosib dileu\'r eitem. Ceisiwch eto o.g.y.dd.',
|
||||
'success' => 'Ategolyn wedi dileu yn llwyddiannus.'
|
||||
),
|
||||
|
||||
'checkout' => array(
|
||||
'error' => 'Ategolyn heb ei nodi allan, ceisiwch eto o. g. y. dd',
|
||||
'success' => 'Ategolyn wedi nodi allan yn llwyddiannus.',
|
||||
'user_does_not_exist' => 'Nid yw\'r defnyddiwr yna yn ddilys. Ceisiwch eto o.g.y.dd.'
|
||||
),
|
||||
|
||||
'checkin' => array(
|
||||
'error' => 'Nid oedd yn bosib nodi\'r ategolyn i fewn, ceisiwch eto o.g.y.dd',
|
||||
'success' => 'Ategolyn wedi nodi i fewn yn llwyddiannus.',
|
||||
'user_does_not_exist' => 'Nid yw\'r defnyddiwr yna yn ddilys. Ceisiwch eto o.g.y.dd.'
|
||||
)
|
||||
|
||||
|
||||
);
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'dl_csv' => 'Lawrlwytho CSV',
|
||||
'eula_text' => 'CTDT',
|
||||
'id' => 'Rhif Unigryw',
|
||||
'require_acceptance' => 'Derbyn',
|
||||
'title' => 'Enw Ategolyn',
|
||||
|
||||
|
||||
);
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'asset_maintenance_type' => 'Manylion Cynnal a Chadw',
|
||||
'title' => 'Teitl',
|
||||
'start_date' => 'Wedi cychwyn',
|
||||
'completion_date' => 'Wedi cwbwlhau',
|
||||
'cost' => 'Cost',
|
||||
'is_warranty' => 'Gwelliant Gwarant',
|
||||
'asset_maintenance_time' => 'Dyddiau',
|
||||
'notes' => 'Nodiadau',
|
||||
'update' => 'Diweddaru',
|
||||
'create' => 'Creu'
|
||||
];
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'asset_maintenances' => 'Cynnal a chadw Ased',
|
||||
'edit' => 'Golygu Cynnal a Chadw Ased',
|
||||
'delete' => 'Dileu Cynnal a Chadw Ased',
|
||||
'view' => 'Gweld manylder Cynnal a Chadw Ased',
|
||||
'repair' => 'Trwsio',
|
||||
'maintenance' => 'Cynnal a Chadw',
|
||||
'upgrade' => 'Uwchraddio'
|
||||
];
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'not_found' => 'Ni ddarganfuwyd cofnod Cynnal a Chadw Ased yr oeddech yn edrych amdan!',
|
||||
'delete' => [
|
||||
'confirm' => 'Ydych chi\'n sicr eich bod eisiau dileu\'r cofnod cynnal a chadw yma?',
|
||||
'error' => 'Nid oedd yn bosib dileu\'r nodyn cynnal a chadw. Ceisiwch eto o.g.y.dd.',
|
||||
'success' => 'Nodyn cynnal a chadw wedi\'i dileu\'n llwyddiannus.'
|
||||
],
|
||||
'create' => [
|
||||
'error' => 'Ni crewyd y cofnod cynnal a chadw, ceisiwch eto o.g.y.dd.',
|
||||
'success' => 'Nodyn cynnal a chadw wedi\'i greu\'n llwyddiannus.'
|
||||
],
|
||||
'edit' => [
|
||||
'error' => 'Wedi methu newid y cofnod cynnal a chadw, ceisiwch eto o.g.y.dd.',
|
||||
'success' => 'Nodyn cynnal a chadw wedi\'i diweddaru\'n llwyddiannus.'
|
||||
],
|
||||
'asset_maintenance_incomplete' => 'Heb cwbwlhau eto',
|
||||
'warranty' => 'Warant',
|
||||
'not_warranty' => 'Dim Warant',
|
||||
];
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'title' => 'Cynnal a chadw Ased',
|
||||
'asset_name' => 'Enw Ased',
|
||||
'is_warranty' => 'Warant',
|
||||
'dl_csv' => 'Lawrlwytho CSV'
|
||||
];
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'about_categories_title' => 'Amdan Categoriau',
|
||||
'about_categories' => 'Mae categoriau yn cynorthwyo chi i cadw trefn ar eich eitemau. Enghreifftiau o categoriau yw "Cyfrifiadur pen-bwrdd", "Gliniadur", "Ffôn Symudol", "Tabledi", ac yn y blaen, ond cewch gosod rhain yn ol eich angen.',
|
||||
'asset_categories' => 'Categoriau Asedau',
|
||||
'category_name' => 'Enw categori',
|
||||
'checkin_email' => 'Gyrru ebost i defnyddiwr wrth nodi fewn/allan.',
|
||||
'checkin_email_notification' => 'Fe geith y defnyddiwr yma ebost wrth nodi i fewn/allan.',
|
||||
'clone' => 'Dyblygu Categori',
|
||||
'create' => 'Creu Categori Newydd',
|
||||
'edit' => 'Golygu Categori',
|
||||
'eula_text' => 'CTDT Categori',
|
||||
'eula_text_help' => 'Mae\'r blwch yma yn caniatau i chi addasu eich CTDTs ar gyfer mathau penodol o asedau. Os ydych yn defnyddio un CTDT ar gyfer eich asedau yna cewch ticio\'r blwch isod i defnyddio\'r fersiwn diofyn.',
|
||||
'name' => 'Enw\'r categori',
|
||||
'require_acceptance' => 'Gorfodi defnyddwyr i cadarnhau derbyn asedau yn y categori yma.',
|
||||
'required_acceptance' => 'Fe geith y defnyddiwr yma ebost hefo linc i cofnodi derbyn yr eitem yma.',
|
||||
'required_eula' => 'Fe geith y defnyddiwr yma copi o\'r CTDT trwy ebost',
|
||||
'no_default_eula' => 'Wedi methu darganfod CTDT, Ychwanegwch un yn gosodiadau.',
|
||||
'update' => 'Diweddaru Categori',
|
||||
'use_default_eula' => 'Defnyddio\'r <a href="#" data-toggle="modal" data-target="#eulaModal">prif CTDT diofyn</a> yn lle.',
|
||||
'use_default_eula_disabled' => '<del>Defnyddio\'r CTDT diofyn yn lle\'r un presennol.</del>Nid oes prif CTDT diofyn wedi gosod. Ychwanegwch yn ynj gosodiadau os gwelwch yn dda.',
|
||||
|
||||
);
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
|
||||
'does_not_exist' => 'Categori ddim yn bodoli.',
|
||||
'assoc_models' => 'Mae\'r categori yma wedi perthnasu i oleiaf un model a nid yw\'n bosib dileu. Diweddarwch eich modelau i beidio cyfeirio at y categori yma ac yna ceisiwch eto. ',
|
||||
'assoc_items' => 'Mae\'r categori yma wedi perthnasu i :asset_type a nid yw\'n bosib dileu. Diweddarwch eich :asset_type i beidio cyfeirio at y categori yma ac yna ceisiwch eto. ',
|
||||
|
||||
'create' => array(
|
||||
'error' => 'Ni crewyd y categori, ceisiwch eto o. g. y. dd.',
|
||||
'success' => 'Categori wedi creu\'n llwyddiannus.'
|
||||
),
|
||||
|
||||
'update' => array(
|
||||
'error' => 'Ni diweddarwyd y categori, ceisiwch eto o. g. y. dd',
|
||||
'success' => 'Categori wedi diweddaru\'n llwyddiannus.'
|
||||
),
|
||||
|
||||
'delete' => array(
|
||||
'confirm' => 'Ydych chi\'n siwr eich bod eisiau dileu\'r categori yma?',
|
||||
'error' => 'Nid oedd yn bosib dileu\'r categori. Ceisiwch eto o.g.y.dd.',
|
||||
'success' => 'Categori wedi dileu\'n llwyddiannus.'
|
||||
)
|
||||
|
||||
);
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'eula_text' => 'CTDT',
|
||||
'id' => 'Rhif Unigryw',
|
||||
'parent' => 'Rhiant',
|
||||
'require_acceptance' => 'Derbyn',
|
||||
'title' => 'Enw Categori Ased',
|
||||
|
||||
);
|
||||
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
return [
|
||||
'about_companies_title' => 'Amdan Cwmniau',
|
||||
'about_companies_text' => 'Defnyddir cwmniau fel maes syml, neu i rheoli mynediad at grwpiau o offer, defnyddwyr os ydi cefnogaeth cwmniau wedi alluogi.',
|
||||
'select_company' => 'Dewis Cwmni',
|
||||
];
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
return array(
|
||||
'does_not_exist' => 'Nid ywr cwmni\'n bodoli.',
|
||||
'assoc_users' => 'Mae\'r cwmni yma wedi perthnasu i oleiaf un model a nid yw\'n bosib dileu. Diweddarwch eich modelau i beidio cyfeirio at y cwmni yma ac yna ceisiwch eto. ',
|
||||
'create' => array(
|
||||
'error' => 'Ni crewyd y cwmni, ceisiwch eto o. g. y. dd.',
|
||||
'success' => 'Cwmni wedi creu yn llwyddiannus.'
|
||||
),
|
||||
'update' => array(
|
||||
'error' => 'Ni diweddarwyd y cwmni, ceisiwch eto o. g. y. dd',
|
||||
'success' => 'Cwmni wedi diweddaru\'n llwyddiannus.'
|
||||
),
|
||||
'delete' => array(
|
||||
'confirm' => 'Ydych chi\'n siwr eich bod eisiau dileu\'r cwmni yma?',
|
||||
'error' => 'Nid oedd yn bosib dileu\'r cwmni. Ceisiwch eto o. g. y. dd.',
|
||||
'success' => 'Cwmni wedi dileu\'n llwyddiannus.'
|
||||
)
|
||||
);
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
return array(
|
||||
'companies' => 'Cwmniau',
|
||||
'create' => 'Creu Cwmni',
|
||||
'title' => 'Cwmni',
|
||||
'update' => 'Diweddaru Cwmni',
|
||||
'name' => 'Enw Cwmni',
|
||||
'id' => 'Rhif Unigryw',
|
||||
);
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'about_components_title' => 'Amdan Cydranau',
|
||||
'about_components_text' => 'Mae cydrannau yn darnau sydd yn rhan o ased, er enghraifft cof, disg caled, ayyb.',
|
||||
'component_name' => 'Enw Cydran',
|
||||
'checkin' => 'Nodi\'r gydran allan',
|
||||
'checkout' => 'Nodi\'r gydran allan',
|
||||
'cost' => 'Cost pwrcasu',
|
||||
'create' => 'Creu Cydran',
|
||||
'edit' => 'Addasu Cydran',
|
||||
'date' => 'Dyddiad Pwrcasu',
|
||||
'order' => 'Rhif Archeb',
|
||||
'remaining' => 'Yn weddill',
|
||||
'total' => 'Cyfanswm',
|
||||
'update' => 'Diweddaru Cydran',
|
||||
);
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
|
||||
'does_not_exist' => 'Nid ywr cydran yn bodoli.',
|
||||
|
||||
'create' => array(
|
||||
'error' => 'Ni crewyd y cydran, ceisiwch eto o. g. y. dd.',
|
||||
'success' => 'Cydran wedi creu yn llwyddiannus.'
|
||||
),
|
||||
|
||||
'update' => array(
|
||||
'error' => 'Ni ddiweddarwyd y cydran, ceisiwch eto o. g. y. dd',
|
||||
'success' => 'Diweddarwyd y gydran yn llwyddiannus.'
|
||||
),
|
||||
|
||||
'delete' => array(
|
||||
'confirm' => 'Ydych chi\'n siwr eich bod eisiau dileu\'r cydran yma?',
|
||||
'error' => 'Nid oedd yn bosib dileu\'r cydran. Ceisiwch eto o. g. y. dd.',
|
||||
'success' => 'Cydran wedi dileu\'n llwyddiannus.'
|
||||
),
|
||||
|
||||
'checkout' => array(
|
||||
'error' => 'Cydran heb ei nodi allan, ceisiwch eto o. g. y. dd',
|
||||
'success' => 'Cydran wedi nodi allan yn llwyddiannus.',
|
||||
'user_does_not_exist' => 'Nid yw\'r defnyddiwr yna yn ddilys. Ceisiwch eto o. g. y. dd.'
|
||||
),
|
||||
|
||||
'checkin' => array(
|
||||
'error' => 'Cydran heb ei nodi i fewn, ceisiwch eto o. g. y. dd',
|
||||
'success' => 'Cydran wedi nodi i fewn yn llwyddiannus.',
|
||||
'user_does_not_exist' => 'Nid yw\'r defnyddiwr yna yn ddilys. Ceisiwch eto o. g. y. dd.'
|
||||
)
|
||||
|
||||
|
||||
);
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'title' => 'Enw Cydran',
|
||||
);
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'about_consumables_title' => 'Amdan Nwyddau Traul',
|
||||
'about_consumables_text' => 'Mae unrhwy eitem sydd yn cael eu defnyddio i fyny dros amser yn nwydd traul. Er enghraifft, inc neu paper argraffydd.',
|
||||
'checkout' => 'Nodi nwydd traul allan i defnyddiwr',
|
||||
'consumable_name' => 'Enw nwydd traul',
|
||||
'create' => 'Creu nwydd traul',
|
||||
'item_no' => 'Rhif eitem.',
|
||||
'remaining' => 'Yn weddill',
|
||||
'total' => 'Cyfanswm',
|
||||
'update' => 'Diweddaru nwydd traul',
|
||||
);
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
|
||||
'does_not_exist' => 'Nid yw\'r nwydd traul yn bodoli.',
|
||||
|
||||
'create' => array(
|
||||
'error' => 'Ni crewyd y nwydd traul, ceisiwch eto o. g. y. dd.',
|
||||
'success' => 'Nwydd traul wedi creu yn llwyddiannus.'
|
||||
),
|
||||
|
||||
'update' => array(
|
||||
'error' => 'Ni diweddarwyd y nwydd traul, ceisiwch eto o. g. y. dd',
|
||||
'success' => 'Nwydd traul wedi diweddaru\'n llwyddiannus.'
|
||||
),
|
||||
|
||||
'delete' => array(
|
||||
'confirm' => 'Ydych chi\'n siwr eich bod eisiau dileu\'r nwydd traul yma?',
|
||||
'error' => 'Nid oedd yn bosib dileu\'r nwydd traul. Ceisiwch eto o. g. y. dd.',
|
||||
'success' => 'Nwydd traul wedi dileu\'n llwyddiannus.'
|
||||
),
|
||||
|
||||
'checkout' => array(
|
||||
'error' => 'Nwydd traul heb ei nodi allan, ceisiwch eto o. g. y. dd',
|
||||
'success' => 'Nwydd traul wedi nodi allan yn llwyddiannus.',
|
||||
'user_does_not_exist' => 'Nid yw\'r defnyddiwr yna yn ddilys. Ceisiwch eto o. g. y. dd.'
|
||||
),
|
||||
|
||||
'checkin' => array(
|
||||
'error' => 'Nwydd traul heb ei nodi i fewn, ceisiwch eto o. g. y. dd',
|
||||
'success' => 'Nwydd traul wedi nodi i fewn yn llwyddiannus.',
|
||||
'user_does_not_exist' => 'Nid yw\'r defnyddiwr yna yn ddilys. Ceisiwch eto o. g. y. dd.'
|
||||
)
|
||||
|
||||
|
||||
);
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'title' => 'Enw nwydd traul',
|
||||
);
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'custom_fields' => 'Meysydd addasedig',
|
||||
'field' => 'Meysydd',
|
||||
'about_fieldsets_title' => 'Amdan grwpiau meysydd',
|
||||
'about_fieldsets_text' => 'Mae grwpiau meysydd yn caniatau i chi creu grwpiau o meysydd addasedig sydd yn cael ei defnyddio yn amal ar gyfer mathau penodol o asedau.',
|
||||
'custom_format' => 'Fformat Regex addasedig...',
|
||||
'encrypt_field' => 'Hamcryptio gwerth y maes yma yn y basdata',
|
||||
'encrypt_field_help' => 'RHYBUDD: Mae hamcryptio maes yn feddwl nid oes modd chwilio amdano.',
|
||||
'encrypted' => 'Wedi hamcryptio',
|
||||
'fieldset' => 'Setiau maes',
|
||||
'qty_fields' => 'Nifer o meysydd',
|
||||
'fieldsets' => 'Setiau maes',
|
||||
'fieldset_name' => 'Enw set maes',
|
||||
'field_name' => 'Enw maes',
|
||||
'field_values' => 'Gwerthoedd maes',
|
||||
'field_values_help' => 'Ychwanegwch opsiynau selectable, un fesul llinell. Anwybyddir llinellau gwag heblaw\'r llinell gyntaf.',
|
||||
'field_element' => 'Ffurf Elfen',
|
||||
'field_element_short' => 'Elfen',
|
||||
'field_format' => 'Fformat',
|
||||
'field_custom_format' => 'Fformat Regex addasedig',
|
||||
'field_custom_format_help' => 'Mae\'r maes hwn yn caniatáu ichi ddefnyddio mynegiad regex i\'w ddilysu. Dylai ddechrau gyda "regex:" - er enghraifft, i ddilysu bod gwerth maes arferiad yn cynnwys IMEI dilys (15 digid rhifol), byddech chi\'n defnyddio <code>regex:/^[0-9]{15}$/</code>.',
|
||||
'required' => 'Gofynnol',
|
||||
'req' => 'Angen.',
|
||||
'used_by_models' => 'Defnyddir gan modelau',
|
||||
'order' => 'Trefn',
|
||||
'create_fieldset' => 'Set maes newydd',
|
||||
'create_field' => 'Maes Addasedig newydd',
|
||||
'value_encrypted' => 'Mae gwerth y maes hwn wedi\'i amgryptio yn y gronfa ddata. Dim ond defnyddwyr gweinyddol fydd yn gallu gweld y gwerth wedi\'i ddadgryptio',
|
||||
'show_in_email' => 'Cynnwys gwerth y maes hwn mewn e-byst talu a anfonir at y defnyddiwr? Ni ellir cynnwys meysydd wedi\'u hamgryptio mewn e-byst.',
|
||||
);
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
|
||||
'field' => array(
|
||||
'invalid' => 'Nid yw\'r maes yn bodoli.',
|
||||
'already_added' => 'Maes eisoes yn bodoli',
|
||||
|
||||
'create' => array(
|
||||
'error' => 'Ni crewyd y maes, ceisiwch eto o. g. y. dd.',
|
||||
'success' => 'Maes wedi creu yn llwyddiannus.',
|
||||
'assoc_success' => 'Maes wedi ychwanegu\'n llwyddiannus ir set maes.'
|
||||
),
|
||||
|
||||
'update' => array(
|
||||
'error' => 'Ni diweddarwyd y maes, ceisiwch eto o. g. y. dd',
|
||||
'success' => 'Maes wedi diweddaru\'n llwyddiannus.'
|
||||
),
|
||||
|
||||
'delete' => array(
|
||||
'confirm' => 'Ydych chi\'n siwr eich bod eisiau dileu\'r maes yma?',
|
||||
'error' => 'Nid oedd yn bosib dileu\'r maes. Ceisiwch eto o. g. y. dd.',
|
||||
'success' => 'Maes wedi dileu\'n llwyddiannus.',
|
||||
'in_use' => 'Maes mewn defnydd.',
|
||||
)
|
||||
|
||||
),
|
||||
|
||||
'fieldset' => array(
|
||||
|
||||
'does_not_exist' => 'Nid yw\'r set maes yn bodoli',
|
||||
|
||||
'create' => array(
|
||||
'error' => 'Ni crewyd y set maes, ceisiwch eto o. g. y. dd.',
|
||||
'success' => 'Set maes wedi creu yn llwyddiannus.'
|
||||
),
|
||||
|
||||
'update' => array(
|
||||
'error' => 'Ni diweddarwyd y set maes, ceisiwch eto o. g. y. dd',
|
||||
'success' => 'Set maes wedi diweddaru\'n llwyddiannus.'
|
||||
),
|
||||
|
||||
'delete' => array(
|
||||
'confirm' => 'Ydych chi\'n siwr eich bod eisiau dileu\'r set maes yma?',
|
||||
'error' => 'Nid oedd yn bosib dileu\'r set maes. Ceisiwch eto o. g. y. dd.',
|
||||
'success' => 'Set maes wedi dileu\'n llwyddiannus.',
|
||||
'in_use' => 'Set maes mewn defnydd.',
|
||||
)
|
||||
|
||||
),
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
);
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
|
||||
'does_not_exist' => 'Nid yw\'r adran yn bodoli.',
|
||||
'assoc_users' => 'Mae\'r adran yma wedi perthnasu i oleiaf un defnyddiwr a nid yw\'n bosib dileu. Diweddarwch eich defnyddwyr i beidio cyfeirio at yr adran yma ac yna ceisiwch eto. ',
|
||||
'create' => array(
|
||||
'error' => 'Ni crewyd yr adran, ceisiwch eto o. g. y. dd.',
|
||||
'success' => 'Adran wedi creu yn llwyddiannus.'
|
||||
),
|
||||
'update' => array(
|
||||
'error' => 'Ni diweddarwyd yr adran, ceisiwch eto o. g. y. dd',
|
||||
'success' => 'Adran wedi diweddaru\'n llwyddiannus.'
|
||||
),
|
||||
'delete' => array(
|
||||
'confirm' => 'Ydych chi\'n sicr eich bod eisiau dileu\'r adran yma?',
|
||||
'error' => 'Nid oedd yn bosib dileu\'r adran. Ceisiwch eto o. g. y. dd.',
|
||||
'success' => 'Adran wedi dileu\'n llwyddiannus.'
|
||||
)
|
||||
|
||||
);
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
|
||||
'id' => 'Rhif Unigryw',
|
||||
'name' => 'Enw Adran',
|
||||
'manager' => 'Rheolwr',
|
||||
'location' => 'Lleoliad',
|
||||
'create' => 'Creu Adran',
|
||||
'update' => 'Diweddaru Adran',
|
||||
);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user