mirror of
https://github.com/snipe/snipe-it.git
synced 2024-11-09 23:24:06 -08:00
Merge branch 'develop' into snipeit_v7_laravel10
This commit is contained in:
commit
f633dbba64
|
@ -96,6 +96,7 @@ APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1
|
|||
ALLOW_IFRAMING=false
|
||||
REFERRER_POLICY=same-origin
|
||||
ENABLE_CSP=false
|
||||
ADDITIONAL_CSP_URLS=null
|
||||
CORS_ALLOWED_ORIGINS=null
|
||||
ENABLE_HSTS=false
|
||||
|
||||
|
|
2
.github/workflows/codacy-analysis.yml
vendored
2
.github/workflows/codacy-analysis.yml
vendored
|
@ -36,7 +36,7 @@ jobs:
|
|||
|
||||
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
|
||||
- name: Run Codacy Analysis CLI
|
||||
uses: codacy/codacy-analysis-cli-action@v4.4.0
|
||||
uses: codacy/codacy-analysis-cli-action@v4.4.1
|
||||
with:
|
||||
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
|
||||
# You can also omit the token and run the tools that support default configurations
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
![snipe-it-by-grok](https://github.com/snipe/snipe-it/assets/197404/b515673b-c7c8-4d9a-80f5-9fa58829a602)
|
||||
|
||||
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/snipe-it/localized.svg)](https://crowdin.com/project/snipe-it) [![Docker Pulls](https://img.shields.io/docker/pulls/snipe/snipe-it.svg)](https://hub.docker.com/r/snipe/snipe-it/) [![Twitter Follow](https://img.shields.io/twitter/follow/snipeitapp.svg?style=social)](https://twitter.com/snipeitapp) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/553ce52037fc43ea99149785afcfe641)](https://www.codacy.com/app/snipe/snipe-it?utm_source=github.com&utm_medium=referral&utm_content=snipe/snipe-it&utm_campaign=Badge_Grade) [![Tests](https://github.com/snipe/snipe-it/actions/workflows/tests.yml/badge.svg)](https://github.com/snipe/snipe-it/actions/workflows/tests.yml)
|
||||
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/snipe-it/localized.svg)](https://crowdin.com/project/snipe-it) [![Docker Pulls](https://img.shields.io/docker/pulls/snipe/snipe-it.svg)](https://hub.docker.com/r/snipe/snipe-it/) [![Twitter Follow](https://img.shields.io/twitter/follow/snipeitapp.svg?style=social)](https://twitter.com/snipeitapp) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/553ce52037fc43ea99149785afcfe641)](https://app.codacy.com/gh/snipe/snipe-it/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) [![Tests](https://github.com/snipe/snipe-it/actions/workflows/tests.yml/badge.svg)](https://github.com/snipe/snipe-it/actions/workflows/tests.yml)
|
||||
[![All Contributors](https://img.shields.io/badge/all_contributors-331-orange.svg?style=flat-square)](#contributing) [![Discord](https://badgen.net/badge/icon/discord?icon=discord&label)](https://discord.gg/yZFtShAcKk)
|
||||
|
||||
## Snipe-IT - Open Source Asset Management System
|
||||
|
|
|
@ -43,12 +43,11 @@ class SendUpcomingAuditReport extends Command
|
|||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
$settings = Setting::getSettings();
|
||||
$interval = $settings->audit_warning_days ?? 0;
|
||||
$today = Carbon::now();
|
||||
$interval_date = $today->copy()->addDays($interval);
|
||||
|
||||
$settings = Setting::getSettings();
|
||||
$assets = Asset::whereNull('deleted_at')->DueOrOverdueForAudit($settings)->orderBy('assets.next_audit_date', 'desc')->get();
|
||||
$this->info($assets->count().' assets must be audited in on or before '.$interval_date.' is deadline');
|
||||
|
||||
|
|
|
@ -223,6 +223,7 @@ class AcceptanceController extends Controller
|
|||
'item_model' => $display_model,
|
||||
'item_serial' => $item->serial,
|
||||
'eula' => $item->getEula(),
|
||||
'note' => $request->input('note'),
|
||||
'check_out_date' => Carbon::parse($acceptance->created_at)->format('Y-m-d'),
|
||||
'accepted_date' => Carbon::parse($acceptance->accepted_at)->format('Y-m-d'),
|
||||
'assigned_to' => $assigned_to,
|
||||
|
@ -238,7 +239,7 @@ class AcceptanceController extends Controller
|
|||
Storage::put('private_uploads/eula-pdfs/' .$pdf_filename, $pdf->output());
|
||||
}
|
||||
|
||||
$acceptance->accept($sig_filename, $item->getEula(), $pdf_filename);
|
||||
$acceptance->accept($sig_filename, $item->getEula(), $pdf_filename, $request->input('note'));
|
||||
$acceptance->notify(new AcceptanceAssetAcceptedNotification($data));
|
||||
event(new CheckoutAccepted($acceptance));
|
||||
|
||||
|
@ -306,10 +307,12 @@ class AcceptanceController extends Controller
|
|||
$assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName;
|
||||
break;
|
||||
}
|
||||
|
||||
$data = [
|
||||
'item_tag' => $item->asset_tag,
|
||||
'item_model' => $display_model,
|
||||
'item_serial' => $item->serial,
|
||||
'note' => $request->input('note'),
|
||||
'declined_date' => Carbon::parse($acceptance->declined_at)->format('Y-m-d'),
|
||||
'signature' => ($sig_filename) ? storage_path() . '/private_uploads/signatures/' . $sig_filename : null,
|
||||
'assigned_to' => $assigned_to,
|
||||
|
@ -323,7 +326,7 @@ class AcceptanceController extends Controller
|
|||
Storage::put('private_uploads/eula-pdfs/' .$pdf_filename, $pdf->output());
|
||||
}
|
||||
|
||||
$acceptance->decline($sig_filename);
|
||||
$acceptance->decline($sig_filename, $request->input('note'));
|
||||
$acceptance->notify(new AcceptanceAssetDeclinedNotification($data));
|
||||
event(new CheckoutDeclined($acceptance));
|
||||
$return_msg = trans('admin/users/message.declined');
|
||||
|
|
|
@ -1032,25 +1032,39 @@ class AssetsController extends Controller
|
|||
|
||||
{
|
||||
$this->authorize('audit', Asset::class);
|
||||
$rules = [
|
||||
'asset_tag' => 'required',
|
||||
'location_id' => 'exists:locations,id|nullable|numeric',
|
||||
'next_audit_date' => 'date|nullable',
|
||||
];
|
||||
|
||||
$validator = Validator::make($request->all(), $rules);
|
||||
if ($validator->fails()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $validator->errors()->all()));
|
||||
}
|
||||
|
||||
$settings = Setting::getSettings();
|
||||
$dt = Carbon::now()->addMonths($settings->audit_interval)->toDateString();
|
||||
|
||||
// No tag passed - return an error
|
||||
if (!$request->filled('asset_tag')) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', [
|
||||
'asset_tag'=> '',
|
||||
'error'=> trans('admin/hardware/message.no_tag'),
|
||||
], trans('admin/hardware/message.no_tag')), 200);
|
||||
}
|
||||
|
||||
|
||||
$asset = Asset::where('asset_tag', '=', $request->input('asset_tag'))->first();
|
||||
|
||||
|
||||
if ($asset) {
|
||||
// We don't want to log this as a normal update, so let's bypass that
|
||||
|
||||
/**
|
||||
* Even though we do a save() further down, we don't want to log this as a "normal" asset update,
|
||||
* which would trigger the Asset Observer and would log an asset *update* log entry (because the
|
||||
* de-normed fields like next_audit_date on the asset itself will change on save()) *in addition* to
|
||||
* the audit log entry we're creating through this controller.
|
||||
*
|
||||
* To prevent this double-logging (one for update and one for audit), we skip the observer and bypass
|
||||
* that de-normed update log entry by using unsetEventDispatcher(), BUT invoking unsetEventDispatcher()
|
||||
* will bypass normal model-level validation that's usually handled at the observer )
|
||||
*
|
||||
* We handle validation on the save() by checking if the asset is valid via the ->isValid() method,
|
||||
* which manually invokes Watson Validating to make sure the asset's model is valid.
|
||||
*
|
||||
* @see \App\Observers\AssetObserver::updating()
|
||||
*/
|
||||
$asset->unsetEventDispatcher();
|
||||
$asset->next_audit_date = $dt;
|
||||
|
||||
|
@ -1066,8 +1080,12 @@ class AssetsController extends Controller
|
|||
|
||||
$asset->last_audit_date = date('Y-m-d H:i:s');
|
||||
|
||||
if ($asset->save()) {
|
||||
$log = $asset->logAudit(request('note'), request('location_id'));
|
||||
/**
|
||||
* Invoke Watson Validating to check the asset itself and check to make sure it saved correctly.
|
||||
* We have to invoke this manually because of the unsetEventDispatcher() above.)
|
||||
*/
|
||||
if ($asset->isValid() && $asset->save()) {
|
||||
$asset->logAudit(request('note'), request('location_id'));
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', [
|
||||
'asset_tag'=> e($asset->asset_tag),
|
||||
|
@ -1075,9 +1093,23 @@ class AssetsController extends Controller
|
|||
'next_audit_date' => Helper::getFormattedDateObject($asset->next_audit_date),
|
||||
], trans('admin/hardware/message.audit.success')));
|
||||
}
|
||||
|
||||
// Asset failed validation or was not able to be saved
|
||||
return response()->json(Helper::formatStandardApiResponse('error', [
|
||||
'asset_tag'=> e($asset->asset_tag),
|
||||
'error'=> $asset->getErrors()->first(),
|
||||
], trans('admin/hardware/message.audit.error', ['error' => $asset->getErrors()->first()])), 200);
|
||||
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', ['asset_tag'=> e($request->input('asset_tag'))], 'Asset with tag '.e($request->input('asset_tag')).' not found'));
|
||||
|
||||
// No matching asset for the asset tag that was passed.
|
||||
return response()->json(Helper::formatStandardApiResponse('error', [
|
||||
'asset_tag'=> e($request->input('asset_tag')),
|
||||
'error'=> trans('admin/hardware/message.audit.error'),
|
||||
], trans('admin/hardware/message.audit.error', ['error' => trans('admin/hardware/message.does_not_exist')])), 200);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -76,8 +76,8 @@ class UsersController extends Controller
|
|||
'users.autoassign_licenses',
|
||||
'users.website',
|
||||
|
||||
])->with('manager', 'groups', 'userloc', 'company', 'department', 'assets', 'licenses', 'accessories', 'consumables', 'createdBy',)
|
||||
->withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count');
|
||||
])->with('manager', 'groups', 'userloc', 'company', 'department', 'assets', 'licenses', 'accessories', 'consumables', 'createdBy')
|
||||
->withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count', 'managesUsers as manages_users_count', 'managedLocations as manages_locations_count');
|
||||
|
||||
|
||||
if ($request->filled('activated')) {
|
||||
|
@ -188,6 +188,14 @@ class UsersController extends Controller
|
|||
$users->has('accessories', '=', $request->input('accessories_count'));
|
||||
}
|
||||
|
||||
if ($request->filled('manages_users_count')) {
|
||||
$users->has('manages_users_count', '=', $request->input('manages_users_count'));
|
||||
}
|
||||
|
||||
if ($request->filled('manages_locations_count')) {
|
||||
$users->has('manages_locations_count', '=', $request->input('manages_locations_count'));
|
||||
}
|
||||
|
||||
if ($request->filled('autoassign_licenses')) {
|
||||
$users->where('autoassign_licenses', '=', $request->input('autoassign_licenses'));
|
||||
}
|
||||
|
@ -247,6 +255,8 @@ class UsersController extends Controller
|
|||
'licenses_count',
|
||||
'consumables_count',
|
||||
'accessories_count',
|
||||
'manages_user_count',
|
||||
'manages_locations_count',
|
||||
'phone',
|
||||
'address',
|
||||
'city',
|
||||
|
@ -408,11 +418,15 @@ class UsersController extends Controller
|
|||
{
|
||||
$this->authorize('view', User::class);
|
||||
|
||||
$user = User::withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count')->findOrFail($id);
|
||||
$user = Company::scopeCompanyables($user)->find($id);
|
||||
$this->authorize('update', $user);
|
||||
$user = User::withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count', 'managesUsers as manages_users_count', 'managedLocations as manages_locations_count');
|
||||
|
||||
if ($user = Company::scopeCompanyables($user)->find($id)) {
|
||||
$this->authorize('view', $user);
|
||||
return (new UsersTransformer)->transformUser($user);
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found', compact('id'))));
|
||||
|
||||
return (new UsersTransformer)->transformUser($user);
|
||||
}
|
||||
|
||||
|
||||
|
@ -473,7 +487,6 @@ class UsersController extends Controller
|
|||
}
|
||||
|
||||
|
||||
|
||||
// Update the location of any assets checked out to this user
|
||||
Asset::where('assigned_type', User::class)
|
||||
->where('assigned_to', $user->id)->update(['location_id' => $request->input('location_id', null)]);
|
||||
|
@ -483,12 +496,6 @@ class UsersController extends Controller
|
|||
|
||||
if ($user->save()) {
|
||||
|
||||
// Sync group memberships:
|
||||
// This was changed in Snipe-IT v4.6.x to 4.7, since we upgraded to Laravel 5.5
|
||||
// which changes the behavior of has vs filled.
|
||||
// The $request->has method will now return true even if the input value is an empty string or null.
|
||||
// A new $request->filled method has was added that provides the previous behavior of the has method.
|
||||
|
||||
// Check if the request has groups passed and has a value
|
||||
if ($request->filled('groups')) {
|
||||
|
||||
|
|
|
@ -70,8 +70,6 @@ class AssetModelsFilesController extends Controller
|
|||
}
|
||||
|
||||
$file = 'private_uploads/assetmodels/'.$log->filename;
|
||||
\Log::debug('Checking for '.$file);
|
||||
|
||||
|
||||
if (! Storage::exists($file)) {
|
||||
return response('File '.$file.' not found on server', 404)
|
||||
|
|
|
@ -62,7 +62,7 @@ class AssetCheckoutController extends Controller
|
|||
$this->authorize('checkout', $asset);
|
||||
$admin = Auth::user();
|
||||
|
||||
$target = $this->determineCheckoutTarget($asset);
|
||||
$target = $this->determineCheckoutTarget();
|
||||
|
||||
$asset = $this->updateAssetLocation($asset, $target);
|
||||
|
||||
|
|
|
@ -70,7 +70,6 @@ class AssetFilesController extends Controller
|
|||
}
|
||||
|
||||
$file = 'private_uploads/assets/'.$log->filename;
|
||||
\Log::debug('Checking for '.$file);
|
||||
|
||||
if ($log->action_type == 'audit') {
|
||||
$file = 'private_uploads/audits/'.$log->filename;
|
||||
|
|
|
@ -6,7 +6,7 @@ use App\Helpers\Helper;
|
|||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Manufacturer;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
|
@ -293,7 +293,7 @@ class AssetsController extends Controller
|
|||
*
|
||||
* @param int $assetId
|
||||
* @return \Illuminate\Http\RedirectResponse|Redirect
|
||||
*@since [v1.0]
|
||||
* @since [v1.0]
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
*/
|
||||
public function update(ImageUploadRequest $request, $assetId = null)
|
||||
|
@ -308,7 +308,8 @@ class AssetsController extends Controller
|
|||
$asset->status_id = $request->input('status_id', null);
|
||||
$asset->warranty_months = $request->input('warranty_months', null);
|
||||
$asset->purchase_cost = $request->input('purchase_cost', null);
|
||||
$asset->purchase_date = $request->input('purchase_date', null);
|
||||
$asset->purchase_date = $request->input('purchase_date', null);
|
||||
$asset->next_audit_date = $request->input('next_audit_date', null);
|
||||
if ($request->filled('purchase_date') && !$request->filled('asset_eol_date') && ($asset->model->eol > 0)) {
|
||||
$asset->purchase_date = $request->input('purchase_date', null);
|
||||
$asset->asset_eol_date = Carbon::parse($request->input('purchase_date'))->addMonths($asset->model->eol)->format('Y-m-d');
|
||||
|
@ -862,7 +863,7 @@ class AssetsController extends Controller
|
|||
}
|
||||
|
||||
|
||||
public function auditStore(Request $request, $id)
|
||||
public function auditStore(UploadFileRequest $request, $id)
|
||||
{
|
||||
$this->authorize('audit', Asset::class);
|
||||
|
||||
|
@ -879,7 +880,21 @@ class AssetsController extends Controller
|
|||
|
||||
$asset = Asset::findOrFail($id);
|
||||
|
||||
// We don't want to log this as a normal update, so let's bypass that
|
||||
/**
|
||||
* Even though we do a save() further down, we don't want to log this as a "normal" asset update,
|
||||
* which would trigger the Asset Observer and would log an asset *update* log entry (because the
|
||||
* de-normed fields like next_audit_date on the asset itself will change on save()) *in addition* to
|
||||
* the audit log entry we're creating through this controller.
|
||||
*
|
||||
* To prevent this double-logging (one for update and one for audit), we skip the observer and bypass
|
||||
* that de-normed update log entry by using unsetEventDispatcher(), BUT invoking unsetEventDispatcher()
|
||||
* will bypass normal model-level validation that's usually handled at the observer )
|
||||
*
|
||||
* We handle validation on the save() by checking if the asset is valid via the ->isValid() method,
|
||||
* which manually invokes Watson Validating to make sure the asset's model is valid.
|
||||
*
|
||||
* @see \App\Observers\AssetObserver::updating()
|
||||
*/
|
||||
$asset->unsetEventDispatcher();
|
||||
|
||||
$asset->next_audit_date = $request->input('next_audit_date');
|
||||
|
@ -888,29 +903,27 @@ class AssetsController extends Controller
|
|||
// Check to see if they checked the box to update the physical location,
|
||||
// not just note it in the audit notes
|
||||
if ($request->input('update_location') == '1') {
|
||||
Log::debug('update location in audit');
|
||||
$asset->location_id = $request->input('location_id');
|
||||
}
|
||||
|
||||
|
||||
if ($asset->save()) {
|
||||
$file_name = '';
|
||||
// Upload an image, if attached
|
||||
if ($request->hasFile('image')) {
|
||||
$path = 'private_uploads/audits';
|
||||
if (! Storage::exists($path)) {
|
||||
Storage::makeDirectory($path, 775);
|
||||
}
|
||||
$upload = $image = $request->file('image');
|
||||
$ext = $image->getClientOriginalExtension();
|
||||
$file_name = 'audit-'.str_random(18).'.'.$ext;
|
||||
Storage::putFileAs($path, $upload, $file_name);
|
||||
}
|
||||
/**
|
||||
* Invoke Watson Validating to check the asset itself and check to make sure it saved correctly.
|
||||
* We have to invoke this manually because of the unsetEventDispatcher() above.)
|
||||
*/
|
||||
if ($asset->isValid() && $asset->save()) {
|
||||
|
||||
$file_name = null;
|
||||
// Create the image (if one was chosen.)
|
||||
if ($request->hasFile('image')) {
|
||||
$file_name = $request->handleFile('private_uploads/audits/', 'audit-'.$asset->id, $request->file('image'));
|
||||
}
|
||||
|
||||
$asset->logAudit($request->input('note'), $request->input('location_id'), $file_name);
|
||||
return redirect()->route('assets.audit.due')->with('success', trans('admin/hardware/message.audit.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withInput()->withErrors($asset->getErrors());
|
||||
}
|
||||
|
||||
public function getRequestedIndex($user_id = null)
|
||||
|
|
|
@ -13,7 +13,9 @@ use App\Models\Setting;
|
|||
use App\View\Label;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use App\Http\Requests\AssetCheckoutRequest;
|
||||
|
@ -189,7 +191,6 @@ class BulkAssetsController extends Controller
|
|||
* Save bulk edits
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @return Redirect
|
||||
* @internal param array $assets
|
||||
* @since [v2.0]
|
||||
*/
|
||||
|
@ -214,7 +215,7 @@ class BulkAssetsController extends Controller
|
|||
}
|
||||
|
||||
|
||||
$assets = Asset::whereIn('id', array_keys($request->input('ids')))->get();
|
||||
$assets = Asset::whereIn('id', $request->input('ids'))->get();
|
||||
|
||||
|
||||
|
||||
|
@ -379,28 +380,30 @@ class BulkAssetsController extends Controller
|
|||
foreach ($asset->model->fieldset->fields as $field) {
|
||||
|
||||
if ((array_key_exists($field->db_column, $this->update_array)) && ($field->field_encrypted == '1')) {
|
||||
$decrypted_old = Helper::gracefulDecrypt($field, $asset->{$field->db_column});
|
||||
if (Gate::allows('admin')) {
|
||||
$decrypted_old = Helper::gracefulDecrypt($field, $asset->{$field->db_column});
|
||||
|
||||
/*
|
||||
* Check if the decrypted existing value is different from one we just submitted
|
||||
* and if not, pull it out of the object since it shouldn't really be updating at all.
|
||||
* If we don't do this, it will try to re-encrypt it, and the same value encrypted two
|
||||
* different times will have different values, so it will *look* like it was updated
|
||||
* but it wasn't.
|
||||
*/
|
||||
if ($decrypted_old != $this->update_array[$field->db_column]) {
|
||||
$asset->{$field->db_column} = \Crypt::encrypt($this->update_array[$field->db_column]);
|
||||
} else {
|
||||
/*
|
||||
* Remove the encrypted custom field from the update_array, since nothing changed
|
||||
* Check if the decrypted existing value is different from one we just submitted
|
||||
* and if not, pull it out of the object since it shouldn't really be updating at all.
|
||||
* If we don't do this, it will try to re-encrypt it, and the same value encrypted two
|
||||
* different times will have different values, so it will *look* like it was updated
|
||||
* but it wasn't.
|
||||
*/
|
||||
unset($this->update_array[$field->db_column]);
|
||||
unset($asset->{$field->db_column});
|
||||
}
|
||||
if ($decrypted_old != $this->update_array[$field->db_column]) {
|
||||
$asset->{$field->db_column} = Crypt::encrypt($this->update_array[$field->db_column]);
|
||||
} else {
|
||||
/*
|
||||
* Remove the encrypted custom field from the update_array, since nothing changed
|
||||
*/
|
||||
unset($this->update_array[$field->db_column]);
|
||||
unset($asset->{$field->db_column});
|
||||
}
|
||||
|
||||
/*
|
||||
* These custom fields aren't encrypted, just carry on as usual
|
||||
*/
|
||||
/*
|
||||
* These custom fields aren't encrypted, just carry on as usual
|
||||
*/
|
||||
}
|
||||
} else {
|
||||
|
||||
if ((array_key_exists($field->db_column, $this->update_array)) && ($asset->{$field->db_column} != $this->update_array[$field->db_column])) {
|
||||
|
|
|
@ -72,7 +72,7 @@ class ProfileController extends Controller
|
|||
|
||||
|
||||
if ($user->save()) {
|
||||
return redirect()->route('profile')->with('success', 'Account successfully updated');
|
||||
return redirect()->route('profile')->with('success', trans('account.general.profile_updated'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withInput()->withErrors($user->getErrors());
|
||||
|
|
|
@ -293,8 +293,15 @@ class UsersController extends Controller
|
|||
$user->password = bcrypt($request->input('password'));
|
||||
}
|
||||
|
||||
|
||||
// Update the location of any assets checked out to this user
|
||||
Asset::where('assigned_type', User::class)
|
||||
->where('assigned_to', $user->id)
|
||||
->update(['location_id' => $user->location_id]);
|
||||
|
||||
$permissions_array = $request->input('permission');
|
||||
|
||||
|
||||
// Strip out the superuser permission if the user isn't a superadmin
|
||||
if (! Auth::user()->isSuperUser()) {
|
||||
unset($permissions_array['superuser']);
|
||||
|
|
|
@ -18,20 +18,39 @@ class AssetCountForSidebar
|
|||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
/**
|
||||
* This needs to be set for the /setup process, since the tables might not exist yet
|
||||
*/
|
||||
$total_assets = 0;
|
||||
$total_due_for_checkin = 0;
|
||||
$total_overdue_for_checkin = 0;
|
||||
$total_due_for_audit = 0;
|
||||
$total_overdue_for_audit = 0;
|
||||
|
||||
try {
|
||||
$total_rtd_sidebar = Asset::RTD()->count();
|
||||
view()->share('total_rtd_sidebar', $total_rtd_sidebar);
|
||||
$settings = Setting::getSettings();
|
||||
view()->share('settings', $settings);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
|
||||
try {
|
||||
$total_assets = Asset::RTD()->count();
|
||||
$total_assets = Asset::count();
|
||||
if ($settings->show_archived_in_list != '1') {
|
||||
$total_assets -= Asset::Archived()->count();
|
||||
}
|
||||
view()->share('total_assets', $total_assets);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
|
||||
try {
|
||||
$total_rtd_sidebar = Asset::RTD()->count();
|
||||
view()->share('total_rtd_sidebar', $total_rtd_sidebar);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
|
||||
try {
|
||||
$total_deployed_sidebar = Asset::Deployed()->count();
|
||||
view()->share('total_deployed_sidebar', $total_deployed_sidebar);
|
||||
|
@ -67,13 +86,6 @@ class AssetCountForSidebar
|
|||
\Log::debug($e);
|
||||
}
|
||||
|
||||
try {
|
||||
$settings = Setting::getSettings();
|
||||
view()->share('settings', $settings);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
|
||||
try {
|
||||
$total_due_for_audit = Asset::DueForAudit($settings)->count();
|
||||
view()->share('total_due_for_audit', $total_due_for_audit);
|
||||
|
|
|
@ -88,13 +88,13 @@ class SecurityHeaders
|
|||
$csp_policy[] = "connect-src 'self'";
|
||||
$csp_policy[] = "object-src 'none'";
|
||||
$csp_policy[] = "font-src 'self' data:";
|
||||
$csp_policy[] = "img-src 'self' data: ".config('app.url').' '.env('PUBLIC_AWS_URL').' https://secure.gravatar.com http://gravatar.com maps.google.com maps.gstatic.com *.googleapis.com';
|
||||
$csp_policy[] = "img-src 'self' data: ".config('app.url').' '.config('app.additional_csp_urls').' '.env('PUBLIC_AWS_URL').' https://secure.gravatar.com http://gravatar.com maps.google.com maps.gstatic.com *.googleapis.com';
|
||||
|
||||
if (config('filesystems.disks.public.driver') == 's3') {
|
||||
$csp_policy[] = "img-src 'self' data: ".config('filesystems.disks.public.url');
|
||||
}
|
||||
$csp_policy = join(';', $csp_policy);
|
||||
|
||||
|
||||
$response->headers->set('Content-Security-Policy', $csp_policy);
|
||||
}
|
||||
|
||||
|
|
|
@ -86,12 +86,8 @@ class ImageUploadRequest extends Request
|
|||
|
||||
if ($this->offsetGet($form_fieldname) instanceof UploadedFile) {
|
||||
$image = $this->offsetGet($form_fieldname);
|
||||
\Log::debug('Image is an instance of UploadedFile');
|
||||
} elseif ($this->hasFile($form_fieldname)) {
|
||||
$image = $this->file($form_fieldname);
|
||||
\Log::debug('Just use regular upload for '.$form_fieldname);
|
||||
} else {
|
||||
\Log::debug('No image found for form fieldname: '.$form_fieldname);
|
||||
}
|
||||
|
||||
if (isset($image)) {
|
||||
|
|
|
@ -85,20 +85,23 @@ class ActionlogsTransformer
|
|||
$enc_old = '';
|
||||
$enc_new = '';
|
||||
|
||||
try {
|
||||
$enc_old = \Crypt::decryptString($this->clean_field($fieldata->old));
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Could not decrypt field - maybe the key changed?');
|
||||
if ($this->clean_field($fieldata->old!='')) {
|
||||
try {
|
||||
$enc_old = \Crypt::decryptString($this->clean_field($fieldata->old));
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Could not decrypt old field value - maybe the key changed?');
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$enc_new = \Crypt::decryptString($this->clean_field($fieldata->new));
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Could not decrypt field - maybe the key changed?');
|
||||
if ($this->clean_field($fieldata->new!='')) {
|
||||
try {
|
||||
$enc_new = \Crypt::decryptString($this->clean_field($fieldata->new));
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Could not decrypt new field value - maybe the key changed?');
|
||||
}
|
||||
}
|
||||
|
||||
if ($enc_old != $enc_new) {
|
||||
\Log::debug('custom fields do not match');
|
||||
$clean_meta[$fieldname]['old'] = "************";
|
||||
$clean_meta[$fieldname]['new'] = "************";
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ class UsersTransformer
|
|||
|
||||
public function transformUser(User $user)
|
||||
{
|
||||
|
||||
$array = [
|
||||
'id' => (int) $user->id,
|
||||
'avatar' => e($user->present()->gravatar),
|
||||
|
@ -64,6 +65,8 @@ class UsersTransformer
|
|||
'licenses_count' => (int) $user->licenses_count,
|
||||
'accessories_count' => (int) $user->accessories_count,
|
||||
'consumables_count' => (int) $user->consumables_count,
|
||||
'manages_users_count' => (int) $user->manages_users_count,
|
||||
'manages_locations_count' => (int) $user->manages_locations_count,
|
||||
'company' => ($user->company) ? ['id' => (int) $user->company->id, 'name'=> e($user->company->name)] : null,
|
||||
'created_by' => ($user->createdBy) ? [
|
||||
'id' => (int) $user->createdBy->id,
|
||||
|
|
|
@ -62,6 +62,7 @@ class LogListener
|
|||
$logaction->target()->associate($event->acceptance->assignedTo);
|
||||
$logaction->accept_signature = $event->acceptance->signature_filename;
|
||||
$logaction->filename = $event->acceptance->stored_eula_file;
|
||||
$logaction->note = $event->acceptance->note;
|
||||
$logaction->action_type = 'accepted';
|
||||
|
||||
// TODO: log the actual license seat that was checked out
|
||||
|
@ -78,6 +79,7 @@ class LogListener
|
|||
$logaction->item()->associate($event->acceptance->checkoutable);
|
||||
$logaction->target()->associate($event->acceptance->assignedTo);
|
||||
$logaction->accept_signature = $event->acceptance->signature_filename;
|
||||
$logaction->note = $event->acceptance->note;
|
||||
$logaction->action_type = 'declined';
|
||||
|
||||
// TODO: log the actual license seat that was checked out
|
||||
|
|
|
@ -99,7 +99,8 @@ class Asset extends Depreciable
|
|||
'last_checkin' => 'nullable|date_format:Y-m-d H:i:s',
|
||||
'expected_checkin' => 'nullable|date',
|
||||
'last_audit_date' => 'nullable|date_format:Y-m-d H:i:s',
|
||||
'next_audit_date' => 'nullable|date|after:last_audit_date',
|
||||
// 'next_audit_date' => 'nullable|date|after:last_audit_date',
|
||||
'next_audit_date' => 'nullable|date',
|
||||
'location_id' => 'nullable|exists:locations,id',
|
||||
'rtd_location_id' => 'nullable|exists:locations,id',
|
||||
'purchase_date' => 'nullable|date|date_format:Y-m-d',
|
||||
|
@ -907,6 +908,23 @@ class Asset extends Depreciable
|
|||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine whether this asset's next audit date is before the last audit date
|
||||
*
|
||||
* @return bool
|
||||
* @since [v6.4.1]
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* */
|
||||
public function checkInvalidNextAuditDate()
|
||||
{
|
||||
if (($this->last_audit_date) && ($this->next_audit_date) && ($this->last_audit_date > $this->next_audit_date)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks for a category-specific EULA, and if that doesn't exist,
|
||||
* checks for a settings level EULA
|
||||
|
@ -944,6 +962,25 @@ class Asset extends Depreciable
|
|||
* -----------------------------------------------
|
||||
**/
|
||||
|
||||
/**
|
||||
* Make sure the next_audit_date is formatted as Y-m-d.
|
||||
*
|
||||
* This is kind of dumb and confusing, since we already cast it that way AND it's a date field
|
||||
* in the database, but here we are.
|
||||
*
|
||||
* @param $value
|
||||
* @return void
|
||||
*/
|
||||
public function getNextAuditDateAttribute($value)
|
||||
{
|
||||
return $this->attributes['next_audit_date'] = $value ? Carbon::parse($value)->format('Y-m-d') : null;
|
||||
}
|
||||
|
||||
public function setNextAuditDateAttribute($value)
|
||||
{
|
||||
$this->attributes['next_audit_date'] = $value ? Carbon::parse($value)->format('Y-m-d') : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This sets the requestable to a boolean 0 or 1. This accounts for forms or API calls that
|
||||
* explicitly pass the requestable field but it has a null or empty value.
|
||||
|
|
|
@ -80,12 +80,13 @@ class CheckoutAcceptance extends Model
|
|||
*
|
||||
* @param string $signature_filename
|
||||
*/
|
||||
public function accept($signature_filename, $eula = null, $filename = null)
|
||||
public function accept($signature_filename, $eula = null, $filename = null, $note = null)
|
||||
{
|
||||
$this->accepted_at = now();
|
||||
$this->signature_filename = $signature_filename;
|
||||
$this->stored_eula = $eula;
|
||||
$this->stored_eula_file = $filename;
|
||||
$this->note = $note;
|
||||
$this->save();
|
||||
|
||||
/**
|
||||
|
@ -99,9 +100,10 @@ class CheckoutAcceptance extends Model
|
|||
*
|
||||
* @param string $signature_filename
|
||||
*/
|
||||
public function decline($signature_filename)
|
||||
public function decline($signature_filename, $note = null)
|
||||
{
|
||||
$this->declined_at = now();
|
||||
$this->note = $note;
|
||||
$this->signature_filename = $signature_filename;
|
||||
$this->save();
|
||||
|
||||
|
|
|
@ -262,7 +262,6 @@ final class Company extends SnipeModel
|
|||
if (! static::isFullMultipleCompanySupportEnabled() || (Auth::check() && Auth::user()->isSuperUser()) || (! Auth::check())) {
|
||||
return $query;
|
||||
} else {
|
||||
\Log::debug('Fire scopeCompanyablesDirectly.');
|
||||
return static::scopeCompanyablesDirectly($query, $column, $table_name);
|
||||
}
|
||||
}
|
||||
|
@ -275,7 +274,6 @@ final class Company extends SnipeModel
|
|||
{
|
||||
// Get the company ID of the logged in user, or set it to null if there is no company assicoated with the user
|
||||
if (Auth::user()) {
|
||||
\Log::debug('Admin company is: '.Auth::user()->company_id);
|
||||
$company_id = Auth::user()->company_id;
|
||||
} else {
|
||||
$company_id = null;
|
||||
|
@ -283,9 +281,6 @@ final class Company extends SnipeModel
|
|||
|
||||
// Dynamically get the table name if it's not passed in, based on the model we're querying against
|
||||
$table = ($table_name) ? $table_name."." : $query->getModel()->getTable().".";
|
||||
\Log::debug('Model is: '.$query->getModel());
|
||||
|
||||
\Log::debug('Table is: '.$table);
|
||||
|
||||
// If the column exists in the table, use it to scope the query
|
||||
if (\Schema::hasColumn($query->getModel()->getTable(), $column)) {
|
||||
|
@ -307,7 +302,6 @@ final class Company extends SnipeModel
|
|||
*/
|
||||
public static function scopeCompanyableChildren(array $companyable_names, $query)
|
||||
{
|
||||
\Log::debug('Company Names in scopeCompanyableChildren: '.print_r($companyable_names, true));
|
||||
|
||||
if (count($companyable_names) == 0) {
|
||||
throw new Exception('No Companyable Children to scope');
|
||||
|
|
|
@ -27,6 +27,11 @@ class FieldOption {
|
|||
|
||||
return $asset->assignedTo ? $asset->assignedTo->present()->fullName() : null;
|
||||
}
|
||||
|
||||
// Handle Laravel's stupid Carbon datetime casting
|
||||
if ($dataPath[0] === 'purchase_date') {
|
||||
return $asset->purchase_date ? $asset->purchase_date->format('Y-m-d') : null;
|
||||
}
|
||||
|
||||
return $dataPath->reduce(function ($myValue, $path) {
|
||||
try { return $myValue ? $myValue->{$path} : ${$myValue}; }
|
||||
|
|
|
@ -214,10 +214,12 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
|||
public function isDeletable()
|
||||
{
|
||||
return Gate::allows('delete', $this)
|
||||
&& ($this->assets()->count() === 0)
|
||||
&& ($this->licenses()->count() === 0)
|
||||
&& ($this->consumables()->count() === 0)
|
||||
&& ($this->accessories()->count() === 0)
|
||||
&& ($this->assets->count() === 0)
|
||||
&& ($this->licenses->count() === 0)
|
||||
&& ($this->consumables->count() === 0)
|
||||
&& ($this->accessories->count() === 0)
|
||||
&& ($this->managedLocations->count() === 0)
|
||||
&& ($this->managesUsers->count() === 0)
|
||||
&& ($this->deleted_at == '');
|
||||
}
|
||||
|
||||
|
@ -410,6 +412,19 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
|||
return $this->belongsTo(self::class, 'manager_id')->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes the user -> managed users relationship
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v6.4.1]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function managesUsers()
|
||||
{
|
||||
return $this->hasMany(\App\Models\User::class, 'manager_id');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Establishes the user -> managed locations relationship
|
||||
*
|
||||
|
|
|
@ -26,6 +26,7 @@ class AcceptanceAssetAcceptedNotification extends Notification
|
|||
$this->item_serial = $params['item_serial'];
|
||||
$this->accepted_date = Helper::getFormattedDateObject($params['accepted_date'], 'date', false);
|
||||
$this->assigned_to = $params['assigned_to'];
|
||||
$this->note = $params['note'];
|
||||
$this->company_name = $params['company_name'];
|
||||
$this->settings = Setting::getSettings();
|
||||
|
||||
|
@ -64,6 +65,7 @@ class AcceptanceAssetAcceptedNotification extends Notification
|
|||
'item_tag' => $this->item_tag,
|
||||
'item_model' => $this->item_model,
|
||||
'item_serial' => $this->item_serial,
|
||||
'note' => $this->note,
|
||||
'accepted_date' => $this->accepted_date,
|
||||
'assigned_to' => $this->assigned_to,
|
||||
'company_name' => $this->company_name,
|
||||
|
|
|
@ -25,6 +25,7 @@ class AcceptanceAssetDeclinedNotification extends Notification
|
|||
$this->item_model = $params['item_model'];
|
||||
$this->item_serial = $params['item_serial'];
|
||||
$this->declined_date = Helper::getFormattedDateObject($params['declined_date'], 'date', false);
|
||||
$this->note = $params['note'];
|
||||
$this->assigned_to = $params['assigned_to'];
|
||||
$this->company_name = $params['company_name'];
|
||||
$this->settings = Setting::getSettings();
|
||||
|
@ -62,6 +63,7 @@ class AcceptanceAssetDeclinedNotification extends Notification
|
|||
'item_tag' => $this->item_tag,
|
||||
'item_model' => $this->item_model,
|
||||
'item_serial' => $this->item_serial,
|
||||
'note' => $this->note,
|
||||
'declined_date' => $this->declined_date,
|
||||
'assigned_to' => $this->assigned_to,
|
||||
'company_name' => $this->company_name,
|
||||
|
|
|
@ -221,7 +221,7 @@ class UserPresenter extends Presenter
|
|||
'switchable' => true,
|
||||
'escape' => true,
|
||||
'class' => 'css-barcode',
|
||||
'title' => 'Assets',
|
||||
'title' => trans('general.assets'),
|
||||
'visible' => true,
|
||||
],
|
||||
[
|
||||
|
@ -230,7 +230,7 @@ class UserPresenter extends Presenter
|
|||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'class' => 'css-license',
|
||||
'title' => 'License',
|
||||
'title' => trans('general.licenses'),
|
||||
'visible' => true,
|
||||
],
|
||||
[
|
||||
|
@ -239,7 +239,7 @@ class UserPresenter extends Presenter
|
|||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'class' => 'css-consumable',
|
||||
'title' => 'Consumables',
|
||||
'title' => trans('general.consumables'),
|
||||
'visible' => true,
|
||||
],
|
||||
[
|
||||
|
@ -248,7 +248,25 @@ class UserPresenter extends Presenter
|
|||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'class' => 'css-accessory',
|
||||
'title' => 'Accessories',
|
||||
'title' => trans('general.accessories'),
|
||||
'visible' => true,
|
||||
],
|
||||
[
|
||||
'field' => 'manages_users_count',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'class' => 'css-users',
|
||||
'title' => trans('admin/users/table.managed_users'),
|
||||
'visible' => true,
|
||||
],
|
||||
[
|
||||
'field' => 'manages_locations_count',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'class' => 'css-location',
|
||||
'title' => trans('admin/users/table.managed_locations'),
|
||||
'visible' => true,
|
||||
],
|
||||
[
|
||||
|
|
|
@ -201,6 +201,9 @@ return [
|
|||
|
||||
'enable_csp' => env('ENABLE_CSP', true),
|
||||
|
||||
'additional_csp_urls' => env('ADDITIONAL_CSP_URLS', ''),
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<?php
|
||||
return array (
|
||||
'app_version' => 'v6.3.4',
|
||||
'full_app_version' => 'v6.3.4 - build 13226-g5229dd65c',
|
||||
'build_version' => '13226',
|
||||
'app_version' => 'v6.4.1',
|
||||
'full_app_version' => 'v6.4.1 - build 13458-gf2cc9ec1dd',
|
||||
'build_version' => '13458',
|
||||
'prerelease_version' => '',
|
||||
'hash_version' => 'g5229dd65c',
|
||||
'full_hash' => 'v6.3.4-85-g5229dd65c',
|
||||
'hash_version' => 'gf2cc9ec1dd',
|
||||
'full_hash' => 'v6.4.1-68-gf2cc9ec1dd',
|
||||
'branch' => 'develop',
|
||||
);
|
|
@ -363,6 +363,15 @@ class AssetFactory extends Factory
|
|||
});
|
||||
}
|
||||
|
||||
public function hasMultipleCustomFields(array $fields = null): self
|
||||
{
|
||||
return $this->state(function () use ($fields) {
|
||||
return [
|
||||
'model_id' => AssetModel::factory()->hasMultipleCustomFields($fields),
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This allows bypassing model level validation if you want to purposefully
|
||||
|
|
|
@ -439,4 +439,13 @@ class AssetModelFactory extends Factory
|
|||
];
|
||||
});
|
||||
}
|
||||
|
||||
public function hasMultipleCustomFields(array $fields = null)
|
||||
{
|
||||
return $this->state(function () use ($fields) {
|
||||
return [
|
||||
'fieldset_id' => CustomFieldset::factory()->hasMultipleCustomFields($fields),
|
||||
];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,4 +53,23 @@ class CustomFieldsetFactory extends Factory
|
|||
$fieldset->fields()->attach($field, ['order' => '1', 'required' => false]);
|
||||
});
|
||||
}
|
||||
|
||||
public function hasMultipleCustomFields(array $fields = null): self
|
||||
{
|
||||
return $this->afterCreating(function (CustomFieldset $fieldset) use ($fields) {
|
||||
if (empty($fields)) {
|
||||
$mac_address = CustomField::factory()->macAddress()->create();
|
||||
$ram = CustomField::factory()->ram()->create();
|
||||
$cpu = CustomField::factory()->cpu()->create();
|
||||
|
||||
$fieldset->fields()->attach($mac_address, ['order' => '1', 'required' => false]);
|
||||
$fieldset->fields()->attach($ram, ['order' => '2', 'required' => false]);
|
||||
$fieldset->fields()->attach($cpu, ['order' => '3', 'required' => false]);
|
||||
} else {
|
||||
foreach ($fields as $field) {
|
||||
$fieldset->fields()->attach($field, ['order' => '1', 'required' => false]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddNoteToCheckoutAcceptanceTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('checkout_acceptances', function (Blueprint $table) {
|
||||
$table->text('note')->after('signature_filename')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('checkout_acceptances', function (Blueprint $table) {
|
||||
$table->dropColumn('note');
|
||||
});
|
||||
}
|
||||
}
|
3510
package-lock.json
generated
3510
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -30,7 +30,7 @@
|
|||
"acorn-import-assertions": "^1.9.0",
|
||||
"admin-lte": "^2.4.18",
|
||||
"ajv": "^6.12.6",
|
||||
"alpinejs": "3.13.5",
|
||||
"alpinejs": "^3.13.10",
|
||||
"blueimp-file-upload": "^9.34.0",
|
||||
"bootstrap": "^3.4.1",
|
||||
"bootstrap-colorpicker": "^2.5.3",
|
||||
|
|
7
public/.well-known/security.txt
Normal file
7
public/.well-known/security.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
Contact: mailto:security@snipeitapp.com
|
||||
Expires: 2025-05-16T11:30:00.000Z
|
||||
Acknowledgments: https://snipeitapp.com/thanks
|
||||
Preferred-Languages: en-US, pt-PT, de-DE
|
||||
Canonical: https://github.com/snipe/snipe-it/blob/master/public/.well-known/security.txt
|
||||
Policy: https://snipeitapp.com/security
|
||||
Hiring: https://snipeitapp.com/company/careers
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
public/css/dist/all.css
vendored
BIN
public/css/dist/all.css
vendored
Binary file not shown.
BIN
public/css/dist/bootstrap-table.css
vendored
BIN
public/css/dist/bootstrap-table.css
vendored
Binary file not shown.
BIN
public/css/dist/signature-pad.min.css
vendored
BIN
public/css/dist/signature-pad.min.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-black-dark.css
vendored
BIN
public/css/dist/skins/skin-black-dark.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-black-dark.min.css
vendored
BIN
public/css/dist/skins/skin-black-dark.min.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-black.css
vendored
BIN
public/css/dist/skins/skin-black.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-black.min.css
vendored
BIN
public/css/dist/skins/skin-black.min.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-blue-dark.css
vendored
BIN
public/css/dist/skins/skin-blue-dark.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-blue-dark.min.css
vendored
BIN
public/css/dist/skins/skin-blue-dark.min.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-blue.css
vendored
BIN
public/css/dist/skins/skin-blue.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-blue.min.css
vendored
BIN
public/css/dist/skins/skin-blue.min.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-contrast.css
vendored
BIN
public/css/dist/skins/skin-contrast.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-contrast.min.css
vendored
BIN
public/css/dist/skins/skin-contrast.min.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-green-dark.css
vendored
BIN
public/css/dist/skins/skin-green-dark.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-green-dark.min.css
vendored
BIN
public/css/dist/skins/skin-green-dark.min.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-green.css
vendored
BIN
public/css/dist/skins/skin-green.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-green.min.css
vendored
BIN
public/css/dist/skins/skin-green.min.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-orange-dark.css
vendored
BIN
public/css/dist/skins/skin-orange-dark.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-orange-dark.min.css
vendored
BIN
public/css/dist/skins/skin-orange-dark.min.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-orange.css
vendored
BIN
public/css/dist/skins/skin-orange.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-orange.min.css
vendored
BIN
public/css/dist/skins/skin-orange.min.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-purple-dark.css
vendored
BIN
public/css/dist/skins/skin-purple-dark.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-purple-dark.min.css
vendored
BIN
public/css/dist/skins/skin-purple-dark.min.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-purple.css
vendored
BIN
public/css/dist/skins/skin-purple.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-purple.min.css
vendored
BIN
public/css/dist/skins/skin-purple.min.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-red-dark.css
vendored
BIN
public/css/dist/skins/skin-red-dark.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-red-dark.min.css
vendored
BIN
public/css/dist/skins/skin-red-dark.min.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-red.css
vendored
BIN
public/css/dist/skins/skin-red.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-red.min.css
vendored
BIN
public/css/dist/skins/skin-red.min.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-yellow-dark.css
vendored
BIN
public/css/dist/skins/skin-yellow-dark.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-yellow-dark.min.css
vendored
BIN
public/css/dist/skins/skin-yellow-dark.min.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-yellow.css
vendored
BIN
public/css/dist/skins/skin-yellow.css
vendored
Binary file not shown.
BIN
public/css/dist/skins/skin-yellow.min.css
vendored
BIN
public/css/dist/skins/skin-yellow.min.css
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
public/js/dist/all-defer.js
vendored
BIN
public/js/dist/all-defer.js
vendored
Binary file not shown.
BIN
public/js/dist/all.js
vendored
BIN
public/js/dist/all.js
vendored
Binary file not shown.
BIN
public/js/dist/bootstrap-table.js
vendored
BIN
public/js/dist/bootstrap-table.js
vendored
Binary file not shown.
|
@ -1,24 +1,24 @@
|
|||
{
|
||||
"/js/build/app.js": "/js/build/app.js?id=ceb28a75cb946bd1ca5b42002e222142",
|
||||
"/css/dist/skins/skin-red.css": "/css/dist/skins/skin-red.css?id=b9a74ec0cd68f83e7480d5ae39919beb",
|
||||
"/css/dist/skins/skin-blue.css": "/css/dist/skins/skin-blue.css?id=392cc93cfc0be0349bab9697669dd091",
|
||||
"/css/build/overrides.css": "/css/build/overrides.css?id=59b5942be1960a787f9d1bb58e7dc068",
|
||||
"/css/build/app.css": "/css/build/app.css?id=bd609c74fd0071b6f93af1869e9482b6",
|
||||
"/css/build/AdminLTE.css": "/css/build/AdminLTE.css?id=a67bd93bed52e6a29967fe472de66d6c",
|
||||
"/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=03075904b967308132b810bc0205ab1c",
|
||||
"/css/dist/skins/skin-blue-dark.css": "/css/dist/skins/skin-blue-dark.css?id=47ab28abd019c2b1f9aae60a3d44824a",
|
||||
"/css/dist/skins/skin-yellow-dark.css": "/css/dist/skins/skin-yellow-dark.css?id=af8c7daf7e9a2c784eafb76f65c418f7",
|
||||
"/css/dist/skins/skin-yellow.css": "/css/dist/skins/skin-yellow.css?id=fc7adb943668ac69fe4b646625a7571f",
|
||||
"/css/dist/skins/skin-purple-dark.css": "/css/dist/skins/skin-purple-dark.css?id=7fb8cf2421ad272b41393fdf5844559f",
|
||||
"/css/dist/skins/skin-purple.css": "/css/dist/skins/skin-purple.css?id=cf6c8c340420724b02d6e787ef9bded5",
|
||||
"/css/dist/skins/skin-red-dark.css": "/css/dist/skins/skin-red-dark.css?id=122d3df19d2c0552d7ef388e69f7d71f",
|
||||
"/css/dist/skins/skin-black-dark.css": "/css/dist/skins/skin-black-dark.css?id=5414c37b1403f41e051ad7b3aac112b4",
|
||||
"/css/dist/skins/skin-black.css": "/css/dist/skins/skin-black.css?id=1f33ca3d860461c1127ec465ab3ebb6b",
|
||||
"/css/dist/skins/skin-green-dark.css": "/css/dist/skins/skin-green-dark.css?id=bd61fefb56b30ed6d8c946f02bc956fb",
|
||||
"/css/dist/skins/skin-green.css": "/css/dist/skins/skin-green.css?id=b48f4d8af0e1ca5621c161e93951109f",
|
||||
"/css/dist/skins/skin-contrast.css": "/css/dist/skins/skin-contrast.css?id=f0fbbb0ac729ea092578fb05ca615460",
|
||||
"/css/dist/all.css": "/css/dist/all.css?id=90098fdcbf06c943723c1857f7c31d5d",
|
||||
"/js/build/app.js": "/js/build/app.js?id=337bd2424ba19bb3c8f200e266caa513",
|
||||
"/css/dist/skins/skin-red.css": "/css/dist/skins/skin-red.css?id=44bf834f2110504a793dadec132a5898",
|
||||
"/css/dist/skins/skin-blue.css": "/css/dist/skins/skin-blue.css?id=f677207c6cf9678eb539abecb408c374",
|
||||
"/css/build/overrides.css": "/css/build/overrides.css?id=004835e70ed3ae2e2340162b7a37c752",
|
||||
"/css/build/app.css": "/css/build/app.css?id=7ecac57fc8cf6fdbe447c18d5f2ae7bc",
|
||||
"/css/build/AdminLTE.css": "/css/build/AdminLTE.css?id=4ea0068716c1bb2434d87a16d51b98c9",
|
||||
"/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=620b684d9dd9d3bb5fdda00a3a2467c3",
|
||||
"/css/dist/skins/skin-blue-dark.css": "/css/dist/skins/skin-blue-dark.css?id=23f2e8df6b60e8d9816e645cc5000874",
|
||||
"/css/dist/skins/skin-yellow-dark.css": "/css/dist/skins/skin-yellow-dark.css?id=2600828a93288ba791de9bf711171796",
|
||||
"/css/dist/skins/skin-yellow.css": "/css/dist/skins/skin-yellow.css?id=7b315b9612b8fde8f9c5b0ddb6bba690",
|
||||
"/css/dist/skins/skin-purple-dark.css": "/css/dist/skins/skin-purple-dark.css?id=e56aa0fcc7789f1efd1e14bc5e0b4159",
|
||||
"/css/dist/skins/skin-purple.css": "/css/dist/skins/skin-purple.css?id=6fe68325d5356197672c27bc77cedcb4",
|
||||
"/css/dist/skins/skin-red-dark.css": "/css/dist/skins/skin-red-dark.css?id=821b68e0a3efc3b6743453bf0ed2a954",
|
||||
"/css/dist/skins/skin-black-dark.css": "/css/dist/skins/skin-black-dark.css?id=b31e80c39b29106d02bf9b3a0a833343",
|
||||
"/css/dist/skins/skin-black.css": "/css/dist/skins/skin-black.css?id=76482123f6c70e866d6b971ba91de7bb",
|
||||
"/css/dist/skins/skin-green-dark.css": "/css/dist/skins/skin-green-dark.css?id=ec0a01609bec55e90f0692d86cb81625",
|
||||
"/css/dist/skins/skin-green.css": "/css/dist/skins/skin-green.css?id=0a82a6ae6bb4e58fe62d162c4fb50397",
|
||||
"/css/dist/skins/skin-contrast.css": "/css/dist/skins/skin-contrast.css?id=da6c7997d9de2f8329142399f0ce50da",
|
||||
"/css/dist/all.css": "/css/dist/all.css?id=3fcc65fb2a4f272a5a453f7421096d90",
|
||||
"/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",
|
||||
"/css/webfonts/fa-brands-400.ttf": "/css/webfonts/fa-brands-400.ttf?id=0141634c24336be626e05c8b77d1fa27",
|
||||
|
@ -32,21 +32,21 @@
|
|||
"/css/dist/bootstrap-table.css": "/css/dist/bootstrap-table.css?id=99c395f0bab5966f32f63f4e55899e64",
|
||||
"/js/build/vendor.js": "/js/build/vendor.js?id=179bfe20e8767f7df32658c6b5a10ca3",
|
||||
"/js/dist/bootstrap-table.js": "/js/dist/bootstrap-table.js?id=e3bde6c62806c5ae510c964de17cd610",
|
||||
"/js/dist/all.js": "/js/dist/all.js?id=99df559d106d7c1da6beff663646d76f",
|
||||
"/js/dist/all-defer.js": "/js/dist/all-defer.js?id=19ccc62a8f1ea103dede4808837384d4",
|
||||
"/css/dist/skins/skin-green.min.css": "/css/dist/skins/skin-green.min.css?id=b48f4d8af0e1ca5621c161e93951109f",
|
||||
"/css/dist/skins/skin-green-dark.min.css": "/css/dist/skins/skin-green-dark.min.css?id=bd61fefb56b30ed6d8c946f02bc956fb",
|
||||
"/css/dist/skins/skin-black.min.css": "/css/dist/skins/skin-black.min.css?id=1f33ca3d860461c1127ec465ab3ebb6b",
|
||||
"/css/dist/skins/skin-black-dark.min.css": "/css/dist/skins/skin-black-dark.min.css?id=5414c37b1403f41e051ad7b3aac112b4",
|
||||
"/css/dist/skins/skin-blue.min.css": "/css/dist/skins/skin-blue.min.css?id=392cc93cfc0be0349bab9697669dd091",
|
||||
"/css/dist/skins/skin-blue-dark.min.css": "/css/dist/skins/skin-blue-dark.min.css?id=47ab28abd019c2b1f9aae60a3d44824a",
|
||||
"/css/dist/skins/skin-yellow.min.css": "/css/dist/skins/skin-yellow.min.css?id=fc7adb943668ac69fe4b646625a7571f",
|
||||
"/css/dist/skins/skin-yellow-dark.min.css": "/css/dist/skins/skin-yellow-dark.min.css?id=af8c7daf7e9a2c784eafb76f65c418f7",
|
||||
"/css/dist/skins/skin-red.min.css": "/css/dist/skins/skin-red.min.css?id=b9a74ec0cd68f83e7480d5ae39919beb",
|
||||
"/css/dist/skins/skin-red-dark.min.css": "/css/dist/skins/skin-red-dark.min.css?id=122d3df19d2c0552d7ef388e69f7d71f",
|
||||
"/css/dist/skins/skin-purple.min.css": "/css/dist/skins/skin-purple.min.css?id=cf6c8c340420724b02d6e787ef9bded5",
|
||||
"/css/dist/skins/skin-purple-dark.min.css": "/css/dist/skins/skin-purple-dark.min.css?id=7fb8cf2421ad272b41393fdf5844559f",
|
||||
"/css/dist/skins/skin-orange.min.css": "/css/dist/skins/skin-orange.min.css?id=268041e902b019730c23ee3875838005",
|
||||
"/css/dist/skins/skin-orange-dark.min.css": "/css/dist/skins/skin-orange-dark.min.css?id=03075904b967308132b810bc0205ab1c",
|
||||
"/css/dist/skins/skin-contrast.min.css": "/css/dist/skins/skin-contrast.min.css?id=f0fbbb0ac729ea092578fb05ca615460"
|
||||
"/js/dist/all.js": "/js/dist/all.js?id=e37ce44903f83119fe3d52717200022e",
|
||||
"/js/dist/all-defer.js": "/js/dist/all-defer.js?id=75d841799f917cbcacf6b87698379726",
|
||||
"/css/dist/skins/skin-green.min.css": "/css/dist/skins/skin-green.min.css?id=0a82a6ae6bb4e58fe62d162c4fb50397",
|
||||
"/css/dist/skins/skin-green-dark.min.css": "/css/dist/skins/skin-green-dark.min.css?id=ec0a01609bec55e90f0692d86cb81625",
|
||||
"/css/dist/skins/skin-black.min.css": "/css/dist/skins/skin-black.min.css?id=76482123f6c70e866d6b971ba91de7bb",
|
||||
"/css/dist/skins/skin-black-dark.min.css": "/css/dist/skins/skin-black-dark.min.css?id=b31e80c39b29106d02bf9b3a0a833343",
|
||||
"/css/dist/skins/skin-blue.min.css": "/css/dist/skins/skin-blue.min.css?id=f677207c6cf9678eb539abecb408c374",
|
||||
"/css/dist/skins/skin-blue-dark.min.css": "/css/dist/skins/skin-blue-dark.min.css?id=23f2e8df6b60e8d9816e645cc5000874",
|
||||
"/css/dist/skins/skin-yellow.min.css": "/css/dist/skins/skin-yellow.min.css?id=7b315b9612b8fde8f9c5b0ddb6bba690",
|
||||
"/css/dist/skins/skin-yellow-dark.min.css": "/css/dist/skins/skin-yellow-dark.min.css?id=2600828a93288ba791de9bf711171796",
|
||||
"/css/dist/skins/skin-red.min.css": "/css/dist/skins/skin-red.min.css?id=44bf834f2110504a793dadec132a5898",
|
||||
"/css/dist/skins/skin-red-dark.min.css": "/css/dist/skins/skin-red-dark.min.css?id=821b68e0a3efc3b6743453bf0ed2a954",
|
||||
"/css/dist/skins/skin-purple.min.css": "/css/dist/skins/skin-purple.min.css?id=6fe68325d5356197672c27bc77cedcb4",
|
||||
"/css/dist/skins/skin-purple-dark.min.css": "/css/dist/skins/skin-purple-dark.min.css?id=e56aa0fcc7789f1efd1e14bc5e0b4159",
|
||||
"/css/dist/skins/skin-orange.min.css": "/css/dist/skins/skin-orange.min.css?id=6f0563e726c2fe4fab4026daaa5bfdf2",
|
||||
"/css/dist/skins/skin-orange-dark.min.css": "/css/dist/skins/skin-orange-dark.min.css?id=620b684d9dd9d3bb5fdda00a3a2467c3",
|
||||
"/css/dist/skins/skin-contrast.min.css": "/css/dist/skins/skin-contrast.min.css?id=da6c7997d9de2f8329142399f0ce50da"
|
||||
}
|
||||
|
|
|
@ -586,6 +586,8 @@ th.css-barcode > .th-inner,
|
|||
th.css-license > .th-inner,
|
||||
th.css-consumable > .th-inner,
|
||||
th.css-envelope > .th-inner,
|
||||
th.css-users > .th-inner,
|
||||
th.css-location > .th-inner,
|
||||
th.css-accessory > .th-inner
|
||||
{
|
||||
font-size: 0px;
|
||||
|
@ -602,6 +604,8 @@ th.css-barcode > .th-inner::before,
|
|||
th.css-license > .th-inner::before,
|
||||
th.css-consumable > .th-inner::before,
|
||||
th.css-envelope > .th-inner::before,
|
||||
th.css-users > .th-inner::before,
|
||||
th.css-location > .th-inner::before,
|
||||
th.css-accessory > .th-inner::before
|
||||
|
||||
{
|
||||
|
@ -621,6 +625,7 @@ th.css-padlock > .th-inner::before
|
|||
}
|
||||
|
||||
/**
|
||||
BEGIN ICON TABLE HEADERS
|
||||
Set the font-weight css property as 900 (For Solid), 400 (Regular or Brands), 300 (Light for pro icons).
|
||||
**/
|
||||
th.css-barcode > .th-inner::before
|
||||
|
@ -643,12 +648,20 @@ th.css-envelope > .th-inner::before
|
|||
content: "\f0e0"; font-family: "Font Awesome 5 Free"; font-weight: 400;
|
||||
}
|
||||
|
||||
|
||||
th.css-accessory > .th-inner::before
|
||||
{
|
||||
content: "\f11c"; font-family: "Font Awesome 5 Free"; font-weight: 400;
|
||||
}
|
||||
|
||||
th.css-users > .th-inner::before {
|
||||
content: "\f0c0"; font-family: "Font Awesome 5 Free"; font-size: 15px;
|
||||
}
|
||||
|
||||
th.css-location > .th-inner::before {
|
||||
content: "\f3c5"; font-family: "Font Awesome 5 Free"; font-size: 19px; margin-bottom: 0px;
|
||||
}
|
||||
|
||||
|
||||
.small-box .inner {
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
|
|
|
@ -4,8 +4,11 @@ return [
|
|||
|
||||
'undeployable' => 'crwdns1173:0crwdne1173:0',
|
||||
'does_not_exist' => 'crwdns740:0crwdne740:0',
|
||||
'does_not_exist_var'=> 'crwdns12188:0crwdne12188:0',
|
||||
'no_tag' => 'crwdns12190:0crwdne12190:0',
|
||||
'does_not_exist_or_not_requestable' => 'crwdns6581:0crwdne6581:0',
|
||||
'assoc_users' => 'crwdns741:0crwdne741:0',
|
||||
'warning_audit_date_mismatch' => 'crwdns12192:0crwdne12192:0',
|
||||
|
||||
'create' => [
|
||||
'error' => 'crwdns742:0crwdne742:0',
|
||||
|
@ -16,6 +19,7 @@ return [
|
|||
'update' => [
|
||||
'error' => 'crwdns744:0crwdne744:0',
|
||||
'success' => 'crwdns745:0crwdne745:0',
|
||||
'encrypted_warning' => 'crwdns12168:0crwdne12168:0',
|
||||
'nothing_updated' => 'crwdns1186:0crwdne1186:0',
|
||||
'no_assets_selected' => 'crwdns6810:0crwdne6810:0',
|
||||
'assets_do_not_exist_or_are_invalid' => 'crwdns12132:0crwdne12132:0',
|
||||
|
@ -29,7 +33,7 @@ return [
|
|||
],
|
||||
|
||||
'audit' => [
|
||||
'error' => 'crwdns1906:0crwdne1906:0',
|
||||
'error' => 'crwdns12194:0crwdne12194:0',
|
||||
'success' => 'crwdns1907:0crwdne1907:0',
|
||||
],
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
return array(
|
||||
|
||||
'does_not_exist' => 'crwdns10556:0crwdne10556:0',
|
||||
'user_does_not_exist' => 'crwdns935:0crwdne935:0',
|
||||
'user_does_not_exist' => 'crwdns12164:0crwdne12164:0',
|
||||
'asset_does_not_exist' => 'crwdns936:0crwdne936:0',
|
||||
'owner_doesnt_match_asset' => 'crwdns937:0crwdne937:0',
|
||||
'assoc_users' => 'crwdns938:0crwdne938:0',
|
||||
|
|
|
@ -4,6 +4,7 @@ return array(
|
|||
|
||||
'assigned_to' => 'crwdns923:0crwdne923:0',
|
||||
'checkout' => 'crwdns924:0crwdne924:0',
|
||||
'deleted_at' => 'crwdns12170:0crwdne12170:0',
|
||||
'id' => 'crwdns925:0crwdne925:0',
|
||||
'license_email' => 'crwdns926:0crwdne926:0',
|
||||
'license_name' => 'crwdns927:0crwdne927:0',
|
||||
|
|
|
@ -49,6 +49,7 @@ return [
|
|||
'default_eula_text' => 'crwdns1259:0crwdne1259:0',
|
||||
'default_language' => 'crwdns1581:0crwdne1581:0',
|
||||
'default_eula_help_text' => 'crwdns1260:0crwdne1260:0',
|
||||
'acceptance_note' => 'crwdns12186:0crwdne12186:0',
|
||||
'display_asset_name' => 'crwdns828:0crwdne828:0',
|
||||
'display_checkout_date' => 'crwdns829:0crwdne829:0',
|
||||
'display_eol' => 'crwdns1118:0crwdne1118:0',
|
||||
|
|
|
@ -20,6 +20,7 @@ return array(
|
|||
'lock_passwords' => 'crwdns1262:0crwdne1262:0',
|
||||
'manager' => 'crwdns778:0crwdne778:0',
|
||||
'managed_locations' => 'crwdns1887:0crwdne1887:0',
|
||||
'managed_users' => 'crwdns12182:0crwdne12182:0',
|
||||
'name' => 'crwdns779:0crwdne779:0',
|
||||
'nogroup' => 'crwdns11906:0crwdne11906:0',
|
||||
'notes' => 'crwdns1268:0crwdne1268:0',
|
||||
|
|
|
@ -176,7 +176,7 @@ return [
|
|||
'last_name' => 'crwdns1059:0crwdne1059:0',
|
||||
'license' => 'crwdns1060:0crwdne1060:0',
|
||||
'license_report' => 'crwdns1141:0crwdne1141:0',
|
||||
'licenses_available' => 'crwdns1061:0crwdne1061:0',
|
||||
'licenses_available' => 'crwdns12172:0crwdne12172:0',
|
||||
'licenses' => 'crwdns1062:0crwdne1062:0',
|
||||
'list_all' => 'crwdns1063:0crwdne1063:0',
|
||||
'loading' => 'crwdns6135:0crwdne6135:0',
|
||||
|
@ -202,6 +202,8 @@ return [
|
|||
'new_password' => 'crwdns6141:0crwdne6141:0',
|
||||
'next' => 'crwdns1275:0crwdne1275:0',
|
||||
'next_audit_date' => 'crwdns1919:0crwdne1919:0',
|
||||
'next_audit_date_help' => 'crwdns12196:0crwdne12196:0',
|
||||
'audit_images_help' => 'crwdns12198:0crwdne12198:0',
|
||||
'no_email' => 'crwdns12130:0crwdne12130:0',
|
||||
'last_audit' => 'crwdns1920:0crwdne1920:0',
|
||||
'new' => 'crwdns1668:0crwdne1668:0',
|
||||
|
@ -245,6 +247,7 @@ return [
|
|||
'select_all' => 'crwdns6155:0crwdne6155:0',
|
||||
'search' => 'crwdns1290:0crwdne1290:0',
|
||||
'select_category' => 'crwdns1663:0crwdne1663:0',
|
||||
'select_datasource' => 'crwdns12166:0crwdne12166:0',
|
||||
'select_department' => 'crwdns1880:0crwdne1880:0',
|
||||
'select_depreciation' => 'crwdns1282:0crwdne1282:0',
|
||||
'select_location' => 'crwdns1283:0crwdne1283:0',
|
||||
|
@ -294,6 +297,7 @@ return [
|
|||
'user' => 'crwdns1095:0crwdne1095:0',
|
||||
'accepted' => 'crwdns1342:0crwdne1342:0',
|
||||
'declined' => 'crwdns1343:0crwdne1343:0',
|
||||
'declined_note' => 'crwdns12184:0crwdne12184:0',
|
||||
'unassigned' => 'crwdns11769:0crwdne11769:0',
|
||||
'unaccepted_asset_report' => 'crwdns1409:0crwdne1409:0',
|
||||
'users' => 'crwdns1271:0crwdne1271:0',
|
||||
|
@ -312,6 +316,10 @@ return [
|
|||
'token_expired' => 'crwdns1578:0crwdne1578:0',
|
||||
'login_enabled' => 'crwdns5984:0crwdne5984:0',
|
||||
'audit_due' => 'crwdns5986:0crwdne5986:0',
|
||||
'audit_due_days' => 'crwdns12174:0crwdne12174:0',
|
||||
'checkin_due' => 'crwdns12176:0crwdne12176:0',
|
||||
'checkin_overdue' => 'crwdns12178:0crwdne12178:0',
|
||||
'checkin_due_days' => 'crwdns12180:0crwdne12180:0',
|
||||
'audit_overdue' => 'crwdns5988:0crwdne5988:0',
|
||||
'accept' => 'crwdns6016:0crwdne6016:0',
|
||||
'i_accept' => 'crwdns6018:0crwdne6018:0',
|
||||
|
@ -506,6 +514,9 @@ return [
|
|||
'or' => 'crwdns12024:0crwdne12024:0',
|
||||
'url' => 'crwdns12054:0crwdne12054:0',
|
||||
'edit_fieldset' => 'crwdns12092:0crwdne12092:0',
|
||||
'permission_denied_superuser_demo' => 'crwdns12158:0crwdne12158:0',
|
||||
'pwd_reset_not_sent' => 'crwdns12160:0crwdne12160:0',
|
||||
'error_sending_email' => 'crwdns12162:0crwdne12162:0',
|
||||
'bulk' => [
|
||||
'delete' =>
|
||||
[
|
||||
|
|
|
@ -4,8 +4,11 @@ return [
|
|||
|
||||
'undeployable' => '<strong>Waarskuwing: </strong> Hierdie bate is gemerk as tans onbruikbaar. As hierdie status verander het, verander asseblief die batestatus.',
|
||||
'does_not_exist' => 'Bate bestaan nie.',
|
||||
'does_not_exist_var'=> 'Asset with tag :asset_tag not found.',
|
||||
'no_tag' => 'No asset tag provided.',
|
||||
'does_not_exist_or_not_requestable' => 'That asset does not exist or is not requestable.',
|
||||
'assoc_users' => 'Hierdie bate word tans na \'n gebruiker nagegaan en kan nie uitgevee word nie. Gaan asseblief die bate eers in, en probeer dan weer uitvee.',
|
||||
'warning_audit_date_mismatch' => 'This asset\'s next audit date (:next_audit_date) is before the last audit date (:last_audit_date). Please update the next audit date.',
|
||||
|
||||
'create' => [
|
||||
'error' => 'Bate is nie geskep nie, probeer asseblief weer. :(',
|
||||
|
@ -16,6 +19,7 @@ return [
|
|||
'update' => [
|
||||
'error' => 'Bate is nie opgedateer nie, probeer asseblief weer',
|
||||
'success' => 'Bate is suksesvol opgedateer.',
|
||||
'encrypted_warning' => 'Asset updated successfully, but encrypted custom fields were not due to permissions',
|
||||
'nothing_updated' => 'Geen velde is gekies nie, dus niks is opgedateer nie.',
|
||||
'no_assets_selected' => 'No assets were selected, so nothing was updated.',
|
||||
'assets_do_not_exist_or_are_invalid' => 'Selected assets cannot be updated.',
|
||||
|
@ -29,7 +33,7 @@ return [
|
|||
],
|
||||
|
||||
'audit' => [
|
||||
'error' => 'Bate-oudit was onsuksesvol. Probeer asseblief weer.',
|
||||
'error' => 'Asset audit unsuccessful: :error ',
|
||||
'success' => 'Bate oudit suksesvol aangemeld.',
|
||||
],
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
return array(
|
||||
|
||||
'does_not_exist' => 'License does not exist or you do not have permission to view it.',
|
||||
'user_does_not_exist' => 'Gebruiker bestaan nie.',
|
||||
'user_does_not_exist' => 'User does not exist or you do not have permission to view them.',
|
||||
'asset_does_not_exist' => 'Die bate wat u met hierdie lisensie probeer assosieer, bestaan nie.',
|
||||
'owner_doesnt_match_asset' => 'Die bate wat u met hierdie lisensie probeer assosieer, is in besit van ander as die persoon wat in die opdrag toegeken is.',
|
||||
'assoc_users' => 'Hierdie lisensie word tans na \'n gebruiker nagegaan en kan nie uitgevee word nie. Gaan asseblief die lisensie eers in, en probeer dan weer uitvee.',
|
||||
|
|
|
@ -4,6 +4,7 @@ return array(
|
|||
|
||||
'assigned_to' => 'Toevertrou aan',
|
||||
'checkout' => 'In uit',
|
||||
'deleted_at' => 'Deleted at',
|
||||
'id' => 'ID',
|
||||
'license_email' => 'Lisensie E-pos',
|
||||
'license_name' => 'Gelisensieer om',
|
||||
|
|
|
@ -49,6 +49,7 @@ return [
|
|||
'default_eula_text' => 'Standaard EULA',
|
||||
'default_language' => 'Verstek taal',
|
||||
'default_eula_help_text' => 'U kan ook aangepaste EULA\'s aan spesifieke batekategorieë assosieer.',
|
||||
'acceptance_note' => 'Add a note for your decision (Optional)',
|
||||
'display_asset_name' => 'Wys bate naam',
|
||||
'display_checkout_date' => 'Vertoon Checkout Date',
|
||||
'display_eol' => 'Wys EOL in tabelweergawe',
|
||||
|
|
|
@ -20,6 +20,7 @@ return array(
|
|||
'lock_passwords' => 'Login besonderhede kan nie op hierdie installasie verander word nie.',
|
||||
'manager' => 'Bestuurder',
|
||||
'managed_locations' => 'Bestuurde plekke',
|
||||
'managed_users' => 'Managed Users',
|
||||
'name' => 'naam',
|
||||
'nogroup' => 'No groups have been created yet. To add one, visit: ',
|
||||
'notes' => 'notas',
|
||||
|
|
|
@ -176,7 +176,7 @@ return [
|
|||
'last_name' => 'Van',
|
||||
'license' => 'lisensie',
|
||||
'license_report' => 'Lisensie Verslag',
|
||||
'licenses_available' => 'lisensies beskikbaar',
|
||||
'licenses_available' => 'Licenses available',
|
||||
'licenses' => 'lisensies',
|
||||
'list_all' => 'Lys almal',
|
||||
'loading' => 'Loading... please wait....',
|
||||
|
@ -202,6 +202,8 @@ return [
|
|||
'new_password' => 'New Password',
|
||||
'next' => 'volgende',
|
||||
'next_audit_date' => 'Volgende ouditdatum',
|
||||
'next_audit_date_help' => 'If you use auditing in your organization, this is usually automatically calculated based on the asset's last audit date and audit frequency (in <code>Admin Settings > Alerts</code>) and you can leave this blank. You can manually set this date here if you need to, but it must be later than the last audit date. ',
|
||||
'audit_images_help' => 'You can find audit images in the asset\'s history tab.',
|
||||
'no_email' => 'No email address associated with this user',
|
||||
'last_audit' => 'Laaste Oudit',
|
||||
'new' => 'nuwe!',
|
||||
|
@ -245,6 +247,7 @@ return [
|
|||
'select_all' => 'Select All',
|
||||
'search' => 'Soek',
|
||||
'select_category' => 'Kies \'n kategorie',
|
||||
'select_datasource' => 'Select a Datasource',
|
||||
'select_department' => 'Kies \'n Departement',
|
||||
'select_depreciation' => 'Kies \'n waardeverminderingstipe',
|
||||
'select_location' => 'Kies \'n plek',
|
||||
|
@ -294,6 +297,7 @@ return [
|
|||
'user' => 'gebruiker',
|
||||
'accepted' => 'aanvaarde',
|
||||
'declined' => 'afgeneem',
|
||||
'declined_note' => 'Declined Notes',
|
||||
'unassigned' => 'Unassigned',
|
||||
'unaccepted_asset_report' => 'Onaanvaarde Bates',
|
||||
'users' => 'gebruikers',
|
||||
|
@ -312,6 +316,10 @@ return [
|
|||
'token_expired' => 'Jou vormsessie het verval. Probeer asseblief weer.',
|
||||
'login_enabled' => 'Login Enabled',
|
||||
'audit_due' => 'Due for Audit',
|
||||
'audit_due_days' => 'Assets Due for Audit Within :days Day|Assets Due for Audit Within :days Days',
|
||||
'checkin_due' => 'Due for Checkin',
|
||||
'checkin_overdue' => 'Overdue for Checkin',
|
||||
'checkin_due_days' => 'Assets Due for Checkin Within :days Day|Assets Due for Checkin Within :days Days',
|
||||
'audit_overdue' => 'Overdue for Audit',
|
||||
'accept' => 'Accept :asset',
|
||||
'i_accept' => 'I accept',
|
||||
|
@ -507,6 +515,9 @@ return [
|
|||
'or' => 'or',
|
||||
'url' => 'URL',
|
||||
'edit_fieldset' => 'Edit fieldset fields and options',
|
||||
'permission_denied_superuser_demo' => 'Permission denied. You cannot update user information for superadmins on the demo.',
|
||||
'pwd_reset_not_sent' => 'User is not activated, is LDAP synced, or does not have an email address',
|
||||
'error_sending_email' => 'Error sending email',
|
||||
'bulk' => [
|
||||
'delete' =>
|
||||
[
|
||||
|
|
|
@ -5,8 +5,11 @@ return [
|
|||
'undeployable' => '<strong>Warning: </strong> This asset has been marked as currently undeployable.
|
||||
If this status has changed, please update the asset status.',
|
||||
'does_not_exist' => 'Asset does not exist.',
|
||||
'does_not_exist_var'=> 'Asset with tag :asset_tag not found.',
|
||||
'no_tag' => 'No asset tag provided.',
|
||||
'does_not_exist_or_not_requestable' => 'That asset does not exist or is not requestable.',
|
||||
'assoc_users' => 'This asset is currently checked out to a user and cannot be deleted. Please check the asset in first, and then try deleting again. ',
|
||||
'warning_audit_date_mismatch' => 'This asset\'s next audit date (:next_audit_date) is before the last audit date (:last_audit_date). Please update the next audit date.',
|
||||
|
||||
'create' => [
|
||||
'error' => 'Asset was not created, please try again. :(',
|
||||
|
@ -17,6 +20,7 @@ return [
|
|||
'update' => [
|
||||
'error' => 'Asset was not updated, please try again',
|
||||
'success' => 'Asset updated successfully.',
|
||||
'encrypted_warning' => 'Asset updated successfully, but encrypted custom fields were not due to permissions',
|
||||
'nothing_updated' => 'No fields were selected, so nothing was updated.',
|
||||
'no_assets_selected' => 'No assets were selected, so nothing was updated.',
|
||||
'assets_do_not_exist_or_are_invalid' => 'Selected assets cannot be updated.',
|
||||
|
@ -30,7 +34,7 @@ return [
|
|||
],
|
||||
|
||||
'audit' => [
|
||||
'error' => 'Asset audit was unsuccessful. Please try again.',
|
||||
'error' => 'Asset audit unsuccessful: :error ',
|
||||
'success' => 'Asset audit successfully logged.',
|
||||
],
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
return array(
|
||||
|
||||
'does_not_exist' => 'License does not exist or you do not have permission to view it.',
|
||||
'user_does_not_exist' => 'User does not exist.',
|
||||
'user_does_not_exist' => 'User does not exist or you do not have permission to view them.',
|
||||
'asset_does_not_exist' => 'The asset you are trying to associate with this license does not exist.',
|
||||
'owner_doesnt_match_asset' => 'The asset you are trying to associate with this license is owned by somene other than the person selected in the assigned to dropdown.',
|
||||
'assoc_users' => 'This license is currently checked out to a user and cannot be deleted. Please check the license in first, and then try deleting again. ',
|
||||
|
|
|
@ -4,6 +4,7 @@ return array(
|
|||
|
||||
'assigned_to' => 'Assigned To',
|
||||
'checkout' => 'In/Out',
|
||||
'deleted_at' => 'Deleted at',
|
||||
'id' => 'ID',
|
||||
'license_email' => 'License Email',
|
||||
'license_name' => 'Licensed To',
|
||||
|
|
|
@ -49,6 +49,7 @@ return [
|
|||
'default_eula_text' => 'Default EULA',
|
||||
'default_language' => 'Default Language',
|
||||
'default_eula_help_text' => 'You can also associate custom EULAs to specific asset categories.',
|
||||
'acceptance_note' => 'Add a note for your decision (Optional)',
|
||||
'display_asset_name' => 'Display Asset Name',
|
||||
'display_checkout_date' => 'Display Checkout Date',
|
||||
'display_eol' => 'Display EOL in table view',
|
||||
|
|
|
@ -20,6 +20,7 @@ return array(
|
|||
'lock_passwords' => 'Login details cannot be changed on this installation.',
|
||||
'manager' => 'Manager',
|
||||
'managed_locations' => 'Managed Locations',
|
||||
'managed_users' => 'Managed Users',
|
||||
'name' => 'Name',
|
||||
'nogroup' => 'No groups have been created yet. To add one, visit: ',
|
||||
'notes' => 'Notes',
|
||||
|
|
|
@ -176,7 +176,7 @@ return [
|
|||
'last_name' => 'Last Name',
|
||||
'license' => 'License',
|
||||
'license_report' => 'License Report',
|
||||
'licenses_available' => 'licenses available',
|
||||
'licenses_available' => 'Licenses available',
|
||||
'licenses' => 'Licenses',
|
||||
'list_all' => 'List All',
|
||||
'loading' => 'Loading... please wait....',
|
||||
|
@ -202,6 +202,8 @@ return [
|
|||
'new_password' => 'New Password',
|
||||
'next' => 'Next',
|
||||
'next_audit_date' => 'Next Audit Date',
|
||||
'next_audit_date_help' => 'If you use auditing in your organization, this is usually automatically calculated based on the asset's last audit date and audit frequency (in <code>Admin Settings > Alerts</code>) and you can leave this blank. You can manually set this date here if you need to, but it must be later than the last audit date. ',
|
||||
'audit_images_help' => 'You can find audit images in the asset\'s history tab.',
|
||||
'no_email' => 'No email address associated with this user',
|
||||
'last_audit' => 'Last Audit',
|
||||
'new' => 'new!',
|
||||
|
@ -245,6 +247,7 @@ return [
|
|||
'select_all' => 'Select All',
|
||||
'search' => 'Search',
|
||||
'select_category' => 'Select a Category',
|
||||
'select_datasource' => 'Select a Datasource',
|
||||
'select_department' => 'Select a Department',
|
||||
'select_depreciation' => 'Select a Depreciation Type',
|
||||
'select_location' => 'Select a Location',
|
||||
|
@ -294,6 +297,7 @@ return [
|
|||
'user' => 'User',
|
||||
'accepted' => 'accepted',
|
||||
'declined' => 'declined',
|
||||
'declined_note' => 'Declined Notes',
|
||||
'unassigned' => 'Unassigned',
|
||||
'unaccepted_asset_report' => 'Unaccepted Assets',
|
||||
'users' => 'Users',
|
||||
|
@ -312,6 +316,10 @@ return [
|
|||
'token_expired' => 'Your form session has expired. Please try again.',
|
||||
'login_enabled' => 'Login Enabled',
|
||||
'audit_due' => 'Due for Audit',
|
||||
'audit_due_days' => 'Assets Due for Audit Within :days Day|Assets Due for Audit Within :days Days',
|
||||
'checkin_due' => 'Due for Checkin',
|
||||
'checkin_overdue' => 'Overdue for Checkin',
|
||||
'checkin_due_days' => 'Assets Due for Checkin Within :days Day|Assets Due for Checkin Within :days Days',
|
||||
'audit_overdue' => 'Overdue for Audit',
|
||||
'accept' => 'Accept :asset',
|
||||
'i_accept' => 'I accept',
|
||||
|
@ -507,6 +515,9 @@ return [
|
|||
'or' => 'or',
|
||||
'url' => 'URL',
|
||||
'edit_fieldset' => 'Edit fieldset fields and options',
|
||||
'permission_denied_superuser_demo' => 'Permission denied. You cannot update user information for superadmins on the demo.',
|
||||
'pwd_reset_not_sent' => 'User is not activated, is LDAP synced, or does not have an email address',
|
||||
'error_sending_email' => 'Error sending email',
|
||||
'bulk' => [
|
||||
'delete' =>
|
||||
[
|
||||
|
|
|
@ -4,8 +4,11 @@ return [
|
|||
|
||||
'undeployable' => '<strong> تحذير: </strong> تم تحديد الحالة لهذا الأصل بانه غير قابل للتوزيع حاليا. إذا تغيرت هذه الحالة، يرجى تحديث حالة الأصل.',
|
||||
'does_not_exist' => 'الأصل غير موجود.',
|
||||
'does_not_exist_var'=> 'Asset with tag :asset_tag not found.',
|
||||
'no_tag' => 'No asset tag provided.',
|
||||
'does_not_exist_or_not_requestable' => 'ذالك الأصل غير موجود أو غير قابل للطلب.',
|
||||
'assoc_users' => 'هذا الأصل مخرج حاليا لمستخدم ولا يمكن حذفه. يرجى التحقق من الأصل أولا، ثم حاول الحذف مرة أخرى. ',
|
||||
'warning_audit_date_mismatch' => 'This asset\'s next audit date (:next_audit_date) is before the last audit date (:last_audit_date). Please update the next audit date.',
|
||||
|
||||
'create' => [
|
||||
'error' => 'لم يتم إنشاء الأصل، يرجى إعادة المحاولة. :(',
|
||||
|
@ -16,6 +19,7 @@ return [
|
|||
'update' => [
|
||||
'error' => 'لم يتم تحديث الأصل، يرجى إعادة المحاولة',
|
||||
'success' => 'تم تحديث الأصل بنجاح.',
|
||||
'encrypted_warning' => 'تم تحديث الأصل بنجاح، ولكن الحقول المخصصة المشفرة لم تكن بسبب الأذونات',
|
||||
'nothing_updated' => 'لم يتم اختيار أي حقول، لذلك لم يتم تحديث أي شيء.',
|
||||
'no_assets_selected' => 'لم يتم اختيار أي أصول، لذلك لم يتم تحديث أي شيء.',
|
||||
'assets_do_not_exist_or_are_invalid' => 'لا يمكن تحديث الأصول المحددة.',
|
||||
|
@ -29,7 +33,7 @@ return [
|
|||
],
|
||||
|
||||
'audit' => [
|
||||
'error' => 'لم تنجح مراجعة الأصل. حاول مرة اخرى.',
|
||||
'error' => 'Asset audit unsuccessful: :error ',
|
||||
'success' => 'تم تسجيل تدقيق الأصل بنجاح.',
|
||||
],
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
return array(
|
||||
|
||||
'does_not_exist' => 'الترخيص غير موجود أو ليس لديك الصلاحية لعرضه.',
|
||||
'user_does_not_exist' => 'المستخدم غير موجود.',
|
||||
'user_does_not_exist' => 'المستخدم غير موجود أو ليس لديك الصلاحية لعرضها.',
|
||||
'asset_does_not_exist' => 'الأصل اللذي تحاول ربطه مع هذا الترخيص غير موجود.',
|
||||
'owner_doesnt_match_asset' => 'الأصل اللذي تحاول ربطه مع هذا الترخيص حاليا مملوك لشخص اخر غير اللذي تم اختياره من القائمة المنسدلة.',
|
||||
'assoc_users' => 'هذا الترخيص حاليا مخرج لمستخدم ولا يمكن حذفه. يرجى التحقق من الترخيص في البداية، ثم محاولة الحذف مرة أخرى. ',
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue