mirror of
https://github.com/snipe/snipe-it.git
synced 2024-11-09 23:24:06 -08:00
Merge remote-tracking branch 'origin/master' into develop
Signed-off-by: snipe <snipe@snipe.net> # Conflicts: # .env.example # app/Http/Controllers/Auth/LoginController.php # app/Http/Kernel.php # app/Http/Transformers/ActionlogsTransformer.php # app/Importer/AssetImporter.php # app/Models/Accessory.php # app/Models/Consumable.php # app/Presenters/AccessoryPresenter.php # app/Presenters/ComponentPresenter.php # app/Presenters/ConsumablePresenter.php # app/Providers/AuthServiceProvider.php # composer.json # composer.lock # config/app.php # config/cors.php # config/version.php # package-lock.json # public/js/build/app.js # public/js/build/app.js.LICENSE.txt # public/js/dist/all.js # public/mix-manifest.json # resources/views/accessories/view.blade.php # resources/views/consumables/view.blade.php # resources/views/settings/saml.blade.php # routes/api.php
This commit is contained in:
commit
b876d0abb0
|
@ -157,4 +157,4 @@ IMPORT_TIME_LIMIT=600
|
|||
IMPORT_MEMORY_LIMIT=500M
|
||||
REPORT_TIME_LIMIT=12000
|
||||
REQUIRE_SAML=false
|
||||
|
||||
API_THROTTLE_PER_MINUTE=120
|
||||
|
|
|
@ -84,10 +84,12 @@ class Handler extends ExceptionHandler
|
|||
switch ($e->getStatusCode()) {
|
||||
case '404':
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $statusCode . ' endpoint not found'), 404);
|
||||
case '405':
|
||||
case '429':
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Too many requests'), 429);
|
||||
case '405':
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Method not allowed'), 405);
|
||||
default:
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $statusCode), 405);
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $statusCode), $statusCode);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,6 +79,8 @@ class AccessoriesController extends Controller
|
|||
$accessory->qty = request('qty');
|
||||
$accessory->user_id = Auth::user()->id;
|
||||
$accessory->supplier_id = request('supplier_id');
|
||||
$accessory->notes = request('notes');
|
||||
|
||||
|
||||
$accessory = $request->handleImages($accessory);
|
||||
|
||||
|
@ -143,6 +145,7 @@ class AccessoriesController extends Controller
|
|||
$accessory->purchase_cost = Helper::ParseCurrency(request('purchase_cost'));
|
||||
$accessory->qty = request('qty');
|
||||
$accessory->supplier_id = request('supplier_id');
|
||||
$accessory->notes = request('notes');
|
||||
|
||||
$accessory = $request->handleImages($accessory);
|
||||
|
||||
|
|
|
@ -40,7 +40,8 @@ class AccessoriesController extends Controller
|
|||
'notes',
|
||||
'created_at',
|
||||
'min_amt',
|
||||
'company_id'
|
||||
'company_id',
|
||||
'notes',
|
||||
];
|
||||
|
||||
|
||||
|
@ -70,6 +71,10 @@ class AccessoriesController extends Controller
|
|||
$accessories->where('location_id','=',$request->input('location_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('notes')) {
|
||||
$accessories->where('notes','=',$request->input('notes'));
|
||||
}
|
||||
|
||||
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
|
||||
// case we override with the actual count, so we should return 0 items.
|
||||
$offset = (($accessories) && ($request->get('offset') > $accessories->count())) ? $accessories->count() : $request->get('offset', 0);
|
||||
|
|
|
@ -102,7 +102,7 @@ class AssetMaintenancesController extends Controller
|
|||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$this->authorize('edit', Asset::class);
|
||||
$this->authorize('update', Asset::class);
|
||||
// create a new model instance
|
||||
$assetMaintenance = new AssetMaintenance();
|
||||
$assetMaintenance->supplier_id = $request->input('supplier_id');
|
||||
|
@ -154,7 +154,7 @@ class AssetMaintenancesController extends Controller
|
|||
*/
|
||||
public function update(Request $request, $assetMaintenanceId = null)
|
||||
{
|
||||
$this->authorize('edit', Asset::class);
|
||||
$this->authorize('update', Asset::class);
|
||||
// Check if the asset maintenance exists
|
||||
$assetMaintenance = AssetMaintenance::findOrFail($assetMaintenanceId);
|
||||
|
||||
|
@ -218,7 +218,7 @@ class AssetMaintenancesController extends Controller
|
|||
*/
|
||||
public function destroy($assetMaintenanceId)
|
||||
{
|
||||
$this->authorize('edit', Asset::class);
|
||||
$this->authorize('update', Asset::class);
|
||||
// Check if the asset maintenance exists
|
||||
$assetMaintenance = AssetMaintenance::findOrFail($assetMaintenanceId);
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ class ComponentsController extends Controller
|
|||
'purchase_cost',
|
||||
'qty',
|
||||
'image',
|
||||
'notes',
|
||||
];
|
||||
|
||||
|
||||
|
@ -62,6 +63,10 @@ class ComponentsController extends Controller
|
|||
$components->where('location_id', '=', $request->input('location_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('notes')) {
|
||||
$components->where('notes','=',$request->input('notes'));
|
||||
}
|
||||
|
||||
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
|
||||
// case we override with the actual count, so we should return 0 items.
|
||||
$offset = (($components) && ($request->get('offset') > $components->count())) ? $components->count() : $request->get('offset', 0);
|
||||
|
|
|
@ -42,6 +42,7 @@ class ConsumablesController extends Controller
|
|||
'item_no',
|
||||
'qty',
|
||||
'image',
|
||||
'notes',
|
||||
];
|
||||
|
||||
|
||||
|
@ -74,6 +75,10 @@ class ConsumablesController extends Controller
|
|||
$consumables->where('location_id','=',$request->input('location_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('notes')) {
|
||||
$consumables->where('notes','=',$request->input('notes'));
|
||||
}
|
||||
|
||||
|
||||
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
|
||||
// case we override with the actual count, so we should return 0 items.
|
||||
|
|
|
@ -7,6 +7,7 @@ use App\Http\Controllers\Controller;
|
|||
use App\Http\Requests\SaveUserRequest;
|
||||
use App\Http\Transformers\AccessoriesTransformer;
|
||||
use App\Http\Transformers\AssetsTransformer;
|
||||
use App\Http\Transformers\ConsumablesTransformer;
|
||||
use App\Http\Transformers\LicensesTransformer;
|
||||
use App\Http\Transformers\SelectlistTransformer;
|
||||
use App\Http\Transformers\UsersTransformer;
|
||||
|
@ -131,6 +132,26 @@ class UsersController extends Controller
|
|||
$users = $users->where('users.manager_id','=',$request->input('manager_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('ldap_import')) {
|
||||
$users = $users->where('ldap_import', '=', $request->input('ldap_import'));
|
||||
}
|
||||
|
||||
if ($request->filled('assets_count')) {
|
||||
$users->has('assets', '=', $request->input('assets_count'));
|
||||
}
|
||||
|
||||
if ($request->filled('consumables_count')) {
|
||||
$users->has('consumables', '=', $request->input('consumables_count'));
|
||||
}
|
||||
|
||||
if ($request->filled('licenses_count')) {
|
||||
$users->has('licenses', '=', $request->input('licenses_count'));
|
||||
}
|
||||
|
||||
if ($request->filled('accessories_count')) {
|
||||
$users->has('accessories', '=', $request->input('accessories_count'));
|
||||
}
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$users = $users->TextSearch($request->input('search'));
|
||||
}
|
||||
|
@ -445,6 +466,24 @@ class UsersController extends Controller
|
|||
return (new AssetsTransformer)->transformAssets($assets, $assets->count(), $request);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return JSON containing a list of consumables assigned to a user.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v3.0]
|
||||
* @param $userId
|
||||
* @return string JSON
|
||||
*/
|
||||
public function consumables(Request $request, $id)
|
||||
{
|
||||
$this->authorize('view', User::class);
|
||||
$this->authorize('view', Consumable::class);
|
||||
$user = User::findOrFail($id);
|
||||
$consumables = $user->consumables;
|
||||
return (new ConsumablesTransformer)->transformConsumables($consumables, $consumables->count(), $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return JSON containing a list of accessories assigned to a user.
|
||||
*
|
||||
|
|
|
@ -65,7 +65,7 @@ class AssetMaintenancesController extends Controller
|
|||
*/
|
||||
public function create()
|
||||
{
|
||||
$this->authorize('edit', Asset::class);
|
||||
$this->authorize('update', Asset::class);
|
||||
$asset = null;
|
||||
|
||||
if ($asset = Asset::find(request('asset_id'))) {
|
||||
|
@ -96,7 +96,7 @@ class AssetMaintenancesController extends Controller
|
|||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$this->authorize('edit', Asset::class);
|
||||
$this->authorize('update', Asset::class);
|
||||
// create a new model instance
|
||||
$assetMaintenance = new AssetMaintenance();
|
||||
$assetMaintenance->supplier_id = $request->input('supplier_id');
|
||||
|
@ -148,7 +148,7 @@ class AssetMaintenancesController extends Controller
|
|||
*/
|
||||
public function edit($assetMaintenanceId = null)
|
||||
{
|
||||
$this->authorize('edit', Asset::class);
|
||||
$this->authorize('update', Asset::class);
|
||||
// Check if the asset maintenance exists
|
||||
if (is_null($assetMaintenance = AssetMaintenance::find($assetMaintenanceId))) {
|
||||
// Redirect to the improvement management page
|
||||
|
@ -199,7 +199,7 @@ class AssetMaintenancesController extends Controller
|
|||
*/
|
||||
public function update(Request $request, $assetMaintenanceId = null)
|
||||
{
|
||||
$this->authorize('edit', Asset::class);
|
||||
$this->authorize('update', Asset::class);
|
||||
// Check if the asset maintenance exists
|
||||
if (is_null($assetMaintenance = AssetMaintenance::find($assetMaintenanceId))) {
|
||||
// Redirect to the asset maintenance management page
|
||||
|
@ -267,7 +267,7 @@ class AssetMaintenancesController extends Controller
|
|||
*/
|
||||
public function destroy($assetMaintenanceId)
|
||||
{
|
||||
$this->authorize('edit', Asset::class);
|
||||
$this->authorize('update', Asset::class);
|
||||
// Check if the asset maintenance exists
|
||||
if (is_null($assetMaintenance = AssetMaintenance::find($assetMaintenanceId))) {
|
||||
// Redirect to the asset maintenance management page
|
||||
|
|
|
@ -68,12 +68,13 @@ class LoginController extends Controller
|
|||
return redirect()->intended('/');
|
||||
}
|
||||
|
||||
//If the environment is set to ALWAYS require SAML, go straight to the SAML route.
|
||||
//We don't need to check other settings, as this should override those.
|
||||
if(config('app.require_saml')) {
|
||||
// If the environment is set to ALWAYS require SAML, go straight to the SAML route.
|
||||
// We don't need to check other settings, as this should override those.
|
||||
if (config('app.require_saml')) {
|
||||
return redirect()->route('saml.login');
|
||||
}
|
||||
|
||||
|
||||
if ($this->saml->isEnabled() && Setting::getSettings()->saml_forcelogin == '1' && ! ($request->has('nosaml') || $request->session()->has('error'))) {
|
||||
return redirect()->route('saml.login');
|
||||
}
|
||||
|
@ -235,8 +236,9 @@ class LoginController extends Controller
|
|||
*/
|
||||
public function login(Request $request)
|
||||
{
|
||||
|
||||
//If the environment is set to ALWAYS require SAML, return access denied
|
||||
if(config('app.require_saml')) {
|
||||
if (config('app.require_saml')) {
|
||||
return view('errors.403');
|
||||
}
|
||||
|
||||
|
|
|
@ -80,6 +80,7 @@ class ComponentsController extends Controller
|
|||
$component->purchase_cost = Helper::ParseCurrency($request->input('purchase_cost', null));
|
||||
$component->qty = $request->input('qty');
|
||||
$component->user_id = Auth::id();
|
||||
$component->notes = $request->input('notes');
|
||||
|
||||
$component = $request->handleImages($component);
|
||||
|
||||
|
@ -152,6 +153,7 @@ class ComponentsController extends Controller
|
|||
$component->purchase_date = $request->input('purchase_date');
|
||||
$component->purchase_cost = Helper::ParseCurrency(request('purchase_cost'));
|
||||
$component->qty = $request->input('qty');
|
||||
$component->notes = $request->input('notes');
|
||||
|
||||
$component = $request->handleImages($component);
|
||||
|
||||
|
|
|
@ -78,6 +78,8 @@ class ConsumablesController extends Controller
|
|||
$consumable->purchase_cost = Helper::ParseCurrency($request->input('purchase_cost'));
|
||||
$consumable->qty = $request->input('qty');
|
||||
$consumable->user_id = Auth::id();
|
||||
$consumable->notes = $request->input('notes');
|
||||
|
||||
|
||||
$consumable = $request->handleImages($consumable);
|
||||
|
||||
|
@ -140,6 +142,7 @@ class ConsumablesController extends Controller
|
|||
$consumable->purchase_date = $request->input('purchase_date');
|
||||
$consumable->purchase_cost = Helper::ParseCurrency($request->input('purchase_cost'));
|
||||
$consumable->qty = Helper::ParseFloat($request->input('qty'));
|
||||
$consumable->notes = $request->input('notes');
|
||||
|
||||
$consumable = $request->handleImages($consumable);
|
||||
|
||||
|
|
|
@ -45,7 +45,6 @@ class Kernel extends HttpKernel
|
|||
],
|
||||
|
||||
'api' => [
|
||||
'throttle:120,1',
|
||||
'auth:api',
|
||||
],
|
||||
];
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Transformers;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
|
@ -9,73 +8,58 @@ use Illuminate\Database\Eloquent\Collection;
|
|||
|
||||
class ActionlogsTransformer
|
||||
{
|
||||
public function transformActionlogs(Collection $actionlogs, $total)
|
||||
|
||||
public function transformActionlogs (Collection $actionlogs, $total)
|
||||
{
|
||||
$array = [];
|
||||
$array = array();
|
||||
$settings = Setting::getSettings();
|
||||
foreach ($actionlogs as $actionlog) {
|
||||
$array[] = self::transformActionlog($actionlog, $settings);
|
||||
}
|
||||
|
||||
return (new DatatablesTransformer)->transformDatatables($array, $total);
|
||||
}
|
||||
|
||||
public function transformActionlog(Actionlog $actionlog, $settings = null)
|
||||
private function clean_field($value)
|
||||
{
|
||||
// This object stuff is weird, and is used to make up for the fact that
|
||||
// older data can get strangely formatted if an asset existed,
|
||||
// then a new custom field is added, and the asset is saved again.
|
||||
// It can result in funnily-formatted strings like:
|
||||
//
|
||||
// {"_snipeit_right_sized_fault_tolerant_localareanetwo_1":
|
||||
// {"old":null,"new":{"value":"1579490695972","_snipeit_new_field_2":2,"_snipeit_new_field_3":"Monday, 20 January 2020 2:24:55 PM"}}
|
||||
// so we have to walk down that next level
|
||||
if(is_object($value) && isset($value->value)) {
|
||||
return $this->clean_field($value->value);
|
||||
}
|
||||
return is_scalar($value) || is_null($value) ? e($value) : e(json_encode($value));
|
||||
}
|
||||
|
||||
public function transformActionlog (Actionlog $actionlog, $settings = null)
|
||||
{
|
||||
$icon = $actionlog->present()->icon();
|
||||
if ($actionlog->filename != '') {
|
||||
$icon = e(Helper::filetype_icon($actionlog->filename));
|
||||
if ($actionlog->filename!='') {
|
||||
$icon = e(\App\Helpers\Helper::filetype_icon($actionlog->filename));
|
||||
}
|
||||
|
||||
// This is necessary since we can't escape special characters within a JSON object
|
||||
if (($actionlog->log_meta) && ($actionlog->log_meta != '')) {
|
||||
if (($actionlog->log_meta) && ($actionlog->log_meta!='')) {
|
||||
$meta_array = json_decode($actionlog->log_meta);
|
||||
|
||||
if ($meta_array) {
|
||||
foreach ($meta_array as $key => $value) {
|
||||
foreach ($value as $meta_key => $meta_value) {
|
||||
if (is_array($meta_value)) {
|
||||
foreach ($meta_value as $meta_value_key => $meta_value_value) {
|
||||
if (is_scalar($meta_value_value)) {
|
||||
$clean_meta[$key][$meta_value_key] = e($meta_value_value);
|
||||
} else {
|
||||
$clean_meta[$key][$meta_value_key] = 'invalid scalar: '.print_r($meta_value_value, true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
// This object stuff is weird, and is used to make up for the fact that
|
||||
// older data can get strangely formatted if an asset existed,
|
||||
// then a new custom field is added, and the asset is saved again.
|
||||
// It can result in funnily-formatted strings like:
|
||||
//
|
||||
// {"_snipeit_right_sized_fault_tolerant_localareanetwo_1":
|
||||
// {"old":null,"new":{"value":"1579490695972","_snipeit_new_field_2":2,"_snipeit_new_field_3":"Monday, 20 January 2020 2:24:55 PM"}}
|
||||
// so we have to walk down that next level
|
||||
|
||||
if (is_object($meta_value)) {
|
||||
foreach ($meta_value as $meta_value_key => $meta_value_value) {
|
||||
if ($meta_value_key == 'value') {
|
||||
$clean_meta[$key]['old'] = null;
|
||||
$clean_meta[$key]['new'] = e($meta_value->value);
|
||||
} else {
|
||||
$clean_meta[$meta_value_key]['old'] = null;
|
||||
$clean_meta[$meta_value_key]['new'] = e($meta_value_value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$clean_meta[$key][$meta_key] = e($meta_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($meta_array as $fieldname => $fieldata) {
|
||||
$clean_meta[$fieldname]['old'] = $this->clean_field($fieldata->old);
|
||||
$clean_meta[$fieldname]['new'] = $this->clean_field($fieldata->new);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$array = [
|
||||
'id' => (int) $actionlog->id,
|
||||
'icon' => $icon,
|
||||
'file' => ($actionlog->filename != '') ?
|
||||
'file' => ($actionlog->filename!='') ?
|
||||
[
|
||||
'url' => route('show/assetfile', ['assetId' => $actionlog->item->id, 'fileId' => $actionlog->id]),
|
||||
'filename' => $actionlog->filename,
|
||||
|
@ -84,7 +68,7 @@ class ActionlogsTransformer
|
|||
|
||||
'item' => ($actionlog->item) ? [
|
||||
'id' => (int) $actionlog->item->id,
|
||||
'name' => ($actionlog->itemType() == 'user') ? $actionlog->filename : e($actionlog->item->getDisplayNameAttribute()),
|
||||
'name' => ($actionlog->itemType()=='user') ? $actionlog->filename : e($actionlog->item->getDisplayNameAttribute()),
|
||||
'type' => e($actionlog->itemType()),
|
||||
] : null,
|
||||
'location' => ($actionlog->location) ? [
|
||||
|
@ -93,18 +77,18 @@ class ActionlogsTransformer
|
|||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($actionlog->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($actionlog->updated_at, 'datetime'),
|
||||
'next_audit_date' => ($actionlog->itemType() == 'asset') ? Helper::getFormattedDateObject($actionlog->calcNextAuditDate(null, $actionlog->item), 'date') : null,
|
||||
'next_audit_date' => ($actionlog->itemType()=='asset') ? Helper::getFormattedDateObject($actionlog->calcNextAuditDate(null, $actionlog->item), 'date'): null,
|
||||
'days_to_next_audit' => $actionlog->daysUntilNextAudit($settings->audit_interval, $actionlog->item),
|
||||
'action_type' => $actionlog->present()->actionType(),
|
||||
'admin' => ($actionlog->user) ? [
|
||||
'id' => (int) $actionlog->user->id,
|
||||
'name' => e($actionlog->user->getFullNameAttribute()),
|
||||
'first_name'=> e($actionlog->user->first_name),
|
||||
'last_name'=> e($actionlog->user->last_name),
|
||||
'last_name'=> e($actionlog->user->last_name)
|
||||
] : null,
|
||||
'target' => ($actionlog->target) ? [
|
||||
'id' => (int) $actionlog->target->id,
|
||||
'name' => ($actionlog->targetType() == 'user') ? e($actionlog->target->getFullNameAttribute()) : e($actionlog->target->getDisplayNameAttribute()),
|
||||
'name' => ($actionlog->targetType()=='user') ? e($actionlog->target->getFullNameAttribute()) : e($actionlog->target->getDisplayNameAttribute()),
|
||||
'type' => e($actionlog->targetType()),
|
||||
] : null,
|
||||
|
||||
|
@ -114,17 +98,23 @@ class ActionlogsTransformer
|
|||
'action_date' => ($actionlog->action_date) ? Helper::getFormattedDateObject($actionlog->action_date, 'datetime'): Helper::getFormattedDateObject($actionlog->created_at, 'datetime'),
|
||||
|
||||
];
|
||||
//\Log::info("Clean Meta is: ".print_r($clean_meta,true));
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
public function transformCheckedoutActionlog(Collection $accessories_users, $total)
|
||||
|
||||
|
||||
public function transformCheckedoutActionlog (Collection $accessories_users, $total)
|
||||
{
|
||||
$array = [];
|
||||
|
||||
$array = array();
|
||||
foreach ($accessories_users as $user) {
|
||||
$array[] = (new UsersTransformer)->transformUser($user);
|
||||
}
|
||||
|
||||
return (new DatatablesTransformer)->transformDatatables($array, $total);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -45,6 +45,7 @@ class ComponentsTransformer
|
|||
'id' => (int) $component->company->id,
|
||||
'name' => e($component->company->name),
|
||||
] : null,
|
||||
'notes' => ($component->notes) ? e($component->notes) : null,
|
||||
'created_at' => Helper::getFormattedDateObject($component->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($component->updated_at, 'datetime'),
|
||||
'user_can_checkout' => ($component->numRemaining() > 0) ? 1 : 0,
|
||||
|
|
|
@ -38,6 +38,7 @@ class ConsumablesTransformer
|
|||
'purchase_cost' => Helper::formatCurrencyOutput($consumable->purchase_cost),
|
||||
'purchase_date' => Helper::getFormattedDateObject($consumable->purchase_date, 'date'),
|
||||
'qty' => (int) $consumable->qty,
|
||||
'notes' => ($consumable->notes) ? e($consumable->notes) : null,
|
||||
'created_at' => Helper::getFormattedDateObject($consumable->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($consumable->updated_at, 'datetime'),
|
||||
];
|
||||
|
|
|
@ -39,6 +39,7 @@ class AssetImporter extends ItemImporter
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
$this->createAssetIfNotExists($row);
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ class Accessory extends SnipeModel
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = ['name', 'model_number', 'order_number', 'purchase_date'];
|
||||
protected $searchableAttributes = ['name', 'model_number', 'order_number', 'purchase_date', 'notes'];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
|
@ -64,6 +64,7 @@ class Accessory extends SnipeModel
|
|||
'purchase_cost' => 'numeric|nullable',
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Whether the model should inject it's identifier to the unique
|
||||
* validation rules before attempting validation. If this property
|
||||
|
@ -94,6 +95,7 @@ class Accessory extends SnipeModel
|
|||
'qty',
|
||||
'min_amt',
|
||||
'requestable',
|
||||
'notes',
|
||||
];
|
||||
|
||||
|
||||
|
@ -110,6 +112,7 @@ class Accessory extends SnipeModel
|
|||
return $this->belongsTo(\App\Models\Supplier::class, 'supplier_id');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the requestable attribute on the accessory
|
||||
*
|
||||
|
@ -220,8 +223,8 @@ class Accessory extends SnipeModel
|
|||
if ($this->image) {
|
||||
return Storage::disk('public')->url(app('accessories_upload_path').$this->image);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -65,6 +65,7 @@ class Component extends SnipeModel
|
|||
'order_number',
|
||||
'qty',
|
||||
'serial',
|
||||
'notes',
|
||||
];
|
||||
|
||||
use Searchable;
|
||||
|
@ -74,7 +75,7 @@ class Component extends SnipeModel
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = ['name', 'order_number', 'serial', 'purchase_cost', 'purchase_date'];
|
||||
protected $searchableAttributes = ['name', 'order_number', 'serial', 'purchase_cost', 'purchase_date', 'notes'];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
|
|
|
@ -27,7 +27,8 @@ class Consumable extends SnipeModel
|
|||
'category_id' => 'integer',
|
||||
'company_id' => 'integer',
|
||||
'qty' => 'integer',
|
||||
'min_amt' => 'integer', ];
|
||||
'min_amt' => 'integer',
|
||||
];
|
||||
|
||||
/**
|
||||
* Category validation rules
|
||||
|
@ -70,6 +71,7 @@ class Consumable extends SnipeModel
|
|||
'qty',
|
||||
'min_amt',
|
||||
'requestable',
|
||||
'notes',
|
||||
];
|
||||
|
||||
use Searchable;
|
||||
|
@ -79,7 +81,7 @@ class Consumable extends SnipeModel
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = ['name', 'order_number', 'purchase_cost', 'purchase_date', 'item_no', 'model_number'];
|
||||
protected $searchableAttributes = ['name', 'order_number', 'purchase_cost', 'purchase_date', 'item_no', 'model_number', 'notes'];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
|
|
|
@ -59,7 +59,9 @@ class AccessoryPresenter extends Presenter
|
|||
'field' => 'manufacturer',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => trans('general.manufacturer'),
|
||||
'visible' => false,
|
||||
'formatter' => 'manufacturersLinkObjFormatter',
|
||||
], [
|
||||
'field' => 'supplier',
|
||||
|
@ -89,6 +91,7 @@ class AccessoryPresenter extends Presenter
|
|||
'field' => 'remaining_qty',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
'visible' => false,
|
||||
'title' => trans('admin/accessories/general.remaining'),
|
||||
], [
|
||||
'field' => 'purchase_date',
|
||||
|
@ -110,6 +113,13 @@ class AccessoryPresenter extends Presenter
|
|||
'sortable' => true,
|
||||
'visible' => false,
|
||||
'title' => trans('general.order_number'),
|
||||
],[
|
||||
'field' => 'notes',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'visible' => false,
|
||||
'title' => trans('general.notes'),
|
||||
'formatter' => 'notesFormatter'
|
||||
], [
|
||||
'field' => 'change',
|
||||
'searchable' => false,
|
||||
|
|
|
@ -103,6 +103,13 @@ class ComponentPresenter extends Presenter
|
|||
'visible' => true,
|
||||
'footerFormatter' => 'sumFormatterQuantity',
|
||||
'class' => 'text-right',
|
||||
], [
|
||||
'field' => 'notes',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'visible' => false,
|
||||
'title' => trans('general.notes'),
|
||||
'formatter' => 'notesFormatter',
|
||||
],
|
||||
];
|
||||
|
||||
|
|
|
@ -115,6 +115,13 @@ class ConsumablePresenter extends Presenter
|
|||
'visible' => true,
|
||||
'footerFormatter' => 'sumFormatterQuantity',
|
||||
'class' => 'text-right',
|
||||
], [
|
||||
'field' => 'notes',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'visible' => false,
|
||||
'title' => trans('general.notes'),
|
||||
'formatter' => 'notesFormatter',
|
||||
], [
|
||||
'field' => 'change',
|
||||
'searchable' => false,
|
||||
|
|
|
@ -121,6 +121,7 @@ class AuthServiceProvider extends ServiceProvider
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
// -----------------------------------------
|
||||
// Reports
|
||||
// -----------------------------------------
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
"erusev/parsedown": "^1.7",
|
||||
"facade/ignition": "^2.10",
|
||||
"fideloper/proxy": "^4.3",
|
||||
"fruitcake/laravel-cors": "^2.0",
|
||||
"fruitcake/laravel-cors": "^2.2",
|
||||
"guzzlehttp/guzzle": "^7.0.1",
|
||||
"intervention/image": "^2.5",
|
||||
"javiereguiluz/easyslugger": "^1.0",
|
||||
|
|
1541
composer.lock
generated
1541
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -250,6 +250,7 @@ return [
|
|||
|
||||
'enable_csp' => env('ENABLE_CSP', false),
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Require SAML Login
|
||||
|
@ -265,7 +266,6 @@ return [
|
|||
|
||||
'require_saml' => env('REQUIRE_SAML', false),
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Demo Mode Lockdown
|
||||
|
@ -418,4 +418,15 @@ return [
|
|||
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| API Throttling
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value determines the number of API requests permitted per minute
|
||||
|
|
||||
*/
|
||||
|
||||
'api_throttle_per_minute' => env('API_THROTTLE_PER_MINUTE', 120),
|
||||
|
||||
];
|
||||
|
|
|
@ -1,48 +1,49 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* ---------------------------------------------------------------------
|
||||
* THIS IS $allowed_origins code IS NOT PART OF THE ORIGINAL CORS PACKAGE.
|
||||
* IT IS A MODIFICATION BY SNIPE-IT TO ALLOW ADDING ALLOWED ORIGINS VIA THE ENV.
|
||||
* ---------------------------------------------------------------------
|
||||
*
|
||||
* Since we don't really want people editing config files (lest they get
|
||||
* overwritten later), this enables the person managing the Snipe-IT
|
||||
* installation to modify these values without modifying the code.
|
||||
*
|
||||
* If APP_CORS_ALLOWED_ORIGINS is not set in the .env (for example if no one added it
|
||||
* after an upgrade from a previous version that didn't include it in the .env.example) or is null,
|
||||
* set it to * to allow all. If there is a value, either a single url or a comma-delimited
|
||||
* list of urls, explode that out into an array to whitelist just those urls.
|
||||
*/
|
||||
|
||||
$allowed_origins = env('CORS_ALLOWED_ORIGINS') !== null ?
|
||||
explode(',', env('CORS_ALLOWED_ORIGINS')) : [];
|
||||
|
||||
/**
|
||||
* Original Laravel CORS package config file modifications end here
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
return [
|
||||
|
||||
'supportsCredentials' => false,
|
||||
|
||||
'allowedOrigins' => $allowed_origins,
|
||||
|
||||
'allowedHeaders' => ['*'],
|
||||
|
||||
'allowedMethods' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
|
||||
|
||||
'maxAge' => 0,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cross-Origin Resource Sharing (CORS) Configuration
|
||||
| Laravel CORS
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure your settings for cross-origin resource sharing
|
||||
| or "CORS". This determines what cross-origin operations may execute
|
||||
| in web browsers. You are free to adjust these settings as needed.
|
||||
|
|
||||
| To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
||||
| allowedOrigins, allowedHeaders and allowedMethods can be set to array('*')
|
||||
| to accept any value.
|
||||
|
|
||||
*/
|
||||
|
||||
|
||||
'supports_credentials' => false,
|
||||
'allowed_origins' => $allowed_origins,
|
||||
'allowed_origins_patterns' => [],
|
||||
'allowed_headers' => ['*'],
|
||||
'allowed_methods' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
|
||||
'exposed_headers' => [],
|
||||
'max_age' => 0,
|
||||
'paths' => ['api/*', 'sanctum/csrf-cookie'],
|
||||
|
||||
'allowed_methods' => ['*'],
|
||||
|
||||
'allowed_origins' => ['*'],
|
||||
|
||||
'allowed_origins_patterns' => [],
|
||||
|
||||
'allowed_headers' => ['*'],
|
||||
|
||||
'exposed_headers' => [],
|
||||
|
||||
'max_age' => 0,
|
||||
|
||||
'supports_credentials' => false,
|
||||
|
||||
];
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddNotesToAccessories extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('accessories', function (Blueprint $table) {
|
||||
$table->text("notes")->nullable()->default(null);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('accessories', function (Blueprint $table) {
|
||||
if (Schema::hasColumn('accessories', 'notes')) {
|
||||
$table->dropColumn('notes');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddNotesToComponents extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('components', function (Blueprint $table) {
|
||||
$table->text("notes")->nullable()->default(null);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('components', function (Blueprint $table) {
|
||||
if (Schema::hasColumn('components', 'notes')) {
|
||||
$table->dropColumn('notes');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddNotesToConsumables extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('consumables', function (Blueprint $table) {
|
||||
$table->text("notes")->nullable()->default(null);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('consumables', function (Blueprint $table) {
|
||||
if (Schema::hasColumn('consumables', 'notes')) {
|
||||
$table->dropColumn('notes');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
Binary file not shown.
BIN
public/js/dist/all.js
vendored
BIN
public/js/dist/all.js
vendored
Binary file not shown.
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"/js/build/app.js": "/js/build/app.js?id=53bb9a89289532242ef7",
|
||||
"/js/build/app.js": "/js/build/app.js?id=869aec997ba93ec756a2",
|
||||
"/css/dist/skins/skin-blue.css": "/css/dist/skins/skin-blue.css?id=83e39e254b7f9035eddc",
|
||||
"/css/build/overrides.css": "/css/build/overrides.css?id=4fc3a0e0a16964643e70",
|
||||
"/css/build/app.css": "/css/build/app.css?id=a7cd7ad6e0e053ccf443",
|
||||
|
@ -26,7 +26,7 @@
|
|||
"/css/dist/bootstrap-table.css": "/css/dist/bootstrap-table.css?id=810d7e520c3057ee500e",
|
||||
"/js/build/vendor.js": "/js/build/vendor.js?id=651427cc4b45d8e68d0c",
|
||||
"/js/dist/bootstrap-table.js": "/js/dist/bootstrap-table.js?id=675a086b82536dd212f0",
|
||||
"/js/dist/all.js": "/js/dist/all.js?id=7fe089bb7f3e8a1fd4a4",
|
||||
"/js/dist/all.js": "/js/dist/all.js?id=d850187bf56be758be7c",
|
||||
"/css/dist/skins/skin-green.min.css": "/css/dist/skins/skin-green.min.css?id=efda2335fa5243175850",
|
||||
"/css/dist/skins/skin-green-dark.min.css": "/css/dist/skins/skin-green-dark.min.css?id=6e35fb4cb2f1063b3047",
|
||||
"/css/dist/skins/skin-black.min.css": "/css/dist/skins/skin-black.min.css?id=ec96c42439cdeb022133",
|
||||
|
|
|
@ -147,6 +147,8 @@
|
|||
assets: [
|
||||
{id: 'asset_tag', text: 'Asset Tag' },
|
||||
{id: 'asset_model', text: 'Model Name' },
|
||||
{id: 'asset_notes', text: 'Asset Notes' },
|
||||
{id: 'model_notes', text: 'Model Notes' },
|
||||
{id: 'checkout_class', text: 'Checkout Type' },
|
||||
{id: 'checkout_location', text: 'Checkout Location' },
|
||||
{id: 'image', text: 'Image Filename' },
|
||||
|
@ -172,6 +174,7 @@
|
|||
{id: 'notes', text: 'Notes' },
|
||||
{id: 'license_email', text: 'Licensed To Email' },
|
||||
{id: 'license_name', text: 'Licensed To Name' },
|
||||
{id: 'notes', text: 'Notes' },
|
||||
{id: 'purchase_order', text: 'Purchase Order' },
|
||||
{id: 'reassignable', text: 'Reassignable' },
|
||||
{id: 'seats', text: 'Seats' },
|
||||
|
@ -185,6 +188,7 @@
|
|||
{id: 'manager_first_name', text: 'Manager First Name' },
|
||||
{id: 'notes', text: 'Notes' },
|
||||
{id: 'manager_last_name', text: 'Manager Last Name' },
|
||||
{id: 'notes', text: 'Notes' },
|
||||
{id: 'activated', text: 'Activated' },
|
||||
{id: 'address', text: 'Address' },
|
||||
{id: 'city', text: 'City' },
|
||||
|
|
|
@ -174,7 +174,7 @@ return [
|
|||
'saml_idp_metadata_help' => 'You can specify the IdP metadata using a URL or XML file.',
|
||||
'saml_attr_mapping_username' => 'Attribute Mapping - Username',
|
||||
'saml_attr_mapping_username_help' => 'NameID will be used if attribute mapping is unspecified or invalid.',
|
||||
'saml_forcelogin_label' => 'SAML Force Login',
|
||||
'saml_forcelogin_label' => 'SAML Default Login',
|
||||
'saml_forcelogin' => 'Make SAML the primary login',
|
||||
'saml_forcelogin_help' => 'You can use \'/login?nosaml\' to get to the normal login page.',
|
||||
'saml_slo_label' => 'SAML Single Log Out',
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
</div>
|
||||
@endif
|
||||
|
||||
@include ('partials.forms.edit.notes')
|
||||
|
||||
@include ('partials.forms.edit.image-upload')
|
||||
|
||||
@stop
|
||||
|
|
|
@ -112,7 +112,7 @@
|
|||
@endif
|
||||
|
||||
|
||||
@if ($accessory->category)
|
||||
@if ($accessory->category)
|
||||
<div class="row">
|
||||
<div class="col-md-4" style="padding-bottom: 15px;">
|
||||
{{ trans('general.category')}}
|
||||
|
@ -122,6 +122,20 @@
|
|||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
@if ($accessory->notes)
|
||||
|
||||
<div class="col-md-12">
|
||||
<strong>
|
||||
{{ trans('general.notes') }}
|
||||
</strong>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
{!! nl2br(e($accessory->notes)) !!}
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<div class="row">
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
</div>
|
||||
@endif
|
||||
|
||||
@include ('partials.forms.edit.notes')
|
||||
|
||||
@include ('partials.forms.edit.image-upload')
|
||||
|
||||
@stop
|
||||
|
|
|
@ -136,6 +136,20 @@
|
|||
<div class="col-md-12" style="padding-bottom: 5px;"><strong>{{ trans('general.order_number') }}:</strong>
|
||||
{{ $component->order_number }} </div>
|
||||
@endif
|
||||
|
||||
@if ($component->notes)
|
||||
|
||||
<div class="col-md-12">
|
||||
<strong>
|
||||
{{ trans('general.notes') }}
|
||||
</strong>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
{!! nl2br(e($component->notes)) !!}
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
</div> <!-- .row-->
|
||||
|
||||
|
|
|
@ -33,5 +33,7 @@
|
|||
</div>
|
||||
@endif
|
||||
|
||||
@include ('partials.forms.edit.notes')
|
||||
|
||||
@include ('partials.forms.edit.image-upload')
|
||||
@stop
|
||||
|
|
|
@ -125,17 +125,24 @@
|
|||
</div>
|
||||
@endif
|
||||
|
||||
@can('checkout', \App\Models\Accessory::class)
|
||||
<div class="col-md-12 text-center">
|
||||
@can('checkout', \App\Models\Consumable::class)
|
||||
<div class="col-md-12">
|
||||
<a href="{{ route('checkout/consumable', $consumable->id) }}" style="padding-bottom:5px;" class="btn btn-primary btn-sm" {{ (($consumable->numRemaining() > 0 ) ? '' : ' disabled') }}>{{ trans('general.checkout') }}</a>
|
||||
</div>
|
||||
@endcan
|
||||
|
||||
@if ($consumable->notes)
|
||||
|
||||
<div class="col-md-12">
|
||||
<strong>
|
||||
{{ trans('general.notes') }}
|
||||
</strong>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
{!! nl2br(e($consumable->notes)) !!}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
||||
|
|
Loading…
Reference in a new issue