diff --git a/app/Console/Commands/CreateAdmin.php b/app/Console/Commands/CreateAdmin.php index 5aebde3777..114f92dae4 100644 --- a/app/Console/Commands/CreateAdmin.php +++ b/app/Console/Commands/CreateAdmin.php @@ -20,13 +20,14 @@ class CreateAdmin extends Command * @property string $password * @property boolean $activated * @property boolean $show_in_list + * @property boolean $autoassign_licenses * @property \Illuminate\Support\Carbon|null $created_at * @property mixed $created_by */ - protected $signature = 'snipeit:create-admin {--first_name=} {--last_name=} {--email=} {--username=} {--password=} {show_in_list?}'; + protected $signature = 'snipeit:create-admin {--first_name=} {--last_name=} {--email=} {--username=} {--password=} {show_in_list?} {autoassign_licenses?}'; /** * The console command description. @@ -54,6 +55,9 @@ class CreateAdmin extends Command $email = $this->option('email'); $password = $this->option('password'); $show_in_list = $this->argument('show_in_list'); + $autoassign_licenses = $this->argument('autoassign_licenses'); + + if (($first_name == '') || ($last_name == '') || ($username == '') || ($email == '') || ($password == '')) { $this->info('ERROR: All fields are required.'); @@ -70,6 +74,11 @@ class CreateAdmin extends Command if ($show_in_list == 'false') { $user->show_in_list = 0; } + + if ($autoassign_licenses == 'false') { + $user->autoassign_licenses = 0; + } + if ($user->save()) { $this->info('New user created'); $user->groups()->attach(1); diff --git a/app/Http/Controllers/Api/UsersController.php b/app/Http/Controllers/Api/UsersController.php index 7c63bb925c..dc444ec9e9 100644 --- a/app/Http/Controllers/Api/UsersController.php +++ b/app/Http/Controllers/Api/UsersController.php @@ -71,6 +71,7 @@ class UsersController extends Controller 'users.start_date', 'users.end_date', 'users.vip', + 'users.autoassign_licenses', ])->with('manager', 'groups', 'userloc', 'company', 'department', 'assets', 'licenses', 'accessories', 'consumables', 'createdBy',) ->withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count'); @@ -187,6 +188,10 @@ class UsersController extends Controller $users->has('accessories', '=', $request->input('accessories_count')); } + if ($request->filled('autoassign_licenses')) { + $users->where('autoassign_licenses', '=', $request->input('autoassign_licenses')); + } + if ($request->filled('search')) { $users = $users->TextSearch($request->input('search')); } @@ -259,6 +264,7 @@ class UsersController extends Controller 'vip', 'start_date', 'end_date', + 'autoassign_licenses', ]; $sort = in_array($request->get('sort'), $allowed_columns) ? $request->get('sort') : 'first_name'; @@ -356,7 +362,7 @@ class UsersController extends Controller $user->permissions = $permissions_array; } - $tmp_pass = substr(str_shuffle('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'), 0, 20); + $tmp_pass = substr(str_shuffle('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'), 0, 40); $user->password = bcrypt($request->get('password', $tmp_pass)); app('App\Http\Requests\ImageUploadRequest')->handleImages($user, 600, 'image', 'avatars', 'avatar'); diff --git a/app/Http/Controllers/Licenses/LicenseCheckinController.php b/app/Http/Controllers/Licenses/LicenseCheckinController.php index 257722b005..50e20c7985 100644 --- a/app/Http/Controllers/Licenses/LicenseCheckinController.php +++ b/app/Http/Controllers/Licenses/LicenseCheckinController.php @@ -112,4 +112,54 @@ class LicenseCheckinController extends Controller // Redirect to the license page with error return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.checkin.error')); } + + /** + * Bulk checkin all license seats + * + * @author [A. Gianotto] [] + * @see LicenseCheckinController::create() method that provides the form view + * @since [v6.1.1] + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + + public function bulkCheckin(Request $request, $licenseId) { + + $license = License::findOrFail($licenseId); + $this->authorize('checkin', $license); + + $licenseSeatsByUser = LicenseSeat::where('license_id', '=', $licenseId) + ->whereNotNull('assigned_to') + ->with('user') + ->get(); + + foreach ($licenseSeatsByUser as $user_seat) { + $user_seat->assigned_to = null; + + if ($user_seat->save()) { + \Log::debug('Checking in '.$license->name.' from user '.$user_seat->username); + $user_seat->logCheckin($user_seat->user, trans('admin/licenses/general.bulk.checkin_all.log_msg')); + } + } + + $licenseSeatsByAsset = LicenseSeat::where('license_id', '=', $licenseId) + ->whereNotNull('asset_id') + ->with('asset') + ->get(); + + $count = 0; + foreach ($licenseSeatsByAsset as $asset_seat) { + $asset_seat->asset_id = null; + + if ($asset_seat->save()) { + \Log::debug('Checking in '.$license->name.' from asset '.$asset_seat->asset_tag); + $asset_seat->logCheckin($asset_seat->asset, trans('admin/licenses/general.bulk.checkin_all.log_msg')); + $count++; + } + } + + return redirect()->back()->with('success', trans_choice('admin/licenses/general.bulk.checkin_all.success', 2, ['count' => $count] )); + + } + } diff --git a/app/Http/Controllers/Licenses/LicenseCheckoutController.php b/app/Http/Controllers/Licenses/LicenseCheckoutController.php index 6f2ae003ca..a710497692 100644 --- a/app/Http/Controllers/Licenses/LicenseCheckoutController.php +++ b/app/Http/Controllers/Licenses/LicenseCheckoutController.php @@ -126,4 +126,70 @@ class LicenseCheckoutController extends Controller return false; } + + /** + * Bulk checkin all license seats + * + * @author [A. Gianotto] [] + * @see LicenseCheckinController::create() method that provides the form view + * @since [v6.1.1] + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + + public function bulkCheckout($licenseId) { + + \Log::debug('Checking out '.$licenseId.' via bulk'); + $license = License::findOrFail($licenseId); + $this->authorize('checkin', $license); + $avail_count = $license->getAvailSeatsCountAttribute(); + + $users = User::whereNull('deleted_at')->where('autoassign_licenses', '=', 1)->with('licenses')->get(); + \Log::debug($avail_count.' will be assigned'); + + if ($users->count() > $avail_count) { + \Log::debug('You do not have enough free seats to complete this task, so we will check out as many as we can. '); + } + + // If the license is valid, check that there is an available seat + if ($license->availCount()->count() < 1) { + return redirect()->back()->with('error', trans('admin/licenses/general.bulk.checkout_all.error_no_seats')); + } + + + $assigned_count = 0; + + foreach ($users as $user) { + + // Check to make sure this user doesn't already have this license checked out to them + if ($user->licenses->where('id', '=', $licenseId)->count()) { + \Log::debug($user->username.' already has this license checked out to them. Skipping... '); + continue; + } + + $licenseSeat = $license->freeSeat(); + + // Update the seat with checkout info + $licenseSeat->assigned_to = $user->id; + + if ($licenseSeat->save()) { + $avail_count--; + $assigned_count++; + $licenseSeat->logCheckout(trans('admin/licenses/general.bulk.checkout_all.log_msg'), $user); + \Log::debug('License '.$license->name.' seat '.$licenseSeat->id.' checked out to '.$user->username); + } + + if ($avail_count == 0) { + return redirect()->back()->with('warning', trans('admin/licenses/general.bulk.checkout_all.warn_not_enough_seats', ['count' => $assigned_count])); + } + } + + if ($assigned_count == 0) { + return redirect()->back()->with('warning', trans('admin/licenses/general.bulk.checkout_all.warn_no_avail_users', ['count' => $assigned_count])); + } + + return redirect()->back()->with('success', trans_choice('admin/licenses/general.bulk.checkout_all.success', 2, ['count' => $assigned_count] )); + + + } } diff --git a/app/Http/Controllers/Licenses/LicensesController.php b/app/Http/Controllers/Licenses/LicensesController.php index a0467654ca..a3607c1810 100755 --- a/app/Http/Controllers/Licenses/LicensesController.php +++ b/app/Http/Controllers/Licenses/LicensesController.php @@ -6,6 +6,8 @@ use App\Helpers\Helper; use App\Http\Controllers\Controller; use App\Models\Company; use App\Models\License; +use App\Models\LicenseSeat; +use App\Models\User; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\DB; @@ -232,17 +234,39 @@ class LicensesController extends Controller public function show($licenseId = null) { $license = License::with('assignedusers')->find($licenseId); + $users_count = User::where('autoassign_licenses', '1')->count(); + $total_seats_count = $license->totalSeatsByLicenseID(); + $available_seats_count = $license->availCount()->count(); + $checkedout_seats_count = ($total_seats_count - $available_seats_count); + + \Log::debug('Total: '.$total_seats_count); + \Log::debug('Users: '.$users_count); + \Log::debug('Available: '.$available_seats_count); + \Log::debug('Checkedout: '.$checkedout_seats_count); + if ($license) { $this->authorize('view', $license); - - return view('licenses/view', compact('license')); + return view('licenses.view', compact('license')) + ->with('users_count', $users_count) + ->with('total_seats_count', $total_seats_count) + ->with('available_seats_count', $available_seats_count) + ->with('checkedout_seats_count', $checkedout_seats_count); } - return redirect()->route('licenses.index') + return redirect()->route('licenses.view') ->with('error', trans('admin/licenses/message.does_not_exist')); } + + /** + * Returns a view with prepopulated data for clone + * + * @author [A. Gianotto] [] + * @param int $licenseId + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ public function getClone($licenseId = null) { if (is_null($license_to_clone = License::find($licenseId))) { diff --git a/app/Http/Controllers/Users/BulkUsersController.php b/app/Http/Controllers/Users/BulkUsersController.php index 67ecae542e..a2d3d496da 100644 --- a/app/Http/Controllers/Users/BulkUsersController.php +++ b/app/Http/Controllers/Users/BulkUsersController.php @@ -113,7 +113,8 @@ class BulkUsersController extends Controller ->conditionallyAddItem('locale') ->conditionallyAddItem('remote') ->conditionallyAddItem('ldap_import') - ->conditionallyAddItem('activated'); + ->conditionallyAddItem('activated') + ->conditionallyAddItem('autoassign_licenses'); // If the manager_id is one of the users being updated, generate a warning. diff --git a/app/Http/Controllers/Users/UsersController.php b/app/Http/Controllers/Users/UsersController.php index 7e95484f6e..b839533658 100755 --- a/app/Http/Controllers/Users/UsersController.php +++ b/app/Http/Controllers/Users/UsersController.php @@ -120,7 +120,7 @@ class UsersController extends Controller $user->created_by = Auth::user()->id; $user->start_date = $request->input('start_date', null); $user->end_date = $request->input('end_date', null); - $user->autoassign_licenses= $request->input('autoassign_licenses', 1); + $user->autoassign_licenses = $request->input('autoassign_licenses', 0); // Strip out the superuser permission if the user isn't a superadmin $permissions_array = $request->input('permission'); @@ -275,7 +275,7 @@ class UsersController extends Controller $user->website = $request->input('website', null); $user->start_date = $request->input('start_date', null); $user->end_date = $request->input('end_date', null); - $user->autoassign_licenses = $request->input('autoassign_licenses', 1); + $user->autoassign_licenses = $request->input('autoassign_licenses', 0); // Update the location of any assets checked out to this user Asset::where('assigned_type', User::class) diff --git a/app/Http/Transformers/LicensesTransformer.php b/app/Http/Transformers/LicensesTransformer.php index 3c389a1b18..8df6b89f19 100644 --- a/app/Http/Transformers/LicensesTransformer.php +++ b/app/Http/Transformers/LicensesTransformer.php @@ -56,7 +56,7 @@ class LicensesTransformer 'checkin' => Gate::allows('checkin', License::class), 'clone' => Gate::allows('create', License::class), 'update' => Gate::allows('update', License::class), - 'delete' => Gate::allows('delete', License::class), + 'delete' => (Gate::allows('delete', License::class) && ($license->seats == $license->availCount()->count())) ? true : false, ]; $array += $permissions_array; diff --git a/app/Http/Transformers/UsersTransformer.php b/app/Http/Transformers/UsersTransformer.php index 9447d65455..867a884619 100644 --- a/app/Http/Transformers/UsersTransformer.php +++ b/app/Http/Transformers/UsersTransformer.php @@ -56,6 +56,7 @@ class UsersTransformer 'notes'=> e($user->notes), 'permissions' => $user->decodePermissions(), 'activated' => ($user->activated == '1') ? true : false, + 'autoassign_licenses' => ($user->autoassign_licenses == '1') ? true : false, 'ldap_import' => ($user->ldap_import == '1') ? true : false, 'two_factor_enrolled' => ($user->two_factor_active_and_enrolled()) ? true : false, 'two_factor_optin' => ($user->two_factor_active()) ? true : false, diff --git a/app/Importer/UserImporter.php b/app/Importer/UserImporter.php index bcbc632eb3..9f2c1c5f43 100644 --- a/app/Importer/UserImporter.php +++ b/app/Importer/UserImporter.php @@ -58,7 +58,8 @@ class UserImporter extends ItemImporter $this->item['department_id'] = $this->createOrFetchDepartment($this->findCsvMatch($row, 'department')); $this->item['manager_id'] = $this->fetchManager($this->findCsvMatch($row, 'manager_first_name'), $this->findCsvMatch($row, 'manager_last_name')); $this->item['remote'] =($this->fetchHumanBoolean($this->findCsvMatch($row, 'remote')) ==1 ) ? '1' : 0; - $this->item['vip'] =($this->fetchHumanBoolean($this->findCsvMatch($row, 'vip')) ==1 ) ? '1' : 0; + $this->item['vip'] = ($this->fetchHumanBoolean($this->findCsvMatch($row, 'vip')) ==1 ) ? '1' : 0; + $this->item['autoassign_licenses'] = ($this->fetchHumanBoolean($this->findCsvMatch($row, 'autoassign_licenses')) ==1 ) ? '1' : 0; $user_department = $this->findCsvMatch($row, 'department'); diff --git a/app/Models/License.php b/app/Models/License.php index ff69d5f66d..162b3d662a 100755 --- a/app/Models/License.php +++ b/app/Models/License.php @@ -106,10 +106,10 @@ class License extends Depreciable * @var array */ protected $searchableRelations = [ - 'manufacturer' => ['name'], - 'company' => ['name'], - 'category' => ['name'], - 'depreciation' => ['name'], + 'manufacturer' => ['name'], + 'company' => ['name'], + 'category' => ['name'], + 'depreciation' => ['name'], ]; /** @@ -425,7 +425,7 @@ class License extends Depreciable public static function assetcount() { return LicenseSeat::whereNull('deleted_at') - ->count(); + ->count(); } @@ -441,8 +441,8 @@ class License extends Depreciable public function totalSeatsByLicenseID() { return LicenseSeat::where('license_id', '=', $this->id) - ->whereNull('deleted_at') - ->count(); + ->whereNull('deleted_at') + ->count(); } /** @@ -486,11 +486,12 @@ class License extends Depreciable public static function availassetcount() { return LicenseSeat::whereNull('assigned_to') - ->whereNull('asset_id') - ->whereNull('deleted_at') - ->count(); + ->whereNull('asset_id') + ->whereNull('deleted_at') + ->count(); } + /** * Returns the number of total available seats for this license * @@ -533,7 +534,7 @@ class License extends Depreciable { return $this->licenseSeatsRelation()->where(function ($query) { $query->whereNotNull('assigned_to') - ->orWhereNotNull('asset_id'); + ->orWhereNotNull('asset_id'); }); } @@ -621,13 +622,13 @@ class License extends Depreciable public function freeSeat() { return $this->licenseseats() - ->whereNull('deleted_at') - ->where(function ($query) { - $query->whereNull('assigned_to') - ->whereNull('asset_id'); - }) - ->orderBy('id', 'asc') - ->first(); + ->whereNull('deleted_at') + ->where(function ($query) { + $query->whereNull('assigned_to') + ->whereNull('asset_id'); + }) + ->orderBy('id', 'asc') + ->first(); } @@ -657,11 +658,11 @@ class License extends Depreciable $days = (is_null($days)) ? 60 : $days; return self::whereNotNull('expiration_date') - ->whereNull('deleted_at') - ->whereRaw(DB::raw('DATE_SUB(`expiration_date`,INTERVAL '.$days.' DAY) <= DATE(NOW()) ')) - ->where('expiration_date', '>', date('Y-m-d')) - ->orderBy('expiration_date', 'ASC') - ->get(); + ->whereNull('deleted_at') + ->whereRaw(DB::raw('DATE_SUB(`expiration_date`,INTERVAL '.$days.' DAY) <= DATE(NOW()) ')) + ->where('expiration_date', '>', date('Y-m-d')) + ->orderBy('expiration_date', 'ASC') + ->get(); } /** @@ -705,4 +706,4 @@ class License extends Depreciable return $query->leftJoin('companies as companies', 'licenses.company_id', '=', 'companies.id')->select('licenses.*') ->orderBy('companies.name', $order); } -} +} \ No newline at end of file diff --git a/app/Models/Supplier.php b/app/Models/Supplier.php index d60d3c42fe..fa00fbad2a 100755 --- a/app/Models/Supplier.php +++ b/app/Models/Supplier.php @@ -78,24 +78,7 @@ class Supplier extends SnipeModel { return $this->hasMany(Asset::class)->whereNull('deleted_at')->selectRaw('supplier_id, count(*) as count')->groupBy('supplier_id'); } - - /** - * Sets the license seat count attribute - * - * @todo I don't see the licenseSeatsRelation here? - * - * @author A. Gianotto - * @since [v1.0] - * @return \Illuminate\Database\Eloquent\Relations\Relation - */ - public function getLicenseSeatsCountAttribute() - { - if ($this->licenseSeatsRelation->first()) { - return $this->licenseSeatsRelation->first()->count; - } - - return 0; - } + /** * Establishes the supplier -> assets relationship diff --git a/app/Models/User.php b/app/Models/User.php index df97800917..44bffe156d 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -65,6 +65,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo 'avatar', 'gravatar', 'vip', + 'autoassign_licenses', ]; protected $casts = [ @@ -76,6 +77,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo 'created_at' => 'datetime', 'updated_at' => 'datetime', 'deleted_at' => 'datetime', + 'autoassign_licenses' => 'boolean', ]; /** @@ -95,6 +97,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo 'location_id' => 'exists:locations,id|nullable', 'start_date' => 'nullable|date_format:Y-m-d', 'end_date' => 'nullable|date_format:Y-m-d|after_or_equal:start_date', + 'autoassign_licenses' => 'boolean', ]; /** diff --git a/app/Presenters/LicensePresenter.php b/app/Presenters/LicensePresenter.php index 1e8784f2fc..5a44bf52ab 100644 --- a/app/Presenters/LicensePresenter.php +++ b/app/Presenters/LicensePresenter.php @@ -33,7 +33,7 @@ class LicensePresenter extends Presenter 'field' => 'name', 'searchable' => true, 'sortable' => true, - 'title' => trans('admin/licenses/table.title'), + 'title' => trans('general.name'), 'formatter' => 'licensesLinkFormatter', ], [ 'field' => 'product_key', diff --git a/app/Presenters/UserPresenter.php b/app/Presenters/UserPresenter.php index b5eefdf811..fbb41a4d51 100644 --- a/app/Presenters/UserPresenter.php +++ b/app/Presenters/UserPresenter.php @@ -294,6 +294,15 @@ class UserPresenter extends Presenter 'visible' => true, 'formatter' => 'trueFalseFormatter', ], + [ + 'field' => 'autoassign_licenses', + 'searchable' => false, + 'sortable' => true, + 'switchable' => true, + 'title' => trans('general.autoassign_licenses'), + 'visible' => false, + 'formatter' => 'trueFalseFormatter', + ], [ 'field' => 'created_by', 'searchable' => false, diff --git a/resources/lang/en/admin/licenses/general.php b/resources/lang/en/admin/licenses/general.php index 25a536ec56..0187d076a3 100644 --- a/resources/lang/en/admin/licenses/general.php +++ b/resources/lang/en/admin/licenses/general.php @@ -1,8 +1,8 @@ 'About Licenses', - 'about_licenses' => 'Licenses are used to track software. They have a specified number of seats that can be checked out to individuals', + 'about_licenses_title' => 'About Licenses', + 'about_licenses' => 'Licenses are used to track software. They have a specified number of seats that can be checked out to individuals', 'checkin' => 'Checkin License Seat', 'checkout_history' => 'Checkout History', 'checkout' => 'Checkout License Seat', @@ -18,4 +18,30 @@ return array( 'software_licenses' => 'Software Licenses', 'user' => 'User', 'view' => 'View License', + 'delete_disabled' => 'This license cannot be deleted yet because some seats are still checked out.', + 'bulk' => + [ + 'checkin_all' => [ + 'button' => 'Checkin All Seats', + 'modal' => 'This will action checkin one seat. | This action will checkin all :checkedout_seats_count seats for this license.', + 'enabled_tooltip' => 'Checkin ALL seats for this license from both users and assets', + 'disabled_tooltip' => 'This is disabled because there are no seats currently checked out', + 'success' => 'License successfully checked in! | All licenses were successfully checked in!', + 'log_msg' => 'Checked in via bulk license checkout in license GUI', + ], + + 'checkout_all' => [ + 'button' => 'Checkout All Seats', + 'modal' => 'This action will checkout one seat to the first available user. | This action will checkout all :available_seats_count seats to the first available users. A user is considered available for this seat if they do not already have this license checked out to them, and the Auto-Assign License property is enabled on their user account.', + 'enabled_tooltip' => 'Checkout ALL seats (or as many as are available) to ALL users', + 'disabled_tooltip' => 'This is disabled because there are no seats currently available', + 'success' => 'License successfully checked out! | :count licenses were successfully checked out!', + 'error_no_seats' => 'There are no remaining seats left for this license.', + 'warn_not_enough_seats' => ':count users were assigned this license, but we ran out of available license seats.', + 'warn_no_avail_users' => 'Nothing to do. There are no users who do not already have this license assigned to them.', + 'log_msg' => 'Checked out via bulk license checkout in license GUI', + + + ], + ], ); diff --git a/resources/lang/en/general.php b/resources/lang/en/general.php index cb51b28a42..1b9d9b623a 100644 --- a/resources/lang/en/general.php +++ b/resources/lang/en/general.php @@ -439,4 +439,12 @@ return [ 'setup_migration_output' => 'Migration output:', 'setup_migration_create_user' => 'Next: Create User', 'importer_generic_error' => 'Your file import is complete, but we did receive an error. This is usually caused by third-party API throttling from a notification webhook (such as Slack) and would not have interfered with the import itself, but you should confirm this.', + 'confirm' => 'Confirm', + 'autoassign_licenses' => 'Auto-Assign Licenses', + 'autoassign_licenses_help' => 'Allow user to be have licenses assigned via the bulk-assign license UI or cli tools.', + 'autoassign_licenses_help_long' => 'This allows a user to be have licenses assigned via the bulk-assign license UI or cli tools. (For example, you might not want contractors to be auto-assigned a license you would provide to only staff members. You can still individually assign licenses to those users, but they will not be included in the Checkout License to All Users functions.)', + 'no_autoassign_licenses_help' => 'Do not include user for bulk-assigning through the license UI or cli tools.', + 'modal_confirm_generic' => 'Are you sure?', + 'cannot_be_deleted' => 'This item cannot be deleted', + ]; diff --git a/resources/views/custom_fields/index.blade.php b/resources/views/custom_fields/index.blade.php index d2435d7db5..0ad8511183 100644 --- a/resources/views/custom_fields/index.blade.php +++ b/resources/views/custom_fields/index.blade.php @@ -21,7 +21,7 @@

{{ trans('admin/custom_fields/general.fieldsets') }}

@@ -111,7 +111,7 @@

{{ trans('admin/custom_fields/general.custom_fields') }}

diff --git a/resources/views/groups/edit.blade.php b/resources/views/groups/edit.blade.php index f5948e4841..cb95b3762a 100755 --- a/resources/views/groups/edit.blade.php +++ b/resources/views/groups/edit.blade.php @@ -77,7 +77,7 @@ @unless (empty($localPermission['label'])) @@ -100,7 +100,7 @@

{{ $area }}

@@ -122,7 +122,7 @@ {{ $this_permission['label'] }} diff --git a/resources/views/hardware/view.blade.php b/resources/views/hardware/view.blade.php index e33f681f6e..ccd3f86536 100755 --- a/resources/views/hardware/view.blade.php +++ b/resources/views/hardware/view.blade.php @@ -456,7 +456,7 @@
@if ($field->field_encrypted=='1') - + @endif @if ($field->isFieldDecryptable($asset->{$field->db_column_name()} )) diff --git a/resources/views/layouts/default.blade.php b/resources/views/layouts/default.blade.php index 98b1c52817..9eb43d35ae 100644 --- a/resources/views/layouts/default.blade.php +++ b/resources/views/layouts/default.blade.php @@ -974,7 +974,7 @@ $(function () { - $('[data-toggle="tooltip"]').tooltip(); + $('[data-tooltip="true"]').tooltip(); $('[data-toggle="popover"]').popover(); $('.select2 span').addClass('needsclick'); $('.select2 span').removeAttr('title'); diff --git a/resources/views/licenses/view.blade.php b/resources/views/licenses/view.blade.php index 21260ae4bb..e48ab859bd 100755 --- a/resources/views/licenses/view.blade.php +++ b/resources/views/licenses/view.blade.php @@ -10,7 +10,7 @@ {{-- Page content --}} @section('content')
-
+
- {!! $license->maintained ? ' '.trans('general.yes') : ' '.trans('general.no') !!} + {!! $license->maintained ? ' '.trans('general.yes') : ' '.trans('general.no') !!}
@@ -358,7 +344,7 @@
- {!! $license->reassignable ? ' '.trans('general.yes') : ' '.trans('general.no') !!} + {!! $license->reassignable ? ' '.trans('general.yes') : ' '.trans('general.no') !!}
@@ -378,8 +364,10 @@
- - + + + + @@ -550,13 +538,100 @@ + + + + +
+ + @can('update', $license) + {{ trans('admin/licenses/general.edit') }} + {{ trans('admin/licenses/general.clone') }} + @endcan + + @can('checkout', $license) + + @if ($license->availCount()->count() > 0) + + {{ trans('general.checkout') }} + + + {{ trans('admin/licenses/general.bulk.checkout_all.button') }} + + + @else + + {{ trans('general.checkout') }} + + + + {{ trans('admin/licenses/general.bulk.checkout_all.button') }} + + + @endif + @endcan + + @can('checkin', $license) + + @if (($license->seats - $license->availCount()->count()) > 0 ) + + {{ trans('admin/licenses/general.bulk.checkin_all.button') }} + + @else + + + {{ trans('admin/licenses/general.bulk.checkin_all.button') }} + + + @endif + @endcan + + @can('delete', $license) + + @if ($license->availCount()->count() == $license->seats) + + @else + + + {{ trans('general.delete') }} + + + @endif + @endcan +
+ + +@can('checkin', \App\Models\License::class) + @include ('modals.confirm-action', + [ + 'modal_name' => 'checkinFromAllModal', + 'route' => route('licenses.bulkcheckin', $license->id), + 'title' => trans('general.modal_confirm_generic'), + 'body' => trans_choice('admin/licenses/general.bulk.checkin_all.modal', 2, ['checkedout_seats_count' => $checkedout_seats_count]) + ]) +@endcan + +@can('checkout', \App\Models\License::class) + @include ('modals.confirm-action', + [ + 'modal_name' => 'checkoutFromAllModal', + 'route' => route('licenses.bulkcheckout', $license->id), + 'title' => trans('general.modal_confirm_generic'), + 'body' => trans_choice('admin/licenses/general.bulk.checkout_all.modal', 2, ['available_seats_count' => $available_seats_count]) + ]) +@endcan + + + @can('update', \App\Models\License::class) @include ('modals.upload-file', ['item_type' => 'license', 'item_id' => $license->id]) @endcan @@ -565,5 +640,15 @@ @section('moar_scripts') + @include ('partials.bootstrap-table') @stop diff --git a/resources/views/modals/confirm-action.blade.php b/resources/views/modals/confirm-action.blade.php new file mode 100644 index 0000000000..135a9799ed --- /dev/null +++ b/resources/views/modals/confirm-action.blade.php @@ -0,0 +1,27 @@ + + diff --git a/resources/views/modals/upload-file.blade.php b/resources/views/modals/upload-file.blade.php index f87e3e4962..09c53751ce 100644 --- a/resources/views/modals/upload-file.blade.php +++ b/resources/views/modals/upload-file.blade.php @@ -4,7 +4,7 @@
- + {{ trans('general.min_amt_help') }} diff --git a/resources/views/partials/forms/edit/permissions-base.blade.php b/resources/views/partials/forms/edit/permissions-base.blade.php index a702c619ae..a6a6abf9e0 100644 --- a/resources/views/partials/forms/edit/permissions-base.blade.php +++ b/resources/views/partials/forms/edit/permissions-base.blade.php @@ -4,7 +4,7 @@ @@ -76,7 +76,7 @@ @if ($permission['display']) diff --git a/resources/views/users/bulk-edit.blade.php b/resources/views/users/bulk-edit.blade.php index 10ae6261d0..bdc1ad9289 100644 --- a/resources/views/users/bulk-edit.blade.php +++ b/resources/views/users/bulk-edit.blade.php @@ -119,6 +119,29 @@
+ +
+
+ {{ trans('general.autoassign_licenses') }} +
+
+ + + + + +
+
+
diff --git a/resources/views/users/edit.blade.php b/resources/views/users/edit.blade.php index a94f0734b7..34005e9bc7 100755 --- a/resources/views/users/edit.blade.php +++ b/resources/views/users/edit.blade.php @@ -370,6 +370,20 @@
+ + +
+
+ + + +

{{ trans('general.autoassign_licenses_help_long') }}

+
+
+
@@ -383,15 +397,6 @@
- -
-
- -
-
@include ('partials.forms.edit.location-select', ['translated_name' => trans('general.location'), 'fieldname' => 'location_id']) @@ -444,8 +449,8 @@
-
- {!! Form::countries('country', old('country', $user->country), 'col-md-6 select2') !!} +
+ {!! Form::countries('country', old('country', $user->country), 'col-md-12 select2') !!} {!! $errors->first('country', '') !!}
diff --git a/resources/views/users/view.blade.php b/resources/views/users/view.blade.php index a130d1629d..47d6dea328 100755 --- a/resources/views/users/view.blade.php +++ b/resources/views/users/view.blade.php @@ -122,7 +122,8 @@ @endcan @can('update', \App\Models\User::class) -
  • +
  • + @@ -519,23 +520,23 @@
  • @endif - +
    {{ trans('admin/users/general.vip_label') }}
    - {!! ($user->vip=='1') ? ' '.trans('general.yes') : ' '.trans('general.no') !!} + {!! ($user->vip=='1') ? ' '.trans('general.yes') : ' '.trans('general.no') !!}
    - +
    {{ trans('admin/users/general.remote') }}
    - {!! ($user->remote=='1') ? ' '.trans('general.yes') : ' '.trans('general.no') !!} + {!! ($user->remote=='1') ? ' '.trans('general.yes') : ' '.trans('general.no') !!}
    @@ -545,17 +546,28 @@ {{ trans('general.login_enabled') }}
    - {!! ($user->activated=='1') ? ' '.trans('general.yes') : ' '.trans('general.no') !!} + {!! ($user->activated=='1') ? ' '.trans('general.yes') : ' '.trans('general.no') !!}
    - + +
    +
    + {{ trans('general.autoassign_licenses') }} +
    +
    + {!! ($user->autoassign_licenses=='1') ? ' '.trans('general.yes') : ' '.trans('general.no') !!} +
    +
    + + +
    LDAP
    - {!! ($user->ldap_import=='1') ? ' '.trans('general.yes') : ' '.trans('general.no') !!} + {!! ($user->ldap_import=='1') ? ' '.trans('general.yes') : ' '.trans('general.no') !!}
    @@ -569,7 +581,7 @@
    - {!! ($user->two_factor_active()) ? ' '.trans('general.yes') : ' '.trans('general.no') !!} + {!! ($user->two_factor_active()) ? ' '.trans('general.yes') : ' '.trans('general.no') !!}
    @@ -580,7 +592,7 @@ {{ trans('admin/users/general.two_factor_enrolled') }}
    - {!! ($user->two_factor_active_and_enrolled()) ? ' '.trans('general.yes') : ' '.trans('general.no') !!} + {!! ($user->two_factor_active_and_enrolled()) ? ' '.trans('general.yes') : ' '.trans('general.no') !!}
    @@ -590,11 +602,11 @@
    - +
    -
    +
    - + {{ trans('admin/settings/general.two_factor_reset') }} @@ -1031,9 +1043,9 @@ $(function () { dataType: 'json', success: function (data) { - $("#two_factor_reset_toggle").html('').html(' {{ trans('general.no') }}'); + $("#two_factor_reset_toggle").html('').html(' {{ trans('general.no') }}'); $("#two_factor_reseticon").html(''); - $("#two_factor_resetstatus").html('' + data.message); + $("#two_factor_resetstatus").html(' ' + data.message + ''); }, diff --git a/routes/web/licenses.php b/routes/web/licenses.php index ebcb5a2b2b..b70347793c 100644 --- a/routes/web/licenses.php +++ b/routes/web/licenses.php @@ -25,10 +25,21 @@ Route::group(['prefix' => 'licenses', 'middleware' => ['auth']], function () { [Licenses\LicenseCheckinController::class, 'store'] )->name('licenses.checkin.save'); + Route::post( + '{licenseId}/bulkcheckin', + [Licenses\LicenseCheckinController::class, 'bulkCheckin'] + )->name('licenses.bulkcheckin'); + + Route::post( + '{licenseId}/bulkcheckout', + [Licenses\LicenseCheckoutController::class, 'bulkCheckout'] + )->name('licenses.bulkcheckout'); + Route::post( '{licenseId}/upload', [Licenses\LicenseFilesController::class, 'store'] )->name('upload/license'); + Route::delete( '{licenseId}/deletefile/{fileId}', [Licenses\LicenseFilesController::class, 'destroy']