Merge branch 'master' into chore/migrate-textarea-helper

This commit is contained in:
snipe 2025-02-10 23:47:13 +00:00 committed by GitHub
commit b4ea75f34f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
403 changed files with 3936 additions and 2163 deletions

View file

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

View file

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

View file

@ -65,7 +65,7 @@ class ResetDemoSettings extends Command
$settings->thumbnail_max_h = '30';
$settings->locale = 'en-US';
$settings->version_footer = 'on';
$settings->support_footer = null;
$settings->support_footer = 'on';
$settings->saml_enabled = '0';
$settings->saml_sp_x509cert = null;
$settings->saml_idp_metadata = null;

28
app/Events/NoteAdded.php Normal file
View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -535,7 +535,7 @@ class AssetsController extends Controller
{
$settings = Setting::getSettings();
if ($settings->qr_code == '1') {
if (($settings->qr_code === '1') && ($settings->label2_2d_type !== 'none')) {
$asset = Asset::withTrashed()->find($assetId);
if ($asset) {
$size = Helper::barcodeDimensions($settings->label2_2d_type);
@ -865,8 +865,8 @@ class AssetsController extends Controller
public function quickScan()
{
$this->authorize('audit', Asset::class);
$dt = Carbon::now()->addMonths(12)->toDateString();
$settings = Setting::getSettings();
$dt = Carbon::now()->addMonths($settings->audit_interval)->toDateString();
return view('hardware/quickscan')->with('next_audit_date', $dt);
}
@ -883,7 +883,6 @@ class AssetsController extends Controller
$this->authorize('audit', Asset::class);
$dt = Carbon::now()->addMonths($settings->audit_interval)->toDateString();
$asset = Asset::findOrFail($id);
return view('hardware/audit')->with('asset', $asset)->with('next_audit_date', $dt)->with('locations_list');
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -11,6 +11,7 @@ use App\Models\AssetModel;
use App\Models\Category;
use App\Models\AssetMaintenance;
use App\Models\CheckoutAcceptance;
use App\Models\Company;
use App\Models\CustomField;
use App\Models\Depreciation;
use App\Models\License;
@ -18,6 +19,7 @@ use App\Models\ReportTemplate;
use App\Models\Setting;
use App\Notifications\CheckoutAssetNotification;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Mail;
@ -1109,28 +1111,31 @@ class ReportsController extends Controller
$this->authorize('reports.view');
$showDeleted = $deleted == 'deleted';
/**
* Get all assets with pending checkout acceptances
*/
if($showDeleted) {
$acceptances = CheckoutAcceptance::pending()->where('checkoutable_type', 'App\Models\Asset')->withTrashed()->with(['assignedTo' , 'checkoutable.assignedTo', 'checkoutable.model'])->get();
} else {
$acceptances = CheckoutAcceptance::pending()->where('checkoutable_type', 'App\Models\Asset')->with(['assignedTo' => function ($query) {
$query->withTrashed();
}, 'checkoutable.assignedTo', 'checkoutable.model'])->get();
$query = CheckoutAcceptance::pending()
->where('checkoutable_type', 'App\Models\Asset')
->with([
'checkoutable' => function (MorphTo $query) {
$query->morphWith([
AssetModel::class => ['model'],
Company::class => ['company'],
Asset::class => ['assignedTo'],
])->with('model.category');
},
'assignedTo' => function($query){
$query->withTrashed();
}
]);
if ($showDeleted) {
$query->withTrashed();
}
$assetsForReport = $acceptances
->filter(function ($acceptance) {
$acceptance_checkoutable_flag = false;
if ($acceptance->checkoutable){
$acceptance_checkoutable_flag = $acceptance->checkoutable->checkedOutToUser();
}
return $acceptance->checkoutable_type == 'App\Models\Asset' && $acceptance_checkoutable_flag;
})
->map(function($acceptance) {
return ['assetItem' => $acceptance->checkoutable, 'acceptance' => $acceptance];
$assetsForReport = $query->get()
->map(function ($acceptance) {
return [
'assetItem' => $acceptance->checkoutable,
'acceptance' => $acceptance,
];
});
return view('reports/unaccepted_assets', compact('assetsForReport','showDeleted' ));

View file

@ -192,6 +192,7 @@ class SettingsController extends Controller
$settings->next_auto_tag_base = 1;
$settings->auto_increment_assets = $request->input('auto_increment_assets', 0);
$settings->auto_increment_prefix = $request->input('auto_increment_prefix');
$settings->zerofill_count = $request->input('zerofill_count') ?: 0;
if ((! $user->isValid()) || (! $settings->isValid())) {
return redirect()->back()->withInput()->withErrors($user->getErrors())->withErrors($settings->getErrors());

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -106,7 +106,13 @@ class CheckoutableListener
}
}
} catch (ClientException $e) {
Log::error("ClientException caught during checkin notification: " . $e->getMessage());
if (strpos($e->getMessage(), 'channel_not_found') !== false) {
Log::warning(Setting::getSettings()->webhook_selected." notification failed: " . $e->getMessage());
return redirect()->back()->with('warning', ucfirst(Setting::getSettings()->webhook_selected) .trans('admin/settings/message.webhook.webhook_channel_not_found') );
}
else {
Log::error("ClientException caught during checkin notification: " . $e->getMessage());
}
return redirect()->back()->with('warning', ucfirst(Setting::getSettings()->webhook_selected) .trans('admin/settings/message.webhook.webhook_fail') );
} catch (Exception $e) {
Log::error(ucfirst(Setting::getSettings()->webhook_selected) . ' webhook notification failed:', [
@ -156,7 +162,7 @@ class CheckoutableListener
$ccEmails = array_filter($adminCcEmailsArray);
$mailable = $this->getCheckinMailType($event);
$notifiable = $this->getNotifiables($event);
if ($event->checkedOutTo->locale){
if ($event->checkedOutTo?->locale) {
$mailable->locale($event->checkedOutTo->locale);
}
// Send email notifications
@ -196,8 +202,14 @@ class CheckoutableListener
}
}
} catch (ClientException $e) {
Log::error("ClientException caught during checkin notification: " . $e->getMessage());
return redirect()->back()->with('warning', ucfirst(Setting::getSettings()->webhook_selected) .trans('admin/settings/message.webhook.webhook_fail'));
if (strpos($e->getMessage(), 'channel_not_found') !== false) {
Log::warning(Setting::getSettings()->webhook_selected." notification failed: " . $e->getMessage());
return redirect()->back()->with('warning', ucfirst(Setting::getSettings()->webhook_selected) .trans('admin/settings/message.webhook.webhook_channel_not_found') );
}
else {
Log::error("ClientException caught during checkin notification: " . $e->getMessage());
return redirect()->back()->with('warning', ucfirst(Setting::getSettings()->webhook_selected) . trans('admin/settings/message.webhook.webhook_fail'));
}
} catch (Exception $e) {
Log::error(ucfirst(Setting::getSettings()->webhook_selected) . ' webhook notification failed:', [
'error' => $e->getMessage(),

View file

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

View file

@ -329,6 +329,7 @@ class Importer extends Component
];
$this->locations_fields = [
'id' => trans('general.id'),
'name' => trans('general.item_name_var', ['item' => trans('general.location')]),
'address' => trans('general.address'),
'address2' => trans('general.importer.address2'),
@ -400,7 +401,6 @@ class Importer extends Component
'requestable',
'Requestable',
],
'gravatar' =>
[
'gravatar',

View file

@ -159,7 +159,7 @@ class SlackSettingsForm extends Component
]);
try {
$test = $webhook->post($this->webhook_endpoint, ['body' => $payload]);
$test = $webhook->post($this->webhook_endpoint, ['body' => $payload, ['headers' => ['Content-Type' => 'application/json']]]);
if(($test->getStatusCode() == 302)||($test->getStatusCode() == 301)){
return session()->flash('error' , trans('admin/settings/message.webhook.error_redirect', ['endpoint' => $this->webhook_endpoint]));

View file

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

View file

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

View file

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

View file

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

View file

@ -48,7 +48,7 @@ class AssetObserver
$changed = [];
foreach ($asset->getRawOriginal() as $key => $value) {
if ($asset->getRawOriginal()[$key] != $asset->getAttributes()[$key]) {
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];
}
@ -80,7 +80,7 @@ class AssetObserver
{
if ($settings = Setting::getSettings()) {
$tag = $asset->asset_tag;
$prefix = $settings->auto_increment_prefix;
$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...

View file

@ -46,7 +46,7 @@ class ActionlogPresenter extends Presenter
return 'fa-solid fa-mobile-screen';
}
if ($this->action_type == 'create new') {
if ($this->action_type == 'create') {
return 'fa-solid fa-user-plus';
}
@ -70,7 +70,7 @@ class ActionlogPresenter extends Presenter
}
// Everything else
if ($this->action_type == 'create new') {
if ($this->action_type == 'create') {
return 'fa-solid fa-plus';
}
@ -98,6 +98,10 @@ class ActionlogPresenter extends Presenter
return 'fa-solid fa-rotate-right';
}
if ($this->action_type == 'note_added') {
return 'fas fa-sticky-note';
}
return 'fa-solid fa-rotate-right';
}

View file

@ -209,7 +209,7 @@ class Saml
}
}
$custom_settings = preg_split('/\r\n|\r|\n/', $setting->saml_custom_settings);
$custom_settings = preg_split('/\r\n|\r|\n/', $setting->saml_custom_settings ?? '');
if ($custom_settings) {
foreach ($custom_settings as $custom_setting) {
$split = explode('=', $custom_setting, 2);

View file

@ -116,12 +116,9 @@ class Label implements View
}
}
if ($template->getSupport2DBarcode()) {
if ($template->getSupport2DBarcode()) {
$barcode2DType = $settings->label2_2d_type;
$barcode2DType = ($barcode2DType == 'default') ?
$settings->barcode_type :
$barcode2DType;
if (($barcode2DType != 'none') && (!is_null($barcode2DType))) {
if (($barcode2DType != 'none') && (!is_null($barcode2DType))) {
switch ($settings->label2_2d_target) {
case 'ht_tag':
$barcode2DTarget = route('ht/assetTag', $asset->asset_tag);

View file

@ -20,6 +20,7 @@
"php": "^8.1",
"ext-curl": "*",
"ext-fileinfo": "*",
"ext-iconv": "*",
"ext-json": "*",
"ext-mbstring": "*",
"ext-pdo": "*",
@ -55,6 +56,7 @@
"nunomaduro/collision": "^7.0",
"okvpn/clock-lts": "^1.0",
"onelogin/php-saml": "^3.4",
"onnov/detect-encoding": "^2.0",
"osa-eg/laravel-teams-notification": "^2.1",
"paragonie/constant_time_encoding": "^2.3",
"paragonie/sodium_compat": "^1.19",

67
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "0750e3a427347b2a56a05a8b9b533d48",
"content-hash": "2a6e7f5e039ee2f40605aefc5c5baf08",
"packages": [
{
"name": "alek13/slack",
@ -5574,6 +5574,70 @@
],
"time": "2024-05-30T15:14:26+00:00"
},
{
"name": "onnov/detect-encoding",
"version": "v2.0.0",
"source": {
"type": "git",
"url": "https://github.com/onnov/detect-encoding.git",
"reference": "6a8159ac3e6178ae043244b9d66a9b2701121e07"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/onnov/detect-encoding/zipball/6a8159ac3e6178ae043244b9d66a9b2701121e07",
"reference": "6a8159ac3e6178ae043244b9d66a9b2701121e07",
"shasum": ""
},
"require": {
"ext-iconv": "*",
"php": ">=7.3"
},
"require-dev": {
"infection/infection": "*",
"phpbench/phpbench": "*",
"phpcompatibility/php-compatibility": "*",
"phpmd/phpmd": "*",
"phpstan/phpstan": "*",
"phpstan/phpstan-strict-rules": "*",
"phpunit/phpunit": "*",
"roave/backward-compatibility-check": "*",
"squizlabs/php_codesniffer": "*"
},
"type": "library",
"autoload": {
"psr-4": {
"Onnov\\DetectEncoding\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "onnov",
"email": "oblnn@yandex.ru"
}
],
"description": "Text encoding definition class instead of mb_detect_encoding. Defines: utf-8, windows-1251, koi8-r, iso-8859-5, ibm866, .....",
"homepage": "https://github.com/onnov/detect-encoding",
"keywords": [
"cyrillic",
"encoding",
"ibm866",
"iconv",
"iso-8859-5",
"koi8-r",
"mb_detect_encoding",
"utf-8",
"windows-1251"
],
"support": {
"issues": "https://github.com/onnov/detect-encoding/issues",
"source": "https://github.com/onnov/detect-encoding/tree/v2.0.0"
},
"time": "2021-01-04T14:29:34+00:00"
},
{
"name": "osa-eg/laravel-teams-notification",
"version": "v2.1.2",
@ -16570,6 +16634,7 @@
"php": "^8.1",
"ext-curl": "*",
"ext-fileinfo": "*",
"ext-iconv": "*",
"ext-json": "*",
"ext-mbstring": "*",
"ext-pdo": "*"

View file

@ -172,7 +172,7 @@ return [
| More info: https://bootstrap-table.com/docs/extensions/cookie/#cookiestorage
*/
'bs_table_storage' => env('BS_TABLE_STORAGE', 'cookieStorage'),
'bs_table_storage' => env('BS_TABLE_STORAGE', 'localStorage'),
/*

View file

@ -1,10 +1,10 @@
<?php
return array (
'app_version' => 'v7.1.15',
'full_app_version' => 'v7.1.15 - build 16052-g25bfd3e84',
'build_version' => '16052',
'app_version' => 'v7.1.16',
'full_app_version' => 'v7.1.16 - build 16564-gfb857ccf5',
'build_version' => '16564',
'prerelease_version' => '',
'hash_version' => 'g25bfd3e84',
'full_hash' => 'v7.1.15-105-g25bfd3e84',
'hash_version' => 'gfb857ccf5',
'full_hash' => 'v7.1.16-510-gfb857ccf5',
'branch' => 'master',
);

View file

@ -103,6 +103,7 @@ php artisan migrate --force
php artisan config:clear
php artisan config:cache
touch /var/www/html/storage/logs/laravel.log
chown -R apache:root /var/www/html/storage/logs/laravel.log
export APACHE_LOG_DIR=/var/log/apache2

16
package-lock.json generated
View file

@ -15,7 +15,7 @@
"bootstrap-colorpicker": "^2.5.3",
"bootstrap-datepicker": "^1.10.0",
"bootstrap-less": "^3.3.8",
"bootstrap-table": "1.23.5",
"bootstrap-table": "1.24.0",
"canvas-confetti": "^1.9.3",
"chart.js": "^2.9.4",
"clipboard": "^2.0.11",
@ -31,7 +31,7 @@
"less-loader": "^6.0",
"list.js": "^1.5.0",
"morris.js": "github:morrisjs/morris.js",
"papaparse": "5.4.1",
"papaparse": "5.5.1",
"select2": "4.0.13",
"sheetjs": "^2.0.0",
"signature_pad": "^4.2.0",
@ -3705,9 +3705,9 @@
"license": "MIT"
},
"node_modules/bootstrap-table": {
"version": "1.23.5",
"resolved": "https://registry.npmjs.org/bootstrap-table/-/bootstrap-table-1.23.5.tgz",
"integrity": "sha512-9WByoSpJvA73gi2YYIlX6IWR74oZtBmSixul/Th8FTBtBd/kZRpbKESGTjhA3BA3AYTnfyY8Iy1KeRWPlV2GWQ==",
"version": "1.24.0",
"resolved": "https://registry.npmjs.org/bootstrap-table/-/bootstrap-table-1.24.0.tgz",
"integrity": "sha512-dyRf5PQwTgFHj9yjuPXa+GIf4JpuQhsgD1CJrOqhw40qI2gTb3mJfRdoBc7iF2bqzOl+k0RnbAlhSPbGe4VS+w==",
"peerDependencies": {
"jquery": "3"
}
@ -8368,9 +8368,9 @@
"license": "(MIT AND Zlib)"
},
"node_modules/papaparse": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.4.1.tgz",
"integrity": "sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw=="
"version": "5.5.1",
"resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.5.1.tgz",
"integrity": "sha512-EuEKUhyxrHVozD7g3/ztsJn6qaKse8RPfR6buNB2dMJvdtXNhcw8jccVi/LxNEY3HVrV6GO6Z4OoeCG9Iy9wpA=="
},
"node_modules/param-case": {
"version": "3.0.4",

View file

@ -35,7 +35,7 @@
"bootstrap-colorpicker": "^2.5.3",
"bootstrap-datepicker": "^1.10.0",
"bootstrap-less": "^3.3.8",
"bootstrap-table": "1.23.5",
"bootstrap-table": "1.24.0",
"canvas-confetti": "^1.9.3",
"chart.js": "^2.9.4",
"clipboard": "^2.0.11",
@ -51,7 +51,7 @@
"less-loader": "^6.0",
"list.js": "^1.5.0",
"morris.js": "github:morrisjs/morris.js",
"papaparse": "5.4.1",
"papaparse": "5.5.1",
"select2": "4.0.13",
"sheetjs": "^2.0.0",
"signature_pad": "^4.2.0",

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
public/js/dist/all.js vendored

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,25 +1,25 @@
{
"/js/build/app.js": "/js/build/app.js?id=65d7af7b9fa7fd0e05737526a0d1d282",
"/css/dist/skins/skin-black-dark.css": "/css/dist/skins/skin-black-dark.css?id=06c13e817cc022028b3f4a33c0ca303a",
"/css/dist/skins/_all-skins.css": "/css/dist/skins/_all-skins.css?id=e71ef4171dee5da63af390966ac60ffc",
"/css/build/overrides.css": "/css/build/overrides.css?id=776ca1fc6f89c40adc7050439f107f50",
"/css/build/app.css": "/css/build/app.css?id=81072cf10a543742f928390c9a40791d",
"/css/build/AdminLTE.css": "/css/build/AdminLTE.css?id=4ea0068716c1bb2434d87a16d51b98c9",
"/css/dist/skins/skin-yellow.css": "/css/dist/skins/skin-yellow.css?id=7b315b9612b8fde8f9c5b0ddb6bba690",
"/css/dist/skins/skin-yellow-dark.css": "/css/dist/skins/skin-yellow-dark.css?id=ea22079836a432d7f46a5d390c445e13",
"/css/dist/skins/skin-red.css": "/css/dist/skins/skin-red.css?id=44bf834f2110504a793dadec132a5898",
"/css/dist/skins/skin-red-dark.css": "/css/dist/skins/skin-red-dark.css?id=05cc02539441b717012c4efc3303192f",
"/css/dist/skins/skin-purple.css": "/css/dist/skins/skin-purple.css?id=6fe68325d5356197672c27bc77cedcb4",
"/css/dist/skins/skin-purple-dark.css": "/css/dist/skins/skin-purple-dark.css?id=fca90dff303e17dc2991ca395c7f7fa8",
"/css/dist/skins/skin-orange.css": "/css/dist/skins/skin-orange.css?id=6f0563e726c2fe4fab4026daaa5bfdf2",
"/css/dist/skins/skin-orange-dark.css": "/css/dist/skins/skin-orange-dark.css?id=71b7731f7ae692eada36b9b08a2e04a9",
"/css/dist/skins/skin-green.css": "/css/dist/skins/skin-green.css?id=0a82a6ae6bb4e58fe62d162c4fb50397",
"/css/dist/skins/skin-green-dark.css": "/css/dist/skins/skin-green-dark.css?id=bb302302d9566adf783a2b7dc31e840c",
"/css/dist/skins/skin-contrast.css": "/css/dist/skins/skin-contrast.css?id=da6c7997d9de2f8329142399f0ce50da",
"/css/dist/skins/skin-blue.css": "/css/dist/skins/skin-blue.css?id=f677207c6cf9678eb539abecb408c374",
"/css/dist/skins/skin-blue-dark.css": "/css/dist/skins/skin-blue-dark.css?id=6ea836d8126de101081c49abbdb89417",
"/css/dist/skins/skin-black.css": "/css/dist/skins/skin-black.css?id=76482123f6c70e866d6b971ba91de7bb",
"/css/dist/all.css": "/css/dist/all.css?id=7ecc2067a5edde786df1acd2775ba035",
"/js/build/app.js": "/js/build/app.js?id=eeefb5463df4ea2a4cbae72c96006e10",
"/css/dist/skins/skin-black-dark.css": "/css/dist/skins/skin-black-dark.css?id=d34ae2483cbe2c77478c45f4006eba55",
"/css/dist/skins/_all-skins.css": "/css/dist/skins/_all-skins.css?id=b1c78591f51b52beab05b52f407ad6e6",
"/css/build/overrides.css": "/css/build/overrides.css?id=4f85f2e6fd839b8812dd68d001aae4a3",
"/css/build/app.css": "/css/build/app.css?id=50f697122a35791df98a58bcf0665220",
"/css/build/AdminLTE.css": "/css/build/AdminLTE.css?id=a67bd93bed52e6a29967fe472de66d6c",
"/css/dist/skins/skin-yellow.css": "/css/dist/skins/skin-yellow.css?id=fc7adb943668ac69fe4b646625a7571f",
"/css/dist/skins/skin-yellow-dark.css": "/css/dist/skins/skin-yellow-dark.css?id=53edc92eb2d272744bc7404ec259930e",
"/css/dist/skins/skin-red.css": "/css/dist/skins/skin-red.css?id=b9a74ec0cd68f83e7480d5ae39919beb",
"/css/dist/skins/skin-red-dark.css": "/css/dist/skins/skin-red-dark.css?id=cdbb4f543fb448f03617c7ed9d2cbec3",
"/css/dist/skins/skin-purple.css": "/css/dist/skins/skin-purple.css?id=cf6c8c340420724b02d6e787ef9bded5",
"/css/dist/skins/skin-purple-dark.css": "/css/dist/skins/skin-purple-dark.css?id=cfa51820f16533fd62b3c3d720e368ec",
"/css/dist/skins/skin-orange.css": "/css/dist/skins/skin-orange.css?id=268041e902b019730c23ee3875838005",
"/css/dist/skins/skin-orange-dark.css": "/css/dist/skins/skin-orange-dark.css?id=98bd6927e46418c642fdd33fe56f4f26",
"/css/dist/skins/skin-green.css": "/css/dist/skins/skin-green.css?id=b48f4d8af0e1ca5621c161e93951109f",
"/css/dist/skins/skin-green-dark.css": "/css/dist/skins/skin-green-dark.css?id=16dc04eb54142bd3c32c2768d365d988",
"/css/dist/skins/skin-contrast.css": "/css/dist/skins/skin-contrast.css?id=f0fbbb0ac729ea092578fb05ca615460",
"/css/dist/skins/skin-blue.css": "/css/dist/skins/skin-blue.css?id=392cc93cfc0be0349bab9697669dd091",
"/css/dist/skins/skin-blue-dark.css": "/css/dist/skins/skin-blue-dark.css?id=18787b3f00a3be7be38ee4e26cbd2a07",
"/css/dist/skins/skin-black.css": "/css/dist/skins/skin-black.css?id=1f33ca3d860461c1127ec465ab3ebb6b",
"/css/dist/all.css": "/css/dist/all.css?id=baad37c1b095168a326c5bb16b0feb38",
"/css/dist/signature-pad.css": "/css/dist/signature-pad.css?id=6a89d3cd901305e66ced1cf5f13147f7",
"/css/dist/signature-pad.min.css": "/css/dist/signature-pad.min.css?id=6a89d3cd901305e66ced1cf5f13147f7",
"/js/select2/i18n/af.js": "/js/select2/i18n/af.js?id=4f6fcd73488ce79fae1b7a90aceaecde",
@ -90,26 +90,26 @@
"/css/webfonts/fa-solid-900.woff2": "/css/webfonts/fa-solid-900.woff2?id=109ad919b74a62a8a223361da1651bbc",
"/css/webfonts/fa-v4compatibility.ttf": "/css/webfonts/fa-v4compatibility.ttf?id=53c2e50ef821f7b8dd514611d5e0772c",
"/css/webfonts/fa-v4compatibility.woff2": "/css/webfonts/fa-v4compatibility.woff2?id=331c85bd61ffa93af09273d1bc2add5a",
"/js/dist/bootstrap-table-locale-all.min.js": "/js/dist/bootstrap-table-locale-all.min.js?id=c5445e15be5ce91a9ffef05e08ad6898",
"/js/dist/bootstrap-table-en-US.min.js": "/js/dist/bootstrap-table-en-US.min.js?id=0f6e85ae692d03a3b11cab445ff263ab",
"/css/dist/skins/_all-skins.min.css": "/css/dist/skins/_all-skins.min.css?id=e71ef4171dee5da63af390966ac60ffc",
"/css/dist/skins/skin-black-dark.min.css": "/css/dist/skins/skin-black-dark.min.css?id=06c13e817cc022028b3f4a33c0ca303a",
"/css/dist/skins/skin-black.min.css": "/css/dist/skins/skin-black.min.css?id=76482123f6c70e866d6b971ba91de7bb",
"/css/dist/skins/skin-blue-dark.min.css": "/css/dist/skins/skin-blue-dark.min.css?id=6ea836d8126de101081c49abbdb89417",
"/css/dist/skins/skin-blue.min.css": "/css/dist/skins/skin-blue.min.css?id=f677207c6cf9678eb539abecb408c374",
"/css/dist/skins/skin-contrast.min.css": "/css/dist/skins/skin-contrast.min.css?id=da6c7997d9de2f8329142399f0ce50da",
"/css/dist/skins/skin-green-dark.min.css": "/css/dist/skins/skin-green-dark.min.css?id=bb302302d9566adf783a2b7dc31e840c",
"/css/dist/skins/skin-green.min.css": "/css/dist/skins/skin-green.min.css?id=0a82a6ae6bb4e58fe62d162c4fb50397",
"/css/dist/skins/skin-orange-dark.min.css": "/css/dist/skins/skin-orange-dark.min.css?id=71b7731f7ae692eada36b9b08a2e04a9",
"/css/dist/skins/skin-orange.min.css": "/css/dist/skins/skin-orange.min.css?id=6f0563e726c2fe4fab4026daaa5bfdf2",
"/css/dist/skins/skin-purple-dark.min.css": "/css/dist/skins/skin-purple-dark.min.css?id=fca90dff303e17dc2991ca395c7f7fa8",
"/css/dist/skins/skin-purple.min.css": "/css/dist/skins/skin-purple.min.css?id=6fe68325d5356197672c27bc77cedcb4",
"/css/dist/skins/skin-red-dark.min.css": "/css/dist/skins/skin-red-dark.min.css?id=05cc02539441b717012c4efc3303192f",
"/css/dist/skins/skin-red.min.css": "/css/dist/skins/skin-red.min.css?id=44bf834f2110504a793dadec132a5898",
"/css/dist/skins/skin-yellow-dark.min.css": "/css/dist/skins/skin-yellow-dark.min.css?id=ea22079836a432d7f46a5d390c445e13",
"/css/dist/skins/skin-yellow.min.css": "/css/dist/skins/skin-yellow.min.css?id=7b315b9612b8fde8f9c5b0ddb6bba690",
"/css/dist/bootstrap-table.css": "/css/dist/bootstrap-table.css?id=c384582a6ba08903af353be861ffe74e",
"/js/dist/bootstrap-table-locale-all.min.js": "/js/dist/bootstrap-table-locale-all.min.js?id=02dfc50d5b951dc6d260bd508968d319",
"/js/dist/bootstrap-table-en-US.min.js": "/js/dist/bootstrap-table-en-US.min.js?id=1c350eabf064c309f67d6779e5cc4afa",
"/css/dist/skins/_all-skins.min.css": "/css/dist/skins/_all-skins.min.css?id=b1c78591f51b52beab05b52f407ad6e6",
"/css/dist/skins/skin-black-dark.min.css": "/css/dist/skins/skin-black-dark.min.css?id=d34ae2483cbe2c77478c45f4006eba55",
"/css/dist/skins/skin-black.min.css": "/css/dist/skins/skin-black.min.css?id=1f33ca3d860461c1127ec465ab3ebb6b",
"/css/dist/skins/skin-blue-dark.min.css": "/css/dist/skins/skin-blue-dark.min.css?id=18787b3f00a3be7be38ee4e26cbd2a07",
"/css/dist/skins/skin-blue.min.css": "/css/dist/skins/skin-blue.min.css?id=392cc93cfc0be0349bab9697669dd091",
"/css/dist/skins/skin-contrast.min.css": "/css/dist/skins/skin-contrast.min.css?id=f0fbbb0ac729ea092578fb05ca615460",
"/css/dist/skins/skin-green-dark.min.css": "/css/dist/skins/skin-green-dark.min.css?id=16dc04eb54142bd3c32c2768d365d988",
"/css/dist/skins/skin-green.min.css": "/css/dist/skins/skin-green.min.css?id=b48f4d8af0e1ca5621c161e93951109f",
"/css/dist/skins/skin-orange-dark.min.css": "/css/dist/skins/skin-orange-dark.min.css?id=98bd6927e46418c642fdd33fe56f4f26",
"/css/dist/skins/skin-orange.min.css": "/css/dist/skins/skin-orange.min.css?id=268041e902b019730c23ee3875838005",
"/css/dist/skins/skin-purple-dark.min.css": "/css/dist/skins/skin-purple-dark.min.css?id=cfa51820f16533fd62b3c3d720e368ec",
"/css/dist/skins/skin-purple.min.css": "/css/dist/skins/skin-purple.min.css?id=cf6c8c340420724b02d6e787ef9bded5",
"/css/dist/skins/skin-red-dark.min.css": "/css/dist/skins/skin-red-dark.min.css?id=cdbb4f543fb448f03617c7ed9d2cbec3",
"/css/dist/skins/skin-red.min.css": "/css/dist/skins/skin-red.min.css?id=b9a74ec0cd68f83e7480d5ae39919beb",
"/css/dist/skins/skin-yellow-dark.min.css": "/css/dist/skins/skin-yellow-dark.min.css?id=53edc92eb2d272744bc7404ec259930e",
"/css/dist/skins/skin-yellow.min.css": "/css/dist/skins/skin-yellow.min.css?id=fc7adb943668ac69fe4b646625a7571f",
"/css/dist/bootstrap-table.css": "/css/dist/bootstrap-table.css?id=ceded08e0cc745a83c13647035b03406",
"/js/build/vendor.js": "/js/build/vendor.js?id=89dffa552c6e3abe3a2aac6c9c7b466b",
"/js/dist/bootstrap-table.js": "/js/dist/bootstrap-table.js?id=b4c3069f1a292527a96c058b77b28d69",
"/js/dist/all.js": "/js/dist/all.js?id=21e041dec60e0785db6d64961b13a9b0"
"/js/dist/bootstrap-table.js": "/js/dist/bootstrap-table.js?id=61285c8ac5ea7b46002ea8c451c94e60",
"/js/dist/all.js": "/js/dist/all.js?id=ba1c5e26a7d391ad40d699be7bea633e"
}

View file

@ -28,7 +28,7 @@ $(function () {
var baseUrl = $('meta[name="baseUrl"]').attr('content');
//handle modal-add-interstitial calls
var model, select, refreshSelector;
var model, select, refreshSelector, hasnopayload;
if($('#createModal').length == 0) {
$('body').append('<div class="modal fade" id="createModal"></div><!-- /.modal -->');
@ -40,6 +40,7 @@ $(function () {
select = link.data("select");
refreshSelector = link.data("refresh");
hasnopayload = link.data("hasnopayload");
$('#createModal').load(link.attr('href'),function () {
@ -122,11 +123,13 @@ $(function () {
$('#modal_error_msg').html(error_message).show();
return false;
}
var id = result.payload.id;
var name = result.payload.name || (result.payload.first_name + " " + result.payload.last_name);
if(!id || !name) {
console.error("Could not find resulting name or ID from modal-create. Name: "+name+", id: "+id);
return false;
if(!hasnopayload) {
var id = result.payload.id;
var name = result.payload.name || (result.payload.first_name + " " + result.payload.last_name);
if (!id || !name) {
console.error("Could not find resulting name or ID from modal-create. Name: " + name + ", id: " + id);
return false;
}
}
$('#createModal').modal('hide');
$('#createModal').html("");

View file

@ -1159,3 +1159,8 @@ input[type="radio"]:checked::before {
filter: brightness(70%);
font-size: 70%;
}
/** this is needed to override ekko-lightboxes card view styles **/
.bootstrap-table .fixed-table-container .table tbody tr .card-view {
display: table-row !important;
}

View file

@ -70,7 +70,6 @@ return [
'footer_text' => 'crwdns1987:0crwdne1987:0',
'footer_text_help' => 'crwdns1988:0crwdne1988:0',
'general_settings' => 'crwdns1297:0crwdne1297:0',
'general_settings_keywords' => 'crwdns12084:0crwdne12084:0',
'general_settings_help' => 'crwdns6341:0crwdne6341:0',
'generate_backup' => 'crwdns1427:0crwdne1427:0',
'google_workspaces' => 'crwdns12080:0crwdne12080:0',
@ -154,7 +153,6 @@ return [
'php' => 'crwdns1120:0crwdne1120:0',
'php_info' => 'crwdns12298:0crwdne12298:0',
'php_overview' => 'crwdns6367:0crwdne6367:0',
'php_overview_keywords' => 'crwdns6369:0crwdne6369:0',
'php_overview_help' => 'crwdns6371:0crwdne6371:0',
'php_gd_info' => 'crwdns833:0crwdne833:0',
'php_gd_warning' => 'crwdns834:0crwdne834:0',
@ -231,7 +229,6 @@ return [
'update' => 'crwdns840:0crwdne840:0',
'value' => 'crwdns841:0crwdne841:0',
'brand' => 'crwdns1433:0crwdne1433:0',
'brand_keywords' => 'crwdns6397:0crwdne6397:0',
'brand_help' => 'crwdns6399:0crwdne6399:0',
'web_brand' => 'crwdns5916:0crwdne5916:0',
'about_settings_title' => 'crwdns1434:0crwdne1434:0',
@ -319,21 +316,17 @@ return [
'filter_by_keyword' => 'crwdns6431:0crwdne6431:0',
'security' => 'crwdns6433:0crwdne6433:0',
'security_title' => 'crwdns6435:0crwdne6435:0',
'security_keywords' => 'crwdns6437:0crwdne6437:0',
'security_help' => 'crwdns6439:0crwdne6439:0',
'groups_keywords' => 'crwdns6441:0crwdne6441:0',
'groups_help' => 'crwdns6443:0crwdne6443:0',
'localization' => 'crwdns6445:0crwdne6445:0',
'localization_title' => 'crwdns6447:0crwdne6447:0',
'localization_keywords' => 'crwdns6449:0crwdne6449:0',
'localization_help' => 'crwdns6451:0crwdne6451:0',
'notifications' => 'crwdns6453:0crwdne6453:0',
'notifications_help' => 'crwdns11363:0crwdne11363:0',
'asset_tags_help' => 'crwdns6457:0crwdne6457:0',
'labels' => 'crwdns6459:0crwdne6459:0',
'labels_title' => 'crwdns6461:0crwdne6461:0',
'labels_help' => 'crwdns6463:0crwdne6463:0',
'purge_keywords' => 'crwdns6467:0crwdne6467:0',
'labels_help' => 'crwdns12840:0crwdne12840:0',
'purge_help' => 'crwdns6469:0crwdne6469:0',
'ldap_extension_warning' => 'crwdns6471:0crwdne6471:0',
'ldap_ad' => 'crwdns6473:0crwdne6473:0',
@ -362,12 +355,14 @@ return [
'label2_2d_type' => 'crwdns11745:0crwdne11745:0',
'label2_2d_type_help' => 'crwdns11747:0crwdne11747:0',
'label2_2d_target' => 'crwdns11749:0crwdne11749:0',
'label2_2d_target_help' => 'crwdns11751:0crwdne11751:0',
'label2_2d_target_help' => 'crwdns12832:0crwdne12832:0',
'label2_fields' => 'crwdns11753:0crwdne11753:0',
'label2_fields_help' => 'crwdns11755:0crwdne11755:0',
'help_asterisk_bold' => 'crwdns11757:0crwdne11757:0',
'help_blank_to_use' => 'crwdns11759:0crwdne11759:0',
'help_default_will_use' => 'crwdns12828:0crwdne12828:0',
'help_default_will_use' => 'crwdns12834:0crwdne12834:0',
'asset_id' => 'crwdns12836:0crwdne12836:0',
'data' => 'crwdns12838:0crwdne12838:0',
'default' => 'crwdns11763:0crwdne11763:0',
'none' => 'crwdns11765:0crwdne11765:0',
'google_callback_help' => 'crwdns11615:0crwdne11615:0',
@ -389,4 +384,17 @@ return [
'due_checkin_days_help' => 'crwdns12682:0crwdne12682:0',
'no_groups' => 'crwdns12760:0crwdne12760:0',
/* Keywords for settings overview help */
'keywords' => [
'brand' => 'crwdns12842:0crwdne12842:0',
'general_settings' => 'crwdns12844:0crwdne12844:0',
'groups' => 'crwdns12846:0crwdne12846:0',
'labels' => 'crwdns12848:0crwdne12848:0',
'localization' => 'crwdns12850:0crwdne12850:0',
'php_overview' => 'crwdns12852:0crwdne12852:0',
'purge' => 'crwdns12854:0crwdne12854:0',
'security' => 'crwdns12856:0crwdne12856:0',
],
];

View file

@ -45,5 +45,6 @@ return [
'error' => 'crwdns11381:0crwdne11381:0',
'error_redirect' => 'crwdns11843:0crwdne11843:0',
'error_misc' => 'crwdns11383:0crwdne11383:0',
'webhook_fail' => 'crwdns12830:0crwdne12830:0',
]
];

View file

@ -216,6 +216,12 @@ return [
'no_results' => 'crwdns1074:0crwdne1074:0',
'no' => 'crwdns1075:0crwdne1075:0',
'notes' => 'crwdns1076:0crwdne1076:0',
'note_added' => 'crwdns12858:0crwdne12858:0',
'add_note' => 'crwdns12860:0crwdne12860:0',
'note_edited' => 'crwdns12862:0crwdne12862:0',
'edit_note' => 'crwdns12864:0crwdne12864:0',
'note_deleted' => 'crwdns12866:0crwdne12866:0',
'delete_note' => 'crwdns12868:0crwdne12868:0',
'order_number' => 'crwdns1829:0crwdne1829:0',
'only_deleted' => 'crwdns10520:0crwdne10520:0',
'page_menu' => 'crwdns1276:0crwdne1276:0',
@ -566,5 +572,8 @@ return [
'import_asset_tag_exists' => 'crwdns12692:0crwdne12692:0',
'countries_manually_entered_help' => 'crwdns12702:0crwdne12702:0',
'accessories_assigned' => 'crwdns12800:0crwdne12800:0',
'user_managed_passwords' => 'crwdns12870:0crwdne12870:0',
'user_managed_passwords_disallow' => 'crwdns12872:0crwdne12872:0',
'user_managed_passwords_allow' => 'crwdns12874:0crwdne12874:0',
];

View file

@ -70,7 +70,6 @@ return [
'footer_text' => 'Additional Footer Text ',
'footer_text_help' => 'This text will appear in the right-side footer. Links are allowed using <a href="https://help.github.com/articles/github-flavored-markdown/">Github flavored markdown</a>. Line breaks, headers, images, etc may result in unpredictable results.',
'general_settings' => 'Algemene instellings',
'general_settings_keywords' => 'company support, signature, acceptance, email format, username format, images, per page, thumbnail, eula, gravatar, tos, dashboard, privacy',
'general_settings_help' => 'Default EULA and more',
'generate_backup' => 'Genereer rugsteun',
'google_workspaces' => 'Google Workspaces',
@ -154,7 +153,6 @@ return [
'php' => 'PHP weergawe',
'php_info' => 'PHP info',
'php_overview' => 'PHP',
'php_overview_keywords' => 'phpinfo, system, info',
'php_overview_help' => 'PHP System info',
'php_gd_info' => 'Jy moet php-gd installeer om QR-kodes te vertoon, sien installeringsinstruksies.',
'php_gd_warning' => 'PHP Image Processing en GD plugin is NIE geïnstalleer nie.',
@ -231,7 +229,6 @@ return [
'update' => 'Opdateer instellings',
'value' => 'waarde',
'brand' => 'Handelsmerk',
'brand_keywords' => 'footer, logo, print, theme, skin, header, colors, color, css',
'brand_help' => 'Logo, Site Name',
'web_brand' => 'Web Branding Type',
'about_settings_title' => 'Oor instellings',
@ -319,21 +316,17 @@ return [
'filter_by_keyword' => 'Filter by setting keyword',
'security' => 'Security',
'security_title' => 'Update Security Settings',
'security_keywords' => 'password, passwords, requirements, two factor, two-factor, common passwords, remote login, logout, authentication',
'security_help' => 'Two-factor, Password Restrictions',
'groups_keywords' => 'permissions, permission groups, authorization',
'groups_help' => 'Account permission groups',
'localization' => 'Localization',
'localization_title' => 'Update Localization Settings',
'localization_keywords' => 'localization, currency, local, locale, time zone, timezone, international, internatinalization, language, languages, translation',
'localization_help' => 'Language, date display',
'notifications' => 'Notifications',
'notifications_help' => 'Email Alerts & Audit Settings',
'asset_tags_help' => 'Incrementing and prefixes',
'labels' => 'Labels',
'labels_title' => 'Update Label Settings',
'labels_help' => 'Label sizes &amp; settings',
'purge_keywords' => 'permanently delete',
'labels_help' => 'Barcodes &amp; label settings',
'purge_help' => 'Verwyder verwyderde rekords',
'ldap_extension_warning' => 'It does not look like the LDAP extension is installed or enabled on this server. You can still save your settings, but you will need to enable the LDAP extension for PHP before LDAP syncing or login will work.',
'ldap_ad' => 'LDAP/AD',
@ -362,12 +355,14 @@ return [
'label2_2d_type' => '2D Barcode Type',
'label2_2d_type_help' => 'Format for 2D barcodes',
'label2_2d_target' => '2D Barcode Target',
'label2_2d_target_help' => 'The URL the 2D barcode points to when scanned',
'label2_2d_target_help' => 'The data that will be contained in the 2D barcode',
'label2_fields' => 'Field Definitions',
'label2_fields_help' => 'Fields can be added, removed, and reordered in the left column. For each field, multiple options for Label and DataSource can be added, removed, and reordered in the right column.',
'help_asterisk_bold' => 'Text entered as <code>**text**</code> will be displayed as bold',
'help_blank_to_use' => 'Leave blank to use the value from <code>:setting_name</code>',
'help_default_will_use' => '<br>Note that the value of the barcodes must comply with the respective barcode spec in order to be successfully generated. Please see <a href="https://snipe-it.readme.io/docs/barcodes">the documentation <i class="fa fa-external-link"></i></a> for more details. ',
'help_default_will_use' => '<code>:default</code> will use the value from <code>:setting_name</code>. <br>Note that the value of the barcodes must comply with the respective barcode spec in order to be successfully generated. Please see <a href="https://snipe-it.readme.io/docs/barcodes">the documentation <i class="fa fa-external-link"></i></a> for more details. ',
'asset_id' => 'Asset ID',
'data' => 'Data',
'default' => 'Default',
'none' => 'None',
'google_callback_help' => 'This should be entered as the callback URL in your Google OAuth app settings in your organization&apos;s <strong><a href="https://console.cloud.google.com/" target="_blank">Google developer console <i class="fa fa-external-link" aria-hidden="true"></i></a></strong>.',
@ -389,4 +384,17 @@ return [
'due_checkin_days_help' => 'How many days before the expected checkin of an asset should it be listed in the "Due for checkin" page?',
'no_groups' => 'No groups have been created yet. Visit <code>Admin Settings > Permission Groups</code> to add one.',
/* Keywords for settings overview help */
'keywords' => [
'brand' => 'footer, logo, print, theme, skin, header, colors, color, css',
'general_settings' => 'company support, signature, acceptance, email format, username format, images, per page, thumbnail, eula, gravatar, tos, dashboard, privacy',
'groups' => 'permissions, permission groups, authorization',
'labels' => 'labels, barcodes, barcode, sheets, print, upc, qr, 1d, 2d',
'localization' => 'localization, currency, local, locale, time zone, timezone, international, internatinalization, language, languages, translation',
'php_overview' => 'phpinfo, system, info',
'purge' => 'permanently delete',
'security' => 'password, passwords, requirements, two factor, two-factor, common passwords, remote login, logout, authentication',
],
];

View file

@ -45,5 +45,6 @@ return [
'error' => 'Something went wrong. :app responded with: :error_message',
'error_redirect' => 'ERROR: 301/302 :endpoint returns a redirect. For security reasons, we dont follow redirects. Please use the actual endpoint.',
'error_misc' => 'Something went wrong. :( ',
'webhook_fail' => ' webhook notification failed: Check to make sure the URL is still valid.',
]
];

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