Merge branch 'develop' into integrations/2020-04-15-v5-merge

# Conflicts:
#	README.md
#	app/Http/Controllers/AccessoriesController.php
#	app/Http/Controllers/Api/AssetsController.php
#	app/Http/Controllers/Api/LicensesController.php
#	app/Http/Controllers/Api/LocationsController.php
#	app/Http/Controllers/Api/SettingsController.php
#	app/Http/Controllers/Api/UsersController.php
#	app/Http/Controllers/AssetModelsController.php
#	app/Http/Controllers/Assets/AssetsController.php
#	app/Http/Controllers/Auth/ForgotPasswordController.php
#	app/Http/Controllers/CategoriesController.php
#	app/Http/Controllers/CompaniesController.php
#	app/Http/Controllers/ComponentsController.php
#	app/Http/Controllers/ConsumablesController.php
#	app/Http/Controllers/CustomFieldsetsController.php
#	app/Http/Controllers/DepartmentsController.php
#	app/Http/Controllers/LicensesController.php
#	app/Http/Controllers/LocationsController.php
#	app/Http/Controllers/ManufacturersController.php
#	app/Http/Controllers/SettingsController.php
#	app/Http/Controllers/SuppliersController.php
#	app/Http/Controllers/UsersController.php
#	app/Http/Requests/AssetRequest.php
#	app/Http/Requests/ImageUploadRequest.php
#	app/Models/LicenseSeat.php
#	app/Models/Location.php
#	app/Models/Setting.php
#	composer.json
#	composer.lock
#	config/database.php
#	config/version.php
#	npm-shrinkwrap.json
#	package.json
#	public/css/AdminLTE.css
#	public/css/AdminLTE.css.map
#	public/css/overrides.css
#	public/css/overrides.css.map
#	public/css/skins/skin-blue-light.css
#	public/css/skins/skin-blue.css
#	public/css/skins/skin-green-dark.min.css
#	public/js/app.js
#	public/js/bootstrap-table.js
#	public/js/bootstrap/js/bootstrap.js
#	public/js/bootstrap/js/bootstrap.min.js
#	public/js/build/all.js
#	public/js/build/vue.js
#	public/js/build/vue.js.map
#	public/js/demo.js
#	public/js/ekko-lightbox.js
#	public/js/ekko-lightbox.min.js
#	public/js/extensions/export/bootstrap-table-export.js
#	public/js/extensions/multiple-sort/bootstrap-table-multiple-sort.js
#	public/js/extensions/multiple-sort/bootstrap-table-multiple-sort.min.js
#	public/js/extensions/toolbar/bootstrap-table-toolbar.min.js
#	public/js/plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.all.js
#	public/js/plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.all.min.js
#	public/js/plugins/timepicker/bootstrap-timepicker.js
#	public/js/plugins/timepicker/bootstrap-timepicker.min.js
#	public/js/vue.js
#	public/mix-manifest.json
#	resources/assets/js/bootstrap-js.js
#	resources/assets/js/bootstrap.min.js
#	resources/assets/js/ekko-lightbox.js
#	resources/assets/js/ekko-lightbox.min.js
#	resources/assets/js/plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.all.js
#	resources/assets/js/plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.all.min.js
#	resources/assets/js/plugins/chartjs/Chart.js
#	resources/assets/js/plugins/timepicker/bootstrap-timepicker.js
#	resources/assets/js/plugins/timepicker/bootstrap-timepicker.min.js
#	resources/assets/less/AdminLTE.less
#	resources/assets/less/overrides.less
#	resources/assets/less/skins/_all-skins.less
#	resources/assets/less/skins/skin-black.less
#	resources/assets/less/skins/skin-blue.less
#	resources/assets/less/skins/skin-green.less
#	resources/assets/less/skins/skin-purple.less
#	resources/assets/less/skins/skin-red.less
#	resources/assets/less/skins/skin-yellow.less
#	resources/assets/less/variables.less
#	resources/js/components/importer/importer-file.vue
#	resources/lang/en/auth/message.php
#	resources/lang/en/passwords.php
#	resources/lang/es-CO/general.php
#	resources/lang/es-ES/general.php
#	resources/lang/es-VE/general.php
#	resources/less/skins/skin-black-dark.less
#	resources/less/skins/skin-blue-dark.less
#	resources/less/skins/skin-contrast.less
#	resources/less/skins/skin-green-dark.less
#	resources/less/skins/skin-orange-dark.less
#	resources/less/skins/skin-orange.less
#	resources/less/skins/skin-purple-dark.less
#	resources/less/skins/skin-red-dark.less
#	resources/less/skins/skin-yellow-dark.less
#	resources/views/accessories/checkin.blade.php
#	resources/views/accessories/checkout.blade.php
#	resources/views/accessories/edit.blade.php
#	resources/views/account/profile.blade.php
#	resources/views/account/view-assets.blade.php
#	resources/views/asset_maintenances/edit.blade.php
#	resources/views/auth/passwords/email.blade.php
#	resources/views/auth/passwords/reset.blade.php
#	resources/views/categories/edit.blade.php
#	resources/views/companies/edit.blade.php
#	resources/views/components/checkin.blade.php
#	resources/views/components/checkout.blade.php
#	resources/views/components/edit.blade.php
#	resources/views/consumables/checkout.blade.php
#	resources/views/consumables/edit.blade.php
#	resources/views/custom_fields/fields/edit.blade.php
#	resources/views/custom_fields/fieldsets/edit.blade.php
#	resources/views/dashboard.blade.php
#	resources/views/departments/edit.blade.php
#	resources/views/groups/edit.blade.php
#	resources/views/hardware/audit.blade.php
#	resources/views/hardware/bulk-checkout.blade.php
#	resources/views/hardware/bulk.blade.php
#	resources/views/hardware/checkin.blade.php
#	resources/views/hardware/checkout.blade.php
#	resources/views/hardware/edit.blade.php
#	resources/views/hardware/index.blade.php
#	resources/views/hardware/quickscan.blade.php
#	resources/views/hardware/view.blade.php
#	resources/views/importer/import.blade.php
#	resources/views/layouts/basic.blade.php
#	resources/views/layouts/default.blade.php
#	resources/views/layouts/edit-form.blade.php
#	resources/views/licenses/checkin.blade.php
#	resources/views/licenses/checkout.blade.php
#	resources/views/licenses/edit.blade.php
#	resources/views/locations/edit.blade.php
#	resources/views/manufacturers/edit.blade.php
#	resources/views/modals/upload-file.blade.php
#	resources/views/models/bulk-edit.blade.php
#	resources/views/models/custom_fields_form.blade.php
#	resources/views/models/edit.blade.php
#	resources/views/partials/bootstrap-table.blade.php
#	resources/views/partials/forms/edit/address.blade.php
#	resources/views/partials/forms/edit/asset-select.blade.php
#	resources/views/partials/forms/edit/category-select.blade.php
#	resources/views/partials/forms/edit/category.blade.php
#	resources/views/partials/forms/edit/company-select.blade.php
#	resources/views/partials/forms/edit/company.blade.php
#	resources/views/partials/forms/edit/department-select.blade.php
#	resources/views/partials/forms/edit/depreciation.blade.php
#	resources/views/partials/forms/edit/email.blade.php
#	resources/views/partials/forms/edit/image-upload.blade.php
#	resources/views/partials/forms/edit/item_number.blade.php
#	resources/views/partials/forms/edit/location-profile-select.blade.php
#	resources/views/partials/forms/edit/location-select.blade.php
#	resources/views/partials/forms/edit/location.blade.php
#	resources/views/partials/forms/edit/maintenance_type.blade.php
#	resources/views/partials/forms/edit/manufacturer-select.blade.php
#	resources/views/partials/forms/edit/manufacturer.blade.php
#	resources/views/partials/forms/edit/minimum_quantity.blade.php
#	resources/views/partials/forms/edit/model-select.blade.php
#	resources/views/partials/forms/edit/model_number.blade.php
#	resources/views/partials/forms/edit/name.blade.php
#	resources/views/partials/forms/edit/notes.blade.php
#	resources/views/partials/forms/edit/order_number.blade.php
#	resources/views/partials/forms/edit/phone.blade.php
#	resources/views/partials/forms/edit/purchase_cost.blade.php
#	resources/views/partials/forms/edit/purchase_date.blade.php
#	resources/views/partials/forms/edit/quantity.blade.php
#	resources/views/partials/forms/edit/serial.blade.php
#	resources/views/partials/forms/edit/status.blade.php
#	resources/views/partials/forms/edit/submit.blade.php
#	resources/views/partials/forms/edit/supplier-select.blade.php
#	resources/views/partials/forms/edit/supplier.blade.php
#	resources/views/partials/forms/edit/user-select.blade.php
#	resources/views/reports/custom.blade.php
#	resources/views/settings/alerts.blade.php
#	resources/views/settings/asset_tags.blade.php
#	resources/views/settings/barcodes.blade.php
#	resources/views/settings/branding.blade.php
#	resources/views/settings/general.blade.php
#	resources/views/settings/labels.blade.php
#	resources/views/settings/ldap.blade.php
#	resources/views/settings/localization.blade.php
#	resources/views/settings/security.blade.php
#	resources/views/setup/user.blade.php
#	resources/views/suppliers/edit.blade.php
#	resources/views/users/bulk-edit.blade.php
#	resources/views/users/edit.blade.php
#	resources/views/users/ldap.blade.php
#	resources/views/users/print.blade.php
#	resources/views/users/view.blade.php
#	routes/api.php
#	routes/web/hardware.php
#	webpack.mix.js
This commit is contained in:
snipe
2020-04-20 23:20:34 -07:00
1780 changed files with 116525 additions and 290164 deletions
@@ -2,16 +2,17 @@
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Helpers\Helper;
use App\Models\Accessory;
use App\Http\Controllers\Controller;
use App\Http\Transformers\AccessoriesTransformer;
use App\Http\Transformers\SelectlistTransformer;
use App\Models\Accessory;
use App\Models\Company;
use App\Models\User;
use Carbon\Carbon;
use Auth;
use DB;
use Illuminate\Http\Request;
class AccessoriesController extends Controller
{
@@ -141,18 +142,37 @@ class AccessoriesController extends Controller
* @param int $id
* @return \Illuminate\Http\Response
*/
public function checkedout($id)
public function checkedout($id, Request $request)
{
$this->authorize('view', Accessory::class);
$accessory = Accessory::findOrFail($id);
$accessory = Accessory::with('lastCheckout')->findOrFail($id);
if (!Company::isCurrentUserHasAccess($accessory)) {
return ['total' => 0, 'rows' => []];
}
$offset = request('offset', 0);
$limit = request('limit', 50);
$accessory->lastCheckoutArray = $accessory->lastCheckout->toArray();
$accessory_users = $accessory->users;
$total = $accessory_users->count();
return (new AccessoriesTransformer)->transformCheckedoutAccessory($accessory_users, $total);
if($total < $offset){
$offset = 0;
}
$accessory_users = $accessory->users()->skip($offset)->take($limit)->get();
if ($request->filled('search')) {
$accessory_users = $accessory->users()
->where('first_name', 'like', '%'.$request->input('search').'%')
->orWhere('last_name', 'like', '%'.$request->input('search').'%')
->get();
$total = $accessory_users->count();
}
return (new AccessoriesTransformer)->transformCheckedoutAccessory($accessory, $accessory_users, $total);
}
@@ -167,7 +187,7 @@ class AccessoriesController extends Controller
*/
public function update(Request $request, $id)
{
$this->authorize('edit', Accessory::class);
$this->authorize('update', Accessory::class);
$accessory = Accessory::findOrFail($id);
$accessory->fill($request->all());
@@ -290,4 +310,31 @@ class AccessoriesController extends Controller
}
/**
* Gets a paginated collection for the select2 menus
*
* @see \App\Http\Transformers\SelectlistTransformer
*
*/
public function selectlist(Request $request)
{
$accessories = Accessory::select([
'accessories.id',
'accessories.name'
]);
if ($request->filled('search')) {
$accessories = $accessories->where('accessories.name', 'LIKE', '%'.$request->get('search').'%');
}
$accessories = $accessories->orderBy('name', 'ASC')->paginate(50);
return (new SelectlistTransformer)->transformSelectlist($accessories);
}
}
@@ -9,7 +9,6 @@ use App\Models\AssetMaintenance;
use App\Models\Company;
use Auth;
use Carbon\Carbon;
use Gate;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Input;
@@ -34,10 +33,10 @@ class AssetMaintenancesController extends Controller
*/
public function index(Request $request)
{
$maintenances = AssetMaintenance::with('asset', 'supplier', 'asset.company', 'admin');
$maintenances = AssetMaintenance::with('asset', 'asset.model','asset.location', 'supplier', 'asset.company', 'admin');
if (Input::has('search')) {
$maintenances = $maintenances->TextSearch(e($request->input('search')));
if ($request->filled('search')) {
$maintenances = $maintenances->TextSearch($request->input('search'));
}
if ($request->filled('asset_id')) {
@@ -65,8 +64,8 @@ class AssetMaintenancesController extends Controller
'asset_name',
'user_id'
];
$order = Input::get('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array(Input::get('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
switch ($sort) {
case 'user_id':
@@ -1,15 +1,15 @@
<?php
namespace App\Http\Controllers\Api;
use App\Models\AssetModel;
use App\Models\Asset;
use App\Http\Controllers\Controller;
use App\Helpers\Helper;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Transformers\AssetModelsTransformer;
use App\Http\Transformers\AssetsTransformer;
use App\Http\Transformers\SelectlistTransformer;
use App\Models\Asset;
use App\Models\AssetModel;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
/**
* This class controls all actions related to asset models for
@@ -30,7 +30,7 @@ class AssetModelsController extends Controller
public function index(Request $request)
{
$this->authorize('view', AssetModel::class);
$allowed_columns = ['id','image','name','model_number','eol','notes','created_at','manufacturer','assets_count'];
$allowed_columns = ['id','image','name','model_number','eol','notes','created_at','manufacturer','requestable', 'assets_count'];
$assetmodels = AssetModel::select([
'models.id',
@@ -38,6 +38,7 @@ class AssetModelsController extends Controller
'models.name',
'model_number',
'eol',
'requestable',
'models.notes',
'models.created_at',
'category_id',
@@ -182,7 +183,7 @@ class AssetModelsController extends Controller
if ($assetmodel->image) {
try {
unlink(public_path().'/uploads/models/'.$assetmodel->image);
Storage::disk('public')->delete('assetmodels/'.$assetmodel->image);
} catch (\Exception $e) {
\Log::info($e);
}
@@ -239,7 +240,7 @@ class AssetModelsController extends Controller
$assetmodel->use_text .= ' (#'.e($assetmodel->model_number).')';
}
$assetmodel->use_image = ($settings->modellistCheckedValue('image') && ($assetmodel->image)) ? url('/').'/uploads/models/'.$assetmodel->image : null;
$assetmodel->use_image = ($settings->modellistCheckedValue('image') && ($assetmodel->image)) ? Storage::disk('public')->url('assetmodels/'.e($assetmodel->image)) : null;
}
return (new SelectlistTransformer)->transformSelectlist($assetmodels);
+94 -25
View File
@@ -1,37 +1,31 @@
<?php
namespace App\Http\Controllers\Api;
use Illuminate\Support\Facades\Gate;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Requests\AssetRequest;
use App\Http\Requests\AssetCheckoutRequest;
use App\Http\Transformers\AssetsTransformer;
use App\Http\Transformers\LicensesTransformer;
use App\Http\Transformers\SelectlistTransformer;
use App\Models\Asset;
use App\Models\AssetModel;
use App\Models\Company;
use App\Models\CustomField;
use App\Models\License;
use App\Models\Location;
use App\Models\Setting;
use App\Models\User;
use Artisan;
use Auth;
use Carbon\Carbon;
use Config;
use DB;
use Gate;
use Illuminate\Http\Request;
use Input;
use Lang;
use Log;
use Mail;
use Paginator;
use Response;
use Slack;
use Str;
use TCPDF;
use Validator;
use View;
use App\Http\Transformers\SelectlistTransformer;
/**
@@ -147,6 +141,7 @@ class AssetsController extends Controller
}
$request->filled('order_number') ? $assets = $assets->where('assets.order_number', '=', e($request->get('order_number'))) : '';
$offset = (($assets) && (request('offset') > $assets->count())) ? 0 : request('offset', 0);
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
@@ -181,7 +176,7 @@ class AssetsController extends Controller
// I am sad. :(
switch ($request->input('status')) {
case 'Deleted':
$assets->withTrashed()->Deleted();
$assets->onlyTrashed();
break;
case 'Pending':
$assets->join('status_labels AS status_alias',function ($join) {
@@ -299,6 +294,7 @@ class AssetsController extends Controller
$total = $assets->count();
$assets = $assets->skip($offset)->take($limit)->get();
// dd($assets);
return (new AssetsTransformer)->transformAssets($assets, $total);
}
@@ -313,7 +309,7 @@ class AssetsController extends Controller
*/
public function showByTag($tag)
{
if ($asset = Asset::with('assetstatus')->with('assignedTo')->withTrashed()->where('asset_tag',$tag)->first()) {
if ($asset = Asset::with('assetstatus')->with('assignedTo')->where('asset_tag',$tag)->first()) {
$this->authorize('view', $asset);
return (new AssetsTransformer)->transformAsset($asset);
}
@@ -334,8 +330,7 @@ class AssetsController extends Controller
$this->authorize('index', Asset::class);
if ($assets = Asset::with('assetstatus')->with('assignedTo')
->withTrashed()->where('serial',$serial)->get()) {
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
}
return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 200);
@@ -352,13 +347,22 @@ class AssetsController extends Controller
*/
public function show($id)
{
if ($asset = Asset::with('assetstatus')->with('assignedTo')->withTrashed()->withCount('checkins as checkins_count', 'checkouts as checkouts_count', 'userRequests as userRequests_count')->findOrFail($id)) {
if ($asset = Asset::with('assetstatus')->with('assignedTo')->withTrashed()
->withCount('checkins as checkins_count', 'checkouts as checkouts_count', 'userRequests as user_requests_count')->findOrFail($id)) {
$this->authorize('view', $asset);
return (new AssetsTransformer)->transformAsset($asset);
}
}
public function licenses($id)
{
$this->authorize('view', Asset::class);
$this->authorize('view', License::class);
$asset = Asset::where('id', $id)->withTrashed()->first();
$licenses = $asset->licenses()->get();
return (new LicensesTransformer())->transformLicenses($licenses, $licenses->count());
}
/**
@@ -380,7 +384,7 @@ class AssetsController extends Controller
'assets.assigned_to',
'assets.assigned_type',
'assets.status_id'
])->with('model', 'assetstatus', 'assignedTo')->NotArchived(),'company_id', 'assets');
])->with('model', 'assetstatus', 'assignedTo')->NotArchived(), 'company_id', 'assets');
if ($request->filled('assetStatusType') && $request->input('assetStatusType') === 'RTD') {
$assets = $assets->RTD();
@@ -426,7 +430,7 @@ class AssetsController extends Controller
* @since [v4.0]
* @return JsonResponse
*/
public function store(AssetRequest $request)
public function store(Request $request)
{
$this->authorize('create', Asset::class);
@@ -454,6 +458,22 @@ class AssetsController extends Controller
$asset->requestable = $request->get('requestable', 0);
$asset->rtd_location_id = $request->get('rtd_location_id', null);
if ($request->has('image_source') && $request->input('image_source') != "") {
$saved_image_path = Helper::processUploadedImage(
$request->input('image_source'), 'uploads/assets/'
);
if (!$saved_image_path) {
return response()->json(Helper::formatStandardApiResponse(
'error',
null,
trans('admin/hardware/message.create.error')
), 200);
}
$asset->image = $saved_image_path;
}
// Update custom fields in the database.
// Validation for these fields is handled through the AssetRequest form request
$model = AssetModel::find($request->get('model_id'));
@@ -481,6 +501,11 @@ class AssetsController extends Controller
if (isset($target)) {
$asset->checkOut($target, Auth::user(), date('Y-m-d H:i:s'), '', 'Checked out on asset creation', e($request->get('name')));
}
if ($asset->image) {
$asset->image = $asset->getImageUrl();
}
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.create.success')));
}
@@ -501,15 +526,40 @@ class AssetsController extends Controller
$this->authorize('update', Asset::class);
if ($asset = Asset::find($id)) {
$asset->fill($request->all());
($request->filled('model_id')) ?
$asset->model()->associate(AssetModel::find($request->get('model_id'))) : null;
($request->filled('rtd_location_id')) ?
$asset->location_id = $request->get('rtd_location_id') : '';
($request->filled('company_id')) ?
$asset->company_id = Company::getIdForCurrentUser($request->get('company_id')) : null;
$asset->company_id = Company::getIdForCurrentUser($request->get('company_id')) : '';
($request->filled('rtd_location_id')) ?
$asset->location_id = $request->get('rtd_location_id') : null;
if ($request->filled('image_source')) {
if ($request->input('image_source') == "") {
($request->filled('rtd_location_id')) ?
$asset->location_id = $request->get('rtd_location_id') : null;
$asset->image = null;
} else {
$saved_image_path = Helper::processUploadedImage(
$request->input('image_source'), 'uploads/assets/'
);
if (!$saved_image_path) {
return response()->json(Helper::formatStandardApiResponse(
'error',
null,
trans('admin/hardware/message.update.error')
), 200);
}
$asset->image = $saved_image_path;
}
}
// Update custom fields
if (($model = AssetModel::find($asset->model_id)) && (isset($model->fieldset))) {
@@ -530,7 +580,7 @@ class AssetsController extends Controller
if ($asset->save()) {
if (($request->filled('assigned_user')) && ($target = User::find($request->get('assigned_user')))) {
$location = $target->location_id;
$location = $target->location_id;
} elseif (($request->filled('assigned_asset')) && ($target = Asset::find($request->get('assigned_asset')))) {
$location = $target->location_id;
@@ -545,6 +595,10 @@ class AssetsController extends Controller
$asset->checkOut($target, Auth::user(), date('Y-m-d H:i:s'), '', 'Checked out on asset update', e($request->get('name')), $location);
}
if ($asset->image) {
$asset->image = $asset->getImageUrl();
}
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.update.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $asset->getErrors()), 200);
@@ -649,6 +703,7 @@ class AssetsController extends Controller
// Wait, why are we doing this? This overrides the stuff we set further up, which makes no sense.
// TODO: Follow up here. WTF. Commented out for now.
// if ((isset($target->rtd_location_id)) && ($asset->rtd_location_id!='')) {
// $asset->location_id = $target->rtd_location_id;
// }
@@ -699,12 +754,12 @@ class AssetsController extends Controller
$asset->location_id = $request->input('location_id');
}
if (Input::has('status_id')) {
$asset->status_id = Input::get('status_id');
if ($request->has('status_id')) {
$asset->status_id = $request->input('status_id');
}
if ($asset->save()) {
$asset->logCheckin($target, e(request('note')));
$asset->logCheckin($target, e($request->input('note')));
return response()->json(Helper::formatStandardApiResponse('success', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkin.success')));
}
@@ -735,13 +790,27 @@ class AssetsController extends Controller
return response()->json(Helper::formatStandardApiResponse('error', null, $validator->errors()->all()));
}
$settings = Setting::getSettings();
$dt = Carbon::now()->addMonths($settings->audit_interval)->toDateString();
$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
$asset->unsetEventDispatcher();
$asset->next_audit_date = $request->input('next_audit_date');
$asset->next_audit_date = $dt;
if ($request->filled('next_audit_date')) {
$asset->next_audit_date = $request->input('next_audit_date');
}
// 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') {
$asset->location_id = $request->input('location_id');
}
$asset->last_audit_date = date('Y-m-d h:i:s');
if ($asset->save()) {
@@ -749,7 +818,7 @@ class AssetsController extends Controller
return response()->json(Helper::formatStandardApiResponse('success', [
'asset_tag'=> e($asset->asset_tag),
'note'=> e($request->input('note')),
'next_audit_date' => Helper::getFormattedDateObject($log->calcNextAuditDate())
'next_audit_date' => Helper::getFormattedDateObject($asset->next_audit_date)
], trans('admin/hardware/message.audit.success')));
}
}
@@ -2,12 +2,13 @@
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Helpers\Helper;
use App\Models\Category;
use App\Http\Controllers\Controller;
use App\Http\Transformers\CategoriesTransformer;
use App\Http\Transformers\SelectlistTransformer;
use App\Models\Category;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class CategoriesController extends Controller
{
@@ -119,15 +120,15 @@ class CategoriesController extends Controller
public function destroy($id)
{
$this->authorize('delete', Category::class);
$category = Category::findOrFail($id);
$category = Category::withCount('models as models_count', 'accessories as accessories_count','consumables as consumables_count','components as components_count')->findOrFail($id);
if ($category->has_models() > 0) {
if ($category->models_count > 0) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/categories/message.assoc_items', ['asset_type'=>'model'])));
} elseif ($category->accessories()->count() > 0) {
} elseif ($category->accessories_count > 0) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/categories/message.assoc_items', ['asset_type'=>'accessory'])));
} elseif ($category->consumables()->count() > 0) {
} elseif ($category->consumables_count > 0) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/categories/message.assoc_items', ['asset_type'=>'consumable'])));
} elseif ($category->components()->count() > 0) {
} elseif ($category->components_count > 0) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/categories/message.assoc_items', ['asset_type'=>'component'])));
}
$category->delete();
@@ -163,7 +164,7 @@ class CategoriesController extends Controller
// This lets us have more flexibility in special cases like assets, where
// they may not have a ->name value but we want to display something anyway
foreach ($categories as $category) {
$category->use_image = ($category->image) ? url('/').'/uploads/categories/'.$category->image : null;
$category->use_image = ($category->image) ? Storage::disk('public')->url('categories/'.$category->image, $category->image) : null;
}
return (new SelectlistTransformer)->transformSelectlist($categories);
@@ -2,12 +2,13 @@
namespace App\Http\Controllers\Api;
use App\Http\Transformers\CompaniesTransformer;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Helpers\Helper;
use App\Models\Company;
use App\Http\Controllers\Controller;
use App\Http\Transformers\CompaniesTransformer;
use App\Http\Transformers\SelectlistTransformer;
use App\Models\Company;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class CompaniesController extends Controller
{
@@ -183,7 +184,7 @@ class CompaniesController extends Controller
// This lets us have more flexibility in special cases like assets, where
// they may not have a ->name value but we want to display something anyway
foreach ($companies as $company) {
$company->use_image = ($company->image) ? url('/').'/uploads/companies/'.$company->image : null;
$company->use_image = ($company->image) ? Storage::disk('public')->url('companies/'.$company->image, $company->image) : null;
}
return (new SelectlistTransformer)->transformSelectlist($companies);
@@ -2,14 +2,12 @@
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Transformers\AssetsTransformer;
use App\Http\Transformers\ComponentsTransformer;
use App\Http\Transformers\ComponentsAssetsTransformer;
use App\Models\Component;
use App\Models\Company;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Transformers\ComponentsTransformer;
use App\Models\Company;
use App\Models\Component;
use Illuminate\Http\Request;
class ComponentsController extends Controller
{
@@ -2,12 +2,13 @@
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Transformers\ConsumablesTransformer;
use App\Http\Transformers\SelectlistTransformer;
use App\Models\Company;
use App\Models\Consumable;
use App\Http\Transformers\ConsumablesTransformer;
use App\Helpers\Helper;
use Illuminate\Http\Request;
class ConsumablesController extends Controller
{
@@ -161,7 +162,7 @@ class ConsumablesController extends Controller
* Returns a JSON response containing details on the users associated with this consumable.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see ConsumablesController::getView() method that returns the form.
* @see \App\Http\Controllers\Consumables\ConsumablesController::getView() method that returns the form.
* @since [v1.0]
* @param int $consumableId
* @return array
@@ -196,4 +197,28 @@ class ConsumablesController extends Controller
$data = array('total' => $consumableCount, 'rows' => $rows);
return $data;
}
/**
* Gets a paginated collection for the select2 menus
*
* @see \App\Http\Transformers\SelectlistTransformer
*
*/
public function selectlist(Request $request)
{
$consumables = Consumable::select([
'consumables.id',
'consumables.name'
]);
if ($request->filled('search')) {
$consumables = $consumables->where('consumables.name', 'LIKE', '%'.$request->get('search').'%');
}
$consumables = $consumables->orderBy('name', 'ASC')->paginate(50);
return (new SelectlistTransformer)->transformSelectlist($consumables);
}
}
@@ -9,7 +9,6 @@ use App\Models\CustomField;
use App\Models\CustomFieldset;
use Illuminate\Http\Request;
use Validator;
use Illuminate\Validation\Rule;
class CustomFieldsController extends Controller
{
@@ -59,9 +58,9 @@ class CustomFieldsController extends Controller
{
$this->authorize('update', CustomField::class);
$field = CustomField::findOrFail($id);
/**
* Updated values for the field,
* Updated values for the field,
* without the "field_encrypted" flag, preventing the change of encryption status
* @var array
*/
@@ -1,22 +1,14 @@
<?php
namespace App\Http\Controllers\Api;
use View;
use App\Models\CustomFieldset;
use App\Models\CustomField;
use Input;
use Validator;
use Redirect;
use App\Models\AssetModel;
use Lang;
use Auth;
use Illuminate\Http\Request;
use Log;
use App\Http\Controllers\Controller;
use App\Helpers\Helper;
use App\Http\Transformers\CustomFieldsTransformer;
use App\Http\Controllers\Controller;
use App\Http\Transformers\CustomFieldsetsTransformer;
use App\Http\Requests\AssetRequest;
use App\Http\Transformers\CustomFieldsTransformer;
use App\Models\CustomFieldset;
use Illuminate\Http\Request;
use Redirect;
use View;
/**
* This controller handles all actions related to Custom Asset Fieldsets for
@@ -2,13 +2,14 @@
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Department;
use App\Http\Transformers\DepartmentsTransformer;
use App\Helpers\Helper;
use Auth;
use App\Http\Controllers\Controller;
use App\Http\Transformers\DepartmentsTransformer;
use App\Http\Transformers\SelectlistTransformer;
use App\Models\Department;
use Auth;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class DepartmentsController extends Controller
{
@@ -105,14 +106,36 @@ class DepartmentsController extends Controller
return (new DepartmentsTransformer)->transformDepartment($department);
}
/**
* Update the specified resource in storage.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v5.0]
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
$this->authorize('update', Department::class);
$department = Department::findOrFail($id);
$department->fill($request->all());
if ($department->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $department, trans('admin/departments/message.update.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $department->getErrors()));
}
/**
* Validates and deletes selected location.
* Validates and deletes selected department.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $locationId
* @since [v1.0]
* @since [v4.0]
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy($id)
@@ -157,7 +180,7 @@ class DepartmentsController extends Controller
// This lets us have more flexibility in special cases like assets, where
// they may not have a ->name value but we want to display something anyway
foreach ($departments as $department) {
$department->use_image = ($department->image) ? url('/').'/uploads/departments/'.$department->image : null;
$department->use_image = ($department->image) ? Storage::disk('public')->url('departments/'.$department->image, $department->image) : null;
}
return (new SelectlistTransformer)->transformSelectlist($departments);
@@ -2,11 +2,11 @@
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Helpers\Helper;
use App\Models\Depreciation;
use App\Http\Controllers\Controller;
use App\Http\Transformers\DepreciationsTransformer;
use App\Models\Depreciation;
use Illuminate\Http\Request;
class DepreciationsController extends Controller
{
@@ -115,10 +115,10 @@ class DepreciationsController extends Controller
public function destroy($id)
{
$this->authorize('delete', Depreciation::class);
$depreciation = Depreciation::findOrFail($id);
$depreciation = Depreciation::withCount('models as models_count')->findOrFail($id);
$this->authorize('delete', $depreciation);
if ($depreciation->has_models() > 0) {
if ($depreciation->models_count > 0) {
return response()->json(Helper::formatStandardApiResponse('error', trans('admin/depreciations/message.assoc_users')));
}
@@ -2,11 +2,11 @@
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Helpers\Helper;
use App\Models\Group;
use App\Http\Controllers\Controller;
use App\Http\Transformers\GroupsTransformer;
use App\Models\Group;
use Illuminate\Http\Request;
class GroupsController extends Controller
{
+22 -15
View File
@@ -6,15 +6,15 @@ use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Requests\ItemImportRequest;
use App\Http\Transformers\ImportsTransformer;
use App\Models\Asset;
use App\Models\Company;
use App\Models\Import;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Input;
use Artisan;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Storage;
use League\Csv\Reader;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Artisan;
use App\Models\Asset;
class ImportController extends Controller
{
@@ -41,7 +41,7 @@ class ImportController extends Controller
{
$this->authorize('import');
if (!config('app.lock_passwords')) {
$files = Input::file('files');
$files = Request::file('files');
$path = config('app.private_uploads').'/imports';
$results = [];
$import = new Import;
@@ -112,7 +112,7 @@ class ImportController extends Controller
/**
* Processes the specified Import.
*
* @param \App\Import $import
* @param int $import_id
* @return \Illuminate\Http\Response
*/
public function process(ItemImportRequest $request, $import_id)
@@ -155,19 +155,26 @@ class ImportController extends Controller
/**
* Remove the specified resource from storage.
*
* @param \App\Import $import
* @param int $import_id
* @return \Illuminate\Http\Response
*/
public function destroy($import_id)
{
$this->authorize('import');
$import = Import::find($import_id);
try {
unlink(config('app.private_uploads').'/imports/'.$import->file_path);
$import->delete();
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/hardware/message.import.file_delete_success')));
} catch (\Exception $e) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.import.file_delete_error')), 500);
$this->authorize('create', Asset::class);
if ($import = Import::find($import_id)) {
try {
// Try to delete the file
Storage::delete('imports/'.$import->file_path);
$import->delete();
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/hardware/message.import.file_delete_success')));
} catch (\Exception $e) {
// If the file delete didn't work, remove it from the database anyway and return a warning
$import->delete();
return response()->json(Helper::formatStandardApiResponse('warning', null, trans('admin/hardware/message.import.file_not_deleted_warning')));
}
}
}
}
@@ -6,6 +6,7 @@ use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Transformers\LicenseSeatsTransformer;
use App\Http\Transformers\LicensesTransformer;
use App\Http\Transformers\SelectlistTransformer;
use App\Models\Company;
use App\Models\License;
use App\Models\LicenseSeat;
@@ -155,7 +156,7 @@ class LicensesController extends Controller
public function show($id)
{
$this->authorize('view', License::class);
$license = License::findOrFail($id);
$license = License::withCount('freeSeats')->findOrFail($id);
$license = $license->load('assignedusers', 'licenseSeats.user', 'licenseSeats.asset');
return (new LicensesTransformer)->transformLicense($license);
}
@@ -231,9 +232,14 @@ class LicensesController extends Controller
$this->authorize('view', $license);
$seats = LicenseSeat::where('license_seats.license_id', $licenseId)
$offset = (($seats) && (request('offset') > $seats->count())) ? 0 : request('offset', 0);
$limit = request('limit', 50);
->with('license', 'user', 'asset', 'user.department');
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$total = $seats->count();
if ($request->input('sort')=='department') {
$seats->OrderDepartments($order);
@@ -257,5 +263,29 @@ class LicensesController extends Controller
}
/**
* Gets a paginated collection for the select2 menus
*
* @see \App\Http\Transformers\SelectlistTransformer
*/
public function selectlist(Request $request)
{
$licenses = License::select([
'licenses.id',
'licenses.name'
]);
if ($request->filled('search')) {
$licenses = $licenses->where('licenses.name', 'LIKE', '%'.$request->get('search').'%');
}
$licenses = $licenses->orderBy('name', 'ASC')->paginate(50);
return (new SelectlistTransformer)->transformSelectlist($licenses);
}
}
@@ -8,8 +8,6 @@ use App\Helpers\Helper;
use App\Models\Location;
use App\Http\Transformers\LocationsTransformer;
use App\Http\Transformers\SelectlistTransformer;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
class LocationsController extends Controller
{
@@ -28,7 +26,7 @@ class LocationsController extends Controller
'updated_at','manager_id','image',
'assigned_assets_count','users_count','assets_count','currency'];
$locations = Location::with('parent', 'manager', 'children')->select([
$locations = Location::with('parent', 'manager', 'childLocations')->select([
'locations.id',
'locations.name',
'locations.address',
@@ -112,7 +110,7 @@ class LocationsController extends Controller
public function show($id)
{
$this->authorize('view', Location::class);
$location = Location::with('parent', 'manager', 'children')
$location = Location::with('parent', 'manager', 'childLocations')
->select([
'locations.id',
'locations.name',
@@ -149,13 +147,6 @@ class LocationsController extends Controller
{
$this->authorize('update', Location::class);
$location = Location::findOrFail($id);
if ($request->input('parent_id') == $id) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'A location cannot be its own parent. Please select a different parent ID.'));
}
$location->fill($request->all());
if ($location->save()) {
@@ -208,35 +199,49 @@ class LocationsController extends Controller
* the entire data set, and then invoke a paginator manually and pass that
* through to the SelectListTransformer.
*
* Many thanks to @uberbrady for the help getting this working better.
* Recursion still sucks, but I guess he doesn't have to get in the
* sea... this time.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
*
*/
public function selectlist(Request $request)
public function selectlist(Request $request, $selected_id = null)
{
$locations = Location::select([
'locations.id',
'locations.name',
'locations.parent_id',
'locations.image',
]);
])->orderBy('name', 'ASC')->paginate(50)->map(function ($location) {
return $location->groupBy('parent_id')
->map(function ($parentName) {
return $parentName->map(function ($parent) {
return $parent->game_types->groupBy('parent_id');
});
});
});
$page = 1;
if ($request->filled('page')) {
$page = $request->input('page');
}
if ($request->filled('search')) {
$locations = $locations->where('locations.name', 'LIKE', '%'.$request->input('search').'%');
}
$locations = $locations->orderBy('name', 'ASC')->get();
// $locations = Location::select([
// 'locations.id',
// 'locations.name',
// 'locations.image',
// ]);
//
// if ($request->filled('search')) {
// $locations = $locations->where('locations.name', 'LIKE', '%'.$request->get('search').'%');
// }
//
//
// $locations = $locations->groupBy(function ($locations) {
// return $locations->parent_id;
// })->orderBy('name', 'ASC')->paginate(50);
$locations_with_children = [];
@@ -254,13 +259,18 @@ class LocationsController extends Controller
$locations_formatted = new Collection($location_options);
}
// so that a location can't be its own parent
$paginated_results = new LengthAwarePaginator($locations_formatted->forPage($page, 500), $locations_formatted->count(), 500, $page, []);
// Loop through and set some custom properties for the transformer to use.
// This lets us have more flexibility in special cases like assets, where
// they may not have a ->name value but we want to display something anyway
// foreach ($location_options as $location) {
// $location->use_text = $location->name;
// $location->use_image = ($location->image) ? url('/').'/uploads/locations/'.$location->image : null;
// }
//return [];
return (new SelectlistTransformer)->transformSelectlist($paginated_results);
return (new SelectlistTransformer)->transformSelectlist($locations);
}
}
@@ -2,13 +2,13 @@
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Helpers\Helper;
use App\Models\Manufacturer;
use App\Http\Transformers\DatatablesTransformer;
use App\Http\Controllers\Controller;
use App\Http\Transformers\ManufacturersTransformer;
use App\Http\Transformers\SelectlistTransformer;
use App\Models\Manufacturer;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class ManufacturersController extends Controller
{
@@ -123,11 +123,21 @@ class ManufacturersController extends Controller
*/
public function destroy($id)
{
$this->authorize('delete', Manufacturer::class);
$manufacturer = Manufacturer::findOrFail($id);
$manufacturer = Manufacturer::withCount('assets as assets_count', 'licenses as licenses_count', 'consumables as consumables_count', 'accessories as accessories_count', 'models as models_count' )->findOrFail($id);
$this->authorize('delete', $manufacturer);
$manufacturer->delete();
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/manufacturers/message.delete.success')));
if (($manufacturer->assets_count == 0) && ($manufacturer->licenses_count==0) && ($manufacturer->consumables_count==0) && ($manufacturer->accessories_count==0) && ($manufacturer->models_count==0) && ($manufacturer->deleted_at=='')) {
$manufacturer->delete();
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/manufacturers/message.delete.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/manufacturers/message.delete.error')));
}
@@ -159,7 +169,7 @@ class ManufacturersController extends Controller
// they may not have a ->name value but we want to display something anyway
foreach ($manufacturers as $manufacturer) {
$manufacturer->use_text = $manufacturer->name;
$manufacturer->use_image = ($manufacturer->image) ? url('/').'/uploads/manufacturers/'.$manufacturer->image : null;
$manufacturer->use_image = ($manufacturer->image) ? Storage::disk('public')->url('manufacturers/'.$manufacturer->image, $manufacturer->image) : null;
}
return (new SelectlistTransformer)->transformSelectlist($manufacturers);
@@ -0,0 +1,449 @@
<?php
namespace App\Http\Controllers\Api;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Transformers\PredefinedKitsTransformer;
use App\Models\PredefinedKit;
use Illuminate\Http\Request;
/**
* @author [D. Minaev.] [<dmitriy.minaev.v@gmail.com>]
*/
class PredefinedKitsController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
{
$this->authorize('view', PredefinedKit::class);
$allowed_columns = ['id', 'name'];
$kits = PredefinedKit::query();
if ($request->filled('search')) {
$kits = $kits->TextSearch($request->input('search'));
}
$offset = $request->input('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'assets_count';
$kits->orderBy($sort, $order);
$total = $kits->count();
$kits = $kits->skip($offset)->take($limit)->get();
return (new PredefinedKitsTransformer)->transformPredefinedKits($kits, $total);
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$this->authorize('create', PredefinedKit::class);
$kit = new PredefinedKit;
$kit->fill($request->all());
if ($kit->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $kit, trans('admin/kits/general.create_success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $kit->getErrors()));
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
$this->authorize('view', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($id);
return (new PredefinedKitsTransformer)->transformPredefinedKit($kit);
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id kit id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($id);
$kit->fill($request->all());
if ($kit->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $kit, trans('admin/kits/general.update_success'))); // TODO: trans
}
return response()->json(Helper::formatStandardApiResponse('error', null, $kit->getErrors()));
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
$this->authorize('delete', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($id);
// Delete childs
$kit->models()->detach();
$kit->licenses()->detach();
$kit->consumables()->detach();
$kit->accessories()->detach();
$kit->delete();
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/kits/general.delete_success'))); // TODO: trans
}
/**
* Gets a paginated collection for the select2 menus
*
* @see \App\Http\Transformers\SelectlistTransformer
*
*/
public function selectlist(Request $request)
{
$kits = PredefinedKit::select([
'id',
'name'
]);
if ($request->filled('search')) {
$kits = $kits->where('name', 'LIKE', '%'.$request->get('search').'%');
}
$kits = $kits->orderBy('name', 'ASC')->paginate(50);
return (new SelectlistTransformer)->transformSelectlist($kits);
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function indexLicenses($kit_id) {
$this->authorize('view', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
$licenses = $kit->licenses;
return (new PredefinedKitsTransformer)->transformElements($licenses, $licenses->count());
}
/**
* Store the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function storeLicense(Request $request, $kit_id)
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
$quantity = $request->input('quantity', 1);
if( $quantity < 1) {
$quantity = 1;
}
$license_id = $request->get('license');
$relation = $kit->licenses();
if( $relation->find($license_id) ) {
return response()->json(Helper::formatStandardApiResponse('error', null, ['license' => 'License already attached to kit']));
}
$relation->attach( $license_id, ['quantity' => $quantity]);
return response()->json(Helper::formatStandardApiResponse('success', $kit, 'License added successfull')); // TODO: trans
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $kit_id
* @return \Illuminate\Http\Response
*/
public function updateLicense(Request $request, $kit_id, $license_id)
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
$quantity = $request->input('quantity', 1);
if( $quantity < 1) {
$quantity = 1;
}
$kit->licenses()->syncWithoutDetaching([$license_id => ['quantity' => $quantity]]);
return response()->json(Helper::formatStandardApiResponse('success', $kit, 'License updated')); // TODO: trans
}
/**
* Remove the specified resource from storage.
*
* @param int $kit_id
* @return \Illuminate\Http\Response
*/
public function detachLicense($kit_id, $license_id)
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
$kit->licenses()->detach($license_id);
return response()->json(Helper::formatStandardApiResponse('success', $kit, trans('admin/kits/general.delete_success')));
}
/**
* Display the specified resource.
*
* @param int $kit_id
* @return \Illuminate\Http\Response
*/
public function indexModels($kit_id) {
$this->authorize('view', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
$models = $kit->models;
return (new PredefinedKitsTransformer)->transformElements($models, $models->count());
}
/**
* Store the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function storeModel(Request $request, $kit_id)
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
$model_id = $request->get('model');
$quantity = $request->input('quantity', 1);
if( $quantity < 1) {
$quantity = 1;
}
$relation = $kit->models();
if( $relation->find($model_id) ) {
return response()->json(Helper::formatStandardApiResponse('error', null, ['model' => 'Model already attached to kit']));
}
$relation->attach($model_id, ['quantity' => $quantity]);
return response()->json(Helper::formatStandardApiResponse('success', $kit, 'Model added successfull'));
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $kit_id
* @return \Illuminate\Http\Response
*/
public function updateModel(Request $request, $kit_id, $model_id)
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
$quantity = $request->input('quantity', 1);
if( $quantity < 1) {
$quantity = 1;
}
$kit->models()->syncWithoutDetaching([$model_id => ['quantity' => $quantity]]);
return response()->json(Helper::formatStandardApiResponse('success', $kit, 'License updated')); // TODO: trans
}
/**
* Remove the specified resource from storage.
*
* @param int $kit_id
* @return \Illuminate\Http\Response
*/
public function detachModel($kit_id, $model_id)
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
$kit->models()->detach($model_id);
return response()->json(Helper::formatStandardApiResponse('success', $kit, trans('admin/kits/general.model_removed_success')));
}
/**
* Display the specified resource.
*
* @param int $kit_id
* @return \Illuminate\Http\Response
*/
public function indexConsumables($kit_id) {
$this->authorize('view', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
$consumables = $kit->consumables;
return (new PredefinedKitsTransformer)->transformElements($consumables, $consumables->count());
}
/**
* Store the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function storeConsumable(Request $request, $kit_id)
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
$quantity = $request->input('quantity', 1);
if( $quantity < 1) {
$quantity = 1;
}
$consumable_id = $request->get('consumable');
$relation = $kit->consumables();
if( $relation->find($consumable_id) ) {
return response()->json(Helper::formatStandardApiResponse('error', null, ['consumable' => 'Consumable already attached to kit']));
}
$relation->attach( $consumable_id, ['quantity' => $quantity]);
return response()->json(Helper::formatStandardApiResponse('success', $kit, 'Consumable added successfull')); // TODO: trans
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $kit_id
* @return \Illuminate\Http\Response
*/
public function updateConsumable(Request $request, $kit_id, $consumable_id)
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
$quantity = $request->input('quantity', 1);
if( $quantity < 1) {
$quantity = 1;
}
$kit->consumables()->syncWithoutDetaching([$consumable_id => ['quantity' => $quantity]]);
return response()->json(Helper::formatStandardApiResponse('success', $kit, 'Consumable updated')); // TODO: trans
}
/**
* Remove the specified resource from storage.
*
* @param int $kit_id
* @return \Illuminate\Http\Response
*/
public function detachConsumable($kit_id, $consumable_id)
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
$kit->consumables()->detach($consumable_id);
return response()->json(Helper::formatStandardApiResponse('success', $kit, 'Delete was successfull')); // TODO: trans
}
/**
* Display the specified resource.
*
* @param int $kit_id
* @return \Illuminate\Http\Response
*/
public function indexAccessories($kit_id) {
$this->authorize('view', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
$accessories = $kit->accessories;
return (new PredefinedKitsTransformer)->transformElements($accessories, $accessories->count());
}
/**
* Store the specified resource.
*
* @param int $kit_id
* @return \Illuminate\Http\Response
*/
public function storeAccessory(Request $request, $kit_id)
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
$quantity = $request->input('quantity', 1);
if( $quantity < 1) {
$quantity = 1;
}
$accessory_id = $request->get('accessory');
$relation = $kit->accessories();
if( $relation->find($accessory_id) ) {
return response()->json(Helper::formatStandardApiResponse('error', null, ['accessory' => 'Accessory already attached to kit']));
}
$relation->attach( $accessory_id, ['quantity' => $quantity]);
return response()->json(Helper::formatStandardApiResponse('success', $kit, 'Accessory added successfull')); // TODO: trans
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $kit_id
* @return \Illuminate\Http\Response
*/
public function updateAccessory(Request $request, $kit_id, $accessory_id)
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
$quantity = $request->input('quantity', 1);
if( $quantity < 1) {
$quantity = 1;
}
$kit->accessories()->syncWithoutDetaching([$accessory_id => ['quantity' => $quantity]]);
return response()->json(Helper::formatStandardApiResponse('success', $kit, 'Accessory updated')); // TODO: trans
}
/**
* Remove the specified resource from storage.
*
* @param int $kit_id
* @return \Illuminate\Http\Response
*/
public function detachAccessory($kit_id, $accessory_id)
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
$kit->accessories()->detach($accessory_id);
return response()->json(Helper::formatStandardApiResponse('success', $kit, 'Delete was successfull')); // TODO: trans
}
}
@@ -2,11 +2,10 @@
namespace App\Http\Controllers\Api;
use App\Models\CheckoutRequest;
use App\Http\Controllers\Controller;
use Auth;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Models\CheckoutRequest;
use Auth;
class ProfileController extends Controller
{
@@ -2,10 +2,10 @@
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Actionlog;
use App\Http\Transformers\ActionlogsTransformer;
use App\Models\Actionlog;
use Illuminate\Http\Request;
class ReportsController extends Controller
{
+84 -74
View File
@@ -2,103 +2,89 @@
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Ldap;
use Validator;
use App\Http\Transformers\LoginAttemptsTransformer;
use App\Models\Setting;
use Mail;
use App\Notifications\SlackTest;
use Notification;
use App\Notifications\MailTest;
use App\Notifications\SlackTest;
use App\Services\LdapAd;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Notification;
class SettingsController extends Controller
{
public function ldaptest()
/**
* Test the ldap settings
*
* @author Wes Hulette <jwhulette@gmail.com>
*
* @since 5.0.0
*
* @param App\Models\LdapAd $ldap
*
* @return \Illuminate\Http\JsonResponse
*/
public function ldapAdSettingsTest(LdapAd $ldap): JsonResponse
{
if (Setting::getSettings()->ldap_enabled!='1') {
\Log::debug('LDAP is not enabled so cannot test.');
return response()->json(['message' => 'LDAP is not enabled, so we cannot test LDAP connections.'], 400);
if(!$ldap->init()) {
Log::info('LDAP is not enabled cannot test.');
return response()->json(['message' => 'LDAP is not enabled, cannot test.'], 400);
}
\Log::debug('Preparing to test LDAP connection');
// The connect, bind and resulting users message
$message = [];
Log::info('Preparing to test LDAP user login');
// Test user can connect to the LDAP server
try {
$connection = Ldap::connectToLdap();
try {
\Log::debug('attempting to bind to LDAP for LDAP test');
Ldap::bindAdminToLdap($connection);
return response()->json(['message' => 'It worked!'], 200);
} catch (\Exception $e) {
$ldap->testLdapAdUserConnection();
$message['login'] = [
'message' => 'Successfully connected to LDAP server.'
];
} catch (\Exception $ex) {
\Log::debug('LDAP connected but Bind failed. Please check your LDAP settings and try again.');
return response()->json(['message' => $e->getMessage()], 400);
//return response()->json(['message' => $e->getMessage()], 500);
}
return response()->json([
'message' => 'Error logging into LDAP server, error: ' . $ex->getMessage() . ' - Verify your that your username and password are correct']);
} catch (\Exception $e) {
\Log::info('LDAP connection failed but we cannot debug it any further on our end.');
return response()->json(['message' => 'The LDAP connection failed but we cannot debug it any further on our end. The error from the server is: '.$e->getMessage()], 500);
}
}
public function ldaptestlogin(Request $request)
{
if (Setting::getSettings()->ldap_enabled!='1') {
\Log::debug('LDAP is not enabled. Cannot test.');
return response()->json(['message' => 'LDAP is not enabled, cannot test.'], 400);
}
$rules = array(
'ldaptest_user' => 'required',
'ldaptest_password' => 'required'
);
$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) {
\Log::debug('LDAP Validation test failed.');
$validation_errors = implode(' ',$validator->errors()->all());
return response()->json(['message' => $validator->errors()->all()], 400);
}
\Log::debug('Preparing to test LDAP login');
Log::info('Preparing to test LDAP bind connection');
// Test user can bind to the LDAP server
try {
$connection = Ldap::connectToLdap();
try {
Ldap::bindAdminToLdap($connection);
\Log::debug('Attempting to bind to LDAP for LDAP test');
try {
$ldap_user = Ldap::findAndBindUserLdap($request->input('ldaptest_user'), $request->input('ldaptest_password'));
if ($ldap_user) {
\Log::debug('It worked! '. $request->input('ldaptest_user').' successfully binded to LDAP.');
return response()->json(['message' => 'It worked! '. $request->input('ldaptest_user').' successfully binded to LDAP.'], 200);
}
return response()->json(['message' => 'Login Failed. '. $request->input('ldaptest_user').' did not successfully bind to LDAP.'], 400);
} catch (\Exception $e) {
\Log::debug('LDAP login failed');
return response()->json(['message' => $e->getMessage()], 400);
}
} catch (\Exception $e) {
\Log::debug('Bind failed');
return response()->json(['message' => $e->getMessage()], 400);
//return response()->json(['message' => $e->getMessage()], 500);
}
} catch (\Exception $e) {
\Log::debug('Connection failed');
return response()->json(['message' => $e->getMessage()], 500);
$ldap->testLdapAdBindConnection();
$message['bind'] = [
'message' => 'Successfully binded to LDAP server.'
];
} catch (\Exception $ex) {
return response()->json([
'message' => 'Error binding to LDAP server, error: ' . $ex->getMessage()
], 400);
}
}
Log::info('Preparing to get sample user set from LDAP directory');
// Get a sample of 10 users so user can verify the data is correct
try {
$users = $ldap->testUserImportSync();
$message['user_sync'] = [
'users' => $users
];
} catch (\Exception $ex) {
$message['user_sync'] = [
'message' => 'Error getting users from LDAP directory, error: ' . $ex->getMessage()
];
return response()->json($message, 400);
}
return response()->json($message, 200);
}
public function slacktest()
{
@@ -143,6 +129,30 @@ class SettingsController extends Controller
}
/**
* Get a list of login attempts
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v5.0.0]
* @param \Illuminate\Http\Request $request
* @return array
*/
public function showLoginAttempts(Request $request)
{
$allowed_columns = ['id', 'username', 'remote_ip', 'user_agent','successful','created_at'];
$login_attempts = DB::table('login_attempts');
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->get('sort'), $allowed_columns) ? $request->get('sort') : 'created_at';
$total = $login_attempts->count();
$login_attempts->orderBy($sort, $order);
$login_attempt_results = $login_attempts->skip(request('offset', 0))->take(request('limit', 20))->get();
return (new LoginAttemptsTransformer)->transformLoginAttempts($login_attempt_results, $total);
}
}
@@ -2,13 +2,13 @@
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Helpers\Helper;
use App\Models\Statuslabel;
use App\Models\Asset;
use App\Http\Transformers\StatuslabelsTransformer;
use App\Http\Controllers\Controller;
use App\Http\Transformers\AssetsTransformer;
use App\Http\Transformers\StatuslabelsTransformer;
use App\Models\Asset;
use App\Models\Statuslabel;
use Illuminate\Http\Request;
class StatuslabelsController extends Controller
{
@@ -209,11 +209,11 @@ class StatuslabelsController extends Controller
{
$this->authorize('view', Statuslabel::class);
$this->authorize('index', Asset::class);
$assets = Asset::where('status_id','=',$id);
$assets = Asset::where('status_id','=',$id)->with('assignedTo');
$allowed_columns = [
'id',
'name'
'name',
];
$offset = request('offset', 0);
@@ -243,8 +243,6 @@ class StatuslabelsController extends Controller
*/
public function checkIfDeployable($id) {
$statuslabel = Statuslabel::findOrFail($id);
$this->authorize('view', Asset::class);
if ($statuslabel->getStatuslabelType()=='deployable') {
return '1';
}
@@ -2,13 +2,13 @@
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Helpers\Helper;
use App\Models\Supplier;
use App\Http\Transformers\SuppliersTransformer;
use App\Http\Controllers\Controller;
use App\Http\Transformers\SelectlistTransformer;
use App\Http\Transformers\SuppliersTransformer;
use App\Models\Supplier;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class SuppliersController extends Controller
{
@@ -22,7 +22,7 @@ class SuppliersController extends Controller
public function index(Request $request)
{
$this->authorize('view', Supplier::class);
$allowed_columns = ['id','name','address','phone','contact','fax','email','image','assets_count','licenses_count', 'accessories_count'];
$allowed_columns = ['id','name','address','phone','contact','fax','email','image','assets_count','licenses_count', 'accessories_count','url'];
$suppliers = Supplier::select(
array('id','name','address','address2','city','state','country','fax', 'phone','email','contact','created_at','updated_at','deleted_at','image','notes')
@@ -169,7 +169,7 @@ class SuppliersController extends Controller
// they may not have a ->name value but we want to display something anyway
foreach ($suppliers as $supplier) {
$supplier->use_text = $supplier->name;
$supplier->use_image = ($supplier->image) ? url('/').'/uploads/suppliers/'.$supplier->image : null;
$supplier->use_image = ($supplier->image) ? Storage::disk('public')->url('suppliers/'.$supplier->image, $supplier->image) : null;
}
return (new SelectlistTransformer)->transformSelectlist($suppliers);
+32 -9
View File
@@ -2,18 +2,19 @@
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Transformers\UsersTransformer;
use App\Models\Company;
use App\Models\User;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Requests\SaveUserRequest;
use App\Models\Asset;
use App\Http\Transformers\AssetsTransformer;
use App\Http\Transformers\SelectlistTransformer;
use App\Http\Transformers\AccessoriesTransformer;
use App\Http\Transformers\AssetsTransformer;
use App\Http\Transformers\LicensesTransformer;
use App\Http\Transformers\SelectlistTransformer;
use App\Http\Transformers\UsersTransformer;
use App\Models\Asset;
use App\Models\Company;
use App\Models\License;
use App\Models\User;
use Illuminate\Http\Request;
use Auth;
class UsersController extends Controller
@@ -89,6 +90,7 @@ class UsersController extends Controller
}
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$offset = (($users) && (request('offset') > $users->count())) ? 0 : request('offset', 0);
// 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.
@@ -222,6 +224,7 @@ class UsersController extends Controller
$tmp_pass = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 20);
$user->password = bcrypt($request->get('password', $tmp_pass));
if ($user->save()) {
if ($request->filled('groups')) {
$user->groups()->sync($request->input('groups'));
@@ -263,6 +266,16 @@ class UsersController extends Controller
$this->authorize('update', User::class);
$user = User::findOrFail($id);
// This is a janky hack to prevent people from changing admin demo user data on the public demo.
// The $ids 1 and 2 are special since they are seeded as superadmins in the demo seeder.
// Thanks, jerks. You are why we can't have nice things. - snipe
if ((($id == 1) || ($id == 2)) && (config('app.lock_passwords'))) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'Permission denied. You cannot update user information via API on the demo.'));
}
$user->fill($request->all());
if ($user->id == $request->input('manager_id')) {
@@ -348,8 +361,16 @@ class UsersController extends Controller
return response()->json(Helper::formatStandardApiResponse('error', null, 'This user still has ' . $user->managedLocations()->count() . ' locations that they manage.'));
}
if ($user->delete()) {
// Remove the user's avatar if they have one
if (Storage::disk('public')->exists('avatars/'.$user->avatar)) {
try {
Storage::disk('public')->delete('avatars/'.$user->avatar);
} catch (\Exception $e) {
\Log::debug($e);
}
}
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.success.delete')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.error.delete')));
@@ -406,6 +427,8 @@ class UsersController extends Controller
}
/**
* Reset the user's two-factor status
*
* @author [A. Gianotto] [<snipe@snipe.net>]