diff --git a/.env.dusk.testing b/.env.dusk.testing index 50cb7aa4c4..9308ad4b7d 100644 --- a/.env.dusk.testing +++ b/.env.dusk.testing @@ -2,4 +2,3 @@ APP_URL=http://localhost:8000 APP_KEY=base64:FSjpEaK3F9HnO40orj7FlbRI0loi1vtB3dVBcB9XaDk= APP_ENV=testing APP_DEBUG=true -#DB_CONNECTION=memory diff --git a/.travis.yml b/.travis.yml index cc4e02119b..b7d238c9ae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ matrix: - php: 7.3 env: SKIP_STYLE_CHECK=1 - php: 7.2 - env: SKIP_UNIT_CHECK=1 BROWSER_TEST=1 + env: SKIP_UNIT_CHECK=1 BROWSER_TEST=1 CHROME_HEADLESS=1 - php: 7.1 env: SKIP_STYLE_CHECK=1 EXECUTE_BUILD_DOCS=true diff --git a/app/Console/Commands/AddUserCommand.php b/app/Console/Commands/AddUserCommand.php index 6bd1b9a8e6..ee644b955c 100644 --- a/app/Console/Commands/AddUserCommand.php +++ b/app/Console/Commands/AddUserCommand.php @@ -28,6 +28,7 @@ namespace App\Console\Commands; use App\Console\LnmsCommand; use App\Models\User; use Illuminate\Validation\Rule; +use LibreNMS\Authentication\LegacyAuth; use LibreNMS\Config; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; @@ -87,14 +88,18 @@ class AddUserCommand extends LnmsCommand $user = new User([ 'username' => $this->argument('username'), 'level' => $roles[$this->option('role')], - 'descr' => (string)$this->option('descr'), - 'email' => (string)$this->option('email'), - 'realname' => (string)$this->option('full-name'), + 'descr' => $this->option('descr'), + 'email' => $this->option('email'), + 'realname' => $this->option('full-name'), 'auth_type' => 'mysql', ]); + $user->setPassword($password); $user->save(); + $user->auth_id = LegacyAuth::get()->getUserid($user->username) ?: $user->user_id; + $user->save(); + $this->info(__('commands.user:add.success', ['username' => $user->username])); return 0; } diff --git a/app/Http/Controllers/TwoFactorController.php b/app/Http/Controllers/Auth/TwoFactorController.php similarity index 81% rename from app/Http/Controllers/TwoFactorController.php rename to app/Http/Controllers/Auth/TwoFactorController.php index 7963db2688..53f1a02888 100644 --- a/app/Http/Controllers/TwoFactorController.php +++ b/app/Http/Controllers/Auth/TwoFactorController.php @@ -1,7 +1,31 @@ . + * + * @package LibreNMS + * @link http://librenms.org + * @copyright 2018 Tony Murray + * @author Tony Murray + */ -namespace App\Http\Controllers; +namespace App\Http\Controllers\Auth; +use App\Http\Controllers\Controller; use App\Models\User; use App\Models\UserPref; use Illuminate\Http\Request; @@ -72,6 +96,7 @@ class TwoFactorController extends Controller /** * Show the form for creating a new resource. * + * @param Request $request * @return \Illuminate\Http\Response */ public function create(Request $request) @@ -80,14 +105,14 @@ class TwoFactorController extends Controller 'twofactor' => Rule::in('time', 'counter') ]); - $key = \LibreNMS\Authentication\TwoFactor::genKey(); + $key = TwoFactor::genKey(); // assume time based $settings = [ 'key' => $key, 'fails' => 0, 'last' => 0, - 'counter' => $request->get('twofactor') == 'counter' ? 0 : false, + 'counter' => $request->get('twofactortype') == 'counter' ? 0 : false, ]; Session::put('twofactoradd', $settings); @@ -95,11 +120,10 @@ class TwoFactorController extends Controller return redirect()->intended(); } - /** * Remove the specified resource from storage. * - * @param int $id + * @param Request $request * @return \Illuminate\Http\Response */ public function destroy(Request $request) @@ -113,7 +137,7 @@ class TwoFactorController extends Controller /** * Remove the specified resource from storage. * - * @param int $id + * @param Request $request * @return \Illuminate\Http\Response */ public function cancelAdd(Request $request) @@ -126,8 +150,8 @@ class TwoFactorController extends Controller /** * @param User $user * @param string $token + * @return true * @throws AuthenticationException - * return true */ private function checkToken($user, $token) { @@ -182,7 +206,7 @@ class TwoFactorController extends Controller private function loadSettings($user) { if (Session::has('twofactoradd')) { - return Session::get('twofactoradd'); + return Session::get('twofactoradd'); } return UserPref::getPref($user, 'twofactor'); @@ -190,7 +214,7 @@ class TwoFactorController extends Controller private function genUri($user, $settings) { - $title = urlencode("Librenms:" . $user->username); + $title = "LibreNMS:" . urlencode($user->username); $key = $settings['key']; // time based diff --git a/app/Http/Controllers/Auth/TwoFactorManagementController.php b/app/Http/Controllers/Auth/TwoFactorManagementController.php new file mode 100644 index 0000000000..b2d3e28108 --- /dev/null +++ b/app/Http/Controllers/Auth/TwoFactorManagementController.php @@ -0,0 +1,55 @@ +. + * + * @package LibreNMS + * @link http://librenms.org + * @copyright 2018 Tony Murray + * @author Tony Murray + */ + +namespace App\Http\Controllers\Auth; + +use App\Http\Controllers\Controller; +use App\Http\Requests\TwoFactorManagementRequest; +use App\Models\User; +use App\Models\UserPref; + +class TwoFactorManagementController extends Controller +{ + public function unlock(TwoFactorManagementRequest $request, User $user) + { + $twofactor = UserPref::getPref($user, 'twofactor'); + $twofactor['fails'] = 0; + + if (UserPref::setPref($user, 'twofactor', $twofactor)) { + return response()->json(['msg' => __('Two-Factor unlocked.')]); + } + + return response()->json(['error' => __("Failed to unlock Two-Factor.")]); + } + + public function destroy(TwoFactorManagementRequest $request, User $user) + { + if (UserPref::forgetPref($user, 'twofactor')) { + return response()->json(['msg' => __('Two-Factor removed.')]); + } + + return response()->json(['error' => __("Failed to remove Two-Factor.")]); + } +} diff --git a/app/Http/Controllers/Select/DeviceController.php b/app/Http/Controllers/Select/DeviceController.php index 5290970c35..0800c3c28e 100644 --- a/app/Http/Controllers/Select/DeviceController.php +++ b/app/Http/Controllers/Select/DeviceController.php @@ -34,6 +34,8 @@ class DeviceController extends SelectController protected function rules() { return [ + 'access' => 'nullable|in:normal,inverted', + 'user' => 'nullable|int', 'id' => 'nullable|in:device_id,hostname' ]; } @@ -46,6 +48,19 @@ class DeviceController extends SelectController protected function baseQuery($request) { $this->id = $request->get('id', 'device_id'); + $user_id = $request->get('user'); + + // list devices the user does not have access to + if ($request->get('access') == 'inverted' && $user_id && $request->user()->isAdmin()) { + return Device::query() + ->select('device_id', 'hostname', 'sysName') + ->whereNotIn('device_id', function ($query) use ($user_id) { + $query->select('device_id') + ->from('devices_perms') + ->where('user_id', $user_id); + }) + ->orderBy('hostname'); + } return Device::hasAccess($request->user()) ->select('device_id', 'hostname', 'sysName') diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php new file mode 100644 index 0000000000..9dcaa53135 --- /dev/null +++ b/app/Http/Controllers/UserController.php @@ -0,0 +1,213 @@ +. + * + * @package LibreNMS + * @link http://librenms.org + * @copyright 2018 Tony Murray + * @author Tony Murray + */ + +namespace App\Http\Controllers; + +use App\Http\Requests\StoreUserRequest; +use App\Http\Requests\UpdateUserRequest; +use App\Models\Dashboard; +use App\Models\User; +use App\Models\UserPref; +use Hash; +use Illuminate\Http\Request; +use Illuminate\Validation\Rule; +use LibreNMS\Authentication\LegacyAuth; +use LibreNMS\Config; +use Toastr; + +class UserController extends Controller +{ + /** + * Display a listing of the resource. + * + * @return \Illuminate\Http\Response + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function index() + { + $this->authorize('manage', User::class); + + return view('user.index', [ + 'users' => User::orderBy('username')->get(), + 'multiauth' => User::query()->distinct('auth_type')->count('auth_type') > 1, + ]); + } + + /** + * Show the form for creating a new resource. + * + * @return \Illuminate\Http\Response + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function create() + { + $this->authorize('create', User::class); + + $tmp_user = new User; + $tmp_user->can_modify_passwd = LegacyAuth::get()->canUpdatePasswords(); // default to true for new users + return view('user.create', [ + 'user' => $tmp_user, + 'dashboard' => null, + 'dashboards' => Dashboard::allAvailable($tmp_user)->get(), + ]); + } + + /** + * Store a newly created resource in storage. + * + * @param StoreUserRequest $request + * @return \Illuminate\Http\Response + */ + public function store(StoreUserRequest $request) + { + $user = $request->only(['username', 'realname', 'email', 'descr', 'level', 'can_modify_passwd']); + $user['auth_type'] = LegacyAuth::getType(); + $user['can_modify_passwd'] = $request->get('can_modify_passwd'); // checkboxes are missing when unchecked + + $user = User::create($user); + + $user->setPassword($request->new_password); + $user->auth_id = LegacyAuth::get()->getUserid($user->username) ?: $user->user_id; + $this->updateDashboard($user, $request->get('dashboard')); + + if ($user->save()) { + Toastr::success(__('User :username created', ['username', $user->username])); + return redirect(route('users.index')); + } + + Toastr::error(__('Failed to create user')); + return redirect()->back(); + } + + /** + * Display the specified resource. + * + * @param User $user + * @return \Illuminate\Http\Response + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function show(User $user) + { + $this->authorize('view', $user); + + return $user->username; + } + + /** + * Show the form for editing the specified resource. + * + * @param User $user + * @return \Illuminate\Http\Response + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function edit(User $user) + { + $this->authorize('update', $user); + + $data = [ + 'user' => $user, + 'dashboard' => UserPref::getPref($user, 'dashboard'), + 'dashboards' => Dashboard::allAvailable($user)->get(), + ]; + + if (Config::get('twofactor')) { + $lockout_time = Config::get('twofactor_lock'); + $twofactor = UserPref::getPref($user, 'twofactor'); + $data['twofactor_enabled'] = isset($twofactor['key']); + + // if enabled and 3 or more failures + $last_failure = isset($twofactor['last']) ? (time() - $twofactor['last']) : 0; + $data['twofactor_locked'] = isset($twofactor['fails']) && $twofactor['fails'] >= 3 && (!$lockout_time || $last_failure < $lockout_time); + } + + return view('user.edit', $data); + } + + /** + * Update the specified resource in storage. + * + * @param UpdateUserRequest $request + * @param User $user + * @return \Illuminate\Http\Response + */ + public function update(UpdateUserRequest $request, User $user) + { + if ($request->get('new_password') && $user->canSetPassword($request->user())) { + $user->setPassword($request->new_password); + } + + $user->fill($request->all()); + $user->can_modify_passwd = $request->get('can_modify_passwd'); // checkboxes are missing when unchecked + + if ($this->updateDashboard($user, $request->get('dashboard'))) { + Toastr::success(__('Updated dashboard for :username', ['username' => $user->username])); + } + + if ($user->isDirty()) { + if ($user->save()) { + Toastr::success(__('User :username updated', ['username' => $user->username])); + } else { + Toastr::error(__('Failed to update user :username', ['username' => $user->username])); + return redirect()->back(); + } + } + + return redirect(route('users.index')); + } + + /** + * Remove the specified resource from storage. + * + * @param User $user + * @return \Illuminate\Http\Response + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function destroy(User $user) + { + $this->authorize('delete', $user); + + $user->delete(); + + return response()->json(__('User :username deleted.', ['username' => $user->username])); + } + + /** + * @param User $user + * @param $dashboard + * @return bool + */ + protected function updateDashboard(User $user, $dashboard) + { + if ($dashboard) { + $existing = UserPref::getPref($user, 'dashboard'); + if ($dashboard != $existing) { + UserPref::setPref($user, 'dashboard', $dashboard); + return true; + } + } + + return false; + } +} diff --git a/app/Http/Requests/StoreUserRequest.php b/app/Http/Requests/StoreUserRequest.php new file mode 100644 index 0000000000..cd2cc24015 --- /dev/null +++ b/app/Http/Requests/StoreUserRequest.php @@ -0,0 +1,45 @@ +user()->can('create', User::class); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + 'username' => [ + 'required', + 'alpha_dash', + 'max:255', + Rule::unique('users', 'username')->where('auth_type', LegacyAuth::getType()), + ], + 'realname' => 'max:64', + 'email' => 'nullable|email|max:64', + 'descr' => 'max:30', + 'level' => 'int', + 'new_password' => 'required|confirmed|min:' . Config::get('password.min_length', 8), + 'dashboard' => 'int', + ]; + } +} diff --git a/app/Http/Requests/TwoFactorManagementRequest.php b/app/Http/Requests/TwoFactorManagementRequest.php new file mode 100644 index 0000000000..4833fe2992 --- /dev/null +++ b/app/Http/Requests/TwoFactorManagementRequest.php @@ -0,0 +1,45 @@ +. + * + * @package LibreNMS + * @link http://librenms.org + * @copyright 2018 Tony Murray + * @author Tony Murray + */ + +namespace App\Http\Requests; + +use Illuminate\Foundation\Http\FormRequest; + +class TwoFactorManagementRequest extends FormRequest +{ + public function rules() + { + return []; + } + + public function authorize() + { + $user = $this->route()->parameter('user'); + $auth_user = auth()->user(); + + // don't allow admins to bypass security for themselves + return $auth_user->isAdmin() && !$user->is($auth_user); + } +} diff --git a/app/Http/Requests/UpdateUserRequest.php b/app/Http/Requests/UpdateUserRequest.php new file mode 100644 index 0000000000..8a557f3750 --- /dev/null +++ b/app/Http/Requests/UpdateUserRequest.php @@ -0,0 +1,74 @@ +user()->isAdmin()) { + return true; + } + + $user = $this->route('user'); + if ($user && $this->user()->can('update', $user)) { + // normal users cannot edit their level or ability to modify a password + unset($this['level'], $this['can_modify_passwd']); + return true; + } + + return false; + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + 'realname' => 'max:64', + 'email' => 'nullable|email|max:64', + 'descr' => 'max:30', + 'level' => 'int', + 'old_password' => 'nullable|string', + 'new_password' => 'nullable|confirmed|min:' . Config::get('password.min_length', 8), + 'dashboard' => 'int', + ]; + } + + /** + * Configure the validator instance. + * + * @param \Illuminate\Validation\Validator $validator + * @return void + */ + public function withValidator($validator) + { + $validator->after(function ($validator) { + // if not an admin and new_password is set, check old password matches + if (!$this->user()->isAdmin()) { + if ($this->has('new_password')) { + if ($this->has('old_password')) { + $user = $this->route('user'); + if ($user && !Hash::check($this->old_password, $user->password)) { + $validator->errors()->add('old_password', __('Existing password did not match')); + } + } else { + $validator->errors()->add('old_password', __('The :attribute field is required.', ['attribute' => 'old_password'])); + } + } + } + }); + } +} diff --git a/app/Jobs/PingCheck.php b/app/Jobs/PingCheck.php index bc9e9eea1b..4ed81ba47d 100644 --- a/app/Jobs/PingCheck.php +++ b/app/Jobs/PingCheck.php @@ -244,20 +244,16 @@ class PingCheck implements ShouldQueue $device->last_ping = Carbon::now(); $device->last_ping_timetaken = isset($data['rtt']) ? $data['rtt'] : 0; - if ($changed = $device->isDirty('status')) { + if ($device->isDirty('status')) { // if changed, update reason $device->status_reason = $device->status ? '' : 'icmp'; $type = $device->status ? 'up' : 'down'; - log_event('Device status changed to ' . ucfirst($type) . " from icmp check.", $device->toArray(), $type); + echo "Device $device->hostname changed status to $type, running alerts\n"; - } - - $device->save(); - - if ($changed) { RunRules($device->device_id); } + $device->save(); // only saves if needed (which is every time because of last_ping) // add data to rrd data_update($device->toArray(), 'ping-perf', $this->rrd_tags, ['ping' => $device->last_ping_timetaken]); diff --git a/app/Models/User.php b/app/Models/User.php index b70c83d565..afaf25c04b 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -19,12 +19,18 @@ class User extends Authenticatable 'descr' => '', 'realname' => '', 'email' => '', - 'can_modify_passwd' => 0, ]; protected $dispatchesEvents = [ 'created' => UserCreated::class, ]; + protected $casts = [ + 'realname' => 'string', + 'descr' => 'string', + 'email' => 'string', + 'can_modify_passwd' => 'integer', + ]; + // ---- Helper Functions ---- /** @@ -90,6 +96,25 @@ class User extends Authenticatable $this->attributes['password'] = $password ? password_hash($password, PASSWORD_DEFAULT) : null; } + /** + * Check if the given user can set the password for this user + * + * @param User $user + * @return bool + */ + public function canSetPassword($user) + { + if ($user && LegacyAuth::get()->canUpdatePasswords()) { + if ($user->isAdmin()) { + return true; + } + + return $user->is($this) && $this->can_modify_passwd; + } + + return false; + } + // ---- Query scopes ---- /** @@ -111,13 +136,33 @@ class User extends Authenticatable }); } + // ---- Accessors/Mutators ---- + + public function setRealnameAttribute($realname) + { + $this->attributes['realname'] = (string)$realname; + } + + public function setDescrAttribute($descr) + { + $this->attributes['descr'] = (string)$descr; + } + + public function setEmailAttribute($email) + { + $this->attributes['email'] = (string)$email; + } + + public function setCanModifyPasswdAttribute($modify) + { + $this->attributes['can_modify_passwd'] = $modify ? 1 : 0; + } + // ---- Define Relationships ---- public function devices() { if ($this->hasGlobalRead()) { -// $instance = $this->newRelatedInstance('App\Models\Device'); -// return new HasAll($instance); return Device::query(); } else { return $this->belongsToMany('App\Models\Device', 'devices_perms', 'user_id', 'device_id'); diff --git a/app/Policies/UserPolicy.php b/app/Policies/UserPolicy.php new file mode 100644 index 0000000000..d4799c6d34 --- /dev/null +++ b/app/Policies/UserPolicy.php @@ -0,0 +1,69 @@ +isAdmin(); + } + + /** + * Determine whether the user can view the user. + * + * @param \App\Models\User $user + * @param \App\Models\User $target + * @return bool + */ + public function view(User $user, User $target) + { + return $user->isAdmin() || $target->is($user); + } + + /** + * Determine whether the user can create users. + * + * @param \App\Models\User $user + * @return bool + */ + public function create(User $user) + { + return $user->isAdmin(); + } + + /** + * Determine whether the user can update the user. + * + * @param \App\Models\User $user + * @param \App\Models\User $target + * @return bool + */ + public function update(User $user, User $target) + { + return $user->isAdmin() || $target->is($user); + } + + /** + * Determine whether the user can delete the user. + * + * @param \App\Models\User $user + * @param \App\Models\User $target + * @return bool + */ + public function delete(User $user, User $target) + { + return $user->isAdmin(); + } +} diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index 4b68ea66a5..e32f71579f 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -2,7 +2,8 @@ namespace App\Providers; -use App\Providers\LegacyUserProvider; +use App\Models\User; +use App\Policies\UserPolicy; use App\Guards\ApiTokenGuard; use Auth; use Illuminate\Support\Facades\Gate; @@ -16,7 +17,7 @@ class AuthServiceProvider extends ServiceProvider * @var array */ protected $policies = [ - 'App\Model' => 'App\Policies\ModelPolicy', + User::class => UserPolicy::class ]; /** diff --git a/database/factories/ModelFactory.php b/database/factories/ModelFactory.php index 5d817b5a2d..a8024f8867 100644 --- a/database/factories/ModelFactory.php +++ b/database/factories/ModelFactory.php @@ -20,6 +20,7 @@ $factory->define(App\Models\User::class, function (Faker\Generator $faker) { static $password; return [ + 'auth_type' => 'mysql', 'username' => $faker->unique()->userName, 'realname' => $faker->name, 'email' => $faker->safeEmail, diff --git a/doc/Support/Configuration.md b/doc/Support/Configuration.md index 2ee69dc670..65ae0e90db 100644 --- a/doc/Support/Configuration.md +++ b/doc/Support/Configuration.md @@ -131,6 +131,13 @@ $config['unflatten'] = "/usr/bin/unflatten"; $config['neato'] = "/usr/bin/neato"; $config['sfdp'] = "/usr/bin/sfdp"; ``` +### Authentication + +Generic Authentication settings. + +```php +$config['password']['min_length'] = 8; // password minimum length for auth that allows user creation +``` ### Proxy support diff --git a/includes/html/pages/edituser.inc.php b/includes/html/pages/edituser.inc.php index 9bcec2198c..b19a73c2e3 100644 --- a/includes/html/pages/edituser.inc.php +++ b/includes/html/pages/edituser.inc.php @@ -19,7 +19,7 @@ if (! Auth::user()->hasGlobalAdmin()) { $user = User::find($vars['user_id']); $user_data = $user->toArray(); // for compatibility with current code - echo '

'.$user_data['realname']."

Change...

"; + echo '

'.$user_data['realname']."

"; // Perform actions if requested if ($vars['action'] == 'deldevperm') { if (dbFetchCell('SELECT COUNT(*) FROM devices_perms WHERE `device_id` = ? AND `user_id` = ?', array($vars['device_id'], $user_data['user_id']))) { @@ -246,238 +246,8 @@ if (! Auth::user()->hasGlobalAdmin()) { "; - } elseif ($vars['user_id'] && $vars['edit']) { - if (Auth::user()->isDemo()) { - demo_account(); - } else { - if (!empty($vars['new_level'])) { - if ($vars['can_modify_passwd'] == 'on') { - $vars['can_modify_passwd'] = '1'; - } - - LegacyAuth::get()->updateUser($vars['user_id'], $vars['new_realname'], $vars['new_level'], $vars['can_modify_passwd'], $vars['new_email']); - print_message('User has been updated'); - if (!empty($vars['new_pass1']) && $vars['new_pass1'] == $vars['new_pass2'] && LegacyAuth::get()->canUpdatePasswords($vars['cur_username'])) { - if (LegacyAuth::get()->changePassword($vars['cur_username'], $vars['new_pass1']) == 1) { - print_message("User password has been updated"); - } else { - print_error("Password couldn't be updated"); - } - } elseif (!empty($vars['new_pass1']) && $vars['new_pass1'] != $vars['new_pass2']) { - print_error("The supplied passwords didn't match so weren't updated"); - } - } - - $users_details = User::find($vars['user_id'])->toArray(); - if (!empty($users_details)) { - if (!empty($vars['dashboard']) && $vars['dashboard'] != $users_details['dashboard']) { - set_user_pref('dashboard', $vars['dashboard']); - print_message("User default dashboard updated"); - } - echo "
- - - -"; - if (LegacyAuth::get()->canUpdateUsers() == '1') { - if (empty($vars['new_realname'])) { - $vars['new_realname'] = $users_details['realname']; - } - - if (empty($vars['new_level'])) { - $vars['new_level'] = $users_details['level']; - } - - if (empty($vars['can_modify_passwd'])) { - $vars['can_modify_passwd'] = $users_details['can_modify_passwd']; - } elseif ($vars['can_modify_passwd'] == 'on') { - $vars['can_modify_passwd'] = '1'; - } - - if (empty($vars['new_email'])) { - $vars['new_email'] = $users_details['email']; - } - - echo " -
- -
- -
-
-
-
-
- -
- -
-
-
-
-
- -
- -
-
-
-
"; - - if (LegacyAuth::get()->canUpdatePasswords($users_details['username'])) { - echo " -
- -
- -
-
-
- -
- -
-
- "; - } - - echo "
-
-
- -
-
-
-
-
-"; - } - echo " -
- -
-
-
- -
"; - - if ($config['twofactor']) { - if ($vars['twofactorremove']) { - if (set_user_pref('twofactor', array(), $vars['user_id'])) { - echo "
TwoFactor credentials removed.
"; - } else { - echo "
Couldnt remove user's TwoFactor credentials.
"; - } - } - - if ($vars['twofactorunlock']) { - $twofactor = get_user_pref('twofactor', array(), $vars['user_id']); - $twofactor['fails'] = 0; - if (set_user_pref('twofactor', $twofactor, $vars['user_id'])) { - echo "
User unlocked.
"; - } else { - echo "
Couldnt reset user's TwoFactor failures.
"; - } - } - echo "

Two-Factor Authentication

"; - $twofactor = get_user_pref('twofactor', array(), $vars['user_id']); - if ($twofactor['fails'] >= 3 && (!$config['twofactor_lock'] || (time() - $twofactor['last']) < $config['twofactor_lock'])) { - echo "
- - -
- - - -
-
"; - } - - if ($twofactor['key']) { - echo "
- - - - -
-
"; - } else { - echo '

No TwoFactor key generated for this user, Nothing to do.

'; - } - }//end if - } else { - print_error('Error getting user details'); - }//end if !empty($users_details) - }//end if } else { - $userlist = User::thisAuth()->get(); - - echo '

Select a user to edit

'; - - echo "
- -
- -
- -
-
-
-
- / -
-
-
"; + echo ''; }//end if }//end if diff --git a/includes/html/pages/preferences.inc.php b/includes/html/pages/preferences.inc.php index c9c92059b4..642d4d2492 100644 --- a/includes/html/pages/preferences.inc.php +++ b/includes/html/pages/preferences.inc.php @@ -124,15 +124,15 @@ if (LegacyAuth::user()->isDemoUser()) {
-
-
- +
+
'; @@ -159,16 +159,16 @@ foreach (get_dashboards() as $dash) { echo " "; } -echo " +echo ' -
-
-
+ +
+
-"; +'; echo "

Add schedule notes to devices notes

diff --git a/includes/html/print-menubar.php b/includes/html/print-menubar.php index fb64ca82d5..45c73e5cf9 100644 --- a/includes/html/print-menubar.php +++ b/includes/html/print-menubar.php @@ -656,14 +656,8 @@ if (Auth::user()->hasGlobalAdmin()) { hasGlobalAdmin()) { - if (LegacyAuth::get()->canManageUsers()) { - echo(' -
  • Add User
  • -
  • Remove User
  • - '); - } echo(' -
  • Edit User
  • +
  • Manage Users
  • Auth History
  • '); echo(' diff --git a/resources/views/layouts/menu.blade.php b/resources/views/layouts/menu.blade.php index 8e93f9643e..1199e2005b 100644 --- a/resources/views/layouts/menu.blade.php +++ b/resources/views/layouts/menu.blade.php @@ -358,11 +358,7 @@
  • Global Settings
  • Validate Config
  • - @if(\LibreNMS\Authentication\LegacyAuth::get()->canManageUsers()) -
  • Add User
  • -
  • Remove User
  • - @endif -
  • Edit User
  • +
  • Manage Users
  • Auth History