mirror of
https://github.com/snipe/snipe-it.git
synced 2025-03-05 20:52:15 -08:00
Merge branch 'develop' into fixes/purify-factories
This commit is contained in:
commit
3b16a65988
2
.github/workflows/docker-alpine.yml
vendored
2
.github/workflows/docker-alpine.yml
vendored
|
@ -72,7 +72,7 @@ jobs:
|
||||||
# https://github.com/docker/build-push-action
|
# https://github.com/docker/build-push-action
|
||||||
- name: Build and push 'snipe-it' image
|
- name: Build and push 'snipe-it' image
|
||||||
id: docker_build
|
id: docker_build
|
||||||
uses: docker/build-push-action@v3
|
uses: docker/build-push-action@v4
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./Dockerfile.alpine
|
file: ./Dockerfile.alpine
|
||||||
|
|
2
.github/workflows/docker.yml
vendored
2
.github/workflows/docker.yml
vendored
|
@ -72,7 +72,7 @@ jobs:
|
||||||
# https://github.com/docker/build-push-action
|
# https://github.com/docker/build-push-action
|
||||||
- name: Build and push 'snipe-it' image
|
- name: Build and push 'snipe-it' image
|
||||||
id: docker_build
|
id: docker_build
|
||||||
uses: docker/build-push-action@v3
|
uses: docker/build-push-action@v4
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./Dockerfile
|
file: ./Dockerfile
|
||||||
|
|
52
app/Console/Commands/NormalizeUserNames.php
Normal file
52
app/Console/Commands/NormalizeUserNames.php
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use App\Models\User;
|
||||||
|
|
||||||
|
class NormalizeUserNames extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'snipeit:normalize-names';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Normalizes weirdly formatted names as first-letter upercased';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new command instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
|
||||||
|
$users = User::get();
|
||||||
|
$this->info($users->count() . ' users');
|
||||||
|
|
||||||
|
foreach ($users as $user) {
|
||||||
|
$user->first_name = ucwords(strtolower($user->first_name));
|
||||||
|
$user->last_name = ucwords(strtolower($user->last_name));
|
||||||
|
$user->email = strtolower($user->email);
|
||||||
|
$user->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
app/Events/UserMerged.php
Normal file
24
app/Events/UserMerged.php
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Events;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Events\Dispatchable;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use App\Models\User;
|
||||||
|
|
||||||
|
class UserMerged
|
||||||
|
{
|
||||||
|
use Dispatchable, SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new event instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(User $from_user, User $to_user, User $admin)
|
||||||
|
{
|
||||||
|
$this->merged_from = $from_user;
|
||||||
|
$this->merged_to = $to_user;
|
||||||
|
$this->admin = $admin;
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ use App\Http\Transformers\GroupsTransformer;
|
||||||
use App\Models\Group;
|
use App\Models\Group;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
|
||||||
class GroupsController extends Controller
|
class GroupsController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -19,6 +20,8 @@ class GroupsController extends Controller
|
||||||
*/
|
*/
|
||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
|
$this->authorize('superadmin');
|
||||||
|
|
||||||
$this->authorize('view', Group::class);
|
$this->authorize('view', Group::class);
|
||||||
$allowed_columns = ['id', 'name', 'created_at', 'users_count'];
|
$allowed_columns = ['id', 'name', 'created_at', 'users_count'];
|
||||||
|
|
||||||
|
@ -59,9 +62,11 @@ class GroupsController extends Controller
|
||||||
*/
|
*/
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
$this->authorize('create', Group::class);
|
$this->authorize('superadmin');
|
||||||
$group = new Group;
|
$group = new Group;
|
||||||
$group->fill($request->all());
|
|
||||||
|
$group->name = $request->input('name');
|
||||||
|
$group->permissions = $request->input('permissions'); // Todo - some JSON validation stuff here
|
||||||
|
|
||||||
if ($group->save()) {
|
if ($group->save()) {
|
||||||
return response()->json(Helper::formatStandardApiResponse('success', $group, trans('admin/groups/message.create.success')));
|
return response()->json(Helper::formatStandardApiResponse('success', $group, trans('admin/groups/message.create.success')));
|
||||||
|
@ -80,7 +85,7 @@ class GroupsController extends Controller
|
||||||
*/
|
*/
|
||||||
public function show($id)
|
public function show($id)
|
||||||
{
|
{
|
||||||
$this->authorize('view', Group::class);
|
$this->authorize('superadmin');
|
||||||
$group = Group::findOrFail($id);
|
$group = Group::findOrFail($id);
|
||||||
|
|
||||||
return (new GroupsTransformer)->transformGroup($group);
|
return (new GroupsTransformer)->transformGroup($group);
|
||||||
|
@ -97,9 +102,11 @@ class GroupsController extends Controller
|
||||||
*/
|
*/
|
||||||
public function update(Request $request, $id)
|
public function update(Request $request, $id)
|
||||||
{
|
{
|
||||||
$this->authorize('update', Group::class);
|
$this->authorize('superadmin');
|
||||||
$group = Group::findOrFail($id);
|
$group = Group::findOrFail($id);
|
||||||
$group->fill($request->all());
|
|
||||||
|
$group->name = $request->input('name');
|
||||||
|
$group->permissions = $request->input('permissions'); // Todo - some JSON validation stuff here
|
||||||
|
|
||||||
if ($group->save()) {
|
if ($group->save()) {
|
||||||
return response()->json(Helper::formatStandardApiResponse('success', $group, trans('admin/groups/message.update.success')));
|
return response()->json(Helper::formatStandardApiResponse('success', $group, trans('admin/groups/message.update.success')));
|
||||||
|
@ -118,9 +125,8 @@ class GroupsController extends Controller
|
||||||
*/
|
*/
|
||||||
public function destroy($id)
|
public function destroy($id)
|
||||||
{
|
{
|
||||||
$this->authorize('delete', Group::class);
|
$this->authorize('superadmin');
|
||||||
$group = Group::findOrFail($id);
|
$group = Group::findOrFail($id);
|
||||||
$this->authorize('delete', $group);
|
|
||||||
$group->delete();
|
$group->delete();
|
||||||
|
|
||||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/groups/message.delete.success')));
|
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/groups/message.delete.success')));
|
||||||
|
|
|
@ -10,7 +10,7 @@ use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Laravel\Passport\TokenRepository;
|
use Laravel\Passport\TokenRepository;
|
||||||
use Illuminate\Contracts\Validation\Factory as ValidationFactory;
|
use Illuminate\Contracts\Validation\Factory as ValidationFactory;
|
||||||
use Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use DB;
|
use DB;
|
||||||
|
|
||||||
class ProfileController extends Controller
|
class ProfileController extends Controller
|
||||||
|
|
|
@ -192,7 +192,6 @@ class UsersController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
$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
|
// 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.
|
// case we override with the actual count, so we should return 0 items.
|
||||||
|
@ -218,6 +217,14 @@ class UsersController extends Controller
|
||||||
case 'company':
|
case 'company':
|
||||||
$users = $users->OrderCompany($order);
|
$users = $users->OrderCompany($order);
|
||||||
break;
|
break;
|
||||||
|
case 'first_name':
|
||||||
|
$users->orderBy('first_name', $order);
|
||||||
|
$users->orderBy('last_name', $order);
|
||||||
|
break;
|
||||||
|
case 'last_name':
|
||||||
|
$users->orderBy('last_name', $order);
|
||||||
|
$users->orderBy('first_name', $order);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
$allowed_columns =
|
$allowed_columns =
|
||||||
[
|
[
|
||||||
|
|
|
@ -16,7 +16,7 @@ use App\Models\User;
|
||||||
use Auth;
|
use Auth;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use DB;
|
use DB;
|
||||||
use Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
|
@ -91,12 +91,11 @@ class LicenseFilesController extends Controller
|
||||||
*/
|
*/
|
||||||
public function destroy($licenseId = null, $fileId = null)
|
public function destroy($licenseId = null, $fileId = null)
|
||||||
{
|
{
|
||||||
$license = License::find($licenseId);
|
if ($license = License::find($licenseId)) {
|
||||||
|
|
||||||
// the asset is valid
|
|
||||||
if (isset($license->id)) {
|
|
||||||
$this->authorize('update', $license);
|
$this->authorize('update', $license);
|
||||||
$log = Actionlog::find($fileId);
|
|
||||||
|
if ($log = Actionlog::find($fileId)) {
|
||||||
|
|
||||||
// Remove the file if one exists
|
// Remove the file if one exists
|
||||||
if (Storage::exists('licenses/'.$log->filename)) {
|
if (Storage::exists('licenses/'.$log->filename)) {
|
||||||
|
@ -113,7 +112,9 @@ class LicenseFilesController extends Controller
|
||||||
->with('success', trans('admin/hardware/message.deletefile.success'));
|
->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redirect to the licence management page
|
return redirect()->route('licenses.index')->with('error', trans('general.log_does_not_exist'));
|
||||||
|
}
|
||||||
|
|
||||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist'));
|
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +130,6 @@ class LicenseFilesController extends Controller
|
||||||
*/
|
*/
|
||||||
public function show($licenseId = null, $fileId = null, $download = true)
|
public function show($licenseId = null, $fileId = null, $download = true)
|
||||||
{
|
{
|
||||||
\Log::info('Private filesystem is: '.config('filesystems.default'));
|
|
||||||
$license = License::find($licenseId);
|
$license = License::find($licenseId);
|
||||||
|
|
||||||
// the license is valid
|
// the license is valid
|
||||||
|
|
|
@ -8,7 +8,7 @@ use App\Models\Setting;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Notifications\CurrentInventory;
|
use App\Notifications\CurrentInventory;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
|
@ -1024,7 +1024,11 @@ class ReportsController extends Controller
|
||||||
if (is_null($acceptance->created_at)){
|
if (is_null($acceptance->created_at)){
|
||||||
return redirect()->route('reports/unaccepted_assets')->with('error', trans('general.bad_data'));
|
return redirect()->route('reports/unaccepted_assets')->with('error', trans('general.bad_data'));
|
||||||
} else {
|
} else {
|
||||||
$logItem = $assetItem->checkouts()->where('created_at', '=', $acceptance->created_at)->get()[0];
|
$logItem_res = $assetItem->checkouts()->where('created_at', '=', $acceptance->created_at)->get();
|
||||||
|
if ($logItem_res->isEmpty()){
|
||||||
|
return redirect()->route('reports/unaccepted_assets')->with('error', trans('general.bad_data'));
|
||||||
|
}
|
||||||
|
$logItem = $logItem_res[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!$assetItem->assignedTo->locale){
|
if(!$assetItem->assignedTo->locale){
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers\Users;
|
namespace App\Http\Controllers\Users;
|
||||||
|
|
||||||
|
use App\Events\UserMerged;
|
||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\Accessory;
|
use App\Models\Accessory;
|
||||||
|
@ -13,6 +14,7 @@ use App\Models\LicenseSeat;
|
||||||
use App\Models\ConsumableAssignment;
|
use App\Models\ConsumableAssignment;
|
||||||
use App\Models\Consumable;
|
use App\Models\Consumable;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use Carbon\Carbon;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
@ -21,7 +23,7 @@ use Illuminate\Support\Facades\Password;
|
||||||
class BulkUsersController extends Controller
|
class BulkUsersController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Returns a view that confirms the user's a bulk delete will be applied to.
|
* Returns a view that confirms the user's a bulk action will be applied to.
|
||||||
*
|
*
|
||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @since [v1.7]
|
* @since [v1.7]
|
||||||
|
@ -35,16 +37,32 @@ class BulkUsersController extends Controller
|
||||||
|
|
||||||
// Make sure there were users selected
|
// Make sure there were users selected
|
||||||
if (($request->filled('ids')) && (count($request->input('ids')) > 0)) {
|
if (($request->filled('ids')) && (count($request->input('ids')) > 0)) {
|
||||||
|
|
||||||
// Get the list of affected users
|
// Get the list of affected users
|
||||||
$user_raw_array = request('ids');
|
$user_raw_array = request('ids');
|
||||||
$users = User::whereIn('id', $user_raw_array)
|
$users = User::whereIn('id', $user_raw_array)
|
||||||
->with('groups', 'assets', 'licenses', 'accessories')->get();
|
->with('groups', 'assets', 'licenses', 'accessories')->get();
|
||||||
|
|
||||||
|
// bulk edit, display the bulk edit form
|
||||||
if ($request->input('bulk_actions') == 'edit') {
|
if ($request->input('bulk_actions') == 'edit') {
|
||||||
return view('users/bulk-edit', compact('users'))
|
return view('users/bulk-edit', compact('users'))
|
||||||
->with('groups', Group::pluck('name', 'id'));
|
->with('groups', Group::pluck('name', 'id'));
|
||||||
|
|
||||||
|
// bulk delete, display the bulk delete confirmation form
|
||||||
} elseif ($request->input('bulk_actions') == 'delete') {
|
} elseif ($request->input('bulk_actions') == 'delete') {
|
||||||
return view('users/confirm-bulk-delete')->with('users', $users)->with('statuslabel_list', Helper::statusLabelList());
|
return view('users/confirm-bulk-delete')->with('users', $users)->with('statuslabel_list', Helper::statusLabelList());
|
||||||
|
|
||||||
|
// merge, confirm they have at least 2 users selected and display the merge screen
|
||||||
|
} elseif ($request->input('bulk_actions') == 'merge') {
|
||||||
|
|
||||||
|
if (($request->filled('ids')) && (count($request->input('ids')) > 1)) {
|
||||||
|
return view('users/confirm-merge')->with('users', $users);
|
||||||
|
// Not enough users selected, send them back
|
||||||
|
} else {
|
||||||
|
return redirect()->back()->with('error', trans('general.not_enough_users_selected', ['count' => 2]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// bulk password reset, just do the thing
|
||||||
} elseif ($request->input('bulk_actions') == 'bulkpasswordreset') {
|
} elseif ($request->input('bulk_actions') == 'bulkpasswordreset') {
|
||||||
foreach ($users as $user) {
|
foreach ($users as $user) {
|
||||||
if (($user->activated == '1') && ($user->email != '')) {
|
if (($user->activated == '1') && ($user->email != '')) {
|
||||||
|
@ -59,7 +77,7 @@ class BulkUsersController extends Controller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return redirect()->back()->with('error', 'No users selected');
|
return redirect()->back()->with('error', trans('general.no_users_selected'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -76,7 +94,7 @@ class BulkUsersController extends Controller
|
||||||
$this->authorize('update', User::class);
|
$this->authorize('update', User::class);
|
||||||
|
|
||||||
if ((! $request->filled('ids')) || $request->input('ids') <= 0) {
|
if ((! $request->filled('ids')) || $request->input('ids') <= 0) {
|
||||||
return redirect()->back()->with('error', 'No users selected');
|
return redirect()->back()->with('error', trans('general.no_users_selected'));
|
||||||
}
|
}
|
||||||
$user_raw_array = $request->input('ids');
|
$user_raw_array = $request->input('ids');
|
||||||
|
|
||||||
|
@ -163,11 +181,11 @@ class BulkUsersController extends Controller
|
||||||
$this->authorize('update', User::class);
|
$this->authorize('update', User::class);
|
||||||
|
|
||||||
if ((! $request->filled('ids')) || (count($request->input('ids')) == 0)) {
|
if ((! $request->filled('ids')) || (count($request->input('ids')) == 0)) {
|
||||||
return redirect()->back()->with('error', 'No users selected');
|
return redirect()->back()->with('error', trans('general.no_users_selected'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config('app.lock_passwords')) {
|
if (config('app.lock_passwords')) {
|
||||||
return redirect()->route('users.index')->with('error', 'Bulk delete is not enabled in this installation');
|
return redirect()->route('users.index')->with('error', trans('general.feature_disabled'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$user_raw_array = request('ids');
|
$user_raw_array = request('ids');
|
||||||
|
@ -249,4 +267,80 @@ class BulkUsersController extends Controller
|
||||||
$logAction->logaction('checkin from');
|
$logAction->logaction('checkin from');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save bulk-edited users
|
||||||
|
*
|
||||||
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
|
* @since [v1.0]
|
||||||
|
* @param Request $request
|
||||||
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
|
*/
|
||||||
|
public function merge(Request $request)
|
||||||
|
{
|
||||||
|
$this->authorize('update', User::class);
|
||||||
|
|
||||||
|
if (config('app.lock_passwords')) {
|
||||||
|
return redirect()->route('users.index')->with('error', trans('general.feature_disabled'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$user_ids_to_merge = $request->input('ids_to_merge');
|
||||||
|
$user_ids_to_merge = array_diff($user_ids_to_merge, array($request->input('merge_into_id')));
|
||||||
|
|
||||||
|
if ((!$request->filled('merge_into_id')) || (count($user_ids_to_merge) < 1)) {
|
||||||
|
return redirect()->back()->with('error', trans('general.no_users_selected'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the users
|
||||||
|
$merge_into_user = User::find($request->input('merge_into_id'));
|
||||||
|
$users_to_merge = User::whereIn('id', $user_ids_to_merge)->with('assets', 'licenses', 'consumables','accessories')->get();
|
||||||
|
$admin = User::find(Auth::user()->id);
|
||||||
|
|
||||||
|
// Walk users
|
||||||
|
foreach ($users_to_merge as $user_to_merge) {
|
||||||
|
|
||||||
|
foreach ($user_to_merge->assets as $asset) {
|
||||||
|
\Log::debug('Updating asset: '.$asset->asset_tag . ' to '.$merge_into_user->id);
|
||||||
|
$asset->assigned_to = $request->input('merge_into_id');
|
||||||
|
$asset->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($user_to_merge->licenses as $license) {
|
||||||
|
\Log::debug('Updating license pivot: '.$license->id . ' to '.$merge_into_user->id);
|
||||||
|
$user_to_merge->licenses()->updateExistingPivot($license->id, ['assigned_to' => $merge_into_user->id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($user_to_merge->consumables as $consumable) {
|
||||||
|
\Log::debug('Updating consumable pivot: '.$consumable->id . ' to '.$merge_into_user->id);
|
||||||
|
$user_to_merge->consumables()->updateExistingPivot($consumable->id, ['assigned_to' => $merge_into_user->id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($user_to_merge->accessories as $accessory) {
|
||||||
|
$user_to_merge->accessories()->updateExistingPivot($accessory->id, ['assigned_to' => $merge_into_user->id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($user_to_merge->userlog as $log) {
|
||||||
|
$log->target_id = $user_to_merge->id;
|
||||||
|
$log->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
User::where('manager_id', '=', $user_to_merge->id)->update(['manager_id' => $merge_into_user->id]);
|
||||||
|
|
||||||
|
foreach ($user_to_merge->managedLocations as $managedLocation) {
|
||||||
|
$managedLocation->manager_id = $merge_into_user->id;
|
||||||
|
$managedLocation->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
$user_to_merge->delete();
|
||||||
|
//$user_to_merge->save();
|
||||||
|
|
||||||
|
event(new UserMerged($user_to_merge, $merge_into_user, $admin));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->route('users.index')->with('success', trans('general.merge_success', ['count' => $users_to_merge->count(), 'into_username' => $merge_into_user->username]));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ class SlackSettingsForm extends Component
|
||||||
$payload = json_encode(
|
$payload = json_encode(
|
||||||
[
|
[
|
||||||
'channel' => e($this->webhook_channel),
|
'channel' => e($this->webhook_channel),
|
||||||
'text' => trans('general.webhook_test_msg'),
|
'text' => trans('general.webhook_test_msg', ['app' => $this->webhook_name]),
|
||||||
'username' => e($this->webhook_botname),
|
'username' => e($this->webhook_botname),
|
||||||
'icon_emoji' => ':heart:',
|
'icon_emoji' => ':heart:',
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
namespace App\Http\Middleware;
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
use Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
|
|
||||||
class CheckPermissions
|
class CheckPermissions
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace App\Http\Transformers;
|
||||||
|
|
||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
use App\Models\Accessory;
|
use App\Models\Accessory;
|
||||||
use Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ namespace App\Http\Transformers;
|
||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\AssetMaintenance;
|
use App\Models\AssetMaintenance;
|
||||||
use Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
|
||||||
class AssetMaintenancesTransformer
|
class AssetMaintenancesTransformer
|
||||||
|
|
|
@ -5,7 +5,7 @@ namespace App\Http\Transformers;
|
||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace App\Http\Transformers;
|
||||||
|
|
||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
use App\Models\Category;
|
use App\Models\Category;
|
||||||
use Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace App\Http\Transformers;
|
||||||
|
|
||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
use Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
namespace App\Http\Transformers;
|
namespace App\Http\Transformers;
|
||||||
|
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
|
||||||
class ComponentsAssetsTransformer
|
class ComponentsAssetsTransformer
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace App\Http\Transformers;
|
||||||
|
|
||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
use App\Models\Component;
|
use App\Models\Component;
|
||||||
use Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace App\Http\Transformers;
|
||||||
|
|
||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
use App\Models\Consumable;
|
use App\Models\Consumable;
|
||||||
use Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace App\Http\Transformers;
|
||||||
|
|
||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
use App\Models\Department;
|
use App\Models\Department;
|
||||||
use Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ namespace App\Http\Transformers;
|
||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
use App\Models\Depreciable;
|
use App\Models\Depreciable;
|
||||||
use App\Models\Depreciation;
|
use App\Models\Depreciation;
|
||||||
use Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
|
||||||
class DepreciationsTransformer
|
class DepreciationsTransformer
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace App\Http\Transformers;
|
||||||
|
|
||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
use App\Models\Group;
|
use App\Models\Group;
|
||||||
use Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
|
||||||
class GroupsTransformer
|
class GroupsTransformer
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace App\Http\Transformers;
|
||||||
|
|
||||||
use App\Models\License;
|
use App\Models\License;
|
||||||
use App\Models\LicenseSeat;
|
use App\Models\LicenseSeat;
|
||||||
use Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
|
||||||
class LicenseSeatsTransformer
|
class LicenseSeatsTransformer
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace App\Http\Transformers;
|
||||||
|
|
||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
use App\Models\License;
|
use App\Models\License;
|
||||||
use Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
|
||||||
class LicensesTransformer
|
class LicensesTransformer
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace App\Http\Transformers;
|
||||||
|
|
||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
use App\Models\Manufacturer;
|
use App\Models\Manufacturer;
|
||||||
use Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace App\Http\Transformers;
|
||||||
|
|
||||||
use App\Models\PredefinedKit;
|
use App\Models\PredefinedKit;
|
||||||
use App\Models\SnipeModel;
|
use App\Models\SnipeModel;
|
||||||
use Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace App\Http\Transformers;
|
||||||
|
|
||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
use App\Models\Statuslabel;
|
use App\Models\Statuslabel;
|
||||||
use Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
|
||||||
class StatuslabelsTransformer
|
class StatuslabelsTransformer
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace App\Http\Transformers;
|
||||||
|
|
||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
use App\Models\Supplier;
|
use App\Models\Supplier;
|
||||||
use Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace App\Http\Transformers;
|
||||||
|
|
||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
|
||||||
class UsersTransformer
|
class UsersTransformer
|
||||||
|
|
|
@ -18,7 +18,9 @@ use App\Events\ItemDeclined;
|
||||||
use App\Events\LicenseCheckedIn;
|
use App\Events\LicenseCheckedIn;
|
||||||
use App\Events\LicenseCheckedOut;
|
use App\Events\LicenseCheckedOut;
|
||||||
use App\Models\Actionlog;
|
use App\Models\Actionlog;
|
||||||
|
use App\Models\User;
|
||||||
use App\Models\LicenseSeat;
|
use App\Models\LicenseSeat;
|
||||||
|
use App\Events\UserMerged;
|
||||||
|
|
||||||
class LogListener
|
class LogListener
|
||||||
{
|
{
|
||||||
|
@ -87,6 +89,43 @@ class LogListener
|
||||||
$logaction->save();
|
$logaction->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function onUserMerged(UserMerged $event)
|
||||||
|
{
|
||||||
|
|
||||||
|
$to_from_array = [
|
||||||
|
'to_id' => $event->merged_to->id,
|
||||||
|
'to_username' => $event->merged_to->username,
|
||||||
|
'from_id' => $event->merged_from->id,
|
||||||
|
'from_username' => $event->merged_from->username,
|
||||||
|
];
|
||||||
|
|
||||||
|
// Add a record to the users being merged FROM
|
||||||
|
\Log::debug('Users merged: '.$event->merged_from->id .' ('.$event->merged_from->username.') merged into '. $event->merged_to->id. ' ('.$event->merged_to->username.')');
|
||||||
|
$logaction = new Actionlog();
|
||||||
|
$logaction->item_id = $event->merged_from->id;
|
||||||
|
$logaction->item_type = User::class;
|
||||||
|
$logaction->target_id = $event->merged_to->id;
|
||||||
|
$logaction->target_type = User::class;
|
||||||
|
$logaction->action_type = 'merged';
|
||||||
|
$logaction->note = trans('general.merged_log_this_user_from', $to_from_array);
|
||||||
|
$logaction->user_id = $event->admin->id;
|
||||||
|
$logaction->save();
|
||||||
|
|
||||||
|
// Add a record to the users being merged TO
|
||||||
|
$logaction = new Actionlog();
|
||||||
|
$logaction->target_id = $event->merged_from->id;
|
||||||
|
$logaction->target_type = User::class;
|
||||||
|
$logaction->item_id = $event->merged_to->id;
|
||||||
|
$logaction->item_type = User::class;
|
||||||
|
$logaction->action_type = 'merged';
|
||||||
|
$logaction->note = trans('general.merged_log_this_user_into', $to_from_array);
|
||||||
|
$logaction->user_id = $event->admin->id;
|
||||||
|
$logaction->save();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register the listeners for the subscriber.
|
* Register the listeners for the subscriber.
|
||||||
*
|
*
|
||||||
|
@ -99,6 +138,7 @@ class LogListener
|
||||||
'CheckoutableCheckedOut',
|
'CheckoutableCheckedOut',
|
||||||
'CheckoutAccepted',
|
'CheckoutAccepted',
|
||||||
'CheckoutDeclined',
|
'CheckoutDeclined',
|
||||||
|
'UserMerged',
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($list as $event) {
|
foreach ($list as $event) {
|
||||||
|
@ -108,4 +148,6 @@ class LogListener
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,11 @@ class Group extends SnipeModel
|
||||||
'name' => 'required|min:2|max:255',
|
'name' => 'required|min:2|max:255',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'name',
|
||||||
|
'permissions'
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the model should inject it's identifier to the unique
|
* Whether the model should inject it's identifier to the unique
|
||||||
* validation rules before attempting validation. If this property
|
* validation rules before attempting validation. If this property
|
||||||
|
|
|
@ -50,6 +50,8 @@ class ActionlogPresenter extends Presenter
|
||||||
return 'far fa-save';
|
return 'far fa-save';
|
||||||
} elseif ($this->itemType() == 'component') {
|
} elseif ($this->itemType() == 'component') {
|
||||||
return 'far fa-hdd';
|
return 'far fa-hdd';
|
||||||
|
} elseif ($this->itemType() == 'user') {
|
||||||
|
return 'fa-solid fa-people-arrows';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,7 +112,19 @@ $config = [
|
||||||
'handler' => \Rollbar\Laravel\MonologHandler::class,
|
'handler' => \Rollbar\Laravel\MonologHandler::class,
|
||||||
'access_token' => env('ROLLBAR_TOKEN'),
|
'access_token' => env('ROLLBAR_TOKEN'),
|
||||||
'level' => env('ROLLBAR_LEVEL', 'error'),
|
'level' => env('ROLLBAR_LEVEL', 'error'),
|
||||||
'check_ignore' => function($isUncaught, $args, $payload) {
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
if ((env('APP_ENV')=='production') && (env('ROLLBAR_TOKEN'))) {
|
||||||
|
// Only add rollbar if the .env has a rollbar token
|
||||||
|
$config['channels']['stack']['channels'] = ['single', 'rollbar'];
|
||||||
|
|
||||||
|
// and only add the rollbar filter under the same conditions
|
||||||
|
// Note: it will *not* be cacheable
|
||||||
|
$config['channels']['rollbar']['check_ignore'] = function ($isUncaught, $args, $payload) {
|
||||||
if (App::environment('production') && is_object($args) && get_class($args) == Rollbar\ErrorWrapper::class && $args->errorLevel == E_WARNING ) {
|
if (App::environment('production') && is_object($args) && get_class($args) == Rollbar\ErrorWrapper::class && $args->errorLevel == E_WARNING ) {
|
||||||
\Log::info("IGNORING E_WARNING in production mode: ".$args->getMessage());
|
\Log::info("IGNORING E_WARNING in production mode: ".$args->getMessage());
|
||||||
return true; // "TRUE - you should ignore it!"
|
return true; // "TRUE - you should ignore it!"
|
||||||
|
@ -123,16 +135,8 @@ $config = [
|
||||||
return true; //yes, *do* ignore it
|
return true; //yes, *do* ignore it
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
};
|
||||||
],
|
|
||||||
],
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
// Only add rollbar if the .env has a rollbar token
|
|
||||||
if ((env('APP_ENV')=='production') && (env('ROLLBAR_TOKEN'))) {
|
|
||||||
$config['channels']['stack']['channels'] = ['single', 'rollbar'];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
18
package-lock.json
generated
18
package-lock.json
generated
|
@ -1533,9 +1533,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@types/eslint": {
|
"@types/eslint": {
|
||||||
"version": "8.4.5",
|
"version": "8.21.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.2.tgz",
|
||||||
"integrity": "sha512-dhsC09y1gpJWnK+Ff4SGvCuSnk9DaU0BJZSzOwa6GVSg65XtTugLBITDAAzRU5duGBoXBHpdR/9jHGxJjNflJQ==",
|
"integrity": "sha512-EMpxUyystd3uZVByZap1DACsMXvb82ypQnGn89e1Y0a+LYu3JJscUd/gqhRsVFDkaD2MIiWo0MT8EfXr3DGRKw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/estree": "*",
|
"@types/estree": "*",
|
||||||
"@types/json-schema": "*"
|
"@types/json-schema": "*"
|
||||||
|
@ -4768,9 +4768,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"enhanced-resolve": {
|
"enhanced-resolve": {
|
||||||
"version": "5.10.0",
|
"version": "5.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz",
|
||||||
"integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==",
|
"integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"graceful-fs": "^4.2.4",
|
"graceful-fs": "^4.2.4",
|
||||||
"tapable": "^2.2.0"
|
"tapable": "^2.2.0"
|
||||||
|
@ -19758,9 +19758,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"webpack": {
|
"webpack": {
|
||||||
"version": "5.74.0",
|
"version": "5.76.1",
|
||||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz",
|
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.1.tgz",
|
||||||
"integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==",
|
"integrity": "sha512-4+YIK4Abzv8172/SGqObnUjaIHjLEuUasz9EwQj/9xmPPkYJy2Mh03Q/lJfSD3YLzbxy5FeTq5Uw0323Oh6SJQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/eslint-scope": "^3.7.3",
|
"@types/eslint-scope": "^3.7.3",
|
||||||
"@types/estree": "^0.0.51",
|
"@types/estree": "^0.0.51",
|
||||||
|
|
|
@ -55,6 +55,6 @@
|
||||||
"tableexport.jquery.plugin": "1.26.0",
|
"tableexport.jquery.plugin": "1.26.0",
|
||||||
"tether": "^1.4.0",
|
"tether": "^1.4.0",
|
||||||
"vue-resource": "^1.5.2",
|
"vue-resource": "^1.5.2",
|
||||||
"webpack": "^5.74.0"
|
"webpack": "^5.76.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,4 +50,5 @@ return [
|
||||||
'email_credentials' => 'Email credentials',
|
'email_credentials' => 'Email credentials',
|
||||||
'email_credentials_text' => 'Email my credentials to the email address above',
|
'email_credentials_text' => 'Email my credentials to the email address above',
|
||||||
'next_save_user' => 'Next: Save User',
|
'next_save_user' => 'Next: Save User',
|
||||||
|
'all_assigned_list_generation' => 'Generated on:'
|
||||||
];
|
];
|
||||||
|
|
|
@ -45,7 +45,7 @@ return [
|
||||||
'bulk_edit' => 'Bulk Edit',
|
'bulk_edit' => 'Bulk Edit',
|
||||||
'bulk_delete' => 'Bulk Delete',
|
'bulk_delete' => 'Bulk Delete',
|
||||||
'bulk_actions' => 'Bulk Actions',
|
'bulk_actions' => 'Bulk Actions',
|
||||||
'bulk_checkin_delete' => 'Bulk Checkin Items from Users',
|
'bulk_checkin_delete' => 'Bulk Checkin / Delete Users',
|
||||||
'byod' => 'BYOD',
|
'byod' => 'BYOD',
|
||||||
'byod_help' => 'This device is owned by the user',
|
'byod_help' => 'This device is owned by the user',
|
||||||
'bystatus' => 'by Status',
|
'bystatus' => 'by Status',
|
||||||
|
@ -407,7 +407,16 @@ return [
|
||||||
'true' => 'True',
|
'true' => 'True',
|
||||||
'false' => 'False',
|
'false' => 'False',
|
||||||
'integration_option' => 'Integration Option',
|
'integration_option' => 'Integration Option',
|
||||||
|
'log_does_not_exist' => 'No matching log record exists.',
|
||||||
|
'merge_users' => 'Merge Users',
|
||||||
|
'merge_information' => 'This will merge the :count users into a single user. Select the user you wish to merge the others into below, and the associated assets, licences, etc will be moved over to the selected user and the other users will be marked as deleted.',
|
||||||
|
'warning_merge_information' => 'This action CANNOT be undone and should ONLY be used when you need to merge users because of a bad import or sync. Be sure to run a backup first.',
|
||||||
|
'no_users_selected' => 'No users selected',
|
||||||
|
'not_enough_users_selected' => 'At least :count users must be selected',
|
||||||
|
'merge_success' => ':count users merged successfully into :into_username!',
|
||||||
|
'merged' => 'merged',
|
||||||
|
'merged_log_this_user_into' => 'Merged this user (ID :to_id - :to_username) into user ID :from_id (:from_username) ',
|
||||||
|
'merged_log_this_user_from' => 'Merged user ID :from_id (:from_username) into this user (ID :to_id - :to_username)',
|
||||||
|
|
||||||
|
|
||||||
];
|
];
|
|
@ -134,7 +134,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!--Webhook Integration Test-->
|
<!--Webhook Integration Test-->
|
||||||
@if($webhook_selected == 'Slack' || $webhook_selected == 'Discord')
|
@if($webhook_selected == 'slack')
|
||||||
@if($webhook_endpoint != null && $webhook_channel != null)
|
@if($webhook_endpoint != null && $webhook_channel != null)
|
||||||
<div class="form-group col-md-12">
|
<div class="form-group col-md-12">
|
||||||
<div class="col-md-offset-3 col-md-9">
|
<div class="col-md-offset-3 col-md-9">
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
{{ trans('button.bulk_actions') }}
|
{{ trans('button.bulk_actions') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<select name="bulk_actions" class="form-control select2" aria-label="bulk_actions">
|
<select name="bulk_actions" class="form-control select2" aria-label="bulk_actions" style="min-width: 350px;">
|
||||||
@can('update', \App\Models\Asset::class)
|
@can('update', \App\Models\Asset::class)
|
||||||
<option value="edit">{{ trans('button.edit') }}</option>
|
<option value="edit">{{ trans('button.edit') }}</option>
|
||||||
@endcan
|
@endcan
|
||||||
|
|
|
@ -9,9 +9,10 @@
|
||||||
@can('delete', \App\Models\User::class)
|
@can('delete', \App\Models\User::class)
|
||||||
<div id="users-toolbar">
|
<div id="users-toolbar">
|
||||||
<label for="bulk_actions" class="sr-only">{{ trans('general.bulk_actions') }}</label>
|
<label for="bulk_actions" class="sr-only">{{ trans('general.bulk_actions') }}</label>
|
||||||
<select name="bulk_actions" class="form-control select2" style="width: 200px;" aria-label="bulk_actions">
|
<select name="bulk_actions" class="form-control select2" style="min-width:300px;" aria-label="bulk_actions">
|
||||||
<option value="edit">{{ trans('general.bulk_edit') }}</option>
|
<option value="edit">{{ trans('general.bulk_edit') }}</option>
|
||||||
<option value="delete">{!! trans('general.bulk_checkin_delete') !!}</option>
|
<option value="delete">{!! trans('general.bulk_checkin_delete') !!}</option>
|
||||||
|
<option value="merge">{!! trans('general.merge_users') !!}</option>
|
||||||
<option value="bulkpasswordreset">{{ trans('button.send_password_link') }}</option>
|
<option value="bulkpasswordreset">{{ trans('button.send_password_link') }}</option>
|
||||||
</select>
|
</select>
|
||||||
<button class="btn btn-primary" id="bulkUserEditButton" disabled>{{ trans('button.go') }}</button>
|
<button class="btn btn-primary" id="bulkUserEditButton" disabled>{{ trans('button.go') }}</button>
|
||||||
|
|
|
@ -106,8 +106,10 @@
|
||||||
</div><!--/col-md-12-->
|
</div><!--/col-md-12-->
|
||||||
</div> <!--/box-body-->
|
</div> <!--/box-body-->
|
||||||
<div class="box-footer text-right">
|
<div class="box-footer text-right">
|
||||||
<a class="btn btn-link" href="{{ URL::previous() }}">{{ trans('button.cancel') }}</a>
|
<a class="btn btn-link pull-left" href="{{ URL::previous() }}">{{ trans('button.cancel') }}</a>
|
||||||
<button type="submit" class="btn btn-success"><i class="fas fa-check icon-white" aria-hidden="true"></i> {{ trans('button.submit') }}</button>
|
|
||||||
|
<button type="submit" class="btn btn-success"{{ (config('app.lock_passwords') ? ' disabled' : '') }} disabled="disabled"><i class="fas fa-check icon-white" aria-hidden="true"></i> {{ trans('button.submit') }}</button>
|
||||||
|
|
||||||
</div><!-- /.box-footer -->
|
</div><!-- /.box-footer -->
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
143
resources/views/users/confirm-merge.blade.php
Normal file
143
resources/views/users/confirm-merge.blade.php
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
@extends('layouts/default')
|
||||||
|
{{-- Page title --}}
|
||||||
|
@section('title')
|
||||||
|
{!! trans('general.merge_users') !!}
|
||||||
|
@parent
|
||||||
|
@stop
|
||||||
|
|
||||||
|
{{-- Page content --}}
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-10 col-md-offset-1">
|
||||||
|
<div class="box box-default">
|
||||||
|
<form class="form-horizontal" role="form" method="post" action="{{ route('users.merge.save') }}">
|
||||||
|
<div class="box-body">
|
||||||
|
|
||||||
|
<div class="col-md-12">
|
||||||
|
<p style="padding:10px">
|
||||||
|
{{ trans('general.merge_information', array('count' => count($users))) }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<!-- CSRF Token -->
|
||||||
|
{{csrf_field()}}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="callout callout-danger">
|
||||||
|
<i class="fas fa-exclamation-triangle"></i>
|
||||||
|
{{ trans('general.warning_merge_information') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if (config('app.lock_passwords'))
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="callout callout-info">
|
||||||
|
<p>{{ trans('general.feature_disabled') }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="display table table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="col-md-3">{{ trans('general.name') }}</th>
|
||||||
|
<th class="col-md-3">{{ trans('general.email') }}</th>
|
||||||
|
<th class="col-md-3">{{ trans('general.username') }}</th>
|
||||||
|
<th class="col-md-3">{{ trans('general.groups') }}</th>
|
||||||
|
<th class="col-md-1 text-right">
|
||||||
|
<i class="fas fa-barcode fa-fw" aria-hidden="true" style="font-size: 17px;"></i>
|
||||||
|
<span class="sr-only">{{ trans('general.assets') }}</span>
|
||||||
|
</th>
|
||||||
|
<th class="col-md-1 text-right">
|
||||||
|
<i class="far fa-keyboard fa-fw" aria-hidden="true" style="font-size: 17px;"></i>
|
||||||
|
<span class="sr-only">{{ trans('general.accessories') }}</span>
|
||||||
|
</th>
|
||||||
|
<th class="col-md-1 text-right">
|
||||||
|
<i class="far fa-save fa-fw" aria-hidden="true" style="font-size: 17px;"></i>
|
||||||
|
<span class="sr-only">{{ trans('general.licenses') }}</span>
|
||||||
|
</th>
|
||||||
|
<th class="col-md-1 text-right">
|
||||||
|
<i class="fas fa-tint fa-fw" aria-hidden="true" style="font-size: 17px;"></i>
|
||||||
|
<span class="sr-only">{{ trans('general.consumables') }}</span>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach ($users as $user)
|
||||||
|
<tr {!! ($user->isSuperUser() ? ' class="danger"':'') !!}>
|
||||||
|
<td>
|
||||||
|
<input type="radio" name="merge_into_id" id="{{ $user->id }}" value="{{ $user->id }}" class="minimal">
|
||||||
|
<label for="{{ $user->id }}"> {{ $user->present()->fullName() }}</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ $user->email }}
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ $user->username }}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
@foreach ($user->groups as $group)
|
||||||
|
<a href=" {{ route('groups.update', $group->id) }}" class="label label-default">
|
||||||
|
{{ $group->name }}
|
||||||
|
</a>
|
||||||
|
@endforeach
|
||||||
|
</td>
|
||||||
|
<td class="text-right">
|
||||||
|
{{ number_format($user->assets()->count()) }}
|
||||||
|
</td>
|
||||||
|
<td class="text-right">
|
||||||
|
{{ number_format($user->accessories()->count()) }}
|
||||||
|
</td>
|
||||||
|
<td class="text-right">
|
||||||
|
{{ number_format($user->licenses()->count()) }}
|
||||||
|
</td>
|
||||||
|
<td class="text-right">
|
||||||
|
{{ number_format($user->consumables()->count()) }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
</div> <!--/table-responsive-->
|
||||||
|
</div><!--/col-md-12-->
|
||||||
|
</div> <!--/box-body-->
|
||||||
|
<div class="box-footer text-right">
|
||||||
|
<a class="btn btn-link pull-left" href="{{ URL::previous() }}">{{ trans('button.cancel') }}</a>
|
||||||
|
<button type="submit" class="btn btn-success"{{ (config('app.lock_passwords') ? ' disabled' : '') }} disabled="disabled"><i class="fas fa-check icon-white" aria-hidden="true"></i> {{ trans('button.submit') }}</button>
|
||||||
|
</div><!-- /.box-footer -->
|
||||||
|
|
||||||
|
@foreach ($users as $user)
|
||||||
|
<input type="hidden" name="ids_to_merge[]" value="{{ $user->id }}">
|
||||||
|
@endforeach
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@stop
|
||||||
|
|
||||||
|
@section('moar_scripts')
|
||||||
|
|
||||||
|
@if (!(config('app.lock_passwords')))
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
$('button[type="submit"]').prop("disabled", true);
|
||||||
|
|
||||||
|
$('input').on('ifChecked', function(event) {
|
||||||
|
$(' button[type="submit"]').prop("disabled", false);
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@stop
|
|
@ -2,7 +2,7 @@
|
||||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||||
<title>{{ trans('general.assigned_to', ['name' => $show_user->present()->fullName()]) }}</title>
|
<title>{{ trans('general.assigned_to', ['name' => $show_user->present()->fullName()]) }} - {{ date('Y-m-d H:i', time()) }}</title>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
font-family: "Arial, Helvetica", sans-serif;
|
font-family: "Arial, Helvetica", sans-serif;
|
||||||
|
@ -49,8 +49,8 @@
|
||||||
@endif
|
@endif
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<h3>{{ trans('general.assigned_to', ['name' => $show_user->present()->fullName()]) }} {{ ($show_user->jobtitle!='' ? ' - '.$show_user->jobtitle : '') }}</h3>
|
<h3>{{ trans('general.assigned_to', ['name' => $show_user->present()->fullName()]) }} {{ ($show_user->jobtitle!='' ? ' - '.$show_user->jobtitle : '') }}
|
||||||
|
</h3>
|
||||||
@if ($assets->count() > 0)
|
@if ($assets->count() > 0)
|
||||||
@php
|
@php
|
||||||
$counter = 1;
|
$counter = 1;
|
||||||
|
@ -243,6 +243,8 @@
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
|
{{ trans('admin/users/general.all_assigned_list_generation')}} {{ Helper::getFormattedDateObject(now(), 'datetime', false) }}
|
||||||
|
<br>
|
||||||
<br>
|
<br>
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
@ -958,16 +958,18 @@
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th data-field="icon" style="width: 40px;" class="hidden-xs" data-formatter="iconFormatter">Icon</th>
|
<th data-field="icon" style="width: 40px;" class="hidden-xs" data-formatter="iconFormatter">Icon</th>
|
||||||
<th class="col-sm-3" data-field="created_at" data-formatter="dateDisplayFormatter" data-sortable="true">{{ trans('general.date') }}</th>
|
<th data-field="created_at" data-formatter="dateDisplayFormatter" data-sortable="true">{{ trans('general.date') }}</th>
|
||||||
<th class="col-sm-2" data-field="admin" data-formatter="usersLinkObjFormatter">{{ trans('general.admin') }}</th>
|
<th data-field="item" data-formatter="polymorphicItemFormatter">{{ trans('general.item') }}</th>
|
||||||
<th class="col-sm-2" data-field="action_type">{{ trans('general.action') }}</th>
|
<th data-field="action_type">{{ trans('general.action') }}</th>
|
||||||
|
<th data-field="target" data-formatter="polymorphicItemFormatter">{{ trans('general.target') }}</th>
|
||||||
|
<th data-field="note">{{ trans('general.notes') }}</th>
|
||||||
@if ($snipeSettings->require_accept_signature=='1')
|
@if ($snipeSettings->require_accept_signature=='1')
|
||||||
<th class="col-md-3" data-field="signature_file" data-visible="false" data-formatter="imageFormatter">{{ trans('general.signature') }}</th>
|
<th data-field="signature_file" data-visible="false" data-formatter="imageFormatter">{{ trans('general.signature') }}</th>
|
||||||
@endif
|
@endif
|
||||||
<th class="col-sm-3" data-field="item.serial" data-visible="false">{{ trans('admin/hardware/table.serial') }}</th>
|
<th data-field="item.serial" data-visible="false">{{ trans('admin/hardware/table.serial') }}</th>
|
||||||
<th class="col-sm-3" data-field="item" data-formatter="polymorphicItemFormatter">{{ trans('general.item') }}</th>
|
<th data-field="admin" data-formatter="usersLinkObjFormatter">{{ trans('general.admin') }}</th>
|
||||||
<th class="col-sm-3" data-field="note">{{ trans('general.notes') }}</th>
|
|
||||||
<th class="col-sm-2" data-field="target" data-formatter="polymorphicItemFormatter">{{ trans('general.target') }}</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -120,6 +120,14 @@ Route::group(['prefix' => 'users', 'middleware' => ['auth']], function () {
|
||||||
]
|
]
|
||||||
)->name('users/bulkedit');
|
)->name('users/bulkedit');
|
||||||
|
|
||||||
|
Route::post(
|
||||||
|
'merge',
|
||||||
|
[
|
||||||
|
Users\BulkUsersController::class,
|
||||||
|
'merge'
|
||||||
|
]
|
||||||
|
)->name('users.merge.save');
|
||||||
|
|
||||||
|
|
||||||
Route::post(
|
Route::post(
|
||||||
'bulksave',
|
'bulksave',
|
||||||
|
|
Loading…
Reference in a new issue