diff --git a/app/Http/Controllers/Api/ImportController.php b/app/Http/Controllers/Api/ImportController.php index d8d550501e..464dee1e1b 100644 --- a/app/Http/Controllers/Api/ImportController.php +++ b/app/Http/Controllers/Api/ImportController.php @@ -25,7 +25,7 @@ class ImportController extends Controller */ public function index() { - // + $this->authorize('import'); $imports = Import::latest()->get(); return (new ImportsTransformer)->transformImports($imports); @@ -39,10 +39,8 @@ class ImportController extends Controller */ public function store() { - // - if (!Company::isCurrentUserAuthorized()) { - return redirect()->route('hardware.index')->with('error', trans('general.insufficient_permissions')); - } elseif (!config('app.lock_passwords')) { + $this->authorize('import'); + if (!config('app.lock_passwords')) { $files = Input::file('files'); $path = config('app.private_uploads').'/imports'; $results = []; @@ -119,7 +117,7 @@ class ImportController extends Controller */ public function process(ItemImportRequest $request, $import_id) { - $this->authorize('create', Asset::class); + $this->authorize('import'); // Run a backup immediately before processing Artisan::call('backup:run'); $errors = $request->import(Import::find($import_id)); @@ -162,7 +160,7 @@ class ImportController extends Controller */ public function destroy($import_id) { - $this->authorize('create', Asset::class); + $this->authorize('import'); $import = Import::find($import_id); try { unlink(config('app.private_uploads').'/imports/'.$import->file_path); diff --git a/app/Http/Controllers/Api/UsersController.php b/app/Http/Controllers/Api/UsersController.php index e91ae8f676..82fd0a0195 100644 --- a/app/Http/Controllers/Api/UsersController.php +++ b/app/Http/Controllers/Api/UsersController.php @@ -52,6 +52,7 @@ class UsersController extends Controller 'users.phone', 'users.state', 'users.two_factor_enrolled', + 'users.two_factor_optin', 'users.updated_at', 'users.username', 'users.zip', diff --git a/app/Http/Controllers/ImportsController.php b/app/Http/Controllers/ImportsController.php index 1331b7dd86..c3bd66245a 100644 --- a/app/Http/Controllers/ImportsController.php +++ b/app/Http/Controllers/ImportsController.php @@ -12,7 +12,7 @@ class ImportsController extends Controller { public function index() { - $this->authorize('create', Asset::class); + $this->authorize('import'); $imports = Import::latest()->get(); $imports = (new ImportsTransformer)->transformImports($imports); return view('importer/import')->with('imports', $imports); diff --git a/app/Http/Transformers/UsersTransformer.php b/app/Http/Transformers/UsersTransformer.php index 569b3b56af..49755db7dc 100644 --- a/app/Http/Transformers/UsersTransformer.php +++ b/app/Http/Transformers/UsersTransformer.php @@ -53,6 +53,8 @@ class UsersTransformer 'permissions' => $user->decodePermissions(), 'activated' => ($user->activated =='1') ? true : false, 'two_factor_activated' => ($user->two_factor_active()) ? true : false, + 'two_factor_enrolled' => ($user->two_factor_active_and_enrolled()) ? true : false, + 'assets_count' => (int) $user->assets_count, 'licenses_count' => (int) $user->licenses_count, 'accessories_count' => (int) $user->accessories_count, diff --git a/app/Models/User.php b/app/Models/User.php index 15e29657d7..edc5883ef1 100755 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -389,7 +389,11 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo } /** - * Check whether two-factor authorization is required and the user has activated it + * Check whether two-factor authorization is requiredfor this user + * + * 0 = 2FA disabled + * 1 = 2FA optional + * 2 = 2FA universally required * * @author [A. Gianotto] [] * @since [v4.0] @@ -398,10 +402,45 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo */ public function two_factor_active () { - if (Setting::getSettings()->two_factor_enabled !='0') { - if (($this->two_factor_optin =='1') && ($this->two_factor_enrolled)) { - return true; - } + // If the 2FA is optional and the user has opted in + if ((Setting::getSettings()->two_factor_enabled =='1') && ($this->two_factor_optin =='1')) + { + return true; + } + // If the 2FA is required for everyone so is implicitly active + elseif (Setting::getSettings()->two_factor_enabled =='2') + { + return true; + } + + return false; + + } + + /** + * Check whether two-factor authorization is required and the user has activated it + * and enrolled a device + * + * 0 = 2FA disabled + * 1 = 2FA optional + * 2 = 2FA universally required + * + * @author [A. Gianotto] [] + * @since [v4.6.14] + * + * @return bool + */ + public function two_factor_active_and_enrolled () { + + // If the 2FA is optional and the user has opted in and is enrolled + if ((Setting::getSettings()->two_factor_enabled =='1') && ($this->two_factor_optin =='1') && ($this->two_factor_enrolled =='1')) + { + return true; + } + // If the 2FA is required for everyone and the user has enrolled + elseif ((Setting::getSettings()->two_factor_enabled =='2') && ($this->two_factor_enrolled)) + { + return true; } return false; diff --git a/app/Policies/SnipePermissionsPolicy.php b/app/Policies/SnipePermissionsPolicy.php index b8d4501bdf..e17f4f68e5 100644 --- a/app/Policies/SnipePermissionsPolicy.php +++ b/app/Policies/SnipePermissionsPolicy.php @@ -53,7 +53,7 @@ abstract class SnipePermissionsPolicy /** * Determine whether the user can view the accessory. * - * @param \App\User $user + * @param \App\Models\User $user * @return mixed */ public function view(User $user, $item = null) @@ -64,7 +64,7 @@ abstract class SnipePermissionsPolicy /** * Determine whether the user can create accessories. * - * @param \App\User $user + * @param \App\Models\User $user * @return mixed */ public function create(User $user) @@ -75,7 +75,7 @@ abstract class SnipePermissionsPolicy /** * Determine whether the user can update the accessory. * - * @param \App\User $user + * @param \App\Models\User $user * @return mixed */ public function update(User $user, $item = null) @@ -86,7 +86,7 @@ abstract class SnipePermissionsPolicy /** * Determine whether the user can delete the accessory. * - * @param \App\User $user + * @param \App\Models\User $user * @return mixed */ public function delete(User $user, $item = null) @@ -97,11 +97,13 @@ abstract class SnipePermissionsPolicy /** * Determine whether the user can manage the accessory. * - * @param \App\User $user + * @param \App\Models\User $user * @return mixed */ public function manage(User $user, $item = null) { return $user->hasAccess($this->columnName().'.edit'); } + + } diff --git a/app/Presenters/UserPresenter.php b/app/Presenters/UserPresenter.php index 0d49852263..aa5d3f268c 100644 --- a/app/Presenters/UserPresenter.php +++ b/app/Presenters/UserPresenter.php @@ -226,14 +226,14 @@ class UserPresenter extends Presenter [ "field" => "two_factor_enrolled", "searchable" => false, - "sortable" => false, + "sortable" => true, "switchable" => true, "title" => trans('admin/users/general.two_factor_enrolled'), "visible" => false, 'formatter' => 'trueFalseFormatter' ], [ - "field" => "two_factor_active", + "field" => "two_factor_activated", "searchable" => false, "sortable" => false, "switchable" => true, @@ -246,7 +246,7 @@ class UserPresenter extends Presenter "searchable" => false, "sortable" => true, "switchable" => true, - "title" => trans('general.activated'), + "title" => trans('general.login_enabled'), "visible" => true, 'formatter' => 'trueFalseFormatter' ], diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index bff39fbf18..2c8e07e518 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -113,6 +113,14 @@ class AuthServiceProvider extends ServiceProvider }); + // Can the user import CSVs? + Gate::define('import', function ($user) { + if ($user->hasAccess('import') ) { + return true; + } + }); + + # ----------------------------------------- # Reports # ----------------------------------------- diff --git a/config/permissions.php b/config/permissions.php index 2950391808..7ffa69e491 100644 --- a/config/permissions.php +++ b/config/permissions.php @@ -27,6 +27,15 @@ return array( ) ), + 'CSV Import' => array( + array( + 'permission' => 'import', + 'label' => '', + 'note' => 'This will allow users to import even if access to users, assets, etc is denied elsewhere.', + 'display' => true, + ) + ), + 'Reports' => array( array( 'permission' => 'reports.view', diff --git a/resources/lang/en/general.php b/resources/lang/en/general.php index ea339cf9a7..ae2bcf0a44 100644 --- a/resources/lang/en/general.php +++ b/resources/lang/en/general.php @@ -221,4 +221,5 @@ 'zip' => 'Zip', 'noimage' => 'No image uploaded or image not found.', 'token_expired' => 'Your form session has expired. Please try again.', + 'login_enabled' => 'Login Enabled', ]; diff --git a/resources/views/layouts/default.blade.php b/resources/views/layouts/default.blade.php index 196b085bbc..03f3037447 100644 --- a/resources/views/layouts/default.blade.php +++ b/resources/views/layouts/default.blade.php @@ -520,7 +520,7 @@ @endcan - @can('create', \App\Models\Asset::class) + @can('import') diff --git a/resources/views/users/view.blade.php b/resources/views/users/view.blade.php index 0a79aa27f1..5c87eb361c 100755 --- a/resources/views/users/view.blade.php +++ b/resources/views/users/view.blade.php @@ -127,22 +127,22 @@ @if (!is_null($user->company)) - + @endif - + - + - + - + @endif @if ($user->employee_num) - + @endif @if ($user->manager) - + - + @endif @if ($user->phone) - + @endif @if ($user->userloc) - + @@ -210,14 +210,14 @@ @endif @if ($user->last_login) - + @endif @if (!is_null($user->department)) - + @endif @@ -227,6 +227,45 @@ @endif + + + + + + @if ($user->activated=='1') + + + + + + + + + + @endif + +
{{ trans('general.company') }}{{ trans('general.company') }} {{ $user->company->name }}
{{ trans('admin/users/table.name') }}{{ trans('admin/users/table.name') }} {{ $user->present()->fullName() }}
{{ trans('admin/users/table.username') }}{{ trans('admin/users/table.username') }} {{ $user->username }}
{{ trans('general.groups') }}{{ trans('general.groups') }} @if ($user->groups->count() > 0) @foreach ($user->groups as $group) @@ -164,21 +164,21 @@ @if ($user->jobtitle)
{{ trans('admin/users/table.job') }}{{ trans('admin/users/table.job') }} {{ $user->jobtitle }}
{{ trans('admin/users/table.employee_num') }}{{ trans('admin/users/table.employee_num') }} {{ $user->employee_num }}
{{ trans('admin/users/table.manager') }}{{ trans('admin/users/table.manager') }} {{ $user->manager->getFullNameAttribute() }} @@ -188,21 +188,21 @@ @if ($user->email)
{{ trans('admin/users/table.email') }}{{ trans('admin/users/table.email') }} {{ $user->email }}
{{ trans('admin/users/table.phone') }}{{ trans('admin/users/table.phone') }} {{ $user->phone }}
{{ trans('admin/users/table.location') }}{{ trans('admin/users/table.location') }} {{ link_to_route('locations.show', $user->userloc->name, [$user->userloc->id]) }}
{{ trans('general.last_login') }}{{ trans('general.last_login') }} {{ \App\Helpers\Helper::getFormattedDateObject($user->last_login, 'datetime', false) }}
{{ trans('general.department') }}{{ trans('general.department') }} {{ $user->department->name }}
{{ $user->created_at->format('F j, Y h:iA') }}
{{ trans('general.login_enabled') }}{{ ($user->activated=='1') ? trans('general.yes') : trans('general.no') }}
{{ trans('admin/users/general.two_factor_active') }}{{ ($user->two_factor_active()) ? trans('general.yes') : trans('general.no') }}
{{ trans('admin/users/general.two_factor_enrolled') }} +
+
+ {{ ($user->two_factor_active_and_enrolled()) ? trans('general.yes') : trans('general.no') }} +
+ + @if ((Auth::user()->isSuperUser()) && ($snipeSettings->two_factor_enabled!='0')) +
+ {{ trans('admin/settings/general.two_factor_reset') }} + + + + + + + +

{{ trans('admin/settings/general.two_factor_reset_help') }}

+
+
+ @endif + +
@@ -542,6 +581,40 @@ @include ('partials.bootstrap-table', ['simple_view' => true])