diff --git a/app/Console/Commands/CreateAdmin.php b/app/Console/Commands/CreateAdmin.php index 5aebde377..114f92dae 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 7c63bb925..dc444ec9e 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 257722b00..50e20c798 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 6f2ae003c..a71049769 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 a0467654c..a3607c181 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 67ecae542..a2d3d496d 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 7e95484f6..b83953365 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 3c389a1b1..8df6b89f1 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 9447d6545..867a88461 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 bcbc632eb..9f2c1c5f4 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 ff69d5f66..162b3d662 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 d60d3c42f..fa00fbad2 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 df9780091..44bffe156 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 1e8784f2f..5a44bf52a 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 b5eefdf81..fbb41a4d5 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 25a536ec5..0187d076a 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 cb51b28a4..1b9d9b623 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 d2435d7db..0ad851118 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 f5948e484..cb95b3762 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 e33f681f6..ccd3f8653 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 98b1c5281..9eb43d35a 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 21260ae4b..e48ab859b 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 000000000..135a9799e --- /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 f87e3e496..09c53751c 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 a702c619a..a6a6abf9e 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 10ae6261d..bdc1ad928 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 a94f0734b..34005e9bc 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 a130d1629..47d6dea32 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 ebcb5a2b2..b70347793 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']