Compare commits
117 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cbae5ce9ab | |||
| be3c8ddd5c | |||
| a0d65520a3 | |||
| a35731d9d5 | |||
| 9d3623cca6 | |||
| 2fe08a721f | |||
| d4a34f1a3c | |||
| ddda4848d3 | |||
| 8516856d37 | |||
| 132327594b | |||
| d2a2c63070 | |||
| 170a5158fa | |||
| 1d8493d388 | |||
| c3442033da | |||
| f1dd84edba | |||
| 06b040a337 | |||
| fa546ddc5b | |||
| f811352c79 | |||
| 7ed8963b9f | |||
| a9fc8b79fd | |||
| afd794b4c7 | |||
| c4a28f0ec4 | |||
| db343bf795 | |||
| 0157043dc5 | |||
| a947f9bd32 | |||
| 2a4181c7c3 | |||
| 30192f5b14 | |||
| c41b5e8844 | |||
| b27928807b | |||
| 16f1b5e23e | |||
| ed651b6869 | |||
| b9d925c7aa | |||
| 3650a29381 | |||
| de84ee3693 | |||
| 42ba31591d | |||
| a78a243e20 | |||
| 38924ced4a | |||
| 5e8cc66f5c | |||
| 1353837584 | |||
| 7cb5a89523 | |||
| 1db09a7953 | |||
| bc6aa12dd0 | |||
| c3bea88979 | |||
| 6e85e466b0 | |||
| 3327cc70c9 | |||
| c9eac66a93 | |||
| 53e9bd6e48 | |||
| eaa18e1efb | |||
| afa3dacc31 | |||
| c803c4a57a | |||
| 2d3a53e449 | |||
| 5e076754ce | |||
| 927e217961 | |||
| 80b48101aa | |||
| 08530e6133 | |||
| 97130ef6c1 | |||
| da37feae6d | |||
| f96172e61f | |||
| e35477b8db | |||
| cea5560a67 | |||
| 311bd5e67e | |||
| 1cfddf2a4c | |||
| abe58117fe | |||
| ee5f89f70d | |||
| 4f545ed101 | |||
| 136de4208e | |||
| 7650a2c2a7 | |||
| c3d1987fac | |||
| 12ef78bb1c | |||
| 16c4241a6e | |||
| 4992c77818 | |||
| 3a0b1de136 | |||
| 1c3ef02c7b | |||
| f268fe9e80 | |||
| 2ed98c17d4 | |||
| 571ae4fbfd | |||
| 6e61e94e02 | |||
| 6a7972c5a1 | |||
| db4fbe315a | |||
| f3613d7103 | |||
| cbbed36428 | |||
| e86e9697b3 | |||
| fd6b2d5715 | |||
| fbb36d1665 | |||
| 07be1b8192 | |||
| 33880393ac | |||
| 5123fe7838 | |||
| cbe26a365d | |||
| f1bb72b2a6 | |||
| dd86de017e | |||
| 3eabde9630 | |||
| 640c51af31 | |||
| 7167b17d25 | |||
| 8a35948678 | |||
| 0fe63d3fb9 | |||
| e4302c3e88 | |||
| a7df6fb465 | |||
| 133e7598e0 | |||
| c1a52ffa75 | |||
| 4f46313388 | |||
| 03b2cc9cd2 | |||
| 1a2bf8dc95 | |||
| dd63fbeb84 | |||
| 59e435c418 | |||
| f89f0a19b5 | |||
| cbc6ef95cb | |||
| 0ceecc9e1d | |||
| c816902025 | |||
| cfb03cdca0 | |||
| 266f77b08c | |||
| d0593c6b8d | |||
| 8a40d7e35c | |||
| e9948f0718 | |||
| 2f74a8afe1 | |||
| 826521f053 | |||
| f9b05bc8de | |||
| b8239e8ed9 |
@@ -28,6 +28,7 @@ PUBLIC_FILESYSTEM_DISK=local_public
|
||||
# --------------------------------------------
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=db
|
||||
DB_SOCKET=null
|
||||
DB_PORT='3306'
|
||||
DB_DATABASE=snipeit
|
||||
DB_USERNAME=snipeit
|
||||
|
||||
@@ -24,6 +24,7 @@ PUBLIC_FILESYSTEM_DISK=local_public
|
||||
# --------------------------------------------
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_SOCKET=null
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=null
|
||||
DB_USERNAME=null
|
||||
|
||||
@@ -151,6 +151,7 @@ class IconHelper
|
||||
case 'location':
|
||||
return 'fas fa-map-marker-alt';
|
||||
case 'superadmin':
|
||||
case 'admin':
|
||||
return 'fas fa-crown';
|
||||
case 'print':
|
||||
return 'fa-solid fa-print';
|
||||
|
||||
@@ -27,6 +27,36 @@ class StorageHelper
|
||||
}
|
||||
}
|
||||
|
||||
public static function getMediaType($file_with_path) {
|
||||
|
||||
// The file exists and is allowed to be displayed inline
|
||||
if (Storage::exists($file_with_path)) {
|
||||
$fileinfo = pathinfo($file_with_path);
|
||||
$extension = strtolower($fileinfo['extension']);
|
||||
switch ($extension) {
|
||||
case 'avif':
|
||||
case 'jpg':
|
||||
case 'png':
|
||||
case 'gif':
|
||||
case 'svg':
|
||||
case 'webp':
|
||||
return 'image';
|
||||
case 'pdf':
|
||||
return 'pdf';
|
||||
case 'mp3':
|
||||
case 'wav':
|
||||
case 'ogg':
|
||||
return 'audio';
|
||||
case 'mp4':
|
||||
case 'webm':
|
||||
case 'mov':
|
||||
return 'video';
|
||||
default:
|
||||
return $extension; // Default for unknown types
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This determines the file types that should be allowed inline and checks their fileinfo extension
|
||||
@@ -52,7 +82,6 @@ class StorageHelper
|
||||
'pdf',
|
||||
'png',
|
||||
'svg',
|
||||
'svg',
|
||||
'wav',
|
||||
'webm',
|
||||
'webp',
|
||||
|
||||
@@ -77,7 +77,18 @@ class AccessoriesController extends Controller
|
||||
$accessory->supplier_id = request('supplier_id');
|
||||
$accessory->notes = request('notes');
|
||||
|
||||
$accessory = $request->handleImages($accessory);
|
||||
if ($request->has('use_cloned_image')) {
|
||||
$cloned_model_img = Accessory::select('image')->find($request->input('clone_image_from_id'));
|
||||
if ($cloned_model_img) {
|
||||
$new_image_name = 'clone-'.date('U').'-'.$cloned_model_img->image;
|
||||
$new_image = 'accessories/'.$new_image_name;
|
||||
Storage::disk('public')->copy('accessories/'.$cloned_model_img->image, $new_image);
|
||||
$accessory->image = $new_image_name;
|
||||
}
|
||||
|
||||
} else {
|
||||
$accessory = $request->handleImages($accessory);
|
||||
}
|
||||
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
// Was the accessory created?
|
||||
@@ -114,11 +125,12 @@ class AccessoriesController extends Controller
|
||||
|
||||
$this->authorize('create', Accessory::class);
|
||||
$cloned = clone $accessory;
|
||||
$accessory_to_clone = $accessory;
|
||||
$cloned->id = null;
|
||||
$cloned->deleted_at = '';
|
||||
$cloned->location_id = null;
|
||||
|
||||
return view('accessories/edit')
|
||||
->with('cloned_model', $accessory_to_clone)
|
||||
->with('item', $cloned);
|
||||
|
||||
}
|
||||
|
||||
@@ -98,15 +98,22 @@ class UploadedFilesController extends Controller
|
||||
'created_at',
|
||||
];
|
||||
|
||||
$uploads = $object->uploads();
|
||||
$offset = ($request->input('offset') > $object->count()) ? $object->count() : abs($request->input('offset'));
|
||||
|
||||
$uploads = Actionlog::select('action_logs.*')
|
||||
->whereNotNull('filename')
|
||||
->where('item_type', self::$map_object_type[$object_type])
|
||||
->where('item_id', $object->id)
|
||||
->where('action_type', '=', 'uploaded')
|
||||
->with('adminuser');
|
||||
|
||||
$offset = ($request->input('offset') > $uploads->count()) ? $uploads->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'action_logs.created_at';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
|
||||
// Text search on action_logs fields
|
||||
// We could use the normal Actionlogs text scope, but it's a very heavy query since it's searcghing across all relations
|
||||
// And we generally won't need that here
|
||||
// We could use the normal Actionlogs text scope, but it's a very heavy query since it's searching across all relations
|
||||
// and we generally won't need that here
|
||||
if ($request->filled('search')) {
|
||||
|
||||
$uploads->where(
|
||||
@@ -117,8 +124,10 @@ class UploadedFilesController extends Controller
|
||||
);
|
||||
}
|
||||
|
||||
$total = $uploads->count();
|
||||
$uploads = $uploads->skip($offset)->take($limit)->orderBy($sort, $order)->get();
|
||||
return (new UploadedFilesTransformer())->transformFiles($uploads, $uploads->count());
|
||||
|
||||
return (new UploadedFilesTransformer())->transformFiles($uploads, $total);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -108,6 +108,14 @@ class UsersController extends Controller
|
||||
$users = $users->where('users.activated', '=', $request->input('activated'));
|
||||
}
|
||||
|
||||
if ($request->input('admins') == 'true') {
|
||||
$users = $users->OnlyAdminsAndSuperAdmins();
|
||||
}
|
||||
|
||||
if ($request->input('superadmins') == 'true') {
|
||||
$users = $users->OnlySuperAdmins();
|
||||
}
|
||||
|
||||
if ($request->filled('company_id')) {
|
||||
$users = $users->where('users.company_id', '=', $request->input('company_id'));
|
||||
}
|
||||
|
||||
@@ -87,7 +87,20 @@ class AssetModelsController extends Controller
|
||||
$model->fieldset_id = $request->input('fieldset_id');
|
||||
}
|
||||
|
||||
$model = $request->handleImages($model);
|
||||
if ($request->has('use_cloned_image')) {
|
||||
$cloned_model_img = AssetModel::select('image')->find($request->input('clone_image_from_id'));
|
||||
if ($cloned_model_img) {
|
||||
$new_image_name = 'clone-'.date('U').'-'.$cloned_model_img->image;
|
||||
$new_image = 'models/'.$new_image_name;
|
||||
Storage::disk('public')->copy('models/'.$cloned_model_img->image, $new_image);
|
||||
$model->image = $new_image_name;
|
||||
}
|
||||
|
||||
} else {
|
||||
$model = $request->handleImages($model);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ($model->save()) {
|
||||
if ($this->shouldAddDefaultValues($request->input())) {
|
||||
@@ -271,7 +284,7 @@ class AssetModelsController extends Controller
|
||||
->with('depreciation_list', Helper::depreciationList())
|
||||
->with('item', $model)
|
||||
->with('model_id', $model->id)
|
||||
->with('clone_model', $cloned_model);
|
||||
->with('cloned_model', $cloned_model);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -157,8 +157,16 @@ class AssetsController extends Controller
|
||||
$asset->location_id = $request->input('rtd_location_id', null);
|
||||
}
|
||||
|
||||
// Create the image (if one was chosen.)
|
||||
if ($request->has('image')) {
|
||||
if ($request->has('use_cloned_image')) {
|
||||
$cloned_model_img = Asset::select('image')->find($request->input('clone_image_from_id'));
|
||||
if ($cloned_model_img) {
|
||||
$new_image_name = 'clone-'.date('U').'-'.$cloned_model_img->image;
|
||||
$new_image = 'assets/'.$new_image_name;
|
||||
Storage::disk('public')->copy('assets/'.$cloned_model_img->image, $new_image);
|
||||
$asset->image = $new_image_name;
|
||||
}
|
||||
|
||||
} else {
|
||||
$asset = $request->handleImages($asset);
|
||||
}
|
||||
|
||||
@@ -644,8 +652,9 @@ class AssetsController extends Controller
|
||||
*/
|
||||
public function getClone(Asset $asset)
|
||||
{
|
||||
$this->authorize('create', $asset);
|
||||
$this->authorize('create', Asset::class);
|
||||
$cloned = clone $asset;
|
||||
$cloned_model = $asset;
|
||||
$cloned->id = null;
|
||||
$cloned->asset_tag = '';
|
||||
$cloned->serial = '';
|
||||
@@ -655,6 +664,7 @@ class AssetsController extends Controller
|
||||
return view('hardware/edit')
|
||||
->with('statuslabel_list', Helper::statusLabelList())
|
||||
->with('statuslabel_types', Helper::statusTypeList())
|
||||
->with('cloned_model', $cloned_model)
|
||||
->with('item', $cloned);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Models\Company;
|
||||
use App\Models\Consumable;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use \Illuminate\Contracts\View\View;
|
||||
@@ -81,11 +81,22 @@ class ConsumablesController extends Controller
|
||||
$consumable->purchase_date = $request->input('purchase_date');
|
||||
$consumable->purchase_cost = $request->input('purchase_cost');
|
||||
$consumable->qty = $request->input('qty');
|
||||
$consumable->created_by = auth()->id();
|
||||
$consumable->created_by = auth()->id();
|
||||
$consumable->notes = $request->input('notes');
|
||||
|
||||
|
||||
$consumable = $request->handleImages($consumable);
|
||||
if ($request->has('use_cloned_image')) {
|
||||
$cloned_model_img = Consumable::select('image')->find($request->input('clone_image_from_id'));
|
||||
if ($cloned_model_img) {
|
||||
$new_image_name = 'clone-'.date('U').'-'.$cloned_model_img->image;
|
||||
$new_image = 'consumables/'.$new_image_name;
|
||||
Storage::disk('public')->copy('consumables/'.$cloned_model_img->image, $new_image);
|
||||
$consumable->image = $new_image_name;
|
||||
}
|
||||
|
||||
} else {
|
||||
$consumable = $request->handleImages($consumable);
|
||||
}
|
||||
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
|
||||
@@ -213,9 +224,10 @@ class ConsumablesController extends Controller
|
||||
$consumable_to_close = $consumable;
|
||||
$consumable = clone $consumable_to_close;
|
||||
$consumable->id = null;
|
||||
$consumable->image = null;
|
||||
$consumable->created_by = null;
|
||||
|
||||
return view('consumables/edit')->with('item', $consumable);
|
||||
return view('consumables/edit')
|
||||
->with('cloned_model', $consumable_to_close)
|
||||
->with('item', $consumable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,13 +304,16 @@ class LicensesController extends Controller
|
||||
$response = new StreamedResponse(function () {
|
||||
// Open output stream
|
||||
$handle = fopen('php://output', 'w');
|
||||
$licenses= License::with('company',
|
||||
$licenses = License::with('company',
|
||||
'manufacturer',
|
||||
'category',
|
||||
'supplier',
|
||||
'adminuser',
|
||||
'assignedusers')
|
||||
->orderBy('created_at', 'DESC');
|
||||
'assignedusers');
|
||||
if (request()->filled('category_id')) {
|
||||
$licenses = $licenses->where('category_id', request()->input('category_id'));
|
||||
}
|
||||
$licenses = $licenses->orderBy('created_at', 'DESC');
|
||||
Company::scopeCompanyables($licenses)
|
||||
->chunk(500, function ($licenses) use ($handle) {
|
||||
$headers = [
|
||||
|
||||
@@ -96,7 +96,18 @@ class LocationsController extends Controller
|
||||
$location->company_id = $request->input('company_id');
|
||||
}
|
||||
|
||||
$location = $request->handleImages($location);
|
||||
if ($request->has('use_cloned_image')) {
|
||||
$cloned_model_img = Location::select('image')->find($request->input('clone_image_from_id'));
|
||||
if ($cloned_model_img) {
|
||||
$new_image_name = 'clone-'.date('U').'-'.$cloned_model_img->image;
|
||||
$new_image = 'locations/'.$new_image_name;
|
||||
Storage::disk('public')->copy('locations/'.$cloned_model_img->image, $new_image);
|
||||
$location->image = $new_image_name;
|
||||
}
|
||||
|
||||
} else {
|
||||
$location = $request->handleImages($location);
|
||||
}
|
||||
|
||||
if ($location->save()) {
|
||||
return redirect()->route('locations.index')->with('success', trans('admin/locations/message.create.success'));
|
||||
@@ -275,9 +286,9 @@ class LocationsController extends Controller
|
||||
|
||||
// unset these values
|
||||
$location->id = null;
|
||||
$location->image = null;
|
||||
|
||||
return view('locations/edit')
|
||||
->with('cloned_model', $location_to_clone)
|
||||
->with('item', $location);
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ class ManufacturersController extends Controller
|
||||
$manufacturers_count = Manufacturer::withTrashed()->count();
|
||||
|
||||
if ($manufacturers_count == 0) {
|
||||
Artisan::call('db:seed', ['--class' => 'ManufacturerSeeder']);
|
||||
Artisan::call('db:seed', ['--class' => 'Database\\Seeders\\ManufacturerSeeder', '--force' => true]);
|
||||
return redirect()->route('manufacturers.index')->with('success', trans('general.seeding.manufacturers.success'));
|
||||
}
|
||||
|
||||
|
||||
@@ -25,32 +25,22 @@ class UserFilesController extends Controller
|
||||
public function store(UploadFileRequest $request, User $user)
|
||||
{
|
||||
$this->authorize('update', $user);
|
||||
$files = $request->file('file');
|
||||
|
||||
if (is_null($files)) {
|
||||
return redirect()->back()->with('error', trans('admin/users/message.upload.nofiles'));
|
||||
}
|
||||
foreach ($files as $file) {
|
||||
$file_name = $request->handleFile('private_uploads/users/', 'user-'.$user->id, $file);
|
||||
|
||||
//Log the uploaded file to the log
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_id = $user->id;
|
||||
$logAction->item_type = User::class;
|
||||
$logAction->created_by = auth()->id();
|
||||
$logAction->note = $request->input('notes');
|
||||
$logAction->target_id = null;
|
||||
$logAction->created_at = date("Y-m-d H:i:s");
|
||||
$logAction->filename = $file_name;
|
||||
$logAction->action_type = 'uploaded';
|
||||
|
||||
if (! $logAction->save()) {
|
||||
return JsonResponse::create(['error' => 'Failed validation: '.print_r($logAction->getErrors(), true)], 500);
|
||||
if ($request->hasFile('file')) {
|
||||
if (! Storage::exists('private_uploads/users')) {
|
||||
Storage::makeDirectory('private_uploads/users', 775);
|
||||
}
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/users/message.upload.success'));
|
||||
foreach ($request->file('file') as $file) {
|
||||
$file_name = $request->handleFile('private_uploads/users/','user-'.$user->id, $file);
|
||||
$user->logUpload($file_name, $request->get('notes'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/users/message.upload.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->with('error', trans('admin/users/message.upload.nofiles'));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -432,7 +432,7 @@ class UsersController extends Controller
|
||||
app('request')->request->set('permissions', $permissions);
|
||||
|
||||
|
||||
$user_to_clone = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find($user->id);
|
||||
$user_to_clone = User::with('userloc')->withTrashed()->find($user->id);
|
||||
// Make sure they can view this particular user
|
||||
$this->authorize('view', $user_to_clone);
|
||||
|
||||
@@ -447,6 +447,8 @@ class UsersController extends Controller
|
||||
$user->last_name = '';
|
||||
$user->email = substr($user->email, ($pos = strpos($user->email, '@')) !== false ? $pos : 0);
|
||||
$user->id = null;
|
||||
$user->username = null;
|
||||
$user->avatar = null;
|
||||
|
||||
// Get this user's groups
|
||||
$userGroups = $user_to_clone->groups()->pluck('name', 'id');
|
||||
@@ -462,7 +464,7 @@ class UsersController extends Controller
|
||||
->with('user', $user)
|
||||
->with('groups', Group::pluck('name', 'id'))
|
||||
->with('userGroups', $userGroups)
|
||||
->with('clone_user', $user_to_clone)
|
||||
->with('cloned_model', $user_to_clone)
|
||||
->with('item', $user);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
namespace App\Http\Transformers;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\CustomField;
|
||||
@@ -16,6 +17,7 @@ use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class ActionlogsTransformer
|
||||
{
|
||||
@@ -133,24 +135,6 @@ class ActionlogsTransformer
|
||||
$clean_meta= $this->changedInfo($clean_meta);
|
||||
}
|
||||
|
||||
$file_url = '';
|
||||
if($actionlog->filename!='') {
|
||||
if ($actionlog->action_type == 'accepted') {
|
||||
$file_url = route('log.storedeula.download', ['filename' => $actionlog->filename]);
|
||||
} else {
|
||||
if ($actionlog->item) {
|
||||
if ($actionlog->itemType() == 'asset') {
|
||||
$file_url = route('show/assetfile', ['asset' => $actionlog->item->id, 'fileId' => $actionlog->id]);
|
||||
} elseif ($actionlog->itemType() == 'accessory') {
|
||||
$file_url = route('show.accessoryfile', ['accessoryId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
|
||||
} elseif ($actionlog->itemType() == 'license') {
|
||||
$file_url = route('show.licensefile', ['licenseId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
|
||||
} elseif ($actionlog->itemType() == 'user') {
|
||||
$file_url = route('show/userfile', ['user' => $actionlog->item->id, 'fileId' => $actionlog->id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$array = [
|
||||
'id' => (int) $actionlog->id,
|
||||
@@ -158,8 +142,10 @@ class ActionlogsTransformer
|
||||
'file' => ($actionlog->filename!='')
|
||||
?
|
||||
[
|
||||
'url' => $file_url,
|
||||
'url' => $actionlog->uploads_file_url(),
|
||||
'filename' => $actionlog->filename,
|
||||
'inlineable' => StorageHelper::allowSafeInline($actionlog->uploads_file_url()),
|
||||
'exists_on_disk' => Storage::exists($actionlog->uploads_file_path()) ? true : false,
|
||||
] : null,
|
||||
|
||||
'item' => ($actionlog->item) ? [
|
||||
|
||||
@@ -62,7 +62,7 @@ class LicensesTransformer
|
||||
'checkin' => Gate::allows('checkin', License::class),
|
||||
'clone' => Gate::allows('create', License::class),
|
||||
'update' => Gate::allows('update', License::class),
|
||||
'delete' => (Gate::allows('delete', License::class) && ($license->free_seats_count > 0)) ? true : false,
|
||||
'delete' => (Gate::allows('delete', License::class) && ($license->free_seats_count == $license->seats)) ? true : false,
|
||||
];
|
||||
|
||||
$array += $permissions_array;
|
||||
|
||||
@@ -32,10 +32,11 @@ class UploadedFilesTransformer
|
||||
'name' => e($file->filename),
|
||||
'item' => ($file->item_type) ? [
|
||||
'id' => (int) $file->item_id,
|
||||
'type' => strtolower(class_basename($file->item_type)),
|
||||
'type' => str_plural(strtolower(class_basename($file->item_type))),
|
||||
] : null,
|
||||
'filename' => e($file->filename),
|
||||
'filetype' => StorageHelper::getFiletype($file->uploads_file_path()),
|
||||
'mediatype' => StorageHelper::getMediaType($file->uploads_file_path()),
|
||||
'url' => $file->uploads_file_url(),
|
||||
'note' => ($file->note) ? e($file->note) : null,
|
||||
'created_by' => ($file->adminuser) ? [
|
||||
@@ -44,7 +45,7 @@ class UploadedFilesTransformer
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($file->created_at, 'datetime'),
|
||||
'deleted_at' => Helper::getFormattedDateObject($file->deleted_at, 'datetime'),
|
||||
'inline' => StorageHelper::allowSafeInline($file->uploads_file_path()),
|
||||
'inlineable' => StorageHelper::allowSafeInline($file->uploads_file_path()),
|
||||
'exists_on_disk' => (Storage::exists($file->uploads_file_path()) ? true : false),
|
||||
];
|
||||
|
||||
|
||||
@@ -22,6 +22,12 @@ class UsersTransformer
|
||||
public function transformUser(User $user)
|
||||
{
|
||||
|
||||
$role = '';
|
||||
if ($user->isSuperUser()) {
|
||||
$role = 'superadmin';
|
||||
} elseif ($user->isAdmin()) {
|
||||
$role = 'admin';
|
||||
}
|
||||
$array = [
|
||||
'id' => (int) $user->id,
|
||||
'avatar' => e($user->present()->gravatar) ?? null,
|
||||
@@ -59,6 +65,7 @@ class UsersTransformer
|
||||
'name'=> e($user->userloc->name),
|
||||
] : null,
|
||||
'notes'=> Helper::parseEscapedMarkedownInline($user->notes),
|
||||
'role' => $role,
|
||||
'permissions' => $user->decodePermissions(),
|
||||
'activated' => ($user->activated == '1') ? true : false,
|
||||
'autoassign_licenses' => ($user->autoassign_licenses == '1') ? true : false,
|
||||
|
||||
@@ -457,6 +457,11 @@ class Actionlog extends SnipeModel
|
||||
public function uploads_file_url()
|
||||
{
|
||||
|
||||
|
||||
if (($this->action_type == 'accepted') || ($this->action_type == 'declined')) {
|
||||
return route('log.storedeula.download', ['filename' => $this->filename]);
|
||||
}
|
||||
|
||||
switch ($this->item_type) {
|
||||
case Accessory::class:
|
||||
return route('show.accessoryfile', [$this->item_id, $this->id]);
|
||||
@@ -465,7 +470,7 @@ class Actionlog extends SnipeModel
|
||||
case AssetModel::class:
|
||||
return route('show/modelfile', [$this->item_id, $this->id]);
|
||||
case Consumable::class:
|
||||
return route('show/locationsfile', [$this->item_id, $this->id]);
|
||||
return route('show.consumablefile', [$this->item_id, $this->id]);
|
||||
case Component::class:
|
||||
return route('show.componentfile', [$this->item_id, $this->id]);
|
||||
case License::class:
|
||||
@@ -482,6 +487,10 @@ class Actionlog extends SnipeModel
|
||||
public function uploads_file_path()
|
||||
{
|
||||
|
||||
if (($this->action_type == 'accepted') || ($this->action_type == 'declined')) {
|
||||
return 'private_uploads/eula-pdfs/'.$this->filename;
|
||||
}
|
||||
|
||||
switch ($this->item_type) {
|
||||
case Accessory::class:
|
||||
return 'private_uploads/accessories/'.$this->filename;
|
||||
|
||||
@@ -226,7 +226,11 @@ class Asset extends Depreciable
|
||||
|
||||
foreach ($this->model->fieldset->fields as $field) {
|
||||
|
||||
if ($field->format == 'BOOLEAN') {
|
||||
// this just casts booleans that may come through as strings to an actual boolean type
|
||||
// adding !$field->field_encrypted because when the encrypted value comes through it
|
||||
// screws things up for the encrypted validation rules (and the encrypted string
|
||||
// is not a valid boolean type)
|
||||
if ($field->format == 'BOOLEAN' && !$field->field_encrypted) {
|
||||
$this->{$field->db_column} = filter_var($this->{$field->db_column}, FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ class CustomField extends Model
|
||||
UniqueUndeletedTrait;
|
||||
|
||||
/**
|
||||
*
|
||||
* Custom field predfined formats
|
||||
*
|
||||
* @var array
|
||||
|
||||
@@ -3,12 +3,19 @@
|
||||
namespace App\Models;
|
||||
|
||||
use App\Rules\AlphaEncrypted;
|
||||
use App\Rules\BooleanEncrypted;
|
||||
use App\Rules\DateEncrypted;
|
||||
use App\Rules\EmailEncrypted;
|
||||
use App\Rules\IPEncrypted;
|
||||
use App\Rules\IPv4Encrypted;
|
||||
use App\Rules\IPv6Encrypted;
|
||||
use App\Rules\MacEncrypted;
|
||||
use App\Rules\NumericEncrypted;
|
||||
use App\Rules\RegexEncrypted;
|
||||
use App\Rules\UrlEncrypted;
|
||||
use Gate;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
class CustomFieldset extends Model
|
||||
@@ -99,7 +106,7 @@ class CustomFieldset extends Model
|
||||
* @since [v3.0]
|
||||
* @return array
|
||||
*/
|
||||
public function validation_rules()
|
||||
public function validation_rules(): array
|
||||
{
|
||||
$rules = [];
|
||||
foreach ($this->fields as $field) {
|
||||
@@ -121,18 +128,65 @@ class CustomFieldset extends Model
|
||||
|
||||
$rules[$field->db_column_name()] = $rule;
|
||||
|
||||
|
||||
// these are to replace the standard 'numeric' and 'alpha' rules if the custom field is also encrypted.
|
||||
// the values need to be decrypted first, because encrypted strings are alphanumeric
|
||||
if ($field->format === 'NUMERIC' && $field->field_encrypted) {
|
||||
// this is to switch the rules to rules specially made for encrypted custom fields that decrypt the value before validating
|
||||
if ($field->field_encrypted) {
|
||||
$numericKey = array_search('numeric', $rules[$field->db_column_name()]);
|
||||
$rules[$field->db_column_name()][$numericKey] = new NumericEncrypted;
|
||||
$alphaKey = array_search('alpha', $rules[$field->db_column_name()]);
|
||||
$emailKey = array_search('email', $rules[$field->db_column_name()]);
|
||||
$dateKey = array_search('date', $rules[$field->db_column_name()]);
|
||||
$urlKey = array_search('url', $rules[$field->db_column_name()]);
|
||||
$ipKey = array_search('ip', $rules[$field->db_column_name()]);
|
||||
$ipv4Key = array_search('ipv4', $rules[$field->db_column_name()]);
|
||||
$ipv6Key = array_search('ipv6', $rules[$field->db_column_name()]);
|
||||
$macKey = array_search('regex:/^[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}$/', $rules[$field->db_column_name()]);
|
||||
$booleanKey = array_search('boolean', $rules[$field->db_column_name()]);
|
||||
// find objects in array that start with "regex:"
|
||||
// collect because i couldn't figure how to do this
|
||||
// with array filter and get keys out of it
|
||||
$regexCollect = collect($rules[$field->db_column_name()]);
|
||||
$regexKeys = $regexCollect->filter(function ($value, $key) {
|
||||
return starts_with($value, 'regex:');
|
||||
})->keys()->values()->toArray();
|
||||
|
||||
switch ($field->format) {
|
||||
case 'NUMERIC':
|
||||
$rules[$field->db_column_name()][$numericKey] = new NumericEncrypted;
|
||||
break;
|
||||
case 'ALPHA':
|
||||
$rules[$field->db_column_name()][$alphaKey] = new AlphaEncrypted;
|
||||
break;
|
||||
case 'EMAIL':
|
||||
$rules[$field->db_column_name()][$emailKey] = new EmailEncrypted;
|
||||
break;
|
||||
case 'DATE':
|
||||
$rules[$field->db_column_name()][$dateKey] = new DateEncrypted;
|
||||
break;
|
||||
case 'URL':
|
||||
$rules[$field->db_column_name()][$urlKey] = new UrlEncrypted;
|
||||
break;
|
||||
case 'IP':
|
||||
$rules[$field->db_column_name()][$ipKey] = new IPEncrypted;
|
||||
break;
|
||||
case 'IPV4':
|
||||
$rules[$field->db_column_name()][$ipv4Key] = new IPv4Encrypted;
|
||||
break;
|
||||
case 'IPV6':
|
||||
$rules[$field->db_column_name()][$ipv6Key] = new IPv6Encrypted;
|
||||
break;
|
||||
case 'MAC':
|
||||
$rules[$field->db_column_name()][$macKey] = new MacEncrypted;
|
||||
break;
|
||||
case 'BOOLEAN':
|
||||
$rules[$field->db_column_name()][$booleanKey] = new BooleanEncrypted;
|
||||
break;
|
||||
case starts_with($field->format, 'regex'):
|
||||
foreach ($regexKeys as $regexKey) {
|
||||
$rules[$field->db_column_name()][$regexKey] = new RegexEncrypted;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($field->format === 'ALPHA' && $field->field_encrypted) {
|
||||
$alphaKey = array_search('alpha', $rules[$field->db_column_name()]);
|
||||
$rules[$field->db_column_name()][$alphaKey] = new AlphaEncrypted;
|
||||
}
|
||||
|
||||
// add not_array to rules for all fields but checkboxes
|
||||
if ($field->element != 'checkbox') {
|
||||
|
||||
+43
-5
@@ -891,6 +891,49 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return only admins and superusers
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
*/
|
||||
public function scopeOnlySuperAdmins($query)
|
||||
{
|
||||
|
||||
return $query->where('users.permissions', 'LIKE', '%"superuser":"1"%')
|
||||
->orWhere('users.permissions', 'LIKE', '%"superuser":1%')
|
||||
->orWhereHas(
|
||||
'groups', function ($query) {
|
||||
$query->where('permission_groups.permissions', 'LIKE', '%"superuser":"1"%')
|
||||
->orWhere('permission_groups.permissions', 'LIKE', '%"superuser":1%');
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return only admins and superusers
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
*/
|
||||
public function scopeOnlyAdminsAndSuperAdmins($query)
|
||||
{
|
||||
|
||||
return $query->where('users.permissions', 'LIKE', '%"superuser":"1"%')
|
||||
->orWhere('users.permissions', 'LIKE', '%"superuser":1%')
|
||||
->orWhere('users.permissions', 'LIKE', '%"admin":1%')
|
||||
->orWhere('users.permissions', 'LIKE', '%"admin":"1"%')
|
||||
->orWhereHas(
|
||||
'groups', function ($query) {
|
||||
$query->where('permission_groups.permissions', 'LIKE', '%"superuser":"1"%')
|
||||
->orWhere('permission_groups.permissions', 'LIKE', '%"superuser":1%')
|
||||
->orWhere('permission_groups.permissions', 'LIKE', '%"admin":1%')
|
||||
->orWhere('permission_groups.permissions', 'LIKE', '%"admin":"1"%');
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope to order on manager
|
||||
@@ -964,7 +1007,6 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the preferred locale for the user.
|
||||
*
|
||||
@@ -1003,7 +1045,6 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
public function scopeUserLocation($query, $location, $search)
|
||||
{
|
||||
|
||||
|
||||
return $query->where('location_id', '=', $location)
|
||||
->where('users.first_name', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('users.email', 'LIKE', '%' . $search . '%')
|
||||
@@ -1016,9 +1057,6 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
->orWhere('users.username', 'LIKE', '%' . $search . '%')
|
||||
->orwhereRaw('CONCAT(users.first_name," ",users.last_name) LIKE \''.$search.'%\'');
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -106,7 +106,7 @@ class HistoryPresenter extends Presenter
|
||||
'switchable' => true,
|
||||
'title' => trans('general.file_name'),
|
||||
'visible' => true,
|
||||
'formatter' => 'fileUploadNameFormatter',
|
||||
'formatter' => 'fileNameFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'file_download',
|
||||
@@ -115,7 +115,7 @@ class HistoryPresenter extends Presenter
|
||||
'switchable' => true,
|
||||
'title' => trans('general.download'),
|
||||
'visible' => true,
|
||||
'formatter' => 'fileUploadFormatter',
|
||||
'formatter' => 'fileDownloadButtonsFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'note',
|
||||
|
||||
@@ -18,7 +18,7 @@ class UploadedFilesPresenter extends Presenter
|
||||
$layout = [
|
||||
[
|
||||
'field' => 'id',
|
||||
'searchable' => false,
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => trans('general.id'),
|
||||
@@ -30,6 +30,7 @@ class UploadedFilesPresenter extends Presenter
|
||||
'sortable' => false,
|
||||
'switchable' => false,
|
||||
'title' => trans('general.type'),
|
||||
'visible' => true,
|
||||
'formatter' => 'iconFormatter',
|
||||
],
|
||||
[
|
||||
@@ -38,16 +39,17 @@ class UploadedFilesPresenter extends Presenter
|
||||
'sortable' => false,
|
||||
'switchable' => true,
|
||||
'title' => trans('general.image'),
|
||||
'formatter' => 'inlineImageFormatter',
|
||||
'visible' => true,
|
||||
'formatter' => 'filePreviewFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'filename',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => trans('general.file_name'),
|
||||
'visible' => true,
|
||||
'formatter' => 'fileUploadNameFormatter',
|
||||
'formatter' => 'fileNameFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'download',
|
||||
@@ -56,7 +58,7 @@ class UploadedFilesPresenter extends Presenter
|
||||
'switchable' => true,
|
||||
'title' => trans('general.download'),
|
||||
'visible' => true,
|
||||
'formatter' => 'downloadOrOpenInNewWindowFormatter',
|
||||
'formatter' => 'fileDownloadButtonsFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'note',
|
||||
@@ -68,10 +70,10 @@ class UploadedFilesPresenter extends Presenter
|
||||
],
|
||||
[
|
||||
'field' => 'created_by',
|
||||
'searchable' => false,
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'title' => trans('general.created_by'),
|
||||
'visible' => false,
|
||||
'visible' => true,
|
||||
'formatter' => 'usersLinkObjFormatter',
|
||||
],
|
||||
[
|
||||
@@ -80,7 +82,7 @@ class UploadedFilesPresenter extends Presenter
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => trans('general.created_at'),
|
||||
'visible' => false,
|
||||
'visible' => true,
|
||||
'formatter' => 'dateDisplayFormatter',
|
||||
], [
|
||||
'field' => 'available_actions',
|
||||
@@ -88,6 +90,7 @@ class UploadedFilesPresenter extends Presenter
|
||||
'sortable' => false,
|
||||
'switchable' => false,
|
||||
'title' => trans('table.actions'),
|
||||
'visible' => true,
|
||||
'formatter' => 'deleteUploadFormatter',
|
||||
],
|
||||
];
|
||||
|
||||
@@ -180,7 +180,7 @@ class UserPresenter extends Presenter
|
||||
'switchable' => false,
|
||||
'title' => trans('admin/users/table.username'),
|
||||
'visible' => true,
|
||||
'formatter' => 'usersLinkFormatter',
|
||||
'formatter' => 'usernameRoleLinkFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'employee_num',
|
||||
|
||||
@@ -539,6 +539,16 @@ class BreadcrumbsServiceProvider extends ServiceProvider
|
||||
->push(trans('general.users'), route('users.index'))
|
||||
->push(trans('general.deleted_users'), route('users.index'))
|
||||
);
|
||||
} elseif ((request()->is('users*')) && (request()->admins=='true')) {
|
||||
Breadcrumbs::for('users.index', fn(Trail $trail) => $trail->parent('home', route('home'))
|
||||
->push(trans('general.users'), route('users.index'))
|
||||
->push(trans('general.show_admins'), route('users.index'))
|
||||
);
|
||||
} elseif ((request()->is('users*')) && (request()->superadmins=='true')) {
|
||||
Breadcrumbs::for('users.index', fn(Trail $trail) => $trail->parent('home', route('home'))
|
||||
->push(trans('general.users'), route('users.index'))
|
||||
->push(trans('general.show_superadmins'), route('users.index'))
|
||||
);
|
||||
} else {
|
||||
Breadcrumbs::for('users.index', fn(Trail $trail) => $trail->parent('home', route('home'))
|
||||
->push(trans('general.users'), route('users.index'))
|
||||
|
||||
@@ -5,9 +5,11 @@ namespace App\Rules;
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Validation\Concerns\ValidatesAttributes;
|
||||
|
||||
class AlphaEncrypted implements ValidationRule
|
||||
{
|
||||
use ValidatesAttributes;
|
||||
/**
|
||||
* Run the validation rule.
|
||||
*
|
||||
@@ -18,7 +20,7 @@ class AlphaEncrypted implements ValidationRule
|
||||
try {
|
||||
$attributeName = trim(preg_replace('/_+|snipeit|\d+/', ' ', $attribute));
|
||||
$decrypted = Crypt::decrypt($value);
|
||||
if (!ctype_alpha($decrypted) && !is_null($decrypted)) {
|
||||
if (!$this->validateAlpha($attributeName, $decrypted, 'ascii') && !is_null($decrypted)) {
|
||||
$fail(trans('validation.alpha', ['attribute' => $attributeName]));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Rules;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Validation\Concerns\ValidatesAttributes;
|
||||
|
||||
class BooleanEncrypted implements ValidationRule
|
||||
{
|
||||
use ValidatesAttributes;
|
||||
|
||||
/**
|
||||
* Run the validation rule.
|
||||
*
|
||||
* @param \Closure(string, ?string=): \Illuminate\Translation\PotentiallyTranslatedString $fail
|
||||
*/
|
||||
public function validate(string $attribute, mixed $value, Closure $fail): void
|
||||
{
|
||||
try {
|
||||
$attributeName = trim(preg_replace('/_+|snipeit|\d+/', ' ', $attribute));
|
||||
$decrypted = Crypt::decrypt($value);
|
||||
|
||||
if (!$this->validateBoolean($attributeName, $decrypted) && !is_null($decrypted)) {
|
||||
$fail(trans('validation.ipv6', ['attribute' => $attributeName]));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
report($e);
|
||||
$fail(trans('general.something_went_wrong'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Rules;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Validation\Concerns\ValidatesAttributes;
|
||||
|
||||
class DateEncrypted implements ValidationRule
|
||||
{
|
||||
use ValidatesAttributes;
|
||||
|
||||
/**
|
||||
* Run the validation rule.
|
||||
*
|
||||
* @param \Closure(string): \Illuminate\Translation\PotentiallyTranslatedString $fail
|
||||
*/
|
||||
public function validate(string $attribute, mixed $value, Closure $fail): void
|
||||
{
|
||||
try {
|
||||
$attributeName = trim(preg_replace('/_+|snipeit|\d+/', ' ', $attribute));
|
||||
$decrypted = Crypt::decrypt($value);
|
||||
if (!$this->validateDate($attributeName, $decrypted) && !is_null($decrypted)) {
|
||||
$fail(trans('validation.date', ['attribute' => $attributeName]));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
report($e);
|
||||
$fail(trans('general.something_went_wrong'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Rules;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Validation\Concerns\ValidatesAttributes;
|
||||
|
||||
class EmailEncrypted implements ValidationRule
|
||||
{
|
||||
use ValidatesAttributes;
|
||||
|
||||
/**
|
||||
* Run the validation rule.
|
||||
*
|
||||
* @param \Closure(string, ?string=): \Illuminate\Translation\PotentiallyTranslatedString $fail
|
||||
*/
|
||||
public function validate(string $attribute, mixed $value, Closure $fail): void
|
||||
{
|
||||
try {
|
||||
$attributeName = trim(preg_replace('/_+|snipeit|\d+/', ' ', $attribute));
|
||||
$decrypted = Crypt::decrypt($value);
|
||||
if (!$this->validateEmail($attribute, $decrypted, []) && !is_null($decrypted)) {
|
||||
$fail(trans('validation.email', ['attribute' => $attributeName]));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
report($e);
|
||||
$fail(trans('general.something_went_wrong'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Rules;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Validation\Concerns\ValidatesAttributes;
|
||||
|
||||
class IPEncrypted implements ValidationRule
|
||||
{
|
||||
use ValidatesAttributes;
|
||||
|
||||
/**
|
||||
* Run the validation rule.
|
||||
*
|
||||
* @param \Closure(string): \Illuminate\Translation\PotentiallyTranslatedString $fail
|
||||
*/
|
||||
public function validate(string $attribute, mixed $value, Closure $fail): void
|
||||
{
|
||||
try {
|
||||
$attributeName = trim(preg_replace('/_+|snipeit|\d+/', ' ', $attribute));
|
||||
$decrypted = Crypt::decrypt($value);
|
||||
if (!$this->validateIp($attributeName, $decrypted) && !is_null($decrypted)) {
|
||||
$fail(trans('validation.ip', ['attribute' => $attributeName]));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
report($e);
|
||||
$fail(trans('general.something_went_wrong'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Rules;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Validation\Concerns\ValidatesAttributes;
|
||||
|
||||
class IPv4Encrypted implements ValidationRule
|
||||
{
|
||||
use ValidatesAttributes;
|
||||
|
||||
/**
|
||||
* Run the validation rule.
|
||||
*
|
||||
* @param \Closure(string): \Illuminate\Translation\PotentiallyTranslatedString $fail
|
||||
*/
|
||||
public function validate(string $attribute, mixed $value, Closure $fail): void
|
||||
{
|
||||
try {
|
||||
$attributeName = trim(preg_replace('/_+|snipeit|\d+/', ' ', $attribute));
|
||||
$decrypted = Crypt::decrypt($value);
|
||||
if (!$this->validateIpv4($attributeName, $decrypted) && !is_null($decrypted)) {
|
||||
$fail(trans('validation.ipv4', ['attribute' => $attributeName]));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
report($e);
|
||||
$fail(trans('general.something_went_wrong'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Rules;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Validation\Concerns\ValidatesAttributes;
|
||||
|
||||
class IPv6Encrypted implements ValidationRule
|
||||
{
|
||||
use ValidatesAttributes;
|
||||
|
||||
/**
|
||||
* Run the validation rule.
|
||||
*
|
||||
* @param \Closure(string): \Illuminate\Translation\PotentiallyTranslatedString $fail
|
||||
*/
|
||||
public function validate(string $attribute, mixed $value, Closure $fail): void
|
||||
{
|
||||
try {
|
||||
$attributeName = trim(preg_replace('/_+|snipeit|\d+/', ' ', $attribute));
|
||||
$decrypted = Crypt::decrypt($value);
|
||||
if (!$this->validateIpv6($attributeName, $decrypted) && !is_null($decrypted)) {
|
||||
$fail(trans('validation.ipv6', ['attribute' => $attributeName]));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
report($e);
|
||||
$fail(trans('general.something_went_wrong'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Rules;
|
||||
|
||||
use App\Models\CustomField;
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Validation\Concerns\ValidatesAttributes;
|
||||
|
||||
class MacEncrypted implements ValidationRule
|
||||
{
|
||||
use ValidatesAttributes;
|
||||
|
||||
/**
|
||||
* Run the validation rule.
|
||||
*
|
||||
* @param \Closure(string): \Illuminate\Translation\PotentiallyTranslatedString $fail
|
||||
*/
|
||||
public function validate(string $attribute, mixed $value, Closure $fail): void
|
||||
{
|
||||
try {
|
||||
$attributeName = trim(preg_replace('/_+|snipeit|\d+/', ' ', $attribute));
|
||||
$decrypted = Crypt::decrypt($value);
|
||||
if (!$this->validateRegex($attributeName, $decrypted, ['/^[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}$/']) && !is_null($decrypted)) {
|
||||
$fail(trans('validation.mac_address', ['attribute' => $attributeName]));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
report($e);
|
||||
$fail(trans('general.something_went_wrong'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,16 @@
|
||||
namespace App\Rules;
|
||||
|
||||
use Closure;
|
||||
use Egulias\EmailValidator\Validation\RFCValidation;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Validation\Concerns\ValidatesAttributes;
|
||||
|
||||
class NumericEncrypted implements ValidationRule
|
||||
{
|
||||
use ValidatesAttributes;
|
||||
|
||||
/**
|
||||
* Run the validation rule.
|
||||
*
|
||||
@@ -16,11 +20,10 @@ class NumericEncrypted implements ValidationRule
|
||||
*/
|
||||
public function validate(string $attribute, mixed $value, Closure $fail): void
|
||||
{
|
||||
|
||||
try {
|
||||
$attributeName = trim(preg_replace('/_+|snipeit|\d+/', ' ', $attribute));
|
||||
$decrypted = Crypt::decrypt($value);
|
||||
if (!is_numeric($decrypted) && !is_null($decrypted)) {
|
||||
if (!$this->validateNumeric($attributeName, $decrypted) && !is_null($decrypted)) {
|
||||
$fail(trans('validation.numeric', ['attribute' => $attributeName]));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Rules;
|
||||
|
||||
use App\Models\CustomField;
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Validation\Concerns\ValidatesAttributes;
|
||||
|
||||
class RegexEncrypted implements ValidationRule
|
||||
{
|
||||
use ValidatesAttributes;
|
||||
|
||||
/**
|
||||
* Run the validation rule.
|
||||
*
|
||||
* @param \Closure(string, ?string=): \Illuminate\Translation\PotentiallyTranslatedString $fail
|
||||
*/
|
||||
public function validate(string $attribute, mixed $value, Closure $fail): void
|
||||
{
|
||||
$field = CustomField::where('db_column', $attribute)->first();
|
||||
$regex = $field->format;
|
||||
$regex = str_replace('regex:', '', $regex);
|
||||
try {
|
||||
$attributeName = trim(preg_replace('/_+|snipeit|\d+/', ' ', $attribute));
|
||||
$decrypted = Crypt::decrypt($value);
|
||||
if (!$this->validateRegex($attributeName, $decrypted, [$regex]) && !is_null($decrypted)) {
|
||||
$fail(trans('validation.regex', ['attribute' => $attributeName]));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
report($e->getMessage());
|
||||
$fail(trans('general.something_went_wrong'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Rules;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Validation\Concerns\ValidatesAttributes;
|
||||
|
||||
class UrlEncrypted implements ValidationRule
|
||||
{
|
||||
use ValidatesAttributes;
|
||||
|
||||
/**
|
||||
* Run the validation rule.
|
||||
*
|
||||
* @param \Closure(string): \Illuminate\Translation\PotentiallyTranslatedString $fail
|
||||
*/
|
||||
public function validate(string $attribute, mixed $value, Closure $fail): void
|
||||
{
|
||||
try {
|
||||
$attributeName = trim(preg_replace('/_+|snipeit|\d+/', ' ', $attribute));
|
||||
$decrypted = Crypt::decrypt($value);
|
||||
if (!$this->validateUrl($attributeName, $decrypted, []) && !is_null($decrypted)) {
|
||||
$fail(trans('validation.url', ['attribute' => $attributeName]));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
report($e);
|
||||
$fail(trans('general.something_went_wrong'));
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -37,7 +37,7 @@
|
||||
"doctrine/dbal": "^3.1",
|
||||
"doctrine/instantiator": "^1.3",
|
||||
"eduardokum/laravel-mail-auto-embed": "^2.0",
|
||||
"enshrined/svg-sanitize": "^0.15.0",
|
||||
"enshrined/svg-sanitize": "^0.16.0",
|
||||
"erusev/parsedown": "^1.7",
|
||||
"fakerphp/faker": "^1.24",
|
||||
"guzzlehttp/guzzle": "^7.0.1",
|
||||
|
||||
Generated
+1190
-1077
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -18,7 +18,7 @@ $dump_options = [
|
||||
//'add_extra_option' => '--optionname=optionvalue',
|
||||
];
|
||||
|
||||
// Some versions of mysql do not support the --skip-ssl option and will fail if it is
|
||||
// Some versions of mysql do not support the --skip-ssl option and will fail if it is even set
|
||||
if (env('DB_DUMP_SKIP_SSL') == 'true') {
|
||||
$dump_options['skip_ssl'] = true;
|
||||
}
|
||||
|
||||
+30
-162
@@ -4,50 +4,31 @@
|
||||
|--------------------------------------------------------------------------
|
||||
| DO NOT EDIT THIS FILE DIRECTLY.
|
||||
|--------------------------------------------------------------------------
|
||||
| This file reads from your .env configuration file and should not
|
||||
| This file reads from your .env configuration file and should NOT
|
||||
| be modified directly.
|
||||
| See https://snipe-it.readme.io/docs/configuration for more info.
|
||||
*/
|
||||
|
||||
|
||||
return [
|
||||
|
||||
|
||||
/*
|
||||
| ***************************************************************************
|
||||
| DO NOT MAKE CHANGES DIRECTLY TO THIS FILE.
|
||||
|
|
||||
| Instead use your .env file to set your application configuration settings.
|
||||
| See https://snipe-it.readme.io/docs/configuration for more info.
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Mail Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Laravel supports both SMTP and PHP's "mail" function as drivers for the
|
||||
| sending of e-mail. You may specify which one you're using throughout
|
||||
| your application here. By default, Laravel is setup for SMTP mail.
|
||||
|
|
||||
|
|
||||
| Supported: "smtp", "mail", "sendmail", "mailgun", "mandrill", "ses", "log"
|
||||
|
|
||||
*/
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Mailer
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default mailer that is used to send any email
|
||||
| messages sent by your application. Alternative mailers may be setup
|
||||
| and used as needed; however, this mailer will be used by default.
|
||||
| This option controls the default mailer that is used to send all email
|
||||
| messages unless another mailer is explicitly specified when sending
|
||||
| the message. All additional mailers can be configured within the
|
||||
| "mailers" array. Examples of each type of mailer are provided.
|
||||
|
|
||||
| Previous versions of Snipe-IT and Laravel used SwiftMailer, which used
|
||||
| MAIL_DRIVER instead of MAIL_MAILER. In order to not break existing
|
||||
| installations, we'll accept both
|
||||
| installations, we'll accept both.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('MAIL_DRIVER') != null ? env('MAIL_DRIVER') : env('MAIL_MAILER', 'smtp'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Mailer Configurations
|
||||
@@ -57,112 +38,29 @@ return [
|
||||
| their respective settings. Several examples have been configured for
|
||||
| you and you are free to add your own as your application requires.
|
||||
|
|
||||
| Laravel supports a variety of mail "transport" drivers to be used while
|
||||
| sending an e-mail. You will specify which one you are using for your
|
||||
| mailers below. You are free to add additional mailers as required.
|
||||
| Laravel supports a variety of mail "transport" drivers that can be used
|
||||
| when delivering an email. You may specify which one you're using for
|
||||
| your mailers below. You may also add additional mailers if needed.
|
||||
|
|
||||
| Supported: "smtp", "sendmail", "mailgun", "ses", "ses-v2",
|
||||
| "postmark", "log", "array", "failover", "roundrobin"
|
||||
| "postmark", "resend", "log", "array",
|
||||
| "failover", "roundrobin"
|
||||
|
|
||||
*/
|
||||
|
||||
'mailers' => [
|
||||
|
||||
'smtp' => [
|
||||
// Don't touch this. For the smtp mailer, the transport needs to be smtp
|
||||
'transport' => 'smtp',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| SMTP Host Address
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may provide the host address of the SMTP server used by your
|
||||
| applications. A default option is provided that is compatible with
|
||||
| the Mailgun mail service which will provide reliable deliveries.
|
||||
|
|
||||
*/
|
||||
'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| SMTP Host Port
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This is the SMTP port used by your application to deliver e-mails to
|
||||
| users of the application. Like the host we have set this value to
|
||||
| stay compatible with the Mailgun e-mail application by default.
|
||||
|
|
||||
*/
|
||||
|
||||
'port' => env('MAIL_PORT', 587),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| SMTP Server Username
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If your SMTP server requires a username for authentication, you should
|
||||
| set it here. This will get used to authenticate with your server on
|
||||
| connection. You may also set the "password" value below this one.
|
||||
|
|
||||
*/
|
||||
|
||||
'scheme' => env('MAIL_SCHEME'),
|
||||
'url' => env('MAIL_URL'),
|
||||
'host' => env('MAIL_HOST', '127.0.0.1'),
|
||||
'port' => env('MAIL_PORT', 2525),
|
||||
'username' => env('MAIL_USERNAME'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| SMTP Server Password
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may set the password required by your SMTP server to send out
|
||||
| messages from your application. This will be given to the server on
|
||||
| connection so that the application will be able to send messages.
|
||||
|
|
||||
*/
|
||||
|
||||
'password' => env('MAIL_PASSWORD'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| SMTP Server connection timeout
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Give up trying to connect to the mail server after this many seconds
|
||||
|
|
||||
*/
|
||||
|
||||
'timeout' => 30,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| mostly pointless encryption option
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This used to let you specify whether or not to use TLS, but now it really
|
||||
| just helps inform the code about which SMTP port to use. SymfonMailer will
|
||||
| still use TLS if the server offers it, regardless of how this is set.
|
||||
| We're only including it here for reference, and the extreme edge-case where
|
||||
| Symfony can't figure out what to do on its own.
|
||||
|
|
||||
*/
|
||||
|
||||
'encryption' => env('MAIL_ENCRYPTION', 'tls'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Verify SMTP TLS certificate
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| As noted above, Swiftmailer WILL use TLS if the server offers it, so if
|
||||
| you're using a self-signed certificate or want to refer to your mailserver
|
||||
| by a name that isn't in the certificate (like the IP address), set this
|
||||
| to 0 or false.
|
||||
|
|
||||
*/
|
||||
|
||||
'timeout' => null,
|
||||
'local_domain' => env('MAIL_EHLO_DOMAIN', parse_url(env('APP_URL', 'http://localhost'), PHP_URL_HOST)),
|
||||
'verify_peer' => env('MAIL_TLS_VERIFY_PEER', 1),
|
||||
|
||||
],
|
||||
|
||||
'ses' => [
|
||||
@@ -171,29 +69,16 @@ return [
|
||||
|
||||
'postmark' => [
|
||||
'transport' => 'postmark',
|
||||
// 'message_stream_id' => null,
|
||||
// 'message_stream_id' => env('POSTMARK_MESSAGE_STREAM_ID'),
|
||||
// 'client' => [
|
||||
// 'timeout' => 5,
|
||||
// ],
|
||||
],
|
||||
|
||||
'mailgun' => [
|
||||
'transport' => 'mailgun',
|
||||
// 'client' => [
|
||||
// 'timeout' => 5,
|
||||
// ],
|
||||
'resend' => [
|
||||
'transport' => 'resend',
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Sendmail System Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the "sendmail" driver to send e-mails, we will need to know
|
||||
| the path to where Sendmail lives on this server. A default path has
|
||||
| been provided here, which will work well on most of your systems.
|
||||
|
|
||||
*/
|
||||
'sendmail' => [
|
||||
'transport' => 'sendmail',
|
||||
'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -bs -i'),
|
||||
@@ -223,6 +108,7 @@ return [
|
||||
'postmark',
|
||||
],
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
@@ -230,15 +116,15 @@ return [
|
||||
| Global "From" Address
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| You may wish for all e-mails sent by your application to be sent from
|
||||
| the same address. Here, you may specify a name and address that is
|
||||
| used globally for all e-mails that are sent by your application.
|
||||
| You may wish for all emails sent by your application to be sent from
|
||||
| the same address. Here you may specify a name and address that is
|
||||
| used globally for all emails that are sent by your application.
|
||||
|
|
||||
*/
|
||||
|
||||
'from' => [
|
||||
'address' => env('MAIL_FROM_ADDR', null),
|
||||
'name' => env('MAIL_FROM_NAME', null),
|
||||
'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'),
|
||||
'name' => env('MAIL_FROM_NAME', 'Example'),
|
||||
],
|
||||
|
||||
/*
|
||||
@@ -257,23 +143,5 @@ return [
|
||||
'name' => env('MAIL_REPLYTO_NAME', null),
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Markdown Mail Settings
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If you are using Markdown based email rendering, you may configure your
|
||||
| theme and component paths here, allowing you to customize the design
|
||||
| of the emails. Or, you may simply stick with the Laravel defaults!
|
||||
|
|
||||
*/
|
||||
|
||||
'markdown' => [
|
||||
'theme' => 'default',
|
||||
|
||||
'paths' => [
|
||||
resource_path('views/vendor/mail'),
|
||||
],
|
||||
],
|
||||
|
||||
];
|
||||
];
|
||||
@@ -93,6 +93,42 @@ class CustomFieldFactory extends Factory
|
||||
});
|
||||
}
|
||||
|
||||
public function encrypt()
|
||||
{
|
||||
return $this->state(function () {
|
||||
return [
|
||||
'field_encrypted' => '1',
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
public function alpha()
|
||||
{
|
||||
return $this->state(function () {
|
||||
return [
|
||||
'format' => 'alpha',
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
public function numeric()
|
||||
{
|
||||
return $this->state(function () {
|
||||
return [
|
||||
'format' => 'numeric',
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
public function email()
|
||||
{
|
||||
return $this->state(function () {
|
||||
return [
|
||||
'format' => 'email',
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
public function testCheckbox()
|
||||
{
|
||||
return $this->state(function () {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use \App\Helpers\Helper;
|
||||
use \App\Models\Setting;
|
||||
use \App\Models\User;
|
||||
|
||||
Generated
+853
-1148
File diff suppressed because it is too large
Load Diff
+8
-9
@@ -17,12 +17,12 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"all-contributors-cli": "^6.26.1",
|
||||
"axios": "^1.7.2",
|
||||
"babel-preset-latest": "^6.24.1",
|
||||
"axios": "^1.11.0",
|
||||
"jquery": "<3.6.0",
|
||||
"laravel-mix": "^6.0.49",
|
||||
"lodash": "^4.17.20",
|
||||
"postcss": "^8.4.5"
|
||||
"postcss": "^8.5.6",
|
||||
"webpack": "^5.98.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^6.7.2",
|
||||
@@ -35,18 +35,18 @@
|
||||
"bootstrap-colorpicker": "^2.5.3",
|
||||
"bootstrap-datepicker": "^1.10.0",
|
||||
"bootstrap-less": "^3.3.8",
|
||||
"bootstrap-table": "1.24.1",
|
||||
"bootstrap-table": "1.24.2",
|
||||
"canvas-confetti": "^1.9.3",
|
||||
"chart.js": "^2.9.4",
|
||||
"clipboard": "^2.0.11",
|
||||
"css-loader": "^5.0.0",
|
||||
"ekko-lightbox": "^5.1.1",
|
||||
"imagemin": "^8.0.1",
|
||||
"imagemin": "^9.0.1",
|
||||
"jquery-slimscroll": "^1.3.8",
|
||||
"jquery-ui": "^1.14.1",
|
||||
"jquery-validation": "^1.21.0",
|
||||
"jquery.iframe-transport": "^1.0.0",
|
||||
"jspdf-autotable": "^3.8.4",
|
||||
"jspdf-autotable": "^5.0.2",
|
||||
"less": "^4.2.2",
|
||||
"less-loader": "^6.0",
|
||||
"list.js": "^1.5.0",
|
||||
@@ -55,8 +55,7 @@
|
||||
"select2": "4.0.13",
|
||||
"sheetjs": "^2.0.0",
|
||||
"signature_pad": "^4.2.0",
|
||||
"tableexport.jquery.plugin": "1.32.0",
|
||||
"tether": "^1.4.0",
|
||||
"webpack": "^5.98.0"
|
||||
"tableexport.jquery.plugin": "^1.33.0",
|
||||
"tether": "^1.4.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5418,3 +5418,5 @@ hr {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=AdminLTE.css.map*/
|
||||
File diff suppressed because one or more lines are too long
@@ -1469,3 +1469,5 @@ caption.tableCaption {
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=app.css.map*/
|
||||
File diff suppressed because one or more lines are too long
@@ -1090,3 +1090,5 @@ caption.tableCaption {
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=overrides.css.map*/
|
||||
File diff suppressed because one or more lines are too long
Vendored
+5
-1
@@ -20167,6 +20167,7 @@ hr {
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=AdminLTE.css.map*/
|
||||
/*!
|
||||
* Datepicker for Bootstrap v1.10.0 (https://github.com/uxsolutions/bootstrap-datepicker)
|
||||
*
|
||||
@@ -21008,7 +21009,7 @@ hr {
|
||||
@charset "UTF-8";
|
||||
/**
|
||||
* @author zhixin wen <wenzhixin2010@gmail.com>
|
||||
* version: 1.24.1
|
||||
* version: 1.24.2
|
||||
* https://github.com/wenzhixin/bootstrap-table/
|
||||
*/
|
||||
/* stylelint-disable annotation-no-unknown, max-line-length */
|
||||
@@ -22805,6 +22806,7 @@ caption.tableCaption {
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=app.css.map*/
|
||||
.select2-container {
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
@@ -24379,3 +24381,5 @@ caption.tableCaption {
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=overrides.css.map*/
|
||||
Vendored
+1
-1
@@ -1,7 +1,7 @@
|
||||
@charset "UTF-8";
|
||||
/**
|
||||
* @author zhixin wen <wenzhixin2010@gmail.com>
|
||||
* version: 1.24.1
|
||||
* version: 1.24.2
|
||||
* https://github.com/wenzhixin/bootstrap-table/
|
||||
*/
|
||||
/* stylelint-disable annotation-no-unknown, max-line-length */
|
||||
|
||||
Vendored
+2
@@ -5471,3 +5471,5 @@ tr th div.th-inner {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=_all-skins.css.map*/
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+2
@@ -5471,3 +5471,5 @@ tr th div.th-inner {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=_all-skins.css.map*/
|
||||
+2
@@ -557,3 +557,5 @@ div.container.row-new-striped {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-black-dark.css.map*/
|
||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -557,3 +557,5 @@ div.container.row-new-striped {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-black-dark.css.map*/
|
||||
Vendored
+2
@@ -217,3 +217,5 @@ a.btn-danger:visited {
|
||||
background-color: #e9d15b;
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-black.css.map*/
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+2
@@ -217,3 +217,5 @@ a.btn-danger:visited {
|
||||
background-color: #e9d15b;
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-black.css.map*/
|
||||
+2
@@ -537,3 +537,5 @@ a:visited {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-blue-dark.css.map*/
|
||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -537,3 +537,5 @@ a:visited {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-blue-dark.css.map*/
|
||||
Vendored
+2
@@ -249,3 +249,5 @@ a.label.label-default:hover {
|
||||
color: #296282;
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-blue.css.map*/
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+2
@@ -249,3 +249,5 @@ a.label.label-default:hover {
|
||||
color: #296282;
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-blue.css.map*/
|
||||
+2
@@ -225,3 +225,5 @@ input::-ms-input-placeholder {
|
||||
background-color: #e9d15b;
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-contrast.css.map*/
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+2
@@ -225,3 +225,5 @@ input::-ms-input-placeholder {
|
||||
background-color: #e9d15b;
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-contrast.css.map*/
|
||||
+2
@@ -524,3 +524,5 @@ a:visited {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-green-dark.css.map*/
|
||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -524,3 +524,5 @@ a:visited {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-green-dark.css.map*/
|
||||
Vendored
+2
@@ -209,3 +209,5 @@ a:visited {
|
||||
background-color: #e9d15b;
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-green.css.map*/
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+2
@@ -209,3 +209,5 @@ a:visited {
|
||||
background-color: #e9d15b;
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-green.css.map*/
|
||||
+2
@@ -525,3 +525,5 @@ input[type=search] {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-orange-dark.css.map*/
|
||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -525,3 +525,5 @@ input[type=search] {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-orange-dark.css.map*/
|
||||
+2
@@ -204,3 +204,5 @@ a.btn-danger:visited {
|
||||
background-color: #e9d15b;
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-orange.css.map*/
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+2
@@ -204,3 +204,5 @@ a.btn-danger:visited {
|
||||
background-color: #e9d15b;
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-orange.css.map*/
|
||||
+2
@@ -535,3 +535,5 @@ a:visited {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-purple-dark.css.map*/
|
||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -535,3 +535,5 @@ a:visited {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-purple-dark.css.map*/
|
||||
+2
@@ -204,3 +204,5 @@ a.btn-danger:visited {
|
||||
background-color: #e9d15b;
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-purple.css.map*/
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+2
@@ -204,3 +204,5 @@ a.btn-danger:visited {
|
||||
background-color: #e9d15b;
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-purple.css.map*/
|
||||
+2
@@ -543,3 +543,5 @@ a:visited {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-red-dark.css.map*/
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+2
@@ -543,3 +543,5 @@ a:visited {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-red-dark.css.map*/
|
||||
Vendored
+2
@@ -211,3 +211,5 @@ a.btn-danger:visited {
|
||||
color: var(--link);
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-red.css.map*/
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+2
@@ -211,3 +211,5 @@ a.btn-danger:visited {
|
||||
color: var(--link);
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-red.css.map*/
|
||||
+2
@@ -499,3 +499,5 @@ tr th div.th-inner {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-yellow-dark.css.map*/
|
||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -499,3 +499,5 @@ tr th div.th-inner {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=skin-yellow-dark.css.map*/
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user