Compare commits

..

4 Commits

Author SHA1 Message Date
snipe
f98f978502 Fixed typos
Signed-off-by: snipe <snipe@snipe.net>
2024-12-11 16:53:15 +00:00
snipe
a0bbafeb30 Removed unused code
Signed-off-by: snipe <snipe@snipe.net>
2024-12-10 14:35:22 +00:00
snipe
dbd33e1a34 Check for specific error message
Signed-off-by: snipe <snipe@snipe.net>
2024-12-10 14:34:16 +00:00
snipe
8afba32169 Validate group data
Signed-off-by: snipe <snipe@snipe.net>
2024-12-10 14:23:23 +00:00
1036 changed files with 7352 additions and 14939 deletions

View File

@@ -3235,42 +3235,6 @@
"contributions": [
"code"
]
},
{
"login": "sgross-emlix",
"name": "Sebastian Groß",
"avatar_url": "https://avatars.githubusercontent.com/u/143394709?v=4",
"profile": "https://github.com/sgross-emlix",
"contributions": [
"code"
]
},
{
"login": "AnouarTouati",
"name": "Anouar Touati",
"avatar_url": "https://avatars.githubusercontent.com/u/41107778?v=4",
"profile": "https://github.com/AnouarTouati",
"contributions": [
"code"
]
},
{
"login": "aHVzY2g",
"name": "aHVzY2g",
"avatar_url": "https://avatars.githubusercontent.com/u/25596663?v=4",
"profile": "https://github.com/aHVzY2g",
"contributions": [
"code"
]
},
{
"login": "brlin-tw",
"name": "林博仁 Buo-ren Lin",
"avatar_url": "https://avatars.githubusercontent.com/u/13408130?v=4",
"profile": "https://brlin.me",
"contributions": [
"code"
]
}
]
}

View File

@@ -11,7 +11,7 @@ MYSQL_ROOT_PASSWORD=changeme1234
# REQUIRED: BASIC APP SETTINGS
# --------------------------------------------
APP_ENV=develop
APP_DEBUG=true
APP_DEBUG=false
# please regenerate the APP_KEY value by calling `docker-compose run --rm snipeit bash` and then `php artisan key:generate --show` and then copy paste the value here
APP_KEY=base64:3ilviXqB9u6DX1NRcyWGJ+sjySF+H18CPDGb3+IVwMQ=
APP_URL=http://localhost:8000
@@ -158,7 +158,7 @@ RESET_PASSWORD_LINK_EXPIRES=900
# --------------------------------------------
# OPTIONAL: MISC
# --------------------------------------------
LOG_CHANNEL=single
LOG_CHANNEL=stderr
LOG_MAX_DAYS=10
APP_LOCKED=false
APP_CIPHER=AES-256-CBC

View File

@@ -1,7 +1,7 @@
# --------------------------------------------
# REQUIRED: DOCKER SPECIFIC SETTINGS
# --------------------------------------------
APP_VERSION=
APP_VERSION=v6.4.1
APP_PORT=8000
# --------------------------------------------
@@ -9,7 +9,7 @@ APP_PORT=8000
# --------------------------------------------
APP_ENV=production
APP_DEBUG=false
# Please regenerate the APP_KEY value by calling `docker compose run --rm app php artisan key:generate --show`. Copy paste the value here
# Please regenerate the APP_KEY value by calling `docker compose run --rm snipeit php artisan key:generate --show`. Copy paste the value here
APP_KEY=base64:3ilviXqB9u6DX1NRcyWGJ+sjySF+H18CPDGb3+IVwMQ=
APP_URL=http://localhost:8000
# https://en.wikipedia.org/wiki/List_of_tz_database_time_zones - TZ identifier

View File

@@ -80,12 +80,6 @@ MAIL_BACKUP_NOTIFICATION_ADDRESS=null
BACKUP_ENV=true
ALLOW_BACKUP_DELETE=false
ALLOW_DATA_PURGE=false
ALL_BACKUP_KEEP_DAYS=7
DAILY_BACKUP_KEEP_DAYS=16
WEEKLY_BACKUP_KEEP_WEEKS=8
MONTHLY_BACKUP_KEEP_MONTHS=4
YEARLY_BACKUP_KEEP_YEARS=2
BACKUP_PURGE_OLDEST_AT_MEGS=5000
# --------------------------------------------
# OPTIONAL: SESSION SETTINGS

View File

@@ -52,8 +52,7 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
| [<img src="https://avatars.githubusercontent.com/u/47315739?v=4" width="110px;"/><br /><sub>bilias</sub>](https://github.com/bilias)<br />[💻](https://github.com/snipe/snipe-it/commits?author=bilias "Code") | [<img src="https://avatars.githubusercontent.com/u/2565989?v=4" width="110px;"/><br /><sub>coach1988</sub>](https://github.com/coach1988)<br />[💻](https://github.com/snipe/snipe-it/commits?author=coach1988 "Code") | [<img src="https://avatars.githubusercontent.com/u/11910225?v=4" width="110px;"/><br /><sub>MrM</sub>](https://github.com/mauro-miatello)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mauro-miatello "Code") | [<img src="https://avatars.githubusercontent.com/u/60405354?v=4" width="110px;"/><br /><sub>koiakoia</sub>](https://github.com/koiakoia)<br />[💻](https://github.com/snipe/snipe-it/commits?author=koiakoia "Code") | [<img src="https://avatars.githubusercontent.com/u/5323832?v=4" width="110px;"/><br /><sub>Mustafa Online</sub>](https://github.com/mustafa-online)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mustafa-online "Code") | [<img src="https://avatars.githubusercontent.com/u/104601439?v=4" width="110px;"/><br /><sub>franceslui</sub>](https://github.com/franceslui)<br />[💻](https://github.com/snipe/snipe-it/commits?author=franceslui "Code") | [<img src="https://avatars.githubusercontent.com/u/125313163?v=4" width="110px;"/><br /><sub>Q4kK</sub>](https://github.com/Q4kK)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Q4kK "Code") |
| [<img src="https://avatars.githubusercontent.com/u/55590532?v=4" width="110px;"/><br /><sub>squintfox</sub>](https://github.com/squintfox)<br />[💻](https://github.com/snipe/snipe-it/commits?author=squintfox "Code") | [<img src="https://avatars.githubusercontent.com/u/1380084?v=4" width="110px;"/><br /><sub>Jeff Clay</sub>](https://github.com/jeffclay)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jeffclay "Code") | [<img src="https://avatars.githubusercontent.com/u/52716446?v=4" width="110px;"/><br /><sub>Phil J R</sub>](https://github.com/PP-JN-RL)<br />[💻](https://github.com/snipe/snipe-it/commits?author=PP-JN-RL "Code") | [<img src="https://avatars.githubusercontent.com/u/1496725?v=4" width="110px;"/><br /><sub>i_virus</sub>](https://www.corelight.com/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=chandanchowdhury "Code") | [<img src="https://avatars.githubusercontent.com/u/1020541?v=4" width="110px;"/><br /><sub>Paul Grime</sub>](https://github.com/gitgrimbo)<br />[💻](https://github.com/snipe/snipe-it/commits?author=gitgrimbo "Code") | [<img src="https://avatars.githubusercontent.com/u/922815?v=4" width="110px;"/><br /><sub>Lee Porte</sub>](https://leeporte.co.uk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=LeePorte "Code") | [<img src="https://avatars.githubusercontent.com/u/23613427?v=4" width="110px;"/><br /><sub>BRYAN </sub>](https://github.com/bryanlopezinc)<br />[💻](https://github.com/snipe/snipe-it/commits?author=bryanlopezinc "Code") [⚠️](https://github.com/snipe/snipe-it/commits?author=bryanlopezinc "Tests") |
| [<img src="https://avatars.githubusercontent.com/u/64061710?v=4" width="110px;"/><br /><sub>U-H-T</sub>](https://github.com/U-H-T)<br />[💻](https://github.com/snipe/snipe-it/commits?author=U-H-T "Code") | [<img src="https://avatars.githubusercontent.com/u/5395363?v=4" width="110px;"/><br /><sub>Matt Tyree</sub>](https://github.com/Tyree)<br />[📖](https://github.com/snipe/snipe-it/commits?author=Tyree "Documentation") | [<img src="https://avatars.githubusercontent.com/u/292081?v=4" width="110px;"/><br /><sub>Florent Bervas</sub>](http://spoontux.net)<br />[💻](https://github.com/snipe/snipe-it/commits?author=FlorentDotMe "Code") | [<img src="https://avatars.githubusercontent.com/u/4498077?v=4" width="110px;"/><br /><sub>Daniel Albertsen</sub>](https://ditscheri.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=dbakan "Code") | [<img src="https://avatars.githubusercontent.com/u/100710244?v=4" width="110px;"/><br /><sub>r-xyz</sub>](https://github.com/r-xyz)<br />[💻](https://github.com/snipe/snipe-it/commits?author=r-xyz "Code") | [<img src="https://avatars.githubusercontent.com/u/47491036?v=4" width="110px;"/><br /><sub>Steven Mainor</sub>](https://github.com/DrekiDegga)<br />[💻](https://github.com/snipe/snipe-it/commits?author=DrekiDegga "Code") | [<img src="https://avatars.githubusercontent.com/u/65785975?v=4" width="110px;"/><br /><sub>arne-kroeger</sub>](https://github.com/arne-kroeger)<br />[💻](https://github.com/snipe/snipe-it/commits?author=arne-kroeger "Code") |
| [<img src="https://avatars.githubusercontent.com/u/167117705?v=4" width="110px;"/><br /><sub>Glukose1</sub>](https://github.com/Glukose1)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Glukose1 "Code") | [<img src="https://avatars.githubusercontent.com/u/1197791?v=4" width="110px;"/><br /><sub>Scarzy</sub>](https://github.com/Scarzy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Scarzy "Code") | [<img src="https://avatars.githubusercontent.com/u/37372069?v=4" width="110px;"/><br /><sub>setpill</sub>](https://github.com/setpill)<br />[💻](https://github.com/snipe/snipe-it/commits?author=setpill "Code") | [<img src="https://avatars.githubusercontent.com/u/3755203?v=4" width="110px;"/><br /><sub>swift2512</sub>](https://github.com/swift2512)<br />[🐛](https://github.com/snipe/snipe-it/issues?q=author%3Aswift2512 "Bug reports") | [<img src="https://avatars.githubusercontent.com/u/6136439?v=4" width="110px;"/><br /><sub>Darren Rainey</sub>](https://darrenraineys.co.uk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=DarrenRainey "Code") | [<img src="https://avatars.githubusercontent.com/u/133033121?v=4" width="110px;"/><br /><sub>maciej-poleszczyk</sub>](https://github.com/maciej-poleszczyk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=maciej-poleszczyk "Code") | [<img src="https://avatars.githubusercontent.com/u/143394709?v=4" width="110px;"/><br /><sub>Sebastian Groß</sub>](https://github.com/sgross-emlix)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sgross-emlix "Code") |
| [<img src="https://avatars.githubusercontent.com/u/41107778?v=4" width="110px;"/><br /><sub>Anouar Touati</sub>](https://github.com/AnouarTouati)<br />[💻](https://github.com/snipe/snipe-it/commits?author=AnouarTouati "Code") | [<img src="https://avatars.githubusercontent.com/u/25596663?v=4" width="110px;"/><br /><sub>aHVzY2g</sub>](https://github.com/aHVzY2g)<br />[💻](https://github.com/snipe/snipe-it/commits?author=aHVzY2g "Code") | [<img src="https://avatars.githubusercontent.com/u/13408130?v=4" width="110px;"/><br /><sub>林博仁 Buo-ren Lin</sub>](https://brlin.me)<br />[💻](https://github.com/snipe/snipe-it/commits?author=brlin-tw "Code") |
| [<img src="https://avatars.githubusercontent.com/u/167117705?v=4" width="110px;"/><br /><sub>Glukose1</sub>](https://github.com/Glukose1)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Glukose1 "Code") | [<img src="https://avatars.githubusercontent.com/u/1197791?v=4" width="110px;"/><br /><sub>Scarzy</sub>](https://github.com/Scarzy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Scarzy "Code") | [<img src="https://avatars.githubusercontent.com/u/37372069?v=4" width="110px;"/><br /><sub>setpill</sub>](https://github.com/setpill)<br />[💻](https://github.com/snipe/snipe-it/commits?author=setpill "Code") | [<img src="https://avatars.githubusercontent.com/u/3755203?v=4" width="110px;"/><br /><sub>swift2512</sub>](https://github.com/swift2512)<br />[🐛](https://github.com/snipe/snipe-it/issues?q=author%3Aswift2512 "Bug reports") | [<img src="https://avatars.githubusercontent.com/u/6136439?v=4" width="110px;"/><br /><sub>Darren Rainey</sub>](https://darrenraineys.co.uk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=DarrenRainey "Code") | [<img src="https://avatars.githubusercontent.com/u/133033121?v=4" width="110px;"/><br /><sub>maciej-poleszczyk</sub>](https://github.com/maciej-poleszczyk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=maciej-poleszczyk "Code") |
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!

View File

@@ -73,7 +73,7 @@ RUN mkdir -p /var/www/.composer && chown apache /var/www/.composer
# Install dependencies
USER apache
RUN COMPOSER_CACHE_DIR=/dev/null composer install --working-dir=/var/www/html
RUN COMPOSER_CACHE_DIR=/dev/null composer install --no-dev --working-dir=/var/www/html
USER root

View File

@@ -427,13 +427,7 @@ class LdapSync extends Command
$user->groups()->attach($ldap_default_group);
}
//updates assets location based on user's location
if ($user->wasChanged('location_id')) {
foreach ($user->assets as $asset) {
$asset->location_id = $user->location_id;
// TODO: somehow add note? "Asset Location Changed because of thing"
$asset->save();
}
}
Asset::where('assigned_to', '=', $user->id)->where('assigned_type', '=', User::class)->update(['location_id' => $user->location_id]);
} else {
foreach ($user->getErrors()->getMessages() as $key => $err) {

View File

@@ -59,7 +59,7 @@ class ObjectImportCommand extends Command
$classString = "App\\Importer\\{$class}Importer";
$importer = new $classString($filename);
$importer->setCallbacks([$this, 'log'], [$this, 'progress'], [$this, 'errorCallback'])
->setCreatedBy($this->option('user_id'))
->setUserId($this->option('user_id'))
->setUpdating($this->option('update'))
->setShouldNotify($this->option('send-welcome'))
->setUsernameFormat($this->option('username_format'));

View File

@@ -50,12 +50,12 @@ class ResetDemoSettings extends Command
$settings->alert_email = 'service@snipe-it.io';
$settings->login_note = 'Use `admin` / `password` to login to the demo.';
$settings->header_color = null;
$settings->label2_2d_type = 'QRCODE';
$settings->barcode_type = 'QRCODE';
$settings->default_currency = 'USD';
$settings->brand = 2;
$settings->ldap_enabled = 0;
$settings->full_multiple_companies_support = 0;
$settings->label2_1d_type = 'C128';
$settings->alt_barcode = 'C128';
$settings->skin = '';
$settings->email_domain = 'snipeitapp.com';
$settings->email_format = 'filastname';
@@ -65,7 +65,7 @@ class ResetDemoSettings extends Command
$settings->thumbnail_max_h = '30';
$settings->locale = 'en-US';
$settings->version_footer = 'on';
$settings->support_footer = 'on';
$settings->support_footer = null;
$settings->saml_enabled = '0';
$settings->saml_sp_x509cert = null;
$settings->saml_idp_metadata = null;

View File

@@ -51,8 +51,6 @@ class SQLStreamer {
/* we *could* have made the ^INSERT INTO blah VALUES$ turn on the capturing state, and closed it with
a ^(blahblah);$ but it's cleaner to not have to manage the state machine. We're just going to
assume that (blahblah), or (blahblah); are values for INSERT and are always acceptable. */
"<^/\*!40101 SET NAMES '?[a-zA-Z0-9_-]+'? \*/;$>" => false, //using weird delimiters (<,>) for readability. allow quoted or unquoted charsets
"<^/\*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' \*/;$>" => false, //same, now handle zero-values
];
foreach($allowed_statements as $statement => $statechange) {
@@ -372,7 +370,7 @@ class RestoreFromBackup extends Command
if ($this->option('sanitize-guess-prefix')) {
$prefix = SQLStreamer::guess_prefix($sql_contents);
$this->line($prefix);
return $this->info("Re-run this command with '--sanitize-with-prefix=".$prefix."' to see an attempt to sanitize your SQL.");
return $this->info("Re-run this command with '--sanitize-with-prefix=".$prefix."' to see an attempt to sanitze your SQL.");
}
// If we're doing --sql-stdout-only, handle that now so we don't have to open pipes to mysql and all of that silliness

View File

@@ -72,7 +72,7 @@ class SendAcceptanceReminder extends Command
$locale = $acceptance->assignedTo?->locale;
$email = $acceptance->assignedTo?->email;
if(!$email){
$this->info($acceptance->assignedTo?->present()->fullName().' has no email address.');
$this->info($acceptance->assignedTo->present()->fullName().' has no email address.');
}
$item_count = $unacceptedAssetGroup->count();

View File

@@ -2,13 +2,13 @@
namespace App\Console\Commands;
use App\Mail\ExpiringAssetsMail;
use App\Mail\ExpiringLicenseMail;
use App\Models\Asset;
use App\Models\License;
use App\Models\Recipients\AlertRecipient;
use App\Models\Setting;
use App\Notifications\ExpiringAssetsNotification;
use App\Notifications\ExpiringLicenseNotification;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Mail;
class SendExpirationAlerts extends Command
{
@@ -47,22 +47,22 @@ class SendExpirationAlerts extends Command
if (($settings->alert_email != '') && ($settings->alerts_enabled == 1)) {
// Send a rollup to the admin, if settings dictate
$recipients = collect(explode(',', $settings->alert_email))
->map(fn($item) => trim($item)) // Trim each email
->all();
$recipients = collect(explode(',', $settings->alert_email))->map(function ($item, $key) {
return new AlertRecipient($item);
});
// Expiring Assets
$assets = Asset::getExpiringWarrantee($threshold);
if ($assets->count() > 0) {
$this->info(trans_choice('mail.assets_warrantee_alert', $assets->count(), ['count' => $assets->count(), 'threshold' => $threshold]));
Mail::to($recipients)->send(new ExpiringAssetsMail($assets, $threshold));
\Notification::send($recipients, new ExpiringAssetsNotification($assets, $threshold));
}
// Expiring licenses
$licenses = License::getExpiringLicenses($threshold);
if ($licenses->count() > 0) {
$this->info(trans_choice('mail.license_expiring_alert', $licenses->count(), ['count' => $licenses->count(), 'threshold' => $threshold]));
Mail::to($recipients)->send(new ExpiringLicenseMail($licenses, $threshold));
\Notification::send($recipients, new ExpiringLicenseNotification($licenses, $threshold));
}
} else {
if ($settings->alert_email == '') {

View File

@@ -1,28 +0,0 @@
<?php
namespace App\Events;
use App\Models\User;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class NoteAdded
{
use Dispatchable, SerializesModels;
public $itemNoteAddedOn;
public $note;
public $noteAddedBy;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct($itemNoteAddedOn, User $noteAddedBy, $note)
{
$this->itemNoteAddedOn = $itemNoteAddedOn;
$this->note = $note;
$this->noteAddedBy = $noteAddedBy;
}
}

View File

@@ -184,9 +184,7 @@ class IconHelper
return 'fa-regular fa-id-card';
case 'department' :
return 'fa-solid fa-building-user';
case 'note':
case 'notes':
return 'fas fa-sticky-note';
}
}
}

View File

@@ -31,7 +31,7 @@ class AccessoriesController extends Controller
public function index() : View
{
$this->authorize('index', Accessory::class);
return view('accessories.index');
return view('accessories/index');
}
/**
@@ -100,7 +100,7 @@ class AccessoriesController extends Controller
if ($item = Accessory::find($accessoryId)) {
$this->authorize($item);
return view('accessories.edit', compact('item'))->with('category_type', 'accessory');
return view('accessories/edit', compact('item'))->with('category_type', 'accessory');
}
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
@@ -236,7 +236,7 @@ class AccessoriesController extends Controller
$accessory = Accessory::withCount('checkouts as checkouts_count')->find($accessoryID);
$this->authorize('view', $accessory);
if (isset($accessory->id)) {
return view('accessories.view', compact('accessory'));
return view('accessories/view', compact('accessory'));
}
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist', ['id' => $accessoryID]));

View File

@@ -51,15 +51,15 @@ class AccessoriesFilesController extends Controller
}
return redirect()->route('accessories.show', $accessory->id)->withFragment('files')->with('success', trans('general.file_upload_success'));
return redirect()->route('accessories.show', $accessory->id)->with('success', trans('general.file_upload_success'));
}
return redirect()->route('accessories.show', $accessory->id)->withFragment('files')->with('error', trans('general.no_files_uploaded'));
return redirect()->route('accessories.show', $accessory->id)->with('error', trans('general.no_files_uploaded'));
}
// Prepare the error message
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
return redirect()->route('accessories.index')
->with('error', trans('general.file_does_not_exist'));
}
/**
@@ -72,27 +72,30 @@ class AccessoriesFilesController extends Controller
*/
public function destroy($accessoryId = null, $fileId = null) : RedirectResponse
{
if ($accessory = Accessory::find($accessoryId)) {
$accessory = Accessory::find($accessoryId);
// the asset is valid
if (isset($accessory->id)) {
$this->authorize('update', $accessory);
$log = Actionlog::find($fileId);
if ($log = Actionlog::find($fileId)) {
if (Storage::exists('private_uploads/accessories/'.$log->filename)) {
try {
Storage::delete('private_uploads/accessories/' . $log->filename);
$log->delete();
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
} catch (\Exception $e) {
Log::debug($e);
return redirect()->route('accessories.index')->with('error', trans('general.file_does_not_exist'));
}
// Remove the file if one exists
if (Storage::exists('accessories/'.$log->filename)) {
try {
Storage::delete('accessories/'.$log->filename);
} catch (\Exception $e) {
Log::debug($e);
}
}
return redirect()->route('accessories.show', ['accessory' => $accessory])->withFragment('files')->with('error', trans('general.log_record_not_found'));
$log->delete();
return redirect()->back()
->with('success', trans('admin/hardware/message.deletefile.success'));
}
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
// Redirect to the licence management page
return redirect()->route('accessories.index')->with('error', trans('general.file_does_not_exist'));
}
/**
@@ -122,11 +125,10 @@ class AccessoriesFilesController extends Controller
}
}
return redirect()->route('accessories.show', ['accessory' => $accessory])->withFragment('files')->with('error', trans('general.log_record_not_found'));
return redirect()->route('accessories.show', ['accessory' => $accessory])->with('error', trans('general.log_record_not_found'));
}
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
return redirect()->route('accessories.index')->with('error', trans('general.file_not_found'));
}
}

View File

@@ -75,23 +75,20 @@ class AccessoryCheckoutController extends Controller
$accessory->checkout_qty = $request->input('checkout_qty', 1);
for ($i = 0; $i < $accessory->checkout_qty; $i++) {
$accessory_checkout = new AccessoryCheckout([
AccessoryCheckout::create([
'accessory_id' => $accessory->id,
'created_at' => Carbon::now(),
'created_by' => auth()->id(),
'assigned_to' => $target->id,
'assigned_type' => $target::class,
'note' => $request->input('note'),
]);
$accessory_checkout->created_by = auth()->id();
$accessory_checkout->save();
}
event(new CheckoutableCheckedOut($accessory, $target, auth()->user(), $request->input('note')));
// Set this as user since we only allow checkout to user for this item type
$request->request->add(['checkout_to_type' => request('checkout_to_type')]);
$request->request->add(['assigned_to' => $target->id]);
$request->request->add(['assigned_user' => $target->id]);
session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => $request->get('checkout_to_type')]);

View File

@@ -40,13 +40,10 @@ class ActionlogController extends Controller
public function getStoredEula($filename) : Response | BinaryFileResponse | RedirectResponse
{
$this->authorize('view', \App\Models\Asset::class);
if (config('filesystems.default') == 's3_private') {
return redirect()->away(Storage::disk('s3_private')->temporaryUrl('private_uploads/eula-pdfs/'.$filename, now()->addMinutes(5)));
}
$file = config('app.private_uploads').'/eula-pdfs/'.$filename;
if (Storage::exists('private_uploads/eula-pdfs/'.$filename)) {
return response()->download(config('app.private_uploads').'/eula-pdfs/'.$filename);
return response()->download($file);
}
return redirect()->back()->with('error', trans('general.file_does_not_exist'));

View File

@@ -13,7 +13,6 @@ use App\Http\Transformers\SelectlistTransformer;
use App\Models\Accessory;
use App\Models\Company;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
@@ -185,33 +184,39 @@ class AccessoriesController extends Controller
/**
* Get the list of checkouts for a specific accessory
* Display the specified resource.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return | array
* @return \Illuminate\Http\Response
*/
public function checkedout(Request $request, $id)
public function checkedout($id, Request $request)
{
$this->authorize('view', Accessory::class);
$accessory = Accessory::with('lastCheckout')->findOrFail($id);
$offset = request('offset', 0);
$limit = request('limit', 50);
// Total count of all checkouts for this asset
$accessory_checkouts = $accessory->checkouts();
$accessory_checkouts = $accessory->checkouts;
$total = $accessory_checkouts->count();
// Check for search text in the request
if ($request->filled('search')) {
$accessory_checkouts = $accessory_checkouts->TextSearch($request->input('search'));
if ($total < $offset) {
$offset = 0;
}
$total = $accessory_checkouts->count();
$accessory_checkouts = $accessory_checkouts->skip($offset)->take($limit)->get();
$accessory_checkouts = $accessory->checkouts()->skip($offset)->take($limit)->get();
return (new AccessoriesTransformer)->transformCheckedoutAccessory($accessory_checkouts, $total);
if ($request->filled('search')) {
$accessory_checkouts = $accessory->checkouts()->TextSearch($request->input('search'))
->get();
$total = $accessory_checkouts->count();
}
return (new AccessoriesTransformer)->transformCheckedoutAccessory($accessory, $accessory_checkouts, $total);
}
@@ -222,7 +227,7 @@ class AccessoriesController extends Controller
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
* @param int $id
* @return \Illuminate\Http\JsonResponse
* @return \Illuminate\Http\Response
*/
public function update(ImageUploadRequest $request, $id)
{
@@ -244,7 +249,7 @@ class AccessoriesController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\JsonResponse
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
@@ -279,17 +284,14 @@ class AccessoriesController extends Controller
$accessory->checkout_qty = $request->input('checkout_qty', 1);
for ($i = 0; $i < $accessory->checkout_qty; $i++) {
$accessory_checkout = new AccessoryCheckout([
AccessoryCheckout::create([
'accessory_id' => $accessory->id,
'created_at' => Carbon::now(),
'created_by' => auth()->id(),
'assigned_to' => $target->id,
'assigned_type' => $target::class,
'note' => $request->input('note'),
]);
$accessory_checkout->created_by = auth()->id();
$accessory_checkout->save();
}
// Set this value to be able to pass the qty through to the event

View File

@@ -122,7 +122,7 @@ class AssetMaintenancesController extends Controller
* @version v1.0
* @since [v1.8]
*/
public function store(Request $request) : JsonResponse | array
public function store(Request $request) : JsonResponse
{
$this->authorize('update', Asset::class);
// create a new model instance
@@ -149,7 +149,7 @@ class AssetMaintenancesController extends Controller
* @version v1.0
* @since [v4.0]
*/
public function update(Request $request, $id) : JsonResponse | array
public function update(Request $request, $id) : JsonResponse
{
$this->authorize('update', Asset::class);
@@ -186,7 +186,7 @@ class AssetMaintenancesController extends Controller
* @version v1.0
* @since [v4.0]
*/
public function destroy($assetMaintenanceId) : JsonResponse | array
public function destroy($assetMaintenanceId) : JsonResponse
{
$this->authorize('update', Asset::class);
// Check if the asset maintenance exists
@@ -208,7 +208,7 @@ class AssetMaintenancesController extends Controller
* @version v1.0
* @since [v4.0]
*/
public function show($assetMaintenanceId) : JsonResponse | array
public function show($assetMaintenanceId) : JsonResponse
{
$this->authorize('view', Asset::class);
$assetMaintenance = AssetMaintenance::findOrFail($assetMaintenanceId);

View File

@@ -9,7 +9,6 @@ use App\Http\Controllers\Controller;
use App\Models\AssetModel;
use App\Models\Actionlog;
use App\Http\Requests\UploadFileRequest;
use App\Http\Transformers\AssetModelsTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\StreamedResponse;
@@ -69,15 +68,37 @@ class AssetModelFilesController extends Controller
/**
* List the files for an asset.
*
* @param int $assetmodel
* @param int $assetModelId
* @since [v7.0.12]
* @author [r-xyz]
*/
public function list($assetmodel_id) : JsonResponse | array
public function list($assetModelId = null) : JsonResponse
{
$assetmodel = AssetModel::with('uploads')->find($assetmodel_id);
$this->authorize('view', $assetmodel);
return (new AssetModelsTransformer)->transformAssetModelFiles($assetmodel, $assetmodel->uploads()->count());
// Start by checking if the asset being acted upon exists
if (! $assetModel = AssetModel::find($assetModelId)) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.does_not_exist')), 404);
}
// the asset is valid
if (isset($assetModel->id)) {
$this->authorize('view', $assetModel);
// Check that there are some uploads on this asset that can be listed
if ($assetModel->uploads->count() > 0) {
$files = array();
foreach ($assetModel->uploads as $upload) {
array_push($files, $upload);
}
// Give the list of files back to the user
return response()->json(Helper::formatStandardApiResponse('success', $files, trans('admin/models/message.upload.success')));
}
// There are no files.
return response()->json(Helper::formatStandardApiResponse('success', array(), trans('admin/models/message.upload.success')));
}
// Send back an error message
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.download.error')), 500);
}
/**

View File

@@ -6,7 +6,6 @@ use App\Events\CheckoutableCheckedIn;
use App\Http\Requests\StoreAssetRequest;
use App\Http\Requests\UpdateAssetRequest;
use App\Http\Traits\MigratesLegacyAssetLocations;
use App\Models\AccessoryCheckout;
use App\Models\CheckoutAcceptance;
use App\Models\LicenseSeat;
use Illuminate\Database\Eloquent\Builder;
@@ -27,9 +26,11 @@ use App\Models\License;
use App\Models\Location;
use App\Models\Setting;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Route;
use App\View\Label;
@@ -128,7 +129,6 @@ class AssetsController extends Controller
$assets = Asset::select('assets.*')
->with(
'model',
'location',
'assetstatus',
'company',
@@ -140,7 +140,7 @@ class AssetsController extends Controller
'model.manufacturer',
'model.fieldset',
'supplier'
); // it might be tempting to add 'assetlog' here, but don't. It blows up update-heavy users.
); //it might be tempting to add 'assetlog' here, but don't. It blows up update-heavy users.
if ($filter_non_deprecable_assets) {
@@ -765,13 +765,9 @@ class AssetsController extends Controller
}
if ($problems_updating_encrypted_custom_fields) {
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.update.encrypted_warning')));
// Below is the *correct* return since it uses the transformer, but we have to use the old, flat return for now until we can update Jamf2Snipe and Kanji2Snipe
// return response()->json(Helper::formatStandardApiResponse('success', (new AssetsTransformer)->transformAsset($asset), trans('admin/hardware/message.update.encrypted_warning')));
return response()->json(Helper::formatStandardApiResponse('success', (new AssetsTransformer)->transformAsset($asset), trans('admin/hardware/message.update.encrypted_warning')));
} else {
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.update.success')));
// Below is the *correct* return since it uses the transformer, but we have to use the old, flat return for now until we can update Jamf2Snipe and Kanji2Snipe
/// return response()->json(Helper::formatStandardApiResponse('success', (new AssetsTransformer)->transformAsset($asset), trans('admin/hardware/message.update.success')));
return response()->json(Helper::formatStandardApiResponse('success', (new AssetsTransformer)->transformAsset($asset), trans('admin/hardware/message.update.success')));
}
}
return response()->json(Helper::formatStandardApiResponse('error', null, $asset->getErrors()), 200);
@@ -1218,27 +1214,6 @@ class AssetsController extends Controller
return (new AssetsTransformer)->transformRequestedAssets($assets, $total);
}
public function assignedAssets(Request $request, Asset $asset) : JsonResponse | array
{
return [];
// to do
}
public function assignedAccessories(Request $request, Asset $asset) : JsonResponse | array
{
$this->authorize('view', Asset::class);
$this->authorize('view', $asset);
$accessory_checkouts = AccessoryCheckout::AssetsAssigned()->with('adminuser')->with('accessories');
$offset = ($request->input('offset') > $accessory_checkouts->count()) ? $accessory_checkouts->count() : app('api_offset_value');
$limit = app('api_limit_value');
$total = $accessory_checkouts->count();
$accessory_checkouts = $accessory_checkouts->skip($offset)->take($limit)->get();
return (new AssetsTransformer)->transformCheckedoutAccessories($accessory_checkouts, $total);
}
/**
* Generate asset labels by tag
*

View File

@@ -39,7 +39,6 @@ class CategoriesController extends Controller
'components_count',
'licenses_count',
'image',
'notes',
];
$categories = Category::select([
@@ -53,7 +52,6 @@ class CategoriesController extends Controller
'require_acceptance',
'checkin_email',
'image',
'notes',
])
->with('adminuser')
->withCount('accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'licenses as licenses_count');

View File

@@ -38,12 +38,11 @@ class CompaniesController extends Controller
'accessories_count',
'consumables_count',
'components_count',
'notes',
];
$companies = Company::withCount(['assets as assets_count' => function ($query) {
$query->AssetsForShow();
}])->withCount('licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'users as users_count');
}])->withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'users as users_count');
if ($request->filled('search')) {
$companies->TextSearch($request->input('search'));

View File

@@ -23,7 +23,7 @@ class DepartmentsController extends Controller
public function index(Request $request) : JsonResponse | array
{
$this->authorize('view', Department::class);
$allowed_columns = ['id', 'name', 'image', 'users_count', 'notes'];
$allowed_columns = ['id', 'name', 'image', 'users_count'];
$departments = Department::select(
'departments.id',
@@ -35,8 +35,7 @@ class DepartmentsController extends Controller
'departments.manager_id',
'departments.created_at',
'departments.updated_at',
'departments.image',
'departments.notes',
'departments.image'
)->with('users')->with('location')->with('manager')->with('company')->withCount('users as users_count');
if ($request->filled('search')) {
@@ -73,9 +72,6 @@ class DepartmentsController extends Controller
case 'manager':
$departments->OrderManager($order);
break;
case 'company':
$departments->OrderCompany($order);
break;
default:
$departments->orderBy($sort, $order);
break;

View File

@@ -24,7 +24,7 @@ class GroupsController extends Controller
$this->authorize('view', Group::class);
$groups = Group::select('id', 'name', 'permissions', 'notes', 'created_at', 'updated_at', 'created_by')->with('adminuser')->withCount('users as users_count');
$groups = Group::select('id', 'name', 'permissions', 'created_at', 'updated_at', 'created_by')->with('adminuser')->withCount('users as users_count');
if ($request->filled('search')) {
$groups = $groups->TextSearch($request->input('search'));
@@ -81,7 +81,6 @@ class GroupsController extends Controller
$group->name = $request->input('name');
$group->created_by = auth()->id();
$group->notes = $request->input('notes');
$group->permissions = json_encode($request->input('permissions', $groupPermissions));
if ($group->save()) {
@@ -119,7 +118,6 @@ class GroupsController extends Controller
$group = Group::findOrFail($id);
$group->name = $request->input('name');
$group->notes = $request->input('notes');
$group->permissions = $request->input('permissions'); // Todo - some JSON validation stuff here
if ($group->save()) {

View File

@@ -9,14 +9,12 @@ use App\Http\Transformers\ImportsTransformer;
use App\Models\Asset;
use App\Models\Company;
use App\Models\Import;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Database\Eloquent\JsonEncodingException;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Storage;
use League\Csv\Reader;
use Onnov\DetectEncoding\EncodingDetector;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Illuminate\Support\Facades\Log;
use Illuminate\Http\JsonResponse;
@@ -47,8 +45,6 @@ class ImportController extends Controller
$path = config('app.private_uploads').'/imports';
$results = [];
$import = new Import;
$detector = new EncodingDetector();
foreach ($files as $file) {
if (! in_array($file->getMimeType(), [
'application/vnd.ms-excel',
@@ -59,6 +55,7 @@ class ImportController extends Controller
'text/comma-separated-values',
'text/tsv', ])) {
$results['error'] = 'File type must be CSV. Uploaded file is '.$file->getMimeType();
return response()->json(Helper::formatStandardApiResponse('error', null, $results['error']), 422);
}
@@ -66,25 +63,7 @@ class ImportController extends Controller
if (! ini_get('auto_detect_line_endings')) {
ini_set('auto_detect_line_endings', '1');
}
$file_contents = $file->getContent(); //TODO - this *does* load the whole file in RAM, but we need that to be able to 'iconv' it?
$encoding = $detector->getEncoding($file_contents);
$reader = null;
if (strcasecmp($encoding, 'UTF-8') != 0) {
$transliterated = iconv($encoding, 'UTF-8', $file_contents);
if ($transliterated !== false) {
$tmpname = tempnam(sys_get_temp_dir(), '');
$tmpresults = file_put_contents($tmpname, $transliterated);
if ($tmpresults !== false) {
$transliterated = null; //save on memory?
$newfile = new UploadedFile($tmpname, $file->getClientOriginalName(), null, null, true); //WARNING: this is enabling 'test mode' - which is gross, but otherwise the file won't be treated as 'uploaded'
if ($newfile->isValid()) {
$file = $newfile;
}
}
}
}
$reader = Reader::createFromFileObject($file->openFile('r')); //file pointer leak?
$file_contents = null; //try to save on memory, I guess?
try {
$import->header_row = $reader->fetchOne(0);

View File

@@ -3,20 +3,17 @@
namespace App\Http\Controllers\Api;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Requests\ImageUploadRequest;
use App\Http\Transformers\AccessoriesTransformer;
use App\Http\Controllers\Controller;
use App\Http\Transformers\AssetsTransformer;
use App\Http\Transformers\LocationsTransformer;
use App\Http\Transformers\SelectlistTransformer;
use App\Models\Accessory;
use App\Models\AccessoryCheckout;
use App\Models\Asset;
use App\Models\Location;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
use Illuminate\Http\JsonResponse;
class LocationsController extends Controller
{
@@ -31,29 +28,26 @@ class LocationsController extends Controller
{
$this->authorize('view', Location::class);
$allowed_columns = [
'accessories_count',
'id',
'name',
'address',
'address2',
'assets_count',
'assets_count',
'assigned_accessories_count',
'assigned_assets_count',
'assigned_assets_count',
'city',
'country',
'created_at',
'currency',
'id',
'image',
'ldap_ou',
'manager_id',
'name',
'rtd_assets_count',
'state',
'updated_at',
'users_count',
'country',
'zip',
'notes',
'created_at',
'updated_at',
'manager_id',
'image',
'assigned_assets_count',
'users_count',
'assets_count',
'assigned_assets_count',
'assets_count',
'rtd_assets_count',
'currency',
'ldap_ou',
];
$locations = Location::with('parent', 'manager', 'children')->select([
@@ -74,12 +68,8 @@ class LocationsController extends Controller
'locations.image',
'locations.ldap_ou',
'locations.currency',
'locations.notes',
])
->withCount('assignedAssets as assigned_assets_count')
])->withCount('assignedAssets as assigned_assets_count')
->withCount('assets as assets_count')
->withCount('assignedAccessories as assigned_accessories_count')
->withCount('accessories as accessories_count')
->withCount('rtd_assets as rtd_assets_count')
->withCount('children as children_count')
->withCount('users as users_count');
@@ -192,7 +182,6 @@ class LocationsController extends Controller
'locations.updated_at',
'locations.image',
'locations.currency',
'locations.notes',
])
->withCount('assignedAssets as assigned_assets_count')
->withCount('assets as assets_count')
@@ -235,17 +224,7 @@ class LocationsController extends Controller
return response()->json(Helper::formatStandardApiResponse('error', null, $location->getErrors()));
}
public function assets(Request $request, Location $location) : JsonResponse | array
{
$this->authorize('view', Asset::class);
$this->authorize('view', $location);
$assets = Asset::where('location_id', '=', $location->id)->with('model', 'model.category', 'assetstatus', 'location', 'company', 'defaultLoc');
$assets = $assets->get();
return (new AssetsTransformer)->transformAssets($assets, $assets->count(), $request);
}
public function assignedAssets(Request $request, Location $location) : JsonResponse | array
{
$this->authorize('view', Asset::class);
$this->authorize('view', $location);
@@ -254,20 +233,6 @@ class LocationsController extends Controller
return (new AssetsTransformer)->transformAssets($assets, $assets->count(), $request);
}
public function assignedAccessories(Request $request, Location $location) : JsonResponse | array
{
$this->authorize('view', Accessory::class);
$this->authorize('view', $location);
$accessory_checkouts = AccessoryCheckout::LocationAssigned()->where('assigned_to', $location->id)->with('adminuser')->with('accessories');
$offset = ($request->input('offset') > $accessory_checkouts->count()) ? $accessory_checkouts->count() : app('api_offset_value');
$limit = app('api_limit_value');
$total = $accessory_checkouts->count();
$accessory_checkouts = $accessory_checkouts->skip($offset)->take($limit)->get();
return (new LocationsTransformer)->transformCheckedoutAccessories($accessory_checkouts, $total);
}
/**
* Remove the specified resource from storage.
*

View File

@@ -39,8 +39,7 @@ class ManufacturersController extends Controller
'assets_count',
'consumables_count',
'components_count',
'licenses_count',
'notes',
'licenses_count'
];
$manufacturers = Manufacturer::select([
@@ -56,7 +55,6 @@ class ManufacturersController extends Controller
'updated_at',
'image',
'deleted_at',
'notes',
])
->with('adminuser')
->withCount('assets as assets_count')

View File

@@ -1,43 +0,0 @@
<?php
namespace App\Http\Controllers\Api;
use App\Events\NoteAdded;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Models\Asset;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\Rule;
class NotesController extends Controller
{
public function store(Request $request)
{
$validated = $request->validate([
'note' => 'required|string|max:500',
'type' => [
'required',
Rule::in(['asset']),
],
]);
// This can be made dynamic by using $request->input('type') to determine which model type to add the note to.
// For now, we are only placing this on Assets
$item = Asset::findOrFail($request->input("id"));
$this->authorize('update', $item);
event(new NoteAdded($item, Auth::user(), $validated['note']));
return response()->json(Helper::formatStandardApiResponse('success'));
}
public function update(Request $request)
{
}
public function destroy(Request $request)
{
}
}

View File

@@ -20,7 +20,6 @@ use App\Models\License;
use App\Models\User;
use App\Notifications\CurrentInventory;
use Illuminate\Support\Facades\Auth;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
@@ -81,16 +80,7 @@ class UsersController extends Controller
'users.website',
])->with('manager', 'groups', 'userloc', 'company', 'department', 'assets', 'licenses', 'accessories', 'consumables', 'createdBy', 'managesUsers', 'managedLocations')
->withCount([
'assets as assets_count' => function(Builder $query) {
$query->withoutTrashed();
},
'licenses as licenses_count',
'accessories as accessories_count',
'consumables as consumables_count',
'managesUsers as manages_users_count',
'managedLocations as manages_locations_count'
]);
->withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count', 'managesUsers as manages_users_count', 'managedLocations as manages_locations_count');
if ($request->filled('search') != '') {

View File

@@ -44,10 +44,10 @@ class AssetModelsFilesController extends Controller
$model->logUpload($file_name, $request->get('notes'));
}
return redirect()->back()->withFragment('files')->with('success', trans('general.file_upload_success'));
return redirect()->back()->with('success', trans('general.file_upload_success'));
}
return redirect()->back()->withFragment('files')->with('error', trans('admin/hardware/message.upload.nofiles'));
return redirect()->back()->with('error', trans('admin/hardware/message.upload.nofiles'));
}
/**
@@ -119,10 +119,11 @@ class AssetModelsFilesController extends Controller
}
$log->delete();
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
return redirect()->back()->with('success', trans('admin/hardware/message.deletefile.success'));
}
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
return redirect()->back()
->with('success', trans('admin/hardware/message.deletefile.success'));
}
// Redirect to the hardware management page

View File

@@ -45,7 +45,7 @@ class AssetFilesController extends Controller
$asset->logUpload($file_name, $request->get('notes'));
}
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.upload.success'));
return redirect()->back()->with('success', trans('admin/hardware/message.upload.success'));
}
return redirect()->back()->with('error', trans('admin/hardware/message.upload.nofiles'));
@@ -97,19 +97,25 @@ class AssetFilesController extends Controller
*/
public function destroy($assetId = null, $fileId = null) : RedirectResponse
{
if ($asset = Asset::find($assetId)) {
$this->authorize('update', $asset);
$rel_path = 'private_uploads/assets';
$asset = Asset::find($assetId);
$this->authorize('update', $asset);
$rel_path = 'private_uploads/assets';
if ($log = Actionlog::find($fileId)) {
// the asset is valid
if (isset($asset->id)) {
$this->authorize('update', $asset);
$log = Actionlog::find($fileId);
if ($log) {
if (Storage::exists($rel_path.'/'.$log->filename)) {
Storage::delete($rel_path.'/'.$log->filename);
}
$log->delete();
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
return redirect()->back()->with('success', trans('admin/hardware/message.deletefile.success'));
}
return redirect()->route('hardware.show', ['hardware' => $asset])->with('error', trans('general.log_record_not_found'));
return redirect()->back()
->with('success', trans('admin/hardware/message.deletefile.success'));
}
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));

View File

@@ -535,10 +535,10 @@ class AssetsController extends Controller
{
$settings = Setting::getSettings();
if (($settings->qr_code == '1') && ($settings->label2_2d_type !== 'none')) {
if ($settings->qr_code == '1') {
$asset = Asset::withTrashed()->find($assetId);
if ($asset) {
$size = Helper::barcodeDimensions($settings->label2_2d_type);
$size = Helper::barcodeDimensions($settings->barcode_type);
$qr_file = public_path().'/uploads/barcodes/qr-'.str_slug($asset->asset_tag).'-'.str_slug($asset->id).'.png';
if (isset($asset->id, $asset->asset_tag)) {
@@ -548,7 +548,7 @@ class AssetsController extends Controller
return response()->file($qr_file, $header);
} else {
$barcode = new \Com\Tecnick\Barcode\Barcode();
$barcode_obj = $barcode->getBarcodeObj($settings->label2_2d_type, route('hardware.show', $asset->id), $size['height'], $size['width'], 'black', [-2, -2, -2, -2]);
$barcode_obj = $barcode->getBarcodeObj($settings->barcode_type, route('hardware.show', $asset->id), $size['height'], $size['width'], 'black', [-2, -2, -2, -2]);
file_put_contents($qr_file, $barcode_obj->getPngData());
return response($barcode_obj->getPngData())->header('Content-type', 'image/png');
@@ -573,7 +573,7 @@ class AssetsController extends Controller
{
$settings = Setting::getSettings();
if ($asset = Asset::withTrashed()->find($assetId)) {
$barcode_file = public_path().'/uploads/barcodes/'.str_slug($settings->label2_1d_type).'-'.str_slug($asset->asset_tag).'.png';
$barcode_file = public_path().'/uploads/barcodes/'.str_slug($settings->alt_barcode).'-'.str_slug($asset->asset_tag).'.png';
if (isset($asset->id, $asset->asset_tag)) {
if (file_exists($barcode_file)) {
@@ -586,7 +586,7 @@ class AssetsController extends Controller
$barcode = new \Com\Tecnick\Barcode\Barcode();
try {
$barcode_obj = $barcode->getBarcodeObj($settings->label2_1d_type, $asset->asset_tag, ($barcode_width < 300 ? $barcode_width : 300), 50);
$barcode_obj = $barcode->getBarcodeObj($settings->alt_barcode, $asset->asset_tag, ($barcode_width < 300 ? $barcode_width : 300), 50);
file_put_contents($barcode_file, $barcode_obj->getPngData());
return response($barcode_obj->getPngData())->header('Content-type', 'image/png');
@@ -865,8 +865,8 @@ class AssetsController extends Controller
public function quickScan()
{
$this->authorize('audit', Asset::class);
$settings = Setting::getSettings();
$dt = Carbon::now()->addMonths($settings->audit_interval)->toDateString();
$dt = Carbon::now()->addMonths(12)->toDateString();
return view('hardware/quickscan')->with('next_audit_date', $dt);
}
@@ -883,6 +883,7 @@ class AssetsController extends Controller
$this->authorize('audit', Asset::class);
$dt = Carbon::now()->addMonths($settings->audit_interval)->toDateString();
$asset = Asset::findOrFail($id);
return view('hardware/audit')->with('asset', $asset)->with('next_audit_date', $dt)->with('locations_list');
}

View File

@@ -50,14 +50,14 @@ class ForgotPasswordController extends Controller
*/
public function sendResetLinkEmail(Request $request)
{
/**
* Let's set a max character count here to prevent potential
* buffer overflow issues with attackers sending very large
* payloads through. The addition of the string rule prevents attackers
* sending arrays through and causing 500s
* payloads through.
*/
$request->validate([
'username' => ['required', 'max:255', 'string'],
'username' => ['required', 'max:255'],
]);
/**

View File

@@ -103,24 +103,22 @@ class ResetPasswordController extends Controller
], $messages);
}
if ($user->ldap_import != '1') {
// set the response
$response = $broker->reset(
$this->credentials($request), function ($user, $password) {
$this->resetPassword($user, $password);
});
// set the response
$response = $broker->reset(
$this->credentials($request), function ($user, $password) {
$this->resetPassword($user, $password);
});
// Check if the password reset above actually worked
if ($response == \Password::PASSWORD_RESET) {
Log::debug('Password reset for ' . $user->username . ' worked');
return redirect()->guest('login')->with('success', trans('passwords.reset'));
}
Log::debug('Password reset for ' . $user->username . ' FAILED - this user exists but the token is not valid');
return redirect()->back()->withInput($request->only('email'))->with('success', trans('passwords.reset'));
// Check if the password reset above actually worked
if ($response == \Password::PASSWORD_RESET) {
Log::debug('Password reset for '.$user->username.' worked');
return redirect()->guest('login')->with('success', trans('passwords.reset'));
}
Log::debug('Password reset for '.$user->username.' FAILED - this user exists but the token is not valid');
return redirect()->back()->withInput($request->only('email'))->with('success', trans('passwords.reset'));
}

View File

@@ -69,7 +69,6 @@ class CategoriesController extends Controller
$category->use_default_eula = $request->input('use_default_eula', '0');
$category->require_acceptance = $request->input('require_acceptance', '0');
$category->checkin_email = $request->input('checkin_email', '0');
$category->notes = $request->input('notes');
$category->created_by = auth()->id();
$category = $request->handleImages($category);
@@ -135,7 +134,6 @@ class CategoriesController extends Controller
$category->use_default_eula = $request->input('use_default_eula', '0');
$category->require_acceptance = $request->input('require_acceptance', '0');
$category->checkin_email = $request->input('checkin_email', '0');
$category->notes = $request->input('notes');
$category = $request->handleImages($category);

View File

@@ -60,7 +60,6 @@ final class CompaniesController extends Controller
$company->phone = $request->input('phone');
$company->fax = $request->input('fax');
$company->email = $request->input('email');
$company->notes = $request->input('notes');
$company->created_by = auth()->id();
$company = $request->handleImages($company);
@@ -112,7 +111,6 @@ final class CompaniesController extends Controller
$company->phone = $request->input('phone');
$company->fax = $request->input('fax');
$company->email = $request->input('email');
$company->notes = $request->input('notes');
$company = $request->handleImages($company);

View File

@@ -50,7 +50,7 @@ class ComponentsFilesController extends Controller
}
return redirect()->route('components.show', $component->id)->withFragment('files')->with('success', trans('general.file_upload_success'));
return redirect()->route('components.show', $component->id)->with('success', trans('general.file_upload_success'));
}
@@ -91,7 +91,7 @@ class ComponentsFilesController extends Controller
$log->delete();
return redirect()->back()->withFragment('files')
return redirect()->back()
->with('success', trans('admin/hardware/message.deletefile.success'));
}

View File

@@ -50,7 +50,7 @@ class ConsumablesController extends Controller
{
$this->authorize('create', Consumable::class);
return view('consumables.edit')->with('category_type', 'consumable')
return view('consumables/edit')->with('category_type', 'consumable')
->with('item', new Consumable);
}

View File

@@ -48,7 +48,7 @@ class ConsumablesFilesController extends Controller
}
return redirect()->route('consumables.show', $consumable->id)->withFragment('files')->with('success', trans('general.file_upload_success'));
return redirect()->route('consumables.show', $consumable->id)->with('success', trans('general.file_upload_success'));
}
@@ -89,7 +89,7 @@ class ConsumablesFilesController extends Controller
$log->delete();
return redirect()->back()->withFragment('files')
return redirect()->back()
->with('success', trans('admin/hardware/message.deletefile.success'));
}

View File

@@ -104,7 +104,7 @@ class CustomFieldsController extends Controller
"auto_add_to_fieldsets" => $request->get("auto_add_to_fieldsets", 0),
"show_in_listview" => $request->get("show_in_listview", 0),
"show_in_requestable_list" => $request->get("show_in_requestable_list", 0),
"created_by" => auth()->id()
"user_id" => auth()->id()
]);

View File

@@ -55,7 +55,6 @@ class DepartmentsController extends Controller
$department->manager_id = ($request->filled('manager_id') ? $request->input('manager_id') : null);
$department->location_id = ($request->filled('location_id') ? $request->input('location_id') : null);
$department->company_id = ($request->filled('company_id') ? $request->input('company_id') : null);
$department->notes = $request->input('notes');
$department = $request->handleImages($department);
if ($department->save()) {
@@ -172,7 +171,7 @@ class DepartmentsController extends Controller
$department->company_id = ($request->filled('company_id') ? $request->input('company_id') : null);
$department->phone = $request->input('phone');
$department->fax = $request->input('fax');
$department->notes = $request->input('notes');
$department = $request->handleImages($department);
if ($department->save()) {

View File

@@ -62,7 +62,6 @@ class GroupsController extends Controller
$group->name = $request->input('name');
$group->permissions = json_encode($request->input('permission'));
$group->created_by = auth()->id();
$group->notes = $request->input('notes');
if ($group->save()) {
return redirect()->route('groups.index')->with('success', trans('admin/groups/message.success.create'));
@@ -109,7 +108,6 @@ class GroupsController extends Controller
}
$group->name = $request->input('name');
$group->permissions = json_encode($request->input('permission'));
$group->notes = $request->input('notes');
if (! config('app.lock_passwords')) {
if ($group->save()) {

View File

@@ -71,7 +71,7 @@ class LicenseCheckinController extends Controller
if (! $license->reassignable) {
// Not allowed to checkin
Session::flash('error', trans('admin/licenses/message.checkin.not_reassignable') . '.');
Session::flash('error', 'License not reassignable.');
return redirect()->back()->withInput();
}

View File

@@ -78,7 +78,6 @@ class LocationsController extends Controller
$location->created_by = auth()->id();
$location->phone = request('phone');
$location->fax = request('fax');
$location->notes = $request->input('notes');
$location = $request->handleImages($location);
@@ -139,7 +138,6 @@ class LocationsController extends Controller
$location->fax = request('fax');
$location->ldap_ou = $request->input('ldap_ou');
$location->manager_id = $request->input('manager_id');
$location->notes = $request->input('notes');
$location = $request->handleImages($location);

View File

@@ -67,7 +67,6 @@ class ManufacturersController extends Controller
$manufacturer->warranty_lookup_url = $request->input('warranty_lookup_url');
$manufacturer->support_phone = $request->input('support_phone');
$manufacturer->support_email = $request->input('support_email');
$manufacturer->notes = $request->input('notes');
$manufacturer = $request->handleImages($manufacturer);
if ($manufacturer->save()) {
@@ -124,7 +123,6 @@ class ManufacturersController extends Controller
$manufacturer->warranty_lookup_url = $request->input('warranty_lookup_url');
$manufacturer->support_phone = $request->input('support_phone');
$manufacturer->support_email = $request->input('support_email');
$manufacturer->notes = $request->input('notes');
// Set the model's image property to null if the image is being deleted
if ($request->input('image_delete') == 1) {

View File

@@ -32,8 +32,7 @@ class ModalController extends Controller
'statuslabel',
'supplier',
'upload-file',
'user',
'add-note',
'user',
];

View File

@@ -99,13 +99,9 @@ class ProfileController extends Controller
* User change email page.
*
*/
public function password() : View | RedirectResponse
public function password() : View
{
$user = auth()->user();
if ($user->ldap_import=='1') {
return redirect()->route('account')->with('error', trans('admin/users/message.error.password_ldap'));
}
return view('account/change-password', compact('user'));
}
@@ -120,7 +116,7 @@ class ProfileController extends Controller
$user = auth()->user();
if ($user->ldap_import == '1') {
return redirect()->route('account')->with('error', trans('admin/users/message.error.password_ldap'));
return redirect()->route('account.password.index')->with('error', trans('admin/users/message.error.password_ldap'));
}
$rules = [

View File

@@ -1,80 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Models\CustomField;
use App\Models\ReportTemplate;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
class ReportTemplatesController extends Controller
{
public function store(Request $request): RedirectResponse
{
$this->authorize('reports.view');
// Ignore "options" rules since data does not come in under that key...
$validated = $request->validate(Arr::except((new ReportTemplate)->getRules(), 'options'));
$report = $request->user()->reportTemplates()->create([
'name' => $validated['name'],
'options' => $request->except(['_token', 'name']),
]);
session()->flash('success', trans('admin/reports/message.create.success'));
return redirect()->route('report-templates.show', $report->id);
}
public function show(ReportTemplate $reportTemplate)
{
$this->authorize('reports.view');
$customfields = CustomField::get();
$report_templates = ReportTemplate::orderBy('name')->get();
return view('reports/custom', [
'customfields' => $customfields,
'report_templates' => $report_templates,
'template' => $reportTemplate,
]);
}
public function edit(ReportTemplate $reportTemplate)
{
$this->authorize('reports.view');
return view('reports/custom', [
'customfields' => CustomField::get(),
'template' => $reportTemplate,
]);
}
public function update(Request $request, ReportTemplate $reportTemplate): RedirectResponse
{
$this->authorize('reports.view');
// Ignore "options" rules since data does not come in under that key...
$validated = $request->validate(Arr::except((new ReportTemplate)->getRules(), 'options'));
$reportTemplate->update([
'name' => $validated['name'],
'options' => $request->except(['_token', 'name']),
]);
session()->flash('success', trans('admin/reports/message.update.success'));
return redirect()->route('report-templates.show', $reportTemplate->id);
}
public function destroy(ReportTemplate $reportTemplate): RedirectResponse
{
$this->authorize('reports.view');
$reportTemplate->delete();
return redirect()->route('reports/custom')
->with('success', trans('admin/reports/message.delete.success'));
}
}

View File

@@ -11,15 +11,12 @@ use App\Models\AssetModel;
use App\Models\Category;
use App\Models\AssetMaintenance;
use App\Models\CheckoutAcceptance;
use App\Models\Company;
use App\Models\CustomField;
use App\Models\Depreciation;
use App\Models\License;
use App\Models\ReportTemplate;
use App\Models\Setting;
use App\Notifications\CheckoutAssetNotification;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Mail;
@@ -397,27 +394,12 @@ class ReportsController extends Controller
* @see ReportsController::postCustomReport() method that generates the CSV
* @since [v1.0]
*/
public function getCustomReport(Request $request) : View
public function getCustomReport() : View
{
$this->authorize('reports.view');
$customfields = CustomField::get();
$report_templates = ReportTemplate::orderBy('name')->get();
// The view needs a template to render correctly, even if it is empty...
$template = new ReportTemplate;
// Set the report's input values in the cases we were redirected back
// with validation errors so the report is populated as expected.
if ($request->old()) {
$template->name = $request->old('name');
$template->options = $request->old();
}
return view('reports/custom', [
'customfields' => $customfields,
'report_templates' => $report_templates,
'template' => $template,
]);
return view('reports/custom')->with('customfields', $customfields);
}
/**
@@ -1111,31 +1093,28 @@ class ReportsController extends Controller
$this->authorize('reports.view');
$showDeleted = $deleted == 'deleted';
$query = CheckoutAcceptance::pending()
->where('checkoutable_type', 'App\Models\Asset')
->with([
'checkoutable' => function (MorphTo $query) {
$query->morphWith([
AssetModel::class => ['model'],
Company::class => ['company'],
Asset::class => ['assignedTo'],
])->with('model.category');
},
'assignedTo' => function($query){
$query->withTrashed();
}
]);
if ($showDeleted) {
$query->withTrashed();
/**
* Get all assets with pending checkout acceptances
*/
if($showDeleted) {
$acceptances = CheckoutAcceptance::pending()->where('checkoutable_type', 'App\Models\Asset')->withTrashed()->with(['assignedTo' , 'checkoutable.assignedTo', 'checkoutable.model'])->get();
} else {
$acceptances = CheckoutAcceptance::pending()->where('checkoutable_type', 'App\Models\Asset')->with(['assignedTo' => function ($query) {
$query->withTrashed();
}, 'checkoutable.assignedTo', 'checkoutable.model'])->get();
}
$assetsForReport = $query->get()
->map(function ($acceptance) {
return [
'assetItem' => $acceptance->checkoutable,
'acceptance' => $acceptance,
];
$assetsForReport = $acceptances
->filter(function ($acceptance) {
$acceptance_checkoutable_flag = false;
if ($acceptance->checkoutable){
$acceptance_checkoutable_flag = $acceptance->checkoutable->checkedOutToUser();
}
return $acceptance->checkoutable_type == 'App\Models\Asset' && $acceptance_checkoutable_flag;
})
->map(function($acceptance) {
return ['assetItem' => $acceptance->checkoutable, 'acceptance' => $acceptance];
});
return view('reports/unaccepted_assets', compact('assetsForReport','showDeleted' ));
@@ -1177,10 +1156,10 @@ class ReportsController extends Controller
$locale = $assetItem->assignedTo?->locale;
// Only send notification if assigned
if ($locale && $email) {
Mail::to($email)->send((new CheckoutAssetMail($assetItem, $assetItem->assignedTo, $logItem->user, $acceptance, $logItem->note))->locale($locale));
Mail::to($email)->send((new CheckoutAssetMail($assetItem, $assetItem->assignedTo, $logItem->user, $logItem->note, $acceptance))->locale($locale));
} elseif ($email) {
Mail::to($email)->send((new CheckoutAssetMail($assetItem, $assetItem->assignedTo, $logItem->user, $acceptance, $logItem->note)));
Mail::to($email)->send((new CheckoutAssetMail($assetItem, $assetItem->assignedTo, $logItem->user, $logItem->note, $acceptance)));
}
if ($email == ''){

View File

@@ -192,7 +192,6 @@ class SettingsController extends Controller
$settings->next_auto_tag_base = 1;
$settings->auto_increment_assets = $request->input('auto_increment_assets', 0);
$settings->auto_increment_prefix = $request->input('auto_increment_prefix');
$settings->zerofill_count = $request->input('zerofill_count') ?: 0;
if ((! $user->isValid()) || (! $settings->isValid())) {
return redirect()->back()->withInput()->withErrors($user->getErrors())->withErrors($settings->getErrors());
@@ -696,6 +695,48 @@ class SettingsController extends Controller
return redirect()->back()->withInput()->withErrors($setting->getErrors());
}
/**
* Return a form to allow a super admin to update settings.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
*
* @since [v1.0]
*/
public function getBarcodes() : View
{
$setting = Setting::getSettings();
$is_gd_installed = extension_loaded('gd');
return view('settings.barcodes', compact('setting'))->with('is_gd_installed', $is_gd_installed);
}
/**
* Saves settings from form.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
*
* @since [v1.0]
*/
public function postBarcodes(Request $request) : RedirectResponse
{
if (is_null($setting = Setting::getSettings())) {
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
}
$setting->qr_code = $request->input('qr_code', '0');
$setting->alt_barcode = $request->input('alt_barcode');
$setting->alt_barcode_enabled = $request->input('alt_barcode_enabled', '0');
$setting->barcode_type = $request->input('barcode_type');
$setting->qr_text = $request->input('qr_text');
if ($setting->save()) {
return redirect()->route('settings.index')
->with('success', trans('admin/settings/message.update.success'));
}
return redirect()->back()->withInput()->withErrors($setting->getErrors());
}
/**
* Return a form to allow a super admin to update settings.
*
@@ -721,11 +762,8 @@ class SettingsController extends Controller
*/
public function getLabels() : View
{
$is_gd_installed = extension_loaded('gd');
return view('settings.labels')
->with('setting', Setting::getSettings())
->with('is_gd_installed', $is_gd_installed)
->with('customFields', CustomField::where('field_encrypted', '=', 0)->get());
}
@@ -761,13 +799,9 @@ class SettingsController extends Controller
$setting->labels_pagewidth = $request->input('labels_pagewidth');
$setting->labels_pageheight = $request->input('labels_pageheight');
$setting->labels_display_company_name = $request->input('labels_display_company_name', '0');
$setting->labels_display_company_name = $request->input('labels_display_company_name', '0');
//Barcodes
$setting->qr_code = $request->input('qr_code', '0');
//1D-Barcode
$setting->alt_barcode_enabled = $request->input('alt_barcode_enabled', '0');
//QR-Code
$setting->qr_text = $request->input('qr_text');
if ($request->filled('labels_display_name')) {
$setting->labels_display_name = 1;
@@ -800,7 +834,6 @@ class SettingsController extends Controller
}
if ($setting->save()) {
return redirect()->route('settings.labels.index')
->with('success', trans('admin/settings/message.update.success'));
}
@@ -870,6 +903,7 @@ class SettingsController extends Controller
}
if ($setting->save()) {
$setting->update_client_side_cert_files();
return redirect()->route('settings.ldap.index')
->with('success', trans('admin/settings/message.update.success'));
}

View File

@@ -70,7 +70,7 @@ class BulkUsersController extends Controller
// bulk password reset, just do the thing
} elseif ($request->input('bulk_actions') == 'bulkpasswordreset') {
foreach ($users as $user) {
if (($user->activated == '1') && ($user->email != '') && ($user->ldap_import != '1')) {
if (($user->activated == '1') && ($user->email != '')) {
$credentials = ['email' => $user->email];
Password::sendResetLink($credentials/* , function (Message $message) {
$message->subject($this->getEmailSubject()); // TODO - I'm not sure if we still need this, but this second parameter is no longer accepted in later Laravel versions.

View File

@@ -56,7 +56,7 @@ class UserFilesController extends Controller
$logActions[] = $logAction;
}
// dd($logActions);
return redirect()->back()->withFragment('files')->with('success', trans('admin/users/message.upload.success'));
return redirect()->back()->with('success', trans('admin/users/message.upload.success'));
}
return redirect()->back()->with('error', trans('admin/users/message.upload.nofiles'));
@@ -87,7 +87,7 @@ class UserFilesController extends Controller
if (Storage::exists($rel_path.'/'.$filename)) {
Storage::delete($rel_path.'/'.$filename);
return redirect()->back()->withFragment('files')->with('success', trans('admin/users/message.deletefile.success'));
return redirect()->back()->with('success', trans('admin/users/message.deletefile.success'));
}
}

View File

@@ -24,9 +24,9 @@ class AssetCheckoutRequest extends Request
$settings = \App\Models\Setting::getSettings();
$rules = [
'assigned_user' => 'numeric|nullable|required_without_all:assigned_asset,assigned_location',
'assigned_asset' => 'numeric|nullable|required_without_all:assigned_user,assigned_location',
'assigned_location' => 'numeric|nullable|required_without_all:assigned_user,assigned_asset',
'assigned_user' => 'required_without_all:assigned_asset,assigned_location',
'assigned_asset' => 'required_without_all:assigned_user,assigned_location',
'assigned_location' => 'required_without_all:assigned_user,assigned_asset',
'status_id' => 'exists:status_labels,id,deployable,1',
'checkout_to_type' => 'required|in:asset,location,user',
'checkout_at' => [

View File

@@ -7,6 +7,7 @@ use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
use App\Rules\UserCannotSwitchCompaniesIfItemsAssigned;
use Illuminate\Support\Facades\Gate;
class SaveUserRequest extends FormRequest
{
@@ -17,7 +18,7 @@ class SaveUserRequest extends FormRequest
*/
public function authorize()
{
return true;
return (Gate::allows('users.create') || Gate::allows('users.edit'));
}
public function response(array $errors)
@@ -35,7 +36,8 @@ class SaveUserRequest extends FormRequest
$rules = [
'department_id' => 'nullable|exists:departments,id',
'manager_id' => 'nullable|exists:users,id',
'company_id' => ['nullable','exists:companies,id']
'company_id' => ['nullable','exists:companies,id'],
'groups' => ['nullable','exists:permission_groups,id']
];
switch ($this->method()) {

View File

@@ -62,7 +62,7 @@ class SettingsSamlRequest extends FormRequest
$custom_privateKey = '';
$custom_x509certNew = '';
if (! empty($this->input('saml_custom_settings'))) {
$req_custom_settings = preg_split('/\r\n|\r|\n/', $this->input('saml_custom_settings', ''));
$req_custom_settings = preg_split('/\r\n|\r|\n/', $this->input('saml_custom_settings'));
$custom_settings = [];
foreach ($req_custom_settings as $custom_setting) {

View File

@@ -2,11 +2,8 @@
namespace App\Http\Requests;
use App\Models\Labels\Label;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Gate;
use Illuminate\Validation\Rule;
class StoreLabelSettings extends FormRequest
{
@@ -25,10 +22,6 @@ class StoreLabelSettings extends FormRequest
*/
public function rules(): array
{
$names = Label::find()?->map(function ($label) {
return $label->getName();
})->values()->toArray();
return [
'labels_per_page' => 'numeric',
'labels_width' => 'numeric',
@@ -43,10 +36,6 @@ class StoreLabelSettings extends FormRequest
'labels_pagewidth' => 'numeric|nullable',
'labels_pageheight' => 'numeric|nullable',
'qr_text' => 'max:31|nullable',
'label2_template' => [
'required',
Rule::in($names),
],
];
}
}

View File

@@ -46,6 +46,8 @@ class UploadFileRequest extends Request
$extension = $file->getClientOriginalExtension();
$file_name = $name_prefix.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$file->guessExtension();
Log::debug("Your filetype IS: ".$file->getMimeType());
// Check for SVG and sanitize it
if ($file->getMimeType() === 'image/svg+xml') {
Log::debug('This is an SVG');
@@ -64,6 +66,7 @@ class UploadFileRequest extends Request
} else {
$put_results = Storage::put($dirname.$file_name, file_get_contents($file));
Log::debug("Here are the '$put_results' (should be 0 or 1 or true or false or something?)");
}
return $file_name;
}

View File

@@ -69,7 +69,7 @@ class AccessoriesTransformer
return $array;
}
public function transformCheckedoutAccessory($accessory_checkouts, $total)
public function transformCheckedoutAccessory($accessory, $accessory_checkouts, $total)
{
$array = [];
@@ -77,13 +77,9 @@ class AccessoriesTransformer
$array[] = [
'id' => $checkout->id,
'assigned_to' => $this->transformAssignedTo($checkout),
'note' => $checkout->note ? e($checkout->note) : null,
'created_by' => $checkout->adminuser ? [
'id' => (int) $checkout->adminuser->id,
'name'=> e($checkout->adminuser->present()->fullName),
]: null,
'created_at' => Helper::getFormattedDateObject($checkout->created_at, 'datetime'),
'available_actions' => Gate::allows('checkout', Accessory::class) ? ['checkin' => true] : ['checkin' => false],
'checkout_notes' => e($checkout->note),
'last_checkout' => Helper::getFormattedDateObject($checkout->created_at, 'datetime'),
'available_actions' => ['checkin' => true],
];
}
@@ -93,11 +89,22 @@ class AccessoriesTransformer
public function transformAssignedTo($accessoryCheckout)
{
if ($accessoryCheckout->checkedOutToUser()) {
return (new UsersTransformer)->transformUserCompact($accessoryCheckout->assigned);
} elseif ($accessoryCheckout->checkedOutToLocation()) {
return (new LocationsTransformer())->transformLocationCompact($accessoryCheckout->assigned);
} elseif ($accessoryCheckout->checkedOutToAsset()) {
return (new AssetsTransformer())->transformAssetCompact($accessoryCheckout->assigned);
return [
'id' => (int) $accessoryCheckout->assigned->id,
'username' => e($accessoryCheckout->assigned->username),
'name' => e($accessoryCheckout->assigned->getFullNameAttribute()),
'first_name'=> e($accessoryCheckout->assigned->first_name),
'last_name'=> ($accessoryCheckout->assigned->last_name) ? e($accessoryCheckout->assigned->last_name) : null,
'email'=> ($accessoryCheckout->assigned->email) ? e($accessoryCheckout->assigned->email) : null,
'employee_number' => ($accessoryCheckout->assigned->employee_num) ? e($accessoryCheckout->assigned->employee_num) : null,
'type' => 'user',
];
}
return $accessoryCheckout->assigned ? [
'id' => $accessoryCheckout->assigned->id,
'name' => e($accessoryCheckout->assigned->display_name),
'type' => $accessoryCheckout->assignedType(),
] : null;
}
}

View File

@@ -29,15 +29,14 @@ class AssetMaintenancesTransformer
'name'=> ($assetmaintenance->asset->name) ? e($assetmaintenance->asset->name) : null,
'asset_tag'=> e($assetmaintenance->asset->asset_tag),
'serial'=> e($assetmaintenance->asset->serial),
'deleted_at'=> Helper::getFormattedDateObject($assetmaintenance->asset->deleted_at, 'datetime'),
'created_at' => Helper::getFormattedDateObject($assetmaintenance->asset->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($assetmaintenance->asset->updated_at, 'datetime'),
'deleted_at'=> e($assetmaintenance->asset->deleted_at),
'created_at'=> e($assetmaintenance->asset->created_at),
] : null,
'model' => (($assetmaintenance->asset) && ($assetmaintenance->asset->model)) ? [
'id' => (int) $assetmaintenance->asset->model->id,
'name'=> ($assetmaintenance->asset->model->name) ? e($assetmaintenance->asset->model->name).' '.e($assetmaintenance->asset->model->model_number) : null,
] : null,
'status_label' => (($assetmaintenance->asset) && ($assetmaintenance->asset->assetstatus)) ? [
'status_label' => ($assetmaintenance->asset->assetstatus) ? [
'id' => (int) $assetmaintenance->asset->assetstatus->id,
'name'=> e($assetmaintenance->asset->assetstatus->name),
'status_type'=> e($assetmaintenance->asset->assetstatus->getStatuslabelType()),
@@ -80,7 +79,7 @@ class AssetMaintenancesTransformer
];
$permissions_array['available_actions'] = [
'update' => (Gate::allows('update', Asset::class) && ((($assetmaintenance->asset) && $assetmaintenance->asset->deleted_at==''))) ? true : false,
'update' => (Gate::allows('update', Asset::class) && ($assetmaintenance->asset->deleted_at=='')) ? true : false,
'delete' => Gate::allows('delete', Asset::class),
];

View File

@@ -87,41 +87,6 @@ class AssetModelsTransformer
return $array;
}
public function transformAssetModelFiles($assetmodel, $total)
{
$array = [];
foreach ($assetmodel->uploads as $file) {
$array[] = self::transformAssetModelFile($file, $assetmodel);
}
return (new DatatablesTransformer)->transformDatatables($array, $total);
}
public function transformAssetModelFile($file, $assetmodel)
{
$array = [
'id' => (int) $file->id,
'filename' => e($file->filename),
'url' => route('show/modelfile', [$assetmodel->id, $file->id]),
'created_by' => ($file->adminuser) ? [
'id' => (int) $file->adminuser->id,
'name'=> e($file->adminuser->present()->fullName),
] : null,
'created_at' => Helper::getFormattedDateObject($file->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($file->updated_at, 'datetime'),
'deleted_at' => Helper::getFormattedDateObject($file->deleted_at, 'datetime'),
];
$permissions_array['available_actions'] = [
'delete' => (Gate::allows('update', AssetModel::class) && ($assetmodel->deleted_at == '')),
];
$array += $permissions_array;
return $array;
}
public function transformAssetModelsDatatable($assetmodels)
{
return (new DatatablesTransformer)->transformDatatables($assetmodels);

View File

@@ -3,14 +3,12 @@
namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\Accessory;
use App\Models\AccessoryCheckout;
use App\Models\Asset;
use App\Models\Setting;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
use Carbon\Carbon;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Auth;
class AssetsTransformer
{
@@ -227,7 +225,7 @@ class AssetsTransformer
public function transformRequestedAsset(Asset $asset)
{
$array = [
'id' => (int)$asset->id,
'id' => (int) $asset->id,
'name' => e($asset->name),
'asset_tag' => e($asset->asset_tag),
'serial' => e($asset->serial),
@@ -236,7 +234,7 @@ class AssetsTransformer
'model_number' => (($asset->model) && ($asset->model->model_number)) ? e($asset->model->model_number) : null,
'expected_checkin' => Helper::getFormattedDateObject($asset->expected_checkin, 'date'),
'location' => ($asset->location) ? e($asset->location->name) : null,
'status' => ($asset->assetstatus) ? $asset->present()->statusMeta : null,
'status'=> ($asset->assetstatus) ? $asset->present()->statusMeta : null,
'assigned_to_self' => ($asset->assigned_to == auth()->id()),
];
@@ -246,7 +244,7 @@ class AssetsTransformer
foreach ($asset->model->fieldset->fields as $field) {
// Only display this if it's allowed via the custom field setting
if (($field->field_encrypted == '0') && ($field->show_in_requestable_list == '1')) {
if (($field->field_encrypted=='0') && ($field->show_in_requestable_list=='1')) {
$value = $asset->{$field->db_column};
if (($field->format == 'DATE') && (!is_null($value)) && ($value != '')) {
@@ -270,61 +268,7 @@ class AssetsTransformer
$array += $permissions_array;
return $array;
}
public function transformAssetCompact(Asset $asset)
{
$array = [
'id' => (int) $asset->id,
'image' => ($asset->getImageUrl()) ? $asset->getImageUrl() : null,
'type' => 'asset',
'name' => e($asset->present()->fullName()),
'model' => ($asset->model) ? e($asset->model->name) : null,
'model_number' => (($asset->model) && ($asset->model->model_number)) ? e($asset->model->model_number) : null,
'asset_tag' => e($asset->asset_tag),
'serial' => e($asset->serial),
];
return $array;
}
public function transformCheckedoutAccessories($accessory_checkouts, $total)
{
$array = [];
foreach ($accessory_checkouts as $checkout) {
$array[] = self::transformCheckedoutAccessory($checkout);
}
return (new DatatablesTransformer)->transformDatatables($array, $total);
}
public function transformCheckedoutAccessory(AccessoryCheckout $accessory_checkout)
{
$array = [
'id' => $accessory_checkout->id,
'accessory' => [
'id' => $accessory_checkout->accessory->id,
'name' => $accessory_checkout->accessory->name,
],
'image' => ($accessory_checkout->accessory->image) ? Storage::disk('public')->url('accessories/'.e($accessory_checkout->accessory->image)) : null,
'note' => $accessory_checkout->note ? e($accessory_checkout->note) : null,
'created_by' => $accessory_checkout->adminuser ? [
'id' => (int) $accessory_checkout->adminuser->id,
'name'=> e($accessory_checkout->adminuser->present()->fullName),
]: null,
'created_at' => Helper::getFormattedDateObject($accessory_checkout->created_at, 'datetime'),
];
$permissions_array['available_actions'] = [
'checkout' => false,
'checkin' => Gate::allows('checkin', Accessory::class),
];
$array += $permissions_array;
return $array;
}
}

View File

@@ -66,7 +66,6 @@ class CategoriesTransformer
'id' => (int) $category->adminuser->id,
'name'=> e($category->adminuser->present()->fullName()),
] : null,
'notes' => Helper::parseEscapedMarkedownInline($category->notes),
'created_at' => Helper::getFormattedDateObject($category->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($category->updated_at, 'datetime'),
];

View File

@@ -40,7 +40,6 @@ class CompaniesTransformer
'id' => (int) $company->adminuser->id,
'name'=> e($company->adminuser->present()->fullName()),
] : null,
'notes' => Helper::parseEscapedMarkedownInline($company->notes),
'created_at' => Helper::getFormattedDateObject($company->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($company->updated_at, 'datetime'),
];

View File

@@ -44,7 +44,6 @@ class DepartmentsTransformer
'name' => e($department->location->name),
] : null,
'users_count' => e($department->users_count),
'notes' => Helper::parseEscapedMarkedownInline($department->notes),
'created_at' => Helper::getFormattedDateObject($department->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($department->updated_at, 'datetime'),
];

View File

@@ -61,7 +61,7 @@ class DepreciationReportTransformer
/**
* Override the previously set null values if there is a valid model and associated depreciation
*/
if (($asset->model) && ($asset->model->depreciation) && ($asset->model->depreciation->months !== 0)) {
if (($asset->model) && ($asset->model->depreciation)) {
$depreciated_value = Helper::formatCurrencyOutput($asset->getDepreciatedValue());
$monthly_depreciation =Helper::formatCurrencyOutput($asset->purchase_cost / $asset->model->depreciation->months);
$diff = Helper::formatCurrencyOutput(($asset->purchase_cost - $asset->getDepreciatedValue()));

View File

@@ -26,7 +26,6 @@ class GroupsTransformer
'name' => e($group->name),
'permissions' => json_decode($group->permissions),
'users_count' => (int) $group->users_count,
'notes' => Helper::parseEscapedMarkedownInline($group->notes),
'created_by' => ($group->adminuser) ? [
'id' => (int) $group->adminuser->id,
'name'=> e($group->adminuser->present()->fullName()),

View File

@@ -3,8 +3,6 @@
namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\Accessory;
use App\Models\AccessoryCheckout;
use App\Models\Location;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
@@ -47,15 +45,12 @@ class LocationsTransformer
'zip' => ($location->zip) ? e($location->zip) : null,
'phone' => ($location->phone!='') ? e($location->phone): null,
'fax' => ($location->fax!='') ? e($location->fax): null,
'accessories_count' => (int) $location->accessories_count,
'assigned_accessories_count' => (int) $location->assigned_accessories_count,
'assigned_assets_count' => (int) $location->assigned_assets_count,
'assets_count' => (int) $location->assets_count,
'rtd_assets_count' => (int) $location->rtd_assets_count,
'users_count' => (int) $location->users_count,
'currency' => ($location->currency) ? e($location->currency) : null,
'ldap_ou' => ($location->ldap_ou) ? e($location->ldap_ou) : null,
'notes' => Helper::parseEscapedMarkedownInline($location->notes),
'created_at' => Helper::getFormattedDateObject($location->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($location->updated_at, 'datetime'),
'parent' => ($location->parent) ? [
@@ -81,75 +76,4 @@ class LocationsTransformer
return $array;
}
}
public function transformCheckedoutAccessories($accessory_checkouts, $total)
{
$array = [];
foreach ($accessory_checkouts as $checkout) {
$array[] = self::transformCheckedoutAccessory($checkout);
}
return (new DatatablesTransformer)->transformDatatables($array, $total);
}
public function transformCheckedoutAccessory(AccessoryCheckout $accessory_checkout)
{
$array = [
'id' => $accessory_checkout->id,
'accessory' => [
'id' => $accessory_checkout->accessory->id,
'name' => $accessory_checkout->accessory->name,
],
'image' => ($accessory_checkout->accessory->image) ? Storage::disk('public')->url('accessories/'.e($accessory_checkout->accessory->image)) : null,
'note' => $accessory_checkout->note ? e($accessory_checkout->note) : null,
'created_by' => $accessory_checkout->adminuser ? [
'id' => (int) $accessory_checkout->adminuser->id,
'name'=> e($accessory_checkout->adminuser->present()->fullName),
]: null,
'created_at' => Helper::getFormattedDateObject($accessory_checkout->created_at, 'datetime'),
];
$permissions_array['available_actions'] = [
'checkout' => false,
'checkin' => Gate::allows('checkin', Accessory::class),
];
$array += $permissions_array;
return $array;
}
/**
* This gives a compact view of the location data without any additional relational queries,
* allowing us to 1) deliver a smaller payload and 2) avoid additional queries on relations that
* have not been easy/lazy loaded already
*
* @param Location $location
* @return array
* @throws \Exception
*/
public function transformLocationCompact(Location $location = null)
{
if ($location) {
$array = [
'id' => (int) $location->id,
'image' => ($location->image) ? Storage::disk('public')->url('locations/'.e($location->image)) : null,
'type' => "location",
'name' => e($location->name),
'created_by' => $location->adminuser ? [
'id' => (int) $location->adminuser->id,
'name'=> e($location->adminuser->present()->fullName),
]: null,
'created_at' => Helper::getFormattedDateObject($location->created_at, 'datetime'),
];
return $array;
}
}
}
}

View File

@@ -37,7 +37,6 @@ class ManufacturersTransformer
'consumables_count' => (int) $manufacturer->consumables_count,
'accessories_count' => (int) $manufacturer->accessories_count,
'components_count' => (int) $manufacturer->components_count,
'notes' => Helper::parseEscapedMarkedownInline($manufacturer->notes),
'created_by' => ($manufacturer->adminuser) ? [
'id' => (int) $manufacturer->adminuser->id,
'name'=> e($manufacturer->adminuser->present()->fullName()),

View File

@@ -3,7 +3,6 @@
namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\Asset;
use App\Models\PredefinedKit;
use App\Models\SnipeModel;
use Illuminate\Support\Facades\Gate;
@@ -43,7 +42,7 @@ class PredefinedKitsTransformer
$permissions_array['available_actions'] = [
'update' => Gate::allows('update', PredefinedKit::class),
'delete' => Gate::allows('delete', PredefinedKit::class),
'checkout' => Gate::allows('checkout', Asset::class),
'checkout' => Gate::allows('checkout', PredefinedKit::class),
// 'clone' => Gate::allows('create', PredefinedKit::class),
// 'restore' => Gate::allows('create', PredefinedKit::class),
];

View File

@@ -4,8 +4,8 @@ namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\User;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
class UsersTransformer
{
@@ -106,37 +106,6 @@ class UsersTransformer
return $array;
}
/**
* This gives a compact view of the user data without any additional relational queries,
* allowing us to 1) deliver a smaller payload and 2) avoid additional queries on relations that
* have not been easy/lazy loaded already
*
* @param User $user
* @return array
* @throws \Exception
*/
public function transformUserCompact(User $user) : array
{
$array = [
'id' => (int) $user->id,
'image' => e($user->present()->gravatar) ?? null,
'type' => 'user',
'name' => e($user->getFullNameAttribute()),
'first_name' => e($user->first_name),
'last_name' => e($user->last_name),
'username' => e($user->username),
'created_by' => $user->adminuser ? [
'id' => (int) $user->adminuser->id,
'name'=> e($user->adminuser->present()->fullName),
]: null,
'created_at' => Helper::getFormattedDateObject($user->created_at, 'datetime'),
'deleted_at' => ($user->deleted_at) ? Helper::getFormattedDateObject($user->deleted_at, 'datetime') : null,
];
return $array;
}
public function transformUsersDatatable($users)
{
return (new DatatablesTransformer)->transformDatatables($users);

View File

@@ -39,7 +39,6 @@ abstract class Importer
* @var array
*/
private $defaultFieldMap = [
'id' => 'id',
'asset_tag' => 'asset tag',
'activated' => 'activated',
'category' => 'category',

View File

@@ -456,13 +456,14 @@ class ItemImporter extends Importer
{
if (empty($asset_location)) {
$this->log('No location given, so none created.');
return null;
}
$location = Location::where(['name' => $asset_location])->first();
if ($location) {
$this->log('Location '.$asset_location.' already exists');
return $location->id;
}
// No matching locations in the collection, create a new one.

View File

@@ -38,16 +38,8 @@ class LocationImporter extends ItemImporter
{
$editingLocation = false;
$location = Location::where('name', '=', $this->findCsvMatch($row, 'name'))->first();
if ($this->findCsvMatch($row, 'id')!='') {
// Override location if an ID was given
\Log::debug('Finding location by ID: '.$this->findCsvMatch($row, 'id'));
$location = Location::find($this->findCsvMatch($row, 'id'));
}
if ($location) {
if (! $this->updating) {
$this->log('A matching Location '.$this->item['name'].' already exists');
@@ -74,8 +66,6 @@ class LocationImporter extends ItemImporter
$this->item['ldap_ou'] = trim($this->findCsvMatch($row, 'ldap_ou'));
$this->item['manager'] = trim($this->findCsvMatch($row, 'manager'));
$this->item['manager_username'] = trim($this->findCsvMatch($row, 'manager_username'));
$this->item['notes'] = trim($this->findCsvMatch($row, 'notes'));
if ($this->findCsvMatch($row, 'parent_location')) {
$this->item['parent_id'] = $this->createOrFetchLocation(trim($this->findCsvMatch($row, 'parent_location')));
@@ -105,7 +95,6 @@ class LocationImporter extends ItemImporter
} else {
Log::debug($location->getErrors());
$this->logError($location, 'Location "'.$this->item['name'].'"');
return $location->errors;
}

View File

@@ -46,7 +46,7 @@ class CheckoutableListener
*/
public function onCheckedOut($event)
{
if ($this->shouldNotSendAnyNotifications($event->checkoutable)) {
if ($this->shouldNotSendAnyNotifications($event->checkoutable)){
return;
}
@@ -57,7 +57,7 @@ class CheckoutableListener
$acceptance = $this->getCheckoutAcceptance($event);
$adminCcEmailsArray = [];
if ($settings->admin_cc_email !== '') {
if($settings->admin_cc_email !== '') {
$adminCcEmail = $settings->admin_cc_email;
$adminCcEmailsArray = array_map('trim', explode(',', $adminCcEmail));
}
@@ -65,7 +65,7 @@ class CheckoutableListener
$mailable = $this->getCheckoutMailType($event, $acceptance);
$notifiable = $this->getNotifiables($event);
if ($event->checkedOutTo->locale) {
if (!$event->checkedOutTo->locale){
$mailable->locale($event->checkedOutTo->locale);
}
// Send email notifications
@@ -77,56 +77,41 @@ class CheckoutableListener
* 3. The item should send an email at check-in/check-out
*/
if ($event->checkoutable->requireAcceptance() || $event->checkoutable->getEula() ||
$this->checkoutableShouldSendEmail($event)) {
Log::info('Sending checkout email, Locale: ' . ($event->checkedOutTo->locale ?? 'default'));
if (!empty($notifiable)) {
Mail::to($notifiable)->cc($ccEmails)->send($mailable);
} elseif (!empty($ccEmails)) {
Mail::cc($ccEmails)->send($mailable);
if ($event->checkoutable->requireAcceptance() || $event->checkoutable->getEula() ||
$this->checkoutableShouldSendEmail($event)) {
Log::info('Sending checkout email, Locale: ' . ($event->checkedOutTo->locale ?? 'default'));
if (!empty($notifiable)) {
Mail::to($notifiable)->cc($ccEmails)->send($mailable);
} elseif (!empty($ccEmails)) {
Mail::cc($ccEmails)->send($mailable);
}
Log::info('Checkout Mail sent.');
}
Log::info('Checkout Mail sent.');
}
} catch (ClientException $e) {
Log::debug("Exception caught during checkout email: " . $e->getMessage());
} catch (Exception $e) {
Log::debug("Exception caught during checkout email: " . $e->getMessage());
}
// Send Webhook notification
try {
if ($this->shouldSendWebhookNotification()) {
if ($this->newMicrosoftTeamsWebhookEnabled()) {
$message = $this->getCheckoutNotification($event)->toMicrosoftTeams();
$notification = new TeamsNotification(Setting::getSettings()->webhook_endpoint);
$notification->success()->sendMessage($message[0], $message[1]); // Send the message to Microsoft Teams
} else {
Notification::route($this->webhookSelected(), Setting::getSettings()->webhook_endpoint)
->notify($this->getCheckoutNotification($event, $acceptance));
try{
if ($this->shouldSendWebhookNotification()) {
if ($this->newMicrosoftTeamsWebhookEnabled()) {
$message = $this->getCheckoutNotification($event)->toMicrosoftTeams();
$notification = new TeamsNotification(Setting::getSettings()->webhook_endpoint);
$notification->success()->sendMessage($message[0], $message[1]); // Send the message to Microsoft Teams
} else {
Notification::route($this->webhookSelected(), Setting::getSettings()->webhook_endpoint)
->notify($this->getCheckoutNotification($event, $acceptance));
}
}
}
} catch (ClientException $e) {
if (strpos($e->getMessage(), 'channel_not_found') !== false) {
Log::warning(Setting::getSettings()->webhook_selected." notification failed: " . $e->getMessage());
return redirect()->back()->with('warning', ucfirst(Setting::getSettings()->webhook_selected) .trans('admin/settings/message.webhook.webhook_channel_not_found') );
}
else {
Log::error("ClientException caught during checkin notification: " . $e->getMessage());
}
return redirect()->back()->with('warning', ucfirst(Setting::getSettings()->webhook_selected) .trans('admin/settings/message.webhook.webhook_fail') );
Log::debug("Exception caught during checkout notification: " . $e->getMessage());
} catch (Exception $e) {
Log::error(ucfirst(Setting::getSettings()->webhook_selected) . ' webhook notification failed:', [
'error' => $e->getMessage(),
'webhook_endpoint' => Setting::getSettings()->webhook_endpoint,
'event' => $event,
]);
return redirect()->back()->with('warning', ucfirst(Setting::getSettings()->webhook_selected) . trans('admin/settings/message.webhook.webhook_fail'));
Log::debug("Exception caught during checkout notification: " . $e->getMessage());
}
}
/**
* Notify the user and post to webhook about the checked in checkoutable
*/
@@ -162,7 +147,7 @@ class CheckoutableListener
$ccEmails = array_filter($adminCcEmailsArray);
$mailable = $this->getCheckinMailType($event);
$notifiable = $this->getNotifiables($event);
if ($event->checkedOutTo?->locale) {
if (!$event->checkedOutTo->locale){
$mailable->locale($event->checkedOutTo->locale);
}
// Send email notifications
@@ -193,30 +178,18 @@ class CheckoutableListener
try {
if ($this->shouldSendWebhookNotification()) {
if ($this->newMicrosoftTeamsWebhookEnabled()) {
$message = $this->getCheckinNotification($event)->toMicrosoftTeams();
$notification = new TeamsNotification(Setting::getSettings()->webhook_endpoint);
$notification->success()->sendMessage($message[0], $message[1]); // Send the message to Microsoft Teams
} else {
Notification::route($this->webhookSelected(), Setting::getSettings()->webhook_endpoint)
->notify($this->getCheckinNotification($event));
$message = $this->getCheckinNotification($event)->toMicrosoftTeams();
$notification = new TeamsNotification(Setting::getSettings()->webhook_endpoint);
$notification->success()->sendMessage($message[0], $message[1]); // Send the message to Microsoft Teams
} else {
Notification::route($this->webhookSelected(), Setting::getSettings()->webhook_endpoint)
->notify($this->getCheckinNotification($event));
}
}
}
} catch (ClientException $e) {
if (strpos($e->getMessage(), 'channel_not_found') !== false) {
Log::warning(Setting::getSettings()->webhook_selected." notification failed: " . $e->getMessage());
return redirect()->back()->with('warning', ucfirst(Setting::getSettings()->webhook_selected) .trans('admin/settings/message.webhook.webhook_channel_not_found') );
}
else {
Log::error("ClientException caught during checkin notification: " . $e->getMessage());
return redirect()->back()->with('warning', ucfirst(Setting::getSettings()->webhook_selected) . trans('admin/settings/message.webhook.webhook_fail'));
}
Log::warning("Exception caught during checkin notification: " . $e->getMessage());
} catch (Exception $e) {
Log::error(ucfirst(Setting::getSettings()->webhook_selected) . ' webhook notification failed:', [
'error' => $e->getMessage(),
'webhook_endpoint' => Setting::getSettings()->webhook_endpoint,
'event' => $event,
]);
return redirect()->back()->with('warning', ucfirst(Setting::getSettings()->webhook_selected) .trans('admin/settings/message.webhook.webhook_fail'));
Log::warning("Exception caught during checkin notification: " . $e->getMessage());
}
}
@@ -309,7 +282,7 @@ class CheckoutableListener
];
$mailable= $lookup[get_class($event->checkoutable)];
return new $mailable($event->checkoutable, $event->checkedOutTo, $event->checkedOutBy, $acceptance, $event->note);
return new $mailable($event->checkoutable, $event->checkedOutTo, $event->checkedOutBy, $event->note, $acceptance);
}
private function getCheckinMailType($event){

View File

@@ -17,7 +17,6 @@ use App\Events\ItemAccepted;
use App\Events\ItemDeclined;
use App\Events\LicenseCheckedIn;
use App\Events\LicenseCheckedOut;
use App\Events\NoteAdded;
use App\Models\Actionlog;
use App\Models\User;
use App\Models\LicenseSeat;
@@ -129,23 +128,6 @@ class LogListener
}
/**
* Note is added to action log
*
*/
public function onNoteAdded(NoteAdded $event)
{
$logaction = new Actionlog();
$logaction->item_id = $event->itemNoteAddedOn->id;
$logaction->item_type = get_class($event->itemNoteAddedOn);
$logaction->note = $event->note; //this is the received alphanumeric text from the box
$logaction->created_by = $event->noteAddedBy->id;
$logaction->action_type = 'note_added';
$logaction->save();
}
/**
* Register the listeners for the subscriber.
*
@@ -159,7 +141,6 @@ class LogListener
'CheckoutAccepted',
'CheckoutDeclined',
'UserMerged',
'NoteAdded',
];
foreach ($list as $event) {

View File

@@ -329,7 +329,6 @@ class Importer extends Component
];
$this->locations_fields = [
'id' => trans('general.id'),
'name' => trans('general.item_name_var', ['item' => trans('general.location')]),
'address' => trans('general.address'),
'address2' => trans('general.importer.address2'),
@@ -342,7 +341,6 @@ class Importer extends Component
'manager_username' => trans('general.importer.manager_username'),
'manager' => trans('general.importer.manager_full_name'),
'parent_location' => trans('admin/locations/table.parent'),
'notes' => trans('general.notes'),
];
$this->assetmodels_fields = [
@@ -402,6 +400,7 @@ class Importer extends Component
'requestable',
'Requestable',
],
'gravatar' =>
[
'gravatar',

View File

@@ -159,7 +159,7 @@ class SlackSettingsForm extends Component
]);
try {
$test = $webhook->post($this->webhook_endpoint, ['body' => $payload, ['headers' => ['Content-Type' => 'application/json']]]);
$test = $webhook->post($this->webhook_endpoint, ['body' => $payload]);
if(($test->getStatusCode() == 302)||($test->getStatusCode() == 301)){
return session()->flash('error' , trans('admin/settings/message.webhook.error_redirect', ['endpoint' => $this->webhook_endpoint]));
@@ -224,7 +224,7 @@ class SlackSettingsForm extends Component
try {
$response = Http::withHeaders([
'content-type' => 'application/json',
'content-type' => 'applications/json',
])->post($this->webhook_endpoint,
$payload)->throw();
@@ -259,7 +259,7 @@ class SlackSettingsForm extends Component
"text" => trans('general.webhook_test_msg', ['app' => $this->webhook_name]),
];
$response = Http::withHeaders([
'content-type' => 'application/json',
'content-type' => 'applications/json',
])->post($this->webhook_endpoint,
$payload)->throw();
}
@@ -269,7 +269,7 @@ class SlackSettingsForm extends Component
$notification->success()->sendMessage($message);
$response = Http::withHeaders([
'content-type' => 'application/json',
'content-type' => 'applications/json',
])->post($this->webhook_endpoint);
}

View File

@@ -21,7 +21,7 @@ class CheckoutAccessoryMail extends Mailable
/**
* Create a new message instance.
*/
public function __construct(Accessory $accessory, $checkedOutTo, User $checkedOutBy, $acceptance, $note)
public function __construct(Accessory $accessory, $checkedOutTo, User $checkedOutBy,$note, $acceptance)
{
$this->item = $accessory;
$this->admin = $checkedOutBy;

View File

@@ -23,7 +23,7 @@ class CheckoutAssetMail extends Mailable
/**
* Create a new message instance.
*/
public function __construct(Asset $asset, $checkedOutTo, User $checkedOutBy, $acceptance, $note)
public function __construct(Asset $asset, $checkedOutTo, User $checkedOutBy, $note, $acceptance)
{
$this->item = $asset;
$this->admin = $checkedOutBy;

View File

@@ -27,6 +27,7 @@ class CheckoutLicenseMail extends Mailable
$this->note = $note;
$this->target = $checkedOutTo;
$this->acceptance = $acceptance;
$this->settings = Setting::getSettings();
}

View File

@@ -1,62 +0,0 @@
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Address;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class ExpiringAssetsMail extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*/
public function __construct($params, $threshold)
{
$this->assets = $params;
$this->threshold = $threshold;
}
/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
$from = new Address(config('mail.from.address'), config('mail.from.name'));
return new Envelope(
from: $from,
subject: trans('mail.Expiring_Assets_Report'),
);
}
/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
markdown: 'notifications.markdown.report-expiring-assets',
with: [
'assets' => $this->assets,
'threshold' => $this->threshold,
]
);
}
/**
* Get the attachments for the message.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [];
}
}

View File

@@ -1,62 +0,0 @@
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Address;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class ExpiringLicenseMail extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*/
public function __construct($params, $threshold)
{
$this->licenses = $params;
$this->threshold = $threshold;
}
/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
$from = new Address(config('mail.from.address'), config('mail.from.name'));
return new Envelope(
from: $from,
subject: trans('mail.Expiring_Licenses_Report'),
);
}
/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
markdown: 'notifications.markdown.report-expiring-licenses',
with: [
'licenses' => $this->licenses,
'threshold' => $this->threshold,
]
);
}
/**
* Get the attachments for the message.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [];
}
}

View File

@@ -22,14 +22,7 @@ class AccessoryCheckout extends Model
{
use Searchable;
protected $fillable = [
'accessory_id',
'assigned_to',
'assigned_type',
'note'
];
protected $presenter = \App\Presenters\AccessoryPresenter::class;
protected $fillable = ['created_by', 'accessory_id', 'assigned_to', 'assigned_type', 'note'];
protected $table = 'accessories_checkout';
/**
@@ -41,13 +34,9 @@ class AccessoryCheckout extends Model
*/
public function accessory()
{
return $this->hasOne(Accessory::class, 'id', 'accessory_id');
return $this->hasOne(\App\Models\Accessory::class, 'accessory_id');
}
public function accessories()
{
return $this->hasMany(Accessory::class, 'id', 'accessory_id');
}
/**
* Establishes the accessory checkout -> user relationship
*
@@ -55,9 +44,9 @@ class AccessoryCheckout extends Model
* @since [v7.0.9]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function adminuser()
public function user()
{
return $this->hasOne(\App\Models\User::class, 'created_by');
return $this->hasOne(\App\Models\User::class, 'user_id');
}
/**
@@ -87,7 +76,7 @@ class AccessoryCheckout extends Model
/**
* Determines whether the accessory is checked out to a user
*
* Even though we allow for checkout to things beyond users
* Even though we allow allow for checkout to things beyond users
* this method is an easy way of seeing if we are checked out to a user.
*
* @author [A. Kroeger]
@@ -95,17 +84,7 @@ class AccessoryCheckout extends Model
*/
public function checkedOutToUser(): bool
{
return $this->assigned_type == User::class;
}
public function checkedOutToLocation(): bool
{
return $this->assigned_type == Location::class;
}
public function checkedOutToAsset(): bool
{
return $this->assigned_type == Asset::class;
return $this->assignedType() === Asset::USER;
}
public function scopeUserAssigned(Builder $query): void
@@ -113,16 +92,6 @@ class AccessoryCheckout extends Model
$query->where('assigned_type', '=', User::class);
}
public function scopeLocationAssigned(Builder $query): void
{
$query->where('assigned_type', '=', Location::class);
}
public function scopeAssetAssigned(Builder $query): void
{
$query->where('assigned_type', '=', Asset::class);
}
/**
* Run additional, advanced searches.
*

View File

@@ -69,7 +69,7 @@ class Actionlog extends SnipeModel
'company' => ['name'],
'adminuser' => ['first_name','last_name','username', 'email'],
'user' => ['first_name','last_name','username', 'email'],
'assets' => ['asset_tag','name', 'serial'],
'assets' => ['asset_tag','name'],
];
/**

View File

@@ -71,7 +71,6 @@ class Category extends SnipeModel
'require_acceptance',
'use_default_eula',
'created_by',
'notes',
];
use Searchable;
@@ -81,7 +80,7 @@ class Category extends SnipeModel
*
* @var array
*/
protected $searchableAttributes = ['name', 'category_type', 'notes'];
protected $searchableAttributes = ['name', 'category_type'];
/**
* The relations and their attributes that should be included when searching the model.

View File

@@ -35,7 +35,7 @@ class CheckoutAcceptance extends Model
/**
* The resource that was is out
*
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
* @return Illuminate\Database\Eloquent\Relations\MorphTo
*/
public function checkoutable()
{

View File

@@ -307,7 +307,7 @@ class CustomField extends Model
public function formatFieldValuesAsArray()
{
$result = [];
$arr = preg_split('/\\r\\n|\\r|\\n/', $this->field_values ?? '');
$arr = preg_split('/\\r\\n|\\r|\\n/', $this->field_values);
if (($this->element != 'checkbox') && ($this->element != 'radio')) {
$result[''] = 'Select '.strtolower($this->format);

View File

@@ -141,17 +141,4 @@ class Department extends SnipeModel
{
return $query->leftJoin('users as department_user', 'departments.manager_id', '=', 'department_user.id')->orderBy('department_user.first_name', $order)->orderBy('department_user.last_name', $order);
}
/**
* Query builder scope to order on company
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeOrderCompany($query, $order)
{
return $query->leftJoin('companies as company_sort', 'departments.company_id', '=', 'company_sort.id')->orderBy('company_sort.name', $order);
}
}

View File

@@ -18,8 +18,7 @@ class Group extends SnipeModel
protected $fillable = [
'name',
'permissions',
'notes',
'permissions'
];
/**
@@ -38,7 +37,7 @@ class Group extends SnipeModel
*
* @var array
*/
protected $searchableAttributes = ['name', 'created_at', 'notes'];
protected $searchableAttributes = ['name', 'created_at'];
/**
* The relations and their attributes that should be included when searching the model.

View File

@@ -411,14 +411,14 @@ abstract class Label
/**
* Checks the template is internally valid
*/
public final function validate() : void {
public final function validate() {
$this->validateUnits();
$this->validateSize();
$this->validateMargins();
$this->validateSupport();
}
private function validateUnits() : void {
private function validateUnits() {
$validUnits = [ 'pt', 'mm', 'cm', 'in' ];
$unit = $this->getUnit();
if (!in_array(strtolower($unit), $validUnits)) {
@@ -430,7 +430,7 @@ abstract class Label
}
}
private function validateSize() : void {
private function validateSize() {
$width = $this->getWidth();
if (!is_numeric($width) || is_string($width)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_type', [
@@ -450,7 +450,7 @@ abstract class Label
}
}
private function validateMargins() : void {
private function validateMargins() {
$marginTop = $this->getMarginTop();
if (!is_numeric($marginTop) || is_string($marginTop)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_type', [
@@ -488,7 +488,7 @@ abstract class Label
}
}
private function validateSupport() : void {
private function validateSupport() {
$support1D = $this->getSupport1DBarcode();
if (!is_bool($support1D)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_type', [

View File

@@ -1,107 +0,0 @@
<?php
namespace App\Models\Labels\Tapes\Brother;
class TZe_24mm_D extends TZe_24mm
{
private const BARCODE_MARGIN = 1.40;
private const TAG_SIZE = 2.80;
private const TITLE_SIZE = 2.80;
private const TITLE_MARGIN = 0.50;
private const LABEL_SIZE = 2.50;
private const LABEL_MARGIN = - 0.35;
private const FIELD_SIZE = 2.50;
private const FIELD_MARGIN = 0.35;
private const BARCODE1D_SIZE = 3.00; // Size for the C128 barcode at bottom
public function getUnit() { return 'mm'; }
public function getWidth() { return 65.0; }
public function getSupportAssetTag() { return true; }
public function getSupport1DBarcode() { return true; }
public function getSupport2DBarcode() { return true; }
public function getSupportFields() { return 3; }
public function getSupportLogo() { return false; }
public function getSupportTitle() { return true; }
public function preparePDF($pdf) {}
public function write($pdf, $record) {
$pa = $this->getPrintableArea();
$currentX = $pa->x1;
$currentY = $pa->y1;
$usableWidth = $pa->w;
// Reserve space at bottom for 1D barcode
$usableHeight = $pa->h - self::BARCODE1D_SIZE;
$barcodeSize = $usableHeight - self::TAG_SIZE;
if ($record->has('barcode2d')) {
static::writeText(
$pdf, $record->get('tag'),
$pa->x1, $pa->y2 - self::TAG_SIZE - self::BARCODE1D_SIZE,
'freemono', 'b', self::TAG_SIZE, 'C',
$barcodeSize, self::TAG_SIZE, true, 0
);
static::write2DBarcode(
$pdf, $record->get('barcode2d')->content, $record->get('barcode2d')->type,
$currentX, $currentY,
$barcodeSize, $barcodeSize
);
$currentX += $barcodeSize + self::BARCODE_MARGIN;
$usableWidth -= $barcodeSize + self::BARCODE_MARGIN;
} else {
static::writeText(
$pdf, $record->get('tag'),
$pa->x1, $pa->y2 - self::TAG_SIZE - self::BARCODE1D_SIZE,
'freemono', 'b', self::TAG_SIZE, 'R',
$usableWidth, self::TAG_SIZE, true, 0
);
}
if ($record->has('title')) {
static::writeText(
$pdf, $record->get('title'),
$currentX, $currentY,
'freesans', '', self::TITLE_SIZE, 'L',
$usableWidth, self::TITLE_SIZE, true, 0
);
$currentY += self::TITLE_SIZE + self::TITLE_MARGIN;
}
foreach ($record->get('fields') as $field) {
// Write label and value on the same line
// Calculate label width with proportional character spacing
$labelWidth = $pdf->GetStringWidth($field['label'], 'freemono', '', self::LABEL_SIZE);
$charCount = strlen($field['label']);
$spacingPerChar = 0.5;
$totalSpacing = $charCount * $spacingPerChar;
$adjustedWidth = $labelWidth + $totalSpacing;
static::writeText(
$pdf, $field['label'],
$currentX, $currentY,
'freemono', 'B', self::LABEL_SIZE, 'L',
$adjustedWidth, self::LABEL_SIZE, true, 0, $spacingPerChar
);
static::writeText(
$pdf, $field['value'],
$currentX + $adjustedWidth + 2, $currentY,
'freemono', 'B', self::FIELD_SIZE, 'L',
$usableWidth - $adjustedWidth - 2, self::FIELD_SIZE, true, 0, 0.3
);
$currentY += max(self::LABEL_SIZE, self::FIELD_SIZE) + self::FIELD_MARGIN;
}
// Add C128 barcode at the bottom
if ($record->has('barcode1d')) {
static::write1DBarcode(
$pdf, $record->get('barcode1d')->content, $record->get('barcode1d')->type,
$pa->x1, $pa->y2 - self::BARCODE1D_SIZE,
$pa->w, self::BARCODE1D_SIZE
);
}
}
}

View File

@@ -72,7 +72,6 @@ class Location extends SnipeModel
'currency',
'manager_id',
'image',
'notes',
];
protected $hidden = ['user_id'];
@@ -83,7 +82,7 @@ class Location extends SnipeModel
*
* @var array
*/
protected $searchableAttributes = ['name', 'address', 'city', 'state', 'zip', 'created_at', 'ldap_ou', 'phone', 'fax', 'notes'];
protected $searchableAttributes = ['name', 'address', 'city', 'state', 'zip', 'created_at', 'ldap_ou', 'phone', 'fax'];
/**
* The relations and their attributes that should be included when searching the model.
@@ -254,18 +253,6 @@ class Location extends SnipeModel
return $this->morphMany(\App\Models\Asset::class, 'assigned', 'assigned_type', 'assigned_to')->withTrashed();
}
/**
* Establishes the accessory -> location assignment relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assignedAccessories()
{
return $this->morphMany(\App\Models\AccessoryCheckout::class, 'assigned', 'assigned_type', 'assigned_to');
}
public function setLdapOuAttribute($ldap_ou)
{
return $this->attributes['ldap_ou'] = empty($ldap_ou) ? null : $ldap_ou;

View File

@@ -53,7 +53,6 @@ class Manufacturer extends SnipeModel
'support_url',
'url',
'warranty_lookup_url',
'notes',
];
use Searchable;
@@ -63,7 +62,7 @@ class Manufacturer extends SnipeModel
*
* @var array
*/
protected $searchableAttributes = ['name', 'created_at', 'notes'];
protected $searchableAttributes = ['name', 'created_at'];
/**
* The relations and their attributes that should be included when searching the model.

View File

@@ -1,241 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
class ReportTemplate extends Model
{
use HasFactory;
use SoftDeletes;
use ValidatingTrait;
protected $casts = [
'options' => 'array',
];
protected $fillable = [
'created_by',
'name',
'options',
];
protected $rules = [
'name' => [
'required',
'string',
],
'options' => [
'required',
'array',
],
];
protected static function booted()
{
// Scope to current user
static::addGlobalScope('current_user', function (Builder $builder) {
if (auth()->check()) {
$builder->where('created_by', auth()->id());
}
});
static::created(function (ReportTemplate $reportTemplate) {
$logAction = new Actionlog([
'item_type' => ReportTemplate::class,
'item_id' => $reportTemplate->id,
'created_by' => auth()->id(),
]);
$logAction->logaction('create');
});
static::updated(function (ReportTemplate $reportTemplate) {
$changed = [];
foreach ($reportTemplate->getDirty() as $key => $value) {
$changed[$key] = [
'old' => $reportTemplate->getOriginal($key),
'new' => $reportTemplate->getAttribute($key),
];
}
$logAction = new Actionlog();
$logAction->item_type = ReportTemplate::class;
$logAction->item_id = $reportTemplate->id;
$logAction->created_by = auth()->id();
$logAction->log_meta = json_encode($changed);
$logAction->logaction('update');
});
static::deleted(function (ReportTemplate $reportTemplate) {
$logAction = new Actionlog([
'item_type' => ReportTemplate::class,
'item_id' => $reportTemplate->id,
'created_by' => auth()->id(),
]);
$logAction->logaction('delete');
});
}
/**
* Establishes the report template -> creator relationship.
*
*/
public function creator(): BelongsTo
{
return $this->belongsTo(User::class, 'created_by');
}
/**
* Get the value of a checkbox field for the given field name.
*
* @param string $fieldName
* @param string $fallbackValue The value to return if the report template is not saved yet.
*
*/
public function checkmarkValue(string $fieldName, string $fallbackValue = '1'): string
{
// Assuming we're using the null object pattern, and an empty model
// was passed to the view when showing the default report page,
// return the fallback value so that checkboxes are checked by default.
if (is_null($this->id)) {
return $fallbackValue;
}
// If the model does exist then return the value of the field
// or return 0 so the checkbox is unchecked.
// Falling back to 0 here is because checkboxes are not sent
// in the request when unchecked so they are not
// actually saved in the model's options.
return $this->options[$fieldName] ?? '0';
}
/**
* Get the value of a radio field for the given field name.
*
* @param string $fieldName
* @param string $value The value to check against.
* @param bool $isDefault Whether the radio input being checked is the default.
*
*/
public function radioValue(string $fieldName, string $value, bool $isDefault = false): bool
{
$fieldExists = array_has($this->options, $fieldName);
// If the field doesn't exist but the radio input
// being checked is the default then return true.
if (!$fieldExists && $isDefault) {
return true;
}
// If the field exists and matches what we're checking then return true.
if ($fieldExists && $this->options[$fieldName] === $value) {
return true;
}
// Otherwise return false.
return false;
}
/**
* Get the value of a select field for the given field name.
*
* @param string $fieldName
* @param string|null $model The Eloquent model to check against.
*
* @return mixed|null
*
*/
public function selectValue(string $fieldName, string $model = null)
{
// If the field does not exist then return null.
if (!isset($this->options[$fieldName])) {
return null;
}
$value = $this->options[$fieldName];
// If the value was stored as an array, most likely
// due to a previously being a multi-select,
// then return the first value.
if (is_array($value)) {
$value = $value[0];
}
// If a model is provided then we should ensure we only return
// the value if the model still exists.
// Note: It is possible $value is an id that no longer exists and this will return null.
if ($model) {
$foundModel = $model::find($value);
return $foundModel ? $foundModel->id : null;
}
return $value;
}
/**
* Get the values of a multi-select field for the given field name.
*
* @param string $fieldName
* @param string|null $model The Eloquent model to check against.
*
* @return iterable
*
*/
public function selectValues(string $fieldName, string $model = null): iterable
{
// If the field does not exist then return an empty array.
if (!isset($this->options[$fieldName])) {
return [];
}
// If a model is provided then we should ensure we only return
// the ids of models that exist and are not deleted.
if ($model) {
return $model::findMany($this->options[$fieldName])->pluck('id');
}
// Wrap the value in an array if needed. This is to ensure
// values previously stored as a single value,
// most likely from a single select, are returned as an array.
if (!is_array($this->options[$fieldName])) {
return [$this->options[$fieldName]];
}
return $this->options[$fieldName];
}
/**
* Get the value of a text field for the given field name.
*
* @param string $fieldName
* @param string|null $fallbackValue
*
* @return string
*/
public function textValue(string $fieldName, string|null $fallbackValue = ''): string
{
// Assuming we're using the null object pattern,
// return the default value if the object is not saved yet.
if (is_null($this->id)) {
return (string) $fallbackValue;
}
// Return the field's value if it exists
// and return the default value if not.
return $this->options[$fieldName] ?? '';
}
public function getDisplayNameAttribute()
{
return $this->name;
}
}

View File

@@ -2,7 +2,6 @@
namespace App\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;
@@ -340,33 +339,6 @@ class Setting extends Model
return collect($ldapSettings);
}
/**
* For a particular cache-file, refresh it if the settings have
* been updated more recently than the file. Then return the
* full filepath
*/
public static function get_fresh_file_path($attribute, $path)
{
$full_path = storage_path().'/'.$path;
$file_exists = file_exists($full_path);
if ($file_exists) {
$statblock = stat($full_path);
}
if (!$file_exists || Carbon::createFromTimestamp($statblock['mtime']) < Setting::getSettings()->updated_at) {
if (Setting::getSettings()->{$attribute}) {
file_put_contents($full_path, Setting::getSettings()->{$attribute});
} else {
//this doesn't fire when you might expect it to because a lot of the time we do something like:
// if ($settings->ldap_client_tls_cert && ...
// so we never get a chance to 'uncache' the file.
if ($file_exists) {
unlink($full_path);
}
}
}
return $full_path;
}
/**
* Return the filename for the client-side SSL cert
*
@@ -374,7 +346,7 @@ class Setting extends Model
*/
public static function get_client_side_cert_path()
{
return self::get_fresh_file_path('ldap_client_tls_cert', 'ldap_client_tls.cert');
return storage_path().'/ldap_client_tls.cert';
}
/**
@@ -384,7 +356,36 @@ class Setting extends Model
*/
public static function get_client_side_key_path()
{
return self::get_fresh_file_path('ldap_client_tls_key', 'ldap_client_tls.key');
return storage_path().'/ldap_client_tls.key';
}
public function update_client_side_cert_files()
{
/**
* I'm not sure if it makes sense to have a cert but no key
* nor vice versa, but for now I'm just leaving it like this.
*
* Also, we could easily set this up with an event handler and
* self::saved() or something like that but there's literally only
* one place where we will do that, so I'll just explicitly call
* this method at that spot instead. It'll be easier to debug and understand.
*/
if ($this->ldap_client_tls_cert) {
file_put_contents(self::get_client_side_cert_path(), $this->ldap_client_tls_cert);
} else {
if (file_exists(self::get_client_side_cert_path())) {
unlink(self::get_client_side_cert_path());
}
}
if ($this->ldap_client_tls_key) {
file_put_contents(self::get_client_side_key_path(), $this->ldap_client_tls_key);
} else {
if (file_exists(self::get_client_side_key_path())) {
unlink(self::get_client_side_key_path());
}
}
}
}

View File

@@ -13,7 +13,6 @@ use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use Illuminate\Contracts\Translation\HasLocalePreference;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Illuminate\Notifications\Notifiable;
@@ -334,7 +333,6 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
public function accessories()
{
return $this->belongsToMany(\App\Models\Accessory::class, 'accessories_checkout', 'assigned_to', 'accessory_id')
->where('assigned_type', '=', 'App\Models\User')
->withPivot('id', 'created_at', 'note')->withTrashed()->orderBy('accessory_id');
}
@@ -362,15 +360,6 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
return $this->belongsToMany(\App\Models\License::class, 'license_seats', 'assigned_to', 'license_id')->withPivot('id', 'created_at', 'updated_at');
}
/**
* Establishes the user -> reportTemplates relationship
*
*/
public function reportTemplates(): HasMany
{
return $this->hasMany(ReportTemplate::class, 'created_by');
}
/**
* Establishes a count of all items assigned
*
@@ -626,8 +615,6 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
$username = str_slug(substr($first_name, 0, 1).'.'.str_slug($last_name));
} elseif ($format == 'lastname_firstinitial') {
$username = str_slug($last_name).'_'.str_slug(substr($first_name, 0, 1));
} elseif ($format == 'lastname.firstinitial') {
$username = str_slug($last_name).'.'.str_slug(substr($first_name, 0, 1));
} elseif ($format == 'firstnamelastname') {
$username = str_slug($first_name).str_slug($last_name);
} elseif ($format == 'firstnamelastinitial') {

View File

@@ -79,7 +79,7 @@ class CheckinAssetNotification extends Notification
$fields = [
trans('general.administrator') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
trans('general.status') => $item->assetstatus?->name,
trans('general.status') => $item->assetstatus->name,
trans('general.location') => ($item->location) ? $item->location->name : '',
];
@@ -106,9 +106,9 @@ class CheckinAssetNotification extends Notification
->title(trans('mail.Asset_Checkin_Notification'))
->addStartGroupToSection('activityText')
->fact(htmlspecialchars_decode($item->present()->name), '', 'activityText')
->fact(trans('mail.checked_into'), ($item->location) ? $item->location->name : '')
->fact(trans('mail.checked_into'), $item->location->name ? $item->location->name : '')
->fact(trans('mail.Asset_Checkin_Notification') . " by ", $admin->present()->fullName())
->fact(trans('admin/hardware/form.status'), $item->assetstatus?->name)
->fact(trans('admin/hardware/form.status'), $item->assetstatus->name)
->fact(trans('mail.notes'), $note ?: '');
}
@@ -116,9 +116,9 @@ class CheckinAssetNotification extends Notification
$message = trans('mail.Asset_Checkin_Notification');
$details = [
trans('mail.asset') => htmlspecialchars_decode($item->present()->name),
trans('mail.checked_into') => ($item->location) ? $item->location->name : '',
trans('mail.checked_into') => $item->location->name ? $item->location->name : '',
trans('mail.Asset_Checkin_Notification')." by " => $admin->present()->fullName(),
trans('admin/hardware/form.status') => $item->assetstatus?->name,
trans('admin/hardware/form.status') => $item->assetstatus->name,
trans('mail.notes') => $note ?: '',
];
@@ -142,8 +142,8 @@ class CheckinAssetNotification extends Notification
Section::create(
KeyValue::create(
trans('mail.checked_into') ?: '',
($item->location) ? $item->location->name : '',
trans('admin/hardware/form.status').": ".$item->assetstatus?->name,
$item->location->name ? $item->location->name : '',
trans('admin/hardware/form.status').": ".$item->assetstatus->name,
)
->onClick(route('hardware.show', $item->id))
)

View File

@@ -48,7 +48,7 @@ class AssetObserver
$changed = [];
foreach ($asset->getRawOriginal() as $key => $value) {
if ((array_key_exists($key, $asset->getAttributes())) && ($asset->getRawOriginal()[$key] != $asset->getAttributes()[$key])) {
if ($asset->getRawOriginal()[$key] != $asset->getAttributes()[$key]) {
$changed[$key]['old'] = $asset->getRawOriginal()[$key];
$changed[$key]['new'] = $asset->getAttributes()[$key];
}
@@ -80,7 +80,7 @@ class AssetObserver
{
if ($settings = Setting::getSettings()) {
$tag = $asset->asset_tag;
$prefix = (string)($settings->auto_increment_prefix ?? '');
$prefix = $settings->auto_increment_prefix;
$number = substr($tag, strlen($prefix));
// IF - auto_increment_assets is on, AND (there is no prefix OR the prefix matches the start of the tag)
// AND the rest of the string after the prefix is all digits, THEN...

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