mirror of
https://github.com/snipe/snipe-it.git
synced 2025-03-05 20:52:15 -08:00
Merge 23c4d82c92
into 2b0127ab0c
This commit is contained in:
commit
21dec772e2
16
app/Enums/ActionType.php
Normal file
16
app/Enums/ActionType.php
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
enum ActionType: string {
|
||||
case Restore = 'restore';
|
||||
case TwoFactorReset = '2FA reset';
|
||||
case CheckinFrom = 'checkin from';
|
||||
case RequestCanceled = 'request canceled';
|
||||
case Requested = 'requested';
|
||||
case DeleteSeats = 'delete seats';
|
||||
case AddSeats = 'add seats';
|
||||
case Update = 'update';
|
||||
case Create = 'create';
|
||||
case Delete = 'delete';
|
||||
}
|
|
@ -218,14 +218,7 @@ class ManufacturersController extends Controller
|
|||
}
|
||||
|
||||
if ($manufacturer->restore()) {
|
||||
|
||||
$logaction = new Actionlog();
|
||||
$logaction->item_type = Manufacturer::class;
|
||||
$logaction->item_id = $manufacturer->id;
|
||||
$logaction->created_at = date('Y-m-d H:i:s');
|
||||
$logaction->created_by = auth()->id();
|
||||
$logaction->logaction('restore');
|
||||
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', trans('admin/manufacturers/message.restore.success')), 200);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Enums\ActionType;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\SaveUserRequest;
|
||||
|
@ -701,17 +702,8 @@ class UsersController extends Controller
|
|||
$this->authorize('update', $user);
|
||||
$user->two_factor_secret = null;
|
||||
$user->two_factor_enrolled = 0;
|
||||
$user->saveQuietly();
|
||||
|
||||
// Log the reset
|
||||
$logaction = new Actionlog();
|
||||
$logaction->target_type = User::class;
|
||||
$logaction->target_id = $user->id;
|
||||
$logaction->item_type = User::class;
|
||||
$logaction->item_id = $user->id;
|
||||
$logaction->created_at = date('Y-m-d H:i:s');
|
||||
$logaction->created_by = auth()->id();
|
||||
$logaction->logaction('2FA reset');
|
||||
$user->setLogMessage(ActionType::TwoFactorReset);
|
||||
$user->save();
|
||||
|
||||
return response()->json(['message' => trans('admin/settings/general.two_factor_reset_success')], 200);
|
||||
} catch (\Exception $e) {
|
||||
|
@ -756,13 +748,6 @@ class UsersController extends Controller
|
|||
|
||||
if ($user->restore()) {
|
||||
|
||||
$logaction = new Actionlog();
|
||||
$logaction->item_type = User::class;
|
||||
$logaction->item_id = $user->id;
|
||||
$logaction->created_at = date('Y-m-d H:i:s');
|
||||
$logaction->created_by = auth()->id();
|
||||
$logaction->logaction('restore');
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.success.restored')), 200);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Enums\ActionType;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Http\Requests\StoreAssetModelRequest;
|
||||
|
@ -213,13 +214,6 @@ class AssetModelsController extends Controller
|
|||
}
|
||||
|
||||
if ($model->restore()) {
|
||||
$logaction = new Actionlog();
|
||||
$logaction->item_type = AssetModel::class;
|
||||
$logaction->item_id = $model->id;
|
||||
$logaction->created_at = date('Y-m-d H:i:s');
|
||||
$logaction->created_by = auth()->id();
|
||||
$logaction->logaction('restore');
|
||||
|
||||
|
||||
// Redirect them to the deleted page if there are more, otherwise the section index
|
||||
$deleted_models = AssetModel::onlyTrashed()->count();
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Enums\ActionType;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
|
@ -266,12 +267,6 @@ class LocationsController extends Controller
|
|||
}
|
||||
|
||||
if ($location->restore()) {
|
||||
$logaction = new Actionlog();
|
||||
$logaction->item_type = Location::class;
|
||||
$logaction->item_id = $location->id;
|
||||
$logaction->created_at = date('Y-m-d H:i:s');
|
||||
$logaction->created_by = auth()->id();
|
||||
$logaction->logaction('restore');
|
||||
|
||||
return redirect()->route('locations.index')->with('success', trans('admin/locations/message.restore.success'));
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Enums\ActionType;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Manufacturer;
|
||||
|
@ -195,12 +196,6 @@ class ManufacturersController extends Controller
|
|||
}
|
||||
|
||||
if ($manufacturer->restore()) {
|
||||
$logaction = new Actionlog();
|
||||
$logaction->item_type = Manufacturer::class;
|
||||
$logaction->item_id = $manufacturer->id;
|
||||
$logaction->created_at = date('Y-m-d H:i:s');
|
||||
$logaction->created_by = auth()->id();
|
||||
$logaction->logaction('restore');
|
||||
|
||||
// Redirect them to the deleted page if there are more, otherwise the section index
|
||||
$deleted_manufacturers = Manufacturer::onlyTrashed()->count();
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Http\Controllers\Users;
|
||||
|
||||
use App\Enums\ActionType;
|
||||
use App\Events\UserMerged;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
|
@ -334,49 +335,50 @@ class BulkUsersController extends Controller
|
|||
protected function logItemCheckinAndDelete($items, $itemType)
|
||||
{
|
||||
foreach ($items as $item) {
|
||||
$item_id = $item->id;
|
||||
$logAction = new Actionlog();
|
||||
if (gettype($item) == 'object' && get_class($item) != 'stdClass') {
|
||||
$real_item = $item;
|
||||
} else {
|
||||
$item_id = $item->id;
|
||||
|
||||
if ($itemType == License::class){
|
||||
$item_id = $item->license_id;
|
||||
if ($itemType == License::class) {
|
||||
$item_id = $item->license_id; //FIXME - funkery happening here
|
||||
$real_item = License::find($item->license_id);
|
||||
} else {
|
||||
$real_item = (new $itemType())::find($item_id);
|
||||
}
|
||||
}
|
||||
if (property_exists($item, 'assigned_type')) {
|
||||
$assigned_to = (new ($item->assigned_type))::find($item->assigned_to);
|
||||
} else {
|
||||
$assigned_to = User::find($item->assigned_to);
|
||||
}
|
||||
|
||||
$logAction->item_id = $item_id;
|
||||
// We can't rely on get_class here because the licenses/accessories fetched above are not eloquent models, but simply arrays.
|
||||
$logAction->item_type = $itemType;
|
||||
$logAction->target_id = $item->assigned_to;
|
||||
$logAction->target_type = User::class;
|
||||
$logAction->created_by = auth()->id();
|
||||
$logAction->note = 'Bulk checkin items';
|
||||
$logAction->logaction('checkin from');
|
||||
$real_item->setLogTarget($assigned_to); // will this work?!!?!?!?
|
||||
//$logAction->target_id = $item->assigned_to;
|
||||
//$logAction->target_type = User::class;
|
||||
$real_item->setLogNote('Bulk checkin items');
|
||||
$real_item->setLogMessage(ActionType::CheckinFrom);
|
||||
$real_item->logWithoutSave(ActionType::CheckinFrom);
|
||||
}
|
||||
}
|
||||
|
||||
private function logAccessoriesCheckin(Collection $accessoryUserRows): void
|
||||
{
|
||||
foreach ($accessoryUserRows as $accessoryUserRow) {
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_id = $accessoryUserRow->accessory_id;
|
||||
$logAction->item_type = Accessory::class;
|
||||
$logAction->target_id = $accessoryUserRow->assigned_to;
|
||||
$logAction->target_type = User::class;
|
||||
$logAction->created_at = auth()->id();
|
||||
$logAction->note = 'Bulk checkin items';
|
||||
$logAction->logaction('checkin from');
|
||||
$accessory = Accessory::find($accessoryUserRow->accessory_id);
|
||||
$accessory->setLogTarget(User::find($accessoryUserRow->assigned_to)); //FIXME - what if accessory was checked out to location?
|
||||
$accessory->setLogNote('Bulk checkin items');
|
||||
$accessory->logWithoutSave(ActionType::CheckinFrom);
|
||||
}
|
||||
}
|
||||
|
||||
private function logConsumablesCheckin(Collection $consumableUserRows): void
|
||||
{
|
||||
foreach ($consumableUserRows as $consumableUserRow) {
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_id = $consumableUserRow->consumable_id;
|
||||
$logAction->item_type = Consumable::class;
|
||||
$logAction->target_id = $consumableUserRow->assigned_to;
|
||||
$logAction->target_type = User::class;
|
||||
$logAction->created_at = auth()->id();
|
||||
$logAction->note = 'Bulk checkin items';
|
||||
$logAction->logaction('checkin from');
|
||||
$consumable = Consumable::find($consumableUserRow->consumable_id);
|
||||
$consumable->setLogTarget(User::find($consumableUserRow->assigned_to));
|
||||
$consumable->setLogNote('Bulk checkin items');
|
||||
$consumable->logWithoutSave(ActionType::CheckinFrom);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Http\Controllers\Users;
|
||||
|
||||
use App\Enums\ActionType;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\DeleteUserRequest;
|
||||
|
@ -357,14 +358,8 @@ class UsersController extends Controller
|
|||
return redirect()->back()->with('error', trans('general.not_deleted', ['item_type' => trans('general.user')]));
|
||||
}
|
||||
|
||||
$user->setLogMessage(ActionType::Restore);
|
||||
if ($user->restore()) {
|
||||
$logaction = new Actionlog();
|
||||
$logaction->item_type = User::class;
|
||||
$logaction->item_id = $user->id;
|
||||
$logaction->created_at = date('Y-m-d H:i:s');
|
||||
$logaction->created_by = auth()->id();
|
||||
$logaction->logaction('restore');
|
||||
|
||||
// Redirect them to the deleted page if there are more, otherwise the section index
|
||||
$deleted_users = User::onlyTrashed()->count();
|
||||
if ($deleted_users > 0) {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Enums\ActionType;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
|
@ -93,17 +94,18 @@ class ViewAssetsController extends Controller
|
|||
|
||||
$user = auth()->user();
|
||||
|
||||
$logaction = new Actionlog();
|
||||
$logaction->item_id = $data['asset_id'] = $item->id;
|
||||
$logaction->item_type = $fullItemType;
|
||||
$logaction->created_at = $data['requested_date'] = date('Y-m-d H:i:s');
|
||||
|
||||
//$logaction = new Actionlog();
|
||||
//$logaction->item_id = $data['asset_id'] = $item->id;
|
||||
//$logaction->item_type = $fullItemType;
|
||||
//$logaction->created_at = $data['requested_date'] = date('Y-m-d H:i:s');
|
||||
$data['requested_date'] = date('Y-m-d H:i:s');
|
||||
if ($user->location_id) {
|
||||
$logaction->location_id = $user->location_id;
|
||||
$item->setLocation($user->location);
|
||||
}
|
||||
|
||||
$logaction->target_id = $data['user_id'] = auth()->id();
|
||||
$logaction->target_type = User::class;
|
||||
$item->setLogTarget($user);
|
||||
//$logaction->target_id = $data['user_id'] = auth()->id();
|
||||
//$logaction->target_type = User::class;
|
||||
|
||||
$data['item_quantity'] = $request->has('request-quantity') ? e($request->input('request-quantity')) : 1;
|
||||
$data['requested_by'] = $user->present()->fullName();
|
||||
|
@ -122,7 +124,7 @@ class ViewAssetsController extends Controller
|
|||
if (($item_request = $item->isRequestedBy($user)) || $cancel_by_admin) {
|
||||
$item->cancelRequest($requestingUser);
|
||||
$data['item_quantity'] = ($item_request) ? $item_request->qty : 1;
|
||||
$logaction->logaction('request_canceled');
|
||||
$item->logWithoutSave(ActionType::RequestCanceled);
|
||||
|
||||
if (($settings->alert_email != '') && ($settings->alerts_enabled == '1') && (! config('app.lock_passwords'))) {
|
||||
$settings->notify(new RequestAssetCancelation($data));
|
||||
|
@ -130,9 +132,9 @@ class ViewAssetsController extends Controller
|
|||
|
||||
return redirect()->back()->with('success')->with('success', trans('admin/hardware/message.requests.canceled'));
|
||||
} else {
|
||||
$item->request();
|
||||
$item->request(); //!!!!!!!!!!!!!
|
||||
if (($settings->alert_email != '') && ($settings->alerts_enabled == '1') && (! config('app.lock_passwords'))) {
|
||||
$logaction->logaction('requested');
|
||||
$item->logWithoutSave(ActionType::Requested);
|
||||
$settings->notify(new RequestAssetNotification($data));
|
||||
}
|
||||
|
||||
|
@ -163,25 +165,23 @@ class ViewAssetsController extends Controller
|
|||
$data['item_quantity'] = 1;
|
||||
$settings = Setting::getSettings();
|
||||
|
||||
$logaction = new Actionlog();
|
||||
$logaction->item_id = $data['asset_id'] = $asset->id;
|
||||
$logaction->item_type = $data['item_type'] = Asset::class;
|
||||
$logaction->created_at = $data['requested_date'] = date('Y-m-d H:i:s');
|
||||
//$logaction = new Actionlog();
|
||||
$data['asset_id'] = $asset->id;
|
||||
$data['item_type'] = Asset::class;
|
||||
$data['requested_date'] = date('Y-m-d H:i:s');
|
||||
|
||||
if ($user->location_id) {
|
||||
$logaction->location_id = $user->location_id;
|
||||
}
|
||||
$logaction->target_id = $data['user_id'] = auth()->id();
|
||||
$logaction->target_type = User::class;
|
||||
$asset->setLocation = $user->location;
|
||||
$asset->setLogTarget($user);
|
||||
$data['user_id'] = auth()->id();
|
||||
|
||||
// If it's already requested, cancel the request.
|
||||
if ($asset->isRequestedBy(auth()->user())) {
|
||||
$asset->cancelRequest();
|
||||
$asset->decrement('requests_counter', 1);
|
||||
$asset->cancelRequest(); //wait, what?
|
||||
$asset->decrement('requests_counter', 1); //this too
|
||||
|
||||
$logaction->logaction('request canceled');
|
||||
$asset->logWithoutSave(ActionType::RequestCanceled);
|
||||
try {
|
||||
$settings->notify(new RequestAssetCancelation($data));
|
||||
$settings->notify(new RequestAssetCancelation($data)); //and probably this
|
||||
} catch (\Exception $e) {
|
||||
Log::warning($e);
|
||||
}
|
||||
|
@ -189,11 +189,11 @@ class ViewAssetsController extends Controller
|
|||
->with('success')->with('success', trans('admin/hardware/message.requests.canceled'));
|
||||
}
|
||||
|
||||
$logaction->logaction('requested');
|
||||
$asset->request();
|
||||
$asset->increment('requests_counter', 1);
|
||||
$asset->logWithoutSave(ActionType::Requested); //ARGH
|
||||
$asset->request(); //HERE <-
|
||||
$asset->increment('requests_counter', 1); //ARGH
|
||||
try {
|
||||
$settings->notify(new RequestAssetNotification($data));
|
||||
$settings->notify(new RequestAssetNotification($data)); // ANd this.
|
||||
} catch (\Exception $e) {
|
||||
Log::warning($e);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace App\Models;
|
|||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Traits\Acceptable;
|
||||
use App\Models\Traits\Loggable;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
|
|
@ -7,19 +7,17 @@ use App\Exceptions\CheckoutNotAllowed;
|
|||
use App\Helpers\Helper;
|
||||
use App\Http\Traits\UniqueUndeletedTrait;
|
||||
use App\Models\Traits\Acceptable;
|
||||
use App\Models\Traits\Loggable;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use App\Presenters\AssetPresenter;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\Presenters\Presentable;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* Model for Assets.
|
||||
|
@ -41,6 +39,66 @@ class Asset extends Depreciable
|
|||
|
||||
use Acceptable;
|
||||
|
||||
public static function boot()
|
||||
{
|
||||
// handle incrementing of asset tags
|
||||
self::created(function ($asset) {
|
||||
if ($settings = Setting::getSettings()) {
|
||||
$tag = $asset->asset_tag;
|
||||
$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...
|
||||
if ($settings->auto_increment_assets && ($prefix == '' || strpos($tag, $prefix) === 0) && preg_match('/\d+/', $number) === 1) {
|
||||
// new way of auto-trueing-up auto_increment ID's
|
||||
$next_asset_tag = intval($number, 10) + 1;
|
||||
// we had to use 'intval' because the $number could be '01234' and
|
||||
// might get interpreted in Octal instead of decimal
|
||||
|
||||
// only modify the 'next' one if it's *bigger* than the stored base
|
||||
//
|
||||
if ($next_asset_tag > $settings->next_auto_tag_base && $next_asset_tag < PHP_INT_MAX) {
|
||||
$settings->next_auto_tag_base = $next_asset_tag;
|
||||
$settings->save();
|
||||
}
|
||||
|
||||
} else {
|
||||
// legacy method
|
||||
$settings->increment('next_auto_tag_base');
|
||||
$settings->save();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
//calculate and update EOL as necessary
|
||||
self::saving(function ($asset) {
|
||||
// determine if calculated eol and then calculate it - this should only happen on a new asset
|
||||
//\Log::error("Asset RAW array: ".print_r($asset->toArray(), true));
|
||||
if (is_null($asset->asset_eol_date) && !is_null($asset->purchase_date) && ($asset->model?->eol > 0)) { //FIXME - I shouldn't have to do this.
|
||||
$asset->asset_eol_date = $asset->purchase_date->addMonths($asset->model->eol)->format('Y-m-d');
|
||||
$asset->eol_explicit = false;
|
||||
}
|
||||
|
||||
// determine if explicit and set eol_explicit to true
|
||||
if (!is_null($asset->asset_eol_date) && !is_null($asset->purchase_date)) {
|
||||
if ($asset->model->eol > 0) {
|
||||
$months = Carbon::parse($asset->asset_eol_date)->diffInMonths($asset->purchase_date);
|
||||
if ($months != $asset->model->eol) {
|
||||
$asset->eol_explicit = true;
|
||||
}
|
||||
}
|
||||
} elseif (!is_null($asset->asset_eol_date) && is_null($asset->purchase_date)) {
|
||||
$asset->eol_explicit = true;
|
||||
}
|
||||
if ((!is_null($asset->asset_eol_date)) && (!is_null($asset->purchase_date)) && (is_null($asset->model->eol) || ($asset->model->eol == 0))) {
|
||||
$asset->eol_explicit = true;
|
||||
}
|
||||
|
||||
});
|
||||
parent::boot();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run after the checkout acceptance was declined by the user
|
||||
*
|
||||
|
@ -345,7 +403,7 @@ class Asset extends Depreciable
|
|||
$this->last_checkout = $checkout_at;
|
||||
$this->name = $name;
|
||||
|
||||
$this->assignedTo()->associate($target);
|
||||
$this->assignedTo()->associate($target); //THIS is causing the save?
|
||||
|
||||
if ($location != null) {
|
||||
$this->location_id = $location;
|
||||
|
@ -365,7 +423,7 @@ class Asset extends Depreciable
|
|||
$originalValues['action_date'] = date('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
if ($this->save()) {
|
||||
if ($this->saveQuietly()) { //THIS is the save that fires that's making the update FIXME - on checkout, this causes an update.
|
||||
if (is_int($admin)) {
|
||||
$checkedOutBy = User::findOrFail($admin);
|
||||
} elseif ($admin && get_class($admin) === \App\Models\User::class) {
|
||||
|
@ -373,7 +431,7 @@ class Asset extends Depreciable
|
|||
} else {
|
||||
$checkedOutBy = auth()->user();
|
||||
}
|
||||
event(new CheckoutableCheckedOut($this, $target, $checkedOutBy, $note, $originalValues));
|
||||
event(new CheckoutableCheckedOut($this, $target, $checkedOutBy, $note, $originalValues)); //THIS is probably causing the checkout?
|
||||
|
||||
$this->increment('checkout_counter', 1);
|
||||
|
||||
|
|
|
@ -2,15 +2,16 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Http\Traits\TwoColumnUniqueUndeletedTrait;
|
||||
use App\Models\Traits\Loggable;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\AssetModelPresenter;
|
||||
use App\Presenters\Presentable;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
use \App\Presenters\AssetModelPresenter;
|
||||
use App\Http\Traits\TwoColumnUniqueUndeletedTrait;
|
||||
|
||||
/**
|
||||
* Model for Asset Models. Asset Models contain higher level
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\Traits\Loggable;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
|
|
@ -4,21 +4,16 @@ namespace App\Models;
|
|||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Traits\Acceptable;
|
||||
use App\Models\Traits\Loggable;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\ConsumablePresenter;
|
||||
use App\Presenters\Presentable;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||
use App\Presenters\ConsumablePresenter;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\ConsumableAssignment;
|
||||
use App\Models\User;
|
||||
use App\Models\Location;
|
||||
use App\Models\Manufacturer;
|
||||
use App\Models\Supplier;
|
||||
use App\Models\Category;
|
||||
|
||||
class Consumable extends SnipeModel
|
||||
{
|
||||
|
@ -54,6 +49,34 @@ class Consumable extends SnipeModel
|
|||
'purchase_date' => 'date_format:Y-m-d|nullable',
|
||||
];
|
||||
|
||||
public static function boot()
|
||||
{
|
||||
self::deleting(function ($consumable) {
|
||||
$consumable->users()->detach();
|
||||
$uploads = $consumable->uploads;
|
||||
|
||||
foreach ($uploads as $file) {
|
||||
try {
|
||||
Storage::delete('private_uploads/consumables/'.$file->filename);
|
||||
$file->delete();
|
||||
} catch (\Exception $e) {
|
||||
Log::info($e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
Storage::disk('public')->delete('consumables/'.$consumable->image);
|
||||
} catch (\Exception $e) {
|
||||
Log::info($e);
|
||||
}
|
||||
|
||||
$consumable->image = null;
|
||||
|
||||
});
|
||||
parent::boot();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the model should inject it's identifier to the unique
|
||||
* validation rules before attempting validation. If this property
|
||||
|
|
|
@ -3,15 +3,16 @@
|
|||
namespace App\Models;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Traits\Loggable;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
use App\Enums\ActionType;
|
||||
|
||||
class License extends Depreciable
|
||||
{
|
||||
|
@ -180,13 +181,8 @@ class License extends Depreciable
|
|||
$seatsAvailableForDelete->pop()->delete();
|
||||
}
|
||||
// Log Deletion of seats.
|
||||
$logAction = new Actionlog;
|
||||
$logAction->item_type = self::class;
|
||||
$logAction->item_id = $license->id;
|
||||
$logAction->created_by = auth()->id() ?: 1; // We don't have an id while running the importer from CLI.
|
||||
$logAction->note = "deleted {$change} seats";
|
||||
$logAction->target_id = null;
|
||||
$logAction->logaction('delete seats');
|
||||
$license->setLogNote("deleted {$change} seats");
|
||||
$license->logWithoutSave(ActionType::DeleteSeats);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -212,13 +208,8 @@ class License extends Depreciable
|
|||
// On initial create, we shouldn't log the addition of seats.
|
||||
if ($license->id) {
|
||||
//Log the addition of license to the log.
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = self::class;
|
||||
$logAction->item_id = $license->id;
|
||||
$logAction->created_by = auth()->id() ?: 1; // Importer.
|
||||
$logAction->note = "added {$change} seats";
|
||||
$logAction->target_id = null;
|
||||
$logAction->logaction('add seats');
|
||||
$license->setLogNote("added {$change} seats");
|
||||
$license->logWithoutSave(ActionType::AddSeats);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Models;
|
||||
|
||||
use App\Models\Traits\Acceptable;
|
||||
use App\Models\Traits\Loggable;
|
||||
use App\Notifications\CheckinLicenseNotification;
|
||||
use App\Notifications\CheckoutLicenseNotification;
|
||||
use App\Presenters\Presentable;
|
||||
|
|
|
@ -28,6 +28,7 @@ trait Requestable
|
|||
|
||||
public function request($qty = 1)
|
||||
{
|
||||
// THIS is where the requested log action thing should go, yeah? FIXME
|
||||
$this->requests()->save(
|
||||
new CheckoutRequest(['user_id' => auth()->id(), 'qty' => $qty])
|
||||
);
|
||||
|
|
|
@ -74,6 +74,14 @@ class Setting extends Model
|
|||
'require_checkinout_notes' => 'boolean',
|
||||
];
|
||||
|
||||
public static function boot()
|
||||
{
|
||||
self::saved(function ($model) {
|
||||
Cache::forget(Setting::SETUP_CHECK_KEY);
|
||||
});
|
||||
parent::boot();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the app settings.
|
||||
* Cache is expired on Setting model saved in EventServiceProvider.
|
||||
|
|
|
@ -1,16 +1,171 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
namespace App\Models\Traits;
|
||||
|
||||
use App\Enums\ActionType;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\License;
|
||||
use App\Models\LicenseSeat;
|
||||
use App\Models\Location;
|
||||
use App\Models\Setting;
|
||||
use App\Notifications\AuditNotification;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
trait Loggable
|
||||
{
|
||||
// an attribute for setting whether or not the item was imported
|
||||
public ?bool $imported = false;
|
||||
private ?string $log_message = null;
|
||||
private ?Model $item = null;
|
||||
private array $log_meta = [];
|
||||
private ?Model $target = null;
|
||||
private ?string $note = null;
|
||||
|
||||
private ?Location $location_override = null;
|
||||
|
||||
//public static array $hide_changes = [];
|
||||
|
||||
public static function bootLoggable()
|
||||
{
|
||||
//these tiny methods just set up what the log message is going to be
|
||||
// it looks like 'restoring' fires *BEFORE* 'updating' - so we need to handle that
|
||||
static::restoring(function ($model) {
|
||||
\Log::error("Restor*ing* callback firing...");
|
||||
$model->setLogMessage(ActionType::Restore);
|
||||
});
|
||||
|
||||
static::updating(function ($model) {
|
||||
\Log::error("Updating is fired, current log message is: ".$model->log_message);
|
||||
// if we're doing a restore, this 'updating' hook fires *after* the restoring hook
|
||||
// so we make sure not to overwrite the log_message
|
||||
if (!$model->log_message) {
|
||||
$model->setLogMessage(ActionType::Update);
|
||||
}
|
||||
});
|
||||
|
||||
static::creating(function ($model) {
|
||||
$model->setLogMessage(ActionType::Create);
|
||||
});
|
||||
|
||||
static::deleting(function ($model) { //TODO - is this only for 'hard' delete? Or soft?
|
||||
\Log::error("DELETING TRIGGER HAS FIRED!!!!!!!!!!!!!!! for id: ".$model->id." old log_message was: ".$model->log_message);
|
||||
if (self::class == \App\Models\User::class) { //FIXME - Janky AF!
|
||||
$model->setLogTarget($model); //FIXME - this makes *NO* sense!!!!
|
||||
}
|
||||
$model->setLogMessage(ActionType::Delete);
|
||||
});
|
||||
|
||||
//static::trashing(function ($model) { //TODO - is *this* the right one?
|
||||
// $model->setLogMessage(ActionType::Delete); // No, no it is very much not. there is 'trashed' but not 'trashING'
|
||||
//});
|
||||
|
||||
// THIS sets up the transaction, and gets the 'diff' between the original for the model,
|
||||
// and the way it's about to get saved to.
|
||||
// note that this may run *BEFORE* the more specific events, above? I don't know why that is though.
|
||||
// OPEN QUESTION - does this run on soft-delete? I don't know.
|
||||
static::saving(function ($model) {
|
||||
//possibly consider a "$this->saveWithoutTransaction" thing you can invoke?
|
||||
// use "BEGIN" here?! TODO FIXME
|
||||
$changed = [];
|
||||
|
||||
foreach ($model->getRawOriginal() as $key => $value) {
|
||||
if ($model->getRawOriginal()[$key] != $model->getAttributes()[$key]) {
|
||||
$changed[$key]['old'] = $model->getRawOriginal()[$key];
|
||||
$changed[$key]['new'] = $model->getAttributes()[$key];
|
||||
|
||||
if (property_exists(self::class, 'hide_changes') && in_array($key, self::$hide_changes)) {
|
||||
$changed[$key]['old'] = '*************';
|
||||
$changed[$key]['new'] = '*************';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$model->setLogMeta($changed);
|
||||
});
|
||||
|
||||
// THIS is the whole enchilada, the MAIN thing that you've got to do to make things work.
|
||||
//if we've set everything up correctly, this should pretty much do everything we want, all in one place
|
||||
static::saved(function ($model) {
|
||||
if (!$model->log_message && !$model->log_meta) {
|
||||
//nothing was changed, nothing was saved, nothing happened. So there should be no log message.
|
||||
//FIXME if we do the transaction thing!!!!
|
||||
\Log::error("LOG MESSAGE IS BLANK, ****AND**** log_meta is blank! Not sure what that means though...");
|
||||
return;
|
||||
}
|
||||
if (!$model->log_message) {
|
||||
throw new \Exception("Log Message was unset, but log_meta *does* exist - it's: ".print_r($model->log_meta, true));
|
||||
}
|
||||
$model->logWithoutSave();
|
||||
// DO COMMIT HERE? TODO FIXME
|
||||
});
|
||||
static::deleted(function ($model) {
|
||||
\Log::error("Deleted callback has fired!!!!!!!!!!! I guess that means do stuff here? For id: ".$model->id);
|
||||
$results = $model->logWithoutSave(); //TODO - if we do commits up there, we should do them here too?
|
||||
\Log::error("result of logging without save? ".($results ? 'true' : 'false'));
|
||||
});
|
||||
static::restored(function ($model) {
|
||||
\Log::error("RestorED callback firing.");
|
||||
$model->logWithoutSave(); //TODO - this is getting duplicative.
|
||||
});
|
||||
|
||||
// CRAP.
|
||||
//static::trashed(function ($model) {
|
||||
// $model->logWithoutSave(ActionType::Delete);
|
||||
//});
|
||||
|
||||
}
|
||||
|
||||
// and THIS is the main, primary logging system
|
||||
// it *can* be called on its own, but in *general* you should let it trigger from the 'save'
|
||||
public function logWithoutSave(ActionType $log_action = null): bool
|
||||
{
|
||||
if ($log_action) {
|
||||
$this->setLogMessage($log_action);
|
||||
}
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = self::class;
|
||||
$logAction->item_id = $this->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->created_by = auth()->id();
|
||||
if ($this->imported) {
|
||||
$logAction->setActionSource('importer');
|
||||
}
|
||||
$logAction->log_meta = $this->log_meta ? json_encode($this->log_meta) : null;
|
||||
if ($this->target) {
|
||||
$logAction->target_type = $this->target::class;
|
||||
$logAction->target_id = $this->target->id;
|
||||
}
|
||||
if ($this->note) {
|
||||
$logAction->note = $this->note;
|
||||
}
|
||||
if ($this->location_override) {
|
||||
$logAction->location_id = $this->location->id;
|
||||
}
|
||||
|
||||
\Log::error("Here is the logaction BEFORE we save it ($this->log_message)...".print_r($logAction->toArray(), true));
|
||||
return $logAction->logaction($this->log_message);
|
||||
}
|
||||
|
||||
public function setLogMessage(ActionType $message)
|
||||
{
|
||||
$this->log_message = $message->value;
|
||||
}
|
||||
|
||||
public function setLogMeta(array $changed)
|
||||
{
|
||||
$this->log_meta = $changed;
|
||||
}
|
||||
|
||||
public function setLogTarget(Model $target)
|
||||
{
|
||||
$this->target = $target;
|
||||
}
|
||||
|
||||
public function setLogNote(string $note)
|
||||
{
|
||||
$this->note = $note;
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Daniel Meltzer <dmeltzer.devel@gmail.com>
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Models;
|
||||
|
||||
use App\Http\Traits\UniqueUndeletedTrait;
|
||||
use App\Models\Traits\Loggable;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use Illuminate\Auth\Authenticatable;
|
||||
|
@ -33,11 +34,16 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
|||
use Notifiable;
|
||||
use Presentable;
|
||||
use Searchable;
|
||||
use Loggable;
|
||||
|
||||
// that 'use Loggable' thing is NEW!
|
||||
|
||||
protected $hidden = ['password', 'remember_token', 'permissions', 'reset_password_code', 'persist_code'];
|
||||
protected $table = 'users';
|
||||
protected $injectUniqueIdentifier = true;
|
||||
|
||||
public static array $hide_changes = ['password', 'remember_token', 'two_factor_secret', 'reset_password_code', 'persist_code'];
|
||||
|
||||
protected $fillable = [
|
||||
'activated',
|
||||
'address',
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Observers;
|
||||
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Actionlog;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class AccessoryObserver
|
||||
{
|
||||
/**
|
||||
* Listen to the User created event.
|
||||
*
|
||||
* @param Accessory $accessory
|
||||
* @return void
|
||||
*/
|
||||
public function updated(Accessory $accessory)
|
||||
{
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = Accessory::class;
|
||||
$logAction->item_id = $accessory->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->created_by = auth()->id();
|
||||
$logAction->logaction('update');
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to the Accessory created event when
|
||||
* a new accessory is created.
|
||||
*
|
||||
* @param Accessory $accessory
|
||||
* @return void
|
||||
*/
|
||||
public function created(Accessory $accessory)
|
||||
{
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = Accessory::class;
|
||||
$logAction->item_id = $accessory->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->created_by = auth()->id();
|
||||
if($accessory->imported) {
|
||||
$logAction->setActionSource('importer');
|
||||
}
|
||||
$logAction->logaction('create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to the Accessory deleting event.
|
||||
*
|
||||
* @param Accessory $accessory
|
||||
* @return void
|
||||
*/
|
||||
public function deleting(Accessory $accessory)
|
||||
{
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = Accessory::class;
|
||||
$logAction->item_id = $accessory->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->created_by = auth()->id();
|
||||
$logAction->logaction('delete');
|
||||
}
|
||||
}
|
|
@ -1,187 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Observers;
|
||||
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Setting;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class AssetObserver
|
||||
{
|
||||
/**
|
||||
* Listen to the Asset updating event. This fires automatically every time an existing asset is saved.
|
||||
*
|
||||
* @param Asset $asset
|
||||
* @return void
|
||||
*/
|
||||
public function updating(Asset $asset)
|
||||
{
|
||||
$attributes = $asset->getAttributes();
|
||||
$attributesOriginal = $asset->getRawOriginal();
|
||||
$same_checkout_counter = false;
|
||||
$same_checkin_counter = false;
|
||||
$restoring_or_deleting = false;
|
||||
|
||||
|
||||
// This is a gross hack to prevent the double logging when restoring an asset
|
||||
if (array_key_exists('deleted_at', $attributes) && array_key_exists('deleted_at', $attributesOriginal)){
|
||||
$restoring_or_deleting = (($attributes['deleted_at'] != $attributesOriginal['deleted_at']));
|
||||
}
|
||||
|
||||
if (array_key_exists('checkout_counter', $attributes) && array_key_exists('checkout_counter', $attributesOriginal)){
|
||||
$same_checkout_counter = (($attributes['checkout_counter'] == $attributesOriginal['checkout_counter']));
|
||||
}
|
||||
|
||||
if (array_key_exists('checkin_counter', $attributes) && array_key_exists('checkin_counter', $attributesOriginal)){
|
||||
$same_checkin_counter = (($attributes['checkin_counter'] == $attributesOriginal['checkin_counter']));
|
||||
}
|
||||
|
||||
// If the asset isn't being checked out or audited, log the update.
|
||||
// (Those other actions already create log entries.)
|
||||
if (($attributes['assigned_to'] == $attributesOriginal['assigned_to'])
|
||||
&& ($same_checkout_counter) && ($same_checkin_counter)
|
||||
&& ((isset( $attributes['next_audit_date']) ? $attributes['next_audit_date'] : null) == (isset($attributesOriginal['next_audit_date']) ? $attributesOriginal['next_audit_date']: null))
|
||||
&& ($attributes['last_checkout'] == $attributesOriginal['last_checkout']) && (!$restoring_or_deleting))
|
||||
{
|
||||
$changed = [];
|
||||
|
||||
foreach ($asset->getRawOriginal() as $key => $value) {
|
||||
if ((array_key_exists($key, $asset->getAttributes())) && ($asset->getRawOriginal()[$key] != $asset->getAttributes()[$key])) {
|
||||
$changed[$key]['old'] = $asset->getRawOriginal()[$key];
|
||||
$changed[$key]['new'] = $asset->getAttributes()[$key];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($changed)){
|
||||
return;
|
||||
}
|
||||
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = Asset::class;
|
||||
$logAction->item_id = $asset->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->created_by = auth()->id();
|
||||
$logAction->log_meta = json_encode($changed);
|
||||
$logAction->logaction('update');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to the Asset created event, and increment
|
||||
* the next_auto_tag_base value in the settings table when i
|
||||
* a new asset is created.
|
||||
*
|
||||
* @param Asset $asset
|
||||
* @return void
|
||||
*/
|
||||
public function created(Asset $asset)
|
||||
{
|
||||
if ($settings = Setting::getSettings()) {
|
||||
$tag = $asset->asset_tag;
|
||||
$prefix = (string)($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...
|
||||
if ($settings->auto_increment_assets && ($prefix=='' || strpos($tag, $prefix) === 0) && preg_match('/\d+/',$number) === 1) {
|
||||
// new way of auto-trueing-up auto_increment ID's
|
||||
$next_asset_tag = intval($number, 10) + 1;
|
||||
// we had to use 'intval' because the $number could be '01234' and
|
||||
// might get interpreted in Octal instead of decimal
|
||||
|
||||
// only modify the 'next' one if it's *bigger* than the stored base
|
||||
//
|
||||
if ($next_asset_tag > $settings->next_auto_tag_base && $next_asset_tag < PHP_INT_MAX) {
|
||||
$settings->next_auto_tag_base = $next_asset_tag;
|
||||
$settings->save();
|
||||
}
|
||||
|
||||
} else {
|
||||
// legacy method
|
||||
$settings->increment('next_auto_tag_base');
|
||||
$settings->save();
|
||||
}
|
||||
}
|
||||
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = Asset::class; // can we instead say $logAction->item = $asset ?
|
||||
$logAction->item_id = $asset->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->created_by = auth()->id();
|
||||
if($asset->imported) {
|
||||
$logAction->setActionSource('importer');
|
||||
}
|
||||
$logAction->logaction('create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to the Asset deleting event.
|
||||
*
|
||||
* @param Asset $asset
|
||||
* @return void
|
||||
*/
|
||||
public function deleting(Asset $asset)
|
||||
{
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = Asset::class;
|
||||
$logAction->item_id = $asset->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->created_by = auth()->id();
|
||||
$logAction->logaction('delete');
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to the Asset deleting event.
|
||||
*
|
||||
* @param Asset $asset
|
||||
* @return void
|
||||
*/
|
||||
public function restoring(Asset $asset)
|
||||
{
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = Asset::class;
|
||||
$logAction->item_id = $asset->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->created_by = auth()->id();
|
||||
$logAction->logaction('restore');
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes every time an asset is saved.
|
||||
*
|
||||
* This matters specifically because any database fields affected here MUST already exist on
|
||||
* the assets table (and/or any related models), or related migrations WILL fail.
|
||||
*
|
||||
* For example, if there is a database migration that's a bit older and modifies an asset, if the save
|
||||
* fires before a field gets created in a later migration and that field in the later migration
|
||||
* is used in this observer, it doesn't actually exist yet and the migration will break unless we
|
||||
* use saveQuietly() in the migration which skips this observer.
|
||||
*
|
||||
* @see https://github.com/snipe/snipe-it/issues/13723#issuecomment-1761315938
|
||||
*/
|
||||
public function saving(Asset $asset)
|
||||
{
|
||||
// determine if calculated eol and then calculate it - this should only happen on a new asset
|
||||
if (is_null($asset->asset_eol_date) && !is_null($asset->purchase_date) && ($asset->model->eol > 0)){
|
||||
$asset->asset_eol_date = $asset->purchase_date->addMonths($asset->model->eol)->format('Y-m-d');
|
||||
$asset->eol_explicit = false;
|
||||
}
|
||||
|
||||
// determine if explicit and set eol_explicit to true
|
||||
if (!is_null($asset->asset_eol_date) && !is_null($asset->purchase_date)) {
|
||||
if($asset->model->eol > 0) {
|
||||
$months = Carbon::parse($asset->asset_eol_date)->diffInMonths($asset->purchase_date);
|
||||
if($months != $asset->model->eol) {
|
||||
$asset->eol_explicit = true;
|
||||
}
|
||||
}
|
||||
} elseif (!is_null($asset->asset_eol_date) && is_null($asset->purchase_date)) {
|
||||
$asset->eol_explicit = true;
|
||||
}
|
||||
if ((!is_null($asset->asset_eol_date)) && (!is_null($asset->purchase_date)) && (is_null($asset->model->eol) || ($asset->model->eol == 0))) {
|
||||
$asset->eol_explicit = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Observers;
|
||||
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Component;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class ComponentObserver
|
||||
{
|
||||
/**
|
||||
* Listen to the User created event.
|
||||
*
|
||||
* @param Component $component
|
||||
* @return void
|
||||
*/
|
||||
public function updated(Component $component)
|
||||
{
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = Component::class;
|
||||
$logAction->item_id = $component->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->created_by = auth()->id();
|
||||
$logAction->logaction('update');
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to the Component created event when
|
||||
* a new component is created.
|
||||
*
|
||||
* @param Component $component
|
||||
* @return void
|
||||
*/
|
||||
public function created(Component $component)
|
||||
{
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = Component::class;
|
||||
$logAction->item_id = $component->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->created_by = auth()->id();
|
||||
if($component->imported) {
|
||||
$logAction->setActionSource('importer');
|
||||
}
|
||||
$logAction->logaction('create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to the Component deleting event.
|
||||
*
|
||||
* @param Component $component
|
||||
* @return void
|
||||
*/
|
||||
public function deleting(Component $component)
|
||||
{
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = Component::class;
|
||||
$logAction->item_id = $component->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->created_by = auth()->id();
|
||||
$logAction->logaction('delete');
|
||||
}
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Observers;
|
||||
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Consumable;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class ConsumableObserver
|
||||
{
|
||||
/**
|
||||
* Listen to the User created event.
|
||||
*
|
||||
* @param Consumable $consumable
|
||||
* @return void
|
||||
*/
|
||||
public function updated(Consumable $consumable)
|
||||
{
|
||||
|
||||
$changed = [];
|
||||
|
||||
foreach ($consumable->getRawOriginal() as $key => $value) {
|
||||
// Check and see if the value changed
|
||||
if ($consumable->getRawOriginal()[$key] != $consumable->getAttributes()[$key]) {
|
||||
$changed[$key]['old'] = $consumable->getRawOriginal()[$key];
|
||||
$changed[$key]['new'] = $consumable->getAttributes()[$key];
|
||||
}
|
||||
}
|
||||
|
||||
if (count($changed) > 0) {
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = Consumable::class;
|
||||
$logAction->item_id = $consumable->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->created_by = auth()->id();
|
||||
$logAction->log_meta = json_encode($changed);
|
||||
$logAction->logaction('update');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to the Consumable created event when
|
||||
* a new consumable is created.
|
||||
*
|
||||
* @param Consumable $consumable
|
||||
* @return void
|
||||
*/
|
||||
public function created(Consumable $consumable)
|
||||
{
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = Consumable::class;
|
||||
$logAction->item_id = $consumable->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->created_by = auth()->id();
|
||||
if($consumable->imported) {
|
||||
$logAction->setActionSource('importer');
|
||||
}
|
||||
$logAction->logaction('create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to the Consumable deleting event.
|
||||
*
|
||||
* @param Consumable $consumable
|
||||
* @return void
|
||||
*/
|
||||
public function deleting(Consumable $consumable)
|
||||
{
|
||||
|
||||
$consumable->users()->detach();
|
||||
$uploads = $consumable->uploads;
|
||||
|
||||
foreach ($uploads as $file) {
|
||||
try {
|
||||
Storage::delete('private_uploads/consumables/'.$file->filename);
|
||||
$file->delete();
|
||||
} catch (\Exception $e) {
|
||||
Log::info($e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
try {
|
||||
Storage::disk('public')->delete('consumables/'.$consumable->image);
|
||||
} catch (\Exception $e) {
|
||||
Log::info($e);
|
||||
}
|
||||
|
||||
$consumable->image = null;
|
||||
$consumable->save();
|
||||
|
||||
|
||||
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = Consumable::class;
|
||||
$logAction->item_id = $consumable->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->created_by = auth()->id();
|
||||
$logAction->logaction('delete');
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Observers;
|
||||
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\License;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class LicenseObserver
|
||||
{
|
||||
/**
|
||||
* Listen to the User created event.
|
||||
*
|
||||
* @param License $license
|
||||
* @return void
|
||||
*/
|
||||
public function updated(License $license)
|
||||
{
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = License::class;
|
||||
$logAction->item_id = $license->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->created_by = auth()->id();
|
||||
$logAction->logaction('update');
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to the License created event when
|
||||
* a new license is created.
|
||||
*
|
||||
* @param License $license
|
||||
* @return void
|
||||
*/
|
||||
public function created(License $license)
|
||||
{
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = License::class;
|
||||
$logAction->item_id = $license->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->created_by = auth()->id();
|
||||
if($license->imported) {
|
||||
$logAction->setActionSource('importer');
|
||||
}
|
||||
$logAction->logaction('create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to the License deleting event.
|
||||
*
|
||||
* @param License $license
|
||||
* @return void
|
||||
*/
|
||||
public function deleting(License $license)
|
||||
{
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = License::class;
|
||||
$logAction->item_id = $license->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->created_by = auth()->id();
|
||||
$logAction->logaction('delete');
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Observers;
|
||||
|
||||
use App\Models\Setting;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
class SettingObserver
|
||||
{
|
||||
/**
|
||||
* Listen to the Setting saved event.
|
||||
*
|
||||
* @param Setting $setting
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function saved(Setting $setting)
|
||||
{
|
||||
Cache::forget(Setting::SETUP_CHECK_KEY);
|
||||
}
|
||||
}
|
|
@ -1,149 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Observers;
|
||||
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class UserObserver
|
||||
{
|
||||
/**
|
||||
* Listen to the User updating event. This fires automatically every time an existing asset is saved.
|
||||
*
|
||||
* @param User $user
|
||||
* @return void
|
||||
*/
|
||||
public function updating(User $user)
|
||||
{
|
||||
|
||||
// ONLY allow these fields to be stored
|
||||
$allowed_fields = [
|
||||
'email',
|
||||
'activated',
|
||||
'first_name',
|
||||
'last_name',
|
||||
'website',
|
||||
'country',
|
||||
'gravatar',
|
||||
'location_id',
|
||||
'phone',
|
||||
'jobtitle',
|
||||
'manager_id',
|
||||
'employee_num',
|
||||
'username',
|
||||
'notes',
|
||||
'company_id',
|
||||
'ldap_import',
|
||||
'locale',
|
||||
'two_factor_enrolled',
|
||||
'two_factor_optin',
|
||||
'department_id',
|
||||
'address',
|
||||
'address2',
|
||||
'city',
|
||||
'state',
|
||||
'zip',
|
||||
'remote',
|
||||
'start_date',
|
||||
'end_date',
|
||||
'autoassign_licenses',
|
||||
'vip',
|
||||
'password'
|
||||
];
|
||||
|
||||
$changed = [];
|
||||
|
||||
foreach ($user->getRawOriginal() as $key => $value) {
|
||||
|
||||
// Make sure the info is in the allow fields array
|
||||
if (in_array($key, $allowed_fields)) {
|
||||
|
||||
// Check and see if the value changed
|
||||
if ($user->getRawOriginal()[$key] != $user->getAttributes()[$key]) {
|
||||
|
||||
$changed[$key]['old'] = $user->getRawOriginal()[$key];
|
||||
$changed[$key]['new'] = $user->getAttributes()[$key];
|
||||
|
||||
// Do not store the hashed password in changes
|
||||
if ($key == 'password') {
|
||||
$changed['password']['old'] = '*************';
|
||||
$changed['password']['new'] = '*************';
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (count($changed) > 0) {
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = User::class;
|
||||
$logAction->item_id = $user->id;
|
||||
$logAction->target_type = User::class; // can we instead say $logAction->item = $asset ?
|
||||
$logAction->target_id = $user->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->created_by = auth()->id();
|
||||
$logAction->log_meta = json_encode($changed);
|
||||
$logAction->logaction('update');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to the User created event, and increment
|
||||
* the next_auto_tag_base value in the settings table when i
|
||||
* a new asset is created.
|
||||
*
|
||||
* @param User $user
|
||||
* @return void
|
||||
*/
|
||||
public function created(User $user)
|
||||
{
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = User::class; // can we instead say $logAction->item = $asset ?
|
||||
$logAction->item_id = $user->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->created_by = auth()->id();
|
||||
$logAction->logaction('create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to the User deleting event.
|
||||
*
|
||||
* @param User $user
|
||||
* @return void
|
||||
*/
|
||||
public function deleting(User $user)
|
||||
{
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = User::class;
|
||||
$logAction->item_id = $user->id;
|
||||
$logAction->target_type = User::class; // can we instead say $logAction->item = $asset ?
|
||||
$logAction->target_id = $user->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->created_by = auth()->id();
|
||||
$logAction->logaction('delete');
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to the User deleting event.
|
||||
*
|
||||
* @param User $user
|
||||
* @return void
|
||||
*/
|
||||
public function restoring(User $user)
|
||||
{
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_type = User::class;
|
||||
$logAction->item_id = $user->id;
|
||||
$logAction->target_type = User::class; // can we instead say $logAction->item = $asset ?
|
||||
$logAction->target_id = $user->id;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->created_by = auth()->id();
|
||||
$logAction->logaction('restore');
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -2,21 +2,7 @@
|
|||
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Component;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\License;
|
||||
use App\Models\User;
|
||||
use App\Models\Setting;
|
||||
use App\Models\SnipeSCIMConfig;
|
||||
use App\Observers\AccessoryObserver;
|
||||
use App\Observers\AssetObserver;
|
||||
use App\Observers\UserObserver;
|
||||
use App\Observers\ComponentObserver;
|
||||
use App\Observers\ConsumableObserver;
|
||||
use App\Observers\LicenseObserver;
|
||||
use App\Observers\SettingObserver;
|
||||
use Illuminate\Routing\UrlGenerator;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
@ -66,13 +52,6 @@ class AppServiceProvider extends ServiceProvider
|
|||
\Illuminate\Pagination\Paginator::useBootstrap();
|
||||
|
||||
Schema::defaultStringLength(191);
|
||||
Asset::observe(AssetObserver::class);
|
||||
User::observe(UserObserver::class);
|
||||
Accessory::observe(AccessoryObserver::class);
|
||||
Component::observe(ComponentObserver::class);
|
||||
Consumable::observe(ConsumableObserver::class);
|
||||
License::observe(LicenseObserver::class);
|
||||
Setting::observe(SettingObserver::class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -204,6 +204,8 @@ class MergeUsersTest extends TestCase
|
|||
|
||||
// This needs to be 2 more than the otherwise expected because the merge action itself is logged for the two merging users
|
||||
$this->assertEquals(11, $user_to_merge_into->refresh()->userlog->count());
|
||||
$this->assertTrue($user1->refresh()->trashed(), "User 1 should be trashed and isn't!");
|
||||
$this->assertTrue($user2->refresh()->trashed(), "User 2 should be trashed and isn't!");
|
||||
$this->assertEquals(2, $user1->refresh()->userlog->count());
|
||||
$this->assertEquals(2, $user2->refresh()->userlog->count());
|
||||
|
||||
|
|
Loading…
Reference in a new issue