Added support for user timezones and user browser timezone by default (incomplete) (#13626)

* Added support for user timezones and user browser timezone byt default

* Formatting fixes

* Use the timezone for alert log display

also added validation for the timezone because it's being used in SQL.

* Formatting fixes

* Added return type

* Formatting"

* Update the latency graphs to use the user timezone

* Simplify the web routes config

* Update phpstan to ignore type error

* Fixed up the phpstan config

* Reverse phpstan change

* Re-apply phpstan override

* Remove the option to unset the session timezone

* Formatting fix

* Update outge and event logs to use session timezone

* Fix route for the timezone control

* Made the timezone more dynamic

* Fix a logic error that was stopping the timezone from being set automatically on login

* Prevent getPref from being called twice

* again prevent getPref double call

* getPref double call

* Fixed typo made during merge

* Fixed merge error in phpstan-baseline.neon

* Change spaces to tabs in phpstan-baseline.neon

* Update error count

---------

Co-authored-by: Tony Murray <murraytony@gmail.com>
This commit is contained in:
eskyuu
2023-05-09 23:24:48 +08:00
committed by GitHub
parent 56e9fa3742
commit ce0734ff5d
19 changed files with 216 additions and 20 deletions

View File

@@ -0,0 +1,55 @@
<?php
/**
* TimezoneController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* @link https://www.librenms.org
*
* @copyright 2021 Steven Wilton
* @author Steven Wilton <swilton@fluentit.com.au>
*/
namespace App\Http\Controllers\Ajax;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class TimezoneController extends Controller
{
public function set(Request $request): string
{
session([
'timezone_static' => $request->boolean('static'),
]);
// laravel session
if ($request->timezone) {
// Only accept valid timezones
if (! in_array($request->timezone, timezone_identifiers_list())) {
return session('timezone');
}
session([
'timezone' => $request->timezone,
]);
return $request->timezone;
}
return session('timezone');
}
}

View File

@@ -58,10 +58,13 @@ class LatencyController implements DeviceTab
public function data(Device $device): array
{
$from = Request::get('dtpickerfrom', Carbon::now()->subDays(2)->format(Config::get('dateformat.byminute')));
$to = Request::get('dtpickerto', Carbon::now()->format(Config::get('dateformat.byminute')));
$from = Request::get('dtpickerfrom', Carbon::now(session('timezone'))->subDays(2)->format(Config::get('dateformat.byminute')));
$to = Request::get('dtpickerto', Carbon::now(session('timezone'))->format(Config::get('dateformat.byminute')));
$perf = $this->fetchPerfData($device, $from, $to);
$dbfrom = Carbon::createFromFormat(Config::get('dateformat.byminute'), $from)->setTimezone(date_default_timezone_get())->format(Config::get('dateformat.byminute'));
$dbto = Carbon::createFromFormat(Config::get('dateformat.byminute'), $to)->setTimezone(date_default_timezone_get())->format(Config::get('dateformat.byminute'));
$perf = $this->fetchPerfData($device, $dbfrom, $dbto);
$duration = $perf && $perf->isNotEmpty()
? abs(strtotime($perf->first()->date) - strtotime($perf->last()->date)) * 1000
@@ -91,7 +94,7 @@ class LatencyController implements DeviceTab
return DB::table('device_perf')
->where('device_id', $device->device_id)
->whereBetween('timestamp', [$from, $to])
->select(DB::raw("DATE_FORMAT(timestamp, '%Y-%m-%d %H:%i') date,xmt,rcv,loss,min,max,avg"))
->selectRaw("DATE_FORMAT(IFNULL(CONVERT_TZ(timestamp, @@global.time_zone, ?), timestamp), '%Y-%m-%d %H:%i') date,xmt,rcv,loss,min,max,avg", [session('timezone')])
->get();
}

View File

@@ -117,7 +117,7 @@ class EventlogController extends TableController
$output = "<span class='alert-status ";
$output .= $this->severityLabel($eventlog->severity);
$output .= " eventlog-status'></span><span style='display:inline;'>";
$output .= (new Carbon($eventlog->datetime))->format(Config::get('dateformat.compact'));
$output .= (new Carbon($eventlog->datetime))->setTimezone(session('timezone'))->format(Config::get('dateformat.compact'));
$output .= '</span>';
return $output;

View File

@@ -64,10 +64,10 @@ class OutagesController extends TableController
return DeviceOutage::hasAccess($request->user())
->with('device')
->when($request->from, function ($query) use ($request) {
$query->where('going_down', '>=', strtotime($request->from));
$query->where('going_down', '>=', Carbon::parse($request->from, session('timezone'))->getTimestamp());
})
->when($request->to, function ($query) use ($request) {
$query->where('going_down', '<=', strtotime($request->to));
$query->where('going_down', '<=', Carbon::parse($request->to, session('timezone'))->getTimestamp());
});
}
@@ -113,7 +113,7 @@ class OutagesController extends TableController
}
$output = "<span style='display:inline;'>";
$output .= Carbon::createFromTimestamp($timestamp)->format(Config::get('dateformat.compact')); // Convert epoch to local time
$output .= Carbon::createFromTimestamp($timestamp, session('timezone'))->format(Config::get('dateformat.compact')); // Convert epoch to local time
$output .= '</span>';
return $output;

View File

@@ -80,6 +80,7 @@ class UserController extends Controller
'user' => $tmp_user,
'dashboard' => null,
'dashboards' => Dashboard::allAvailable($tmp_user)->get(),
'timezone' => 'default',
]);
}
@@ -100,6 +101,7 @@ class UserController extends Controller
$user->setPassword($request->new_password);
$user->auth_id = (string) LegacyAuth::get()->getUserid($user->username) ?: $user->user_id;
$this->updateDashboard($user, $request->get('dashboard'));
$this->updateTimezone($user, $request->get('timezone'));
if ($user->save()) {
$flasher->addSuccess(__('User :username created', ['username' => $user->username]));
@@ -143,6 +145,7 @@ class UserController extends Controller
'user' => $user,
'dashboard' => UserPref::getPref($user, 'dashboard'),
'dashboards' => Dashboard::allAvailable($user)->get(),
'timezone' => UserPref::getPref($user, 'timezone') ?: 'default',
];
if (Config::get('twofactor')) {
@@ -186,6 +189,14 @@ class UserController extends Controller
$flasher->addSuccess(__('Updated dashboard for :username', ['username' => $user->username]));
}
if ($request->has('timezone') && $this->updateTimezone($user, $request->get('timezone'))) {
if ($request->get('timezone') != 'default') {
$flasher->addSuccess(__('Updated timezone for :username', ['username' => $user->username]));
} else {
$flasher->addSuccess(__('Cleared timezone for :username', ['username' => $user->username]));
}
}
if ($user->save()) {
$flasher->addSuccess(__('User :username updated', ['username' => $user->username]));
@@ -233,6 +244,35 @@ class UserController extends Controller
return false;
}
/**
* @param User $user
* @param string $timezone
* @return bool
*/
protected function updateTimezone(User $user, $timezone)
{
$existing = UserPref::getPref($user, 'timezone');
if ($timezone != 'default') {
if (! in_array($timezone, timezone_identifiers_list())) {
return false;
}
if ($timezone != $existing) {
UserPref::setPref($user, 'timezone', $timezone);
return true;
}
} else {
if ($existing != '') {
UserPref::forgetPref($user, 'timezone');
return true;
}
}
return false;
}
public function authlog()
{
$this->authorize('manage', User::class);

View File

@@ -73,6 +73,7 @@ class UserPreferencesController extends Controller
'site_style' => UserPref::getPref($user, 'site_style'),
'site_style_default' => $styles[$default_style] ?? $default_style,
'site_styles' => $styles,
'timezone' => UserPref::getPref($user, 'timezone'),
'hide_dashboard_editor' => UserPref::getPref($user, 'hide_dashboard_editor') ?? 0,
];
@@ -110,6 +111,10 @@ class UserPreferencesController extends Controller
'required',
Rule::in(array_merge(['default'], array_keys($this->getValidStyles()))),
],
'timezone' => [
'required',
Rule::in(array_merge(['default'], timezone_identifiers_list())),
],
'hide_dashboard_editor' => 'required|integer',
];