Skip to content

Commit

Permalink
Generate the Laravel Queue migration in case you want to use database…
Browse files Browse the repository at this point in the history
… queues. Provide that as a default in config example.

Rewrite system/status page using blade templates because the XHR/Ajax didnt really add anything useful except a delay.
Create new route for just displaying phpinfo which we used instead of parsing the output into a table which can be bad for generating errors.
Disabled routes /system/DataBaseInfo and /system/phpInfo because they are server side now.
Don't do client side sorting of navigation menus (listings)
Database upgrade page really didnt need a disclosure control because having it minimised means nothing at all.
Move all the system diag functions into App\SystemInformation so they dont live in controllers
Migrated the system summary widgets into a blade component based system, provided the "table" widget as an example.
  • Loading branch information
mosen committed Jan 5, 2024
1 parent 4fecd7d commit b5dd3f2
Show file tree
Hide file tree
Showing 22 changed files with 433 additions and 320 deletions.
4 changes: 2 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,8 @@ REDIS_PORT=6379

# The default Queue driver, "sync" just doesn't use any Queue and invokes the job right now.
# This is probably not what you want, but it allows people to use Queues without setting anything up.
QUEUE_CONNECTION=sync
#QUEUE_CONNECTION=database
#QUEUE_CONNECTION=sync
QUEUE_CONNECTION=database

# Mailer configuration
# So far, no MunkiReport functionality uses this, but there is an outgoing mail integration available
Expand Down
26 changes: 16 additions & 10 deletions app/Http/Controllers/ClientsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -155,30 +155,36 @@ public function detail(Request $request, string $sn = '')
// Optionally:
// 'view_vars' => array with variables to pass to the views
// 'badge' => id of a badge for this tab
$tab_list = [
'summary' => [
'view' => 'client/summary_tab',
'view_vars' => [
'widget_list' => [],
],
'i18n' => 'client.tab.summary',
],
];
// 'blade' => truthy value means "use a blade template instead of a .php one" (Added in v6)

$tab_list = [];
// Include module tabs
$modules = app(Modules::class)->loadInfo();
$modules->addTabs($tab_list);

// Add custom tabs
$tab_list = array_merge($tab_list, conf('client_tabs', []));

ksort($tab_list);

// Prepend the summary after items are sorted by name so it appears at the top.
$tab_list = array_merge([
'summary' => [
'blade' => true,
'view' => 'client/summary_tab',
'view_vars' => [
'widget_list' => [],
],
'i18n' => 'client.tab.summary',
],
], $tab_list);


// Add widgets to summary tab
$modules->addWidgets(
$tab_list['summary']['view_vars']['widget_list'],
conf('detail_widget_list', [])
);

$data['tab_list'] = $tab_list;

return view("clients.detail", $data);
Expand Down
107 changes: 26 additions & 81 deletions app/Http/Controllers/SystemController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

namespace App\Http\Controllers;

use App\SystemInformation;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Gate;
use munkireport\lib\Dashboard;
use Compatibility\Kiss\Database;
use munkireport\lib\Modules;
use Munkireport\Osquery\Tables\SystemInfo;

/**
* Class SystemController
Expand All @@ -16,84 +20,6 @@
*/
class SystemController extends Controller
{
/**
* DataBase
*
* Get Database info and status
*
*/
public function DataBaseInfo()
{
$out = array(
'db.driver' => '',
'db.connectable' => false,
'db.writable' => false,
'db.size' => '',
'error' => '',
'version' => ''
);

$db = new Database(conf('connection'));
//echo '<pre>'; var_dump($db);
if ($db->connect()) {
$out['db.connectable'] = true;
$out['db.driver'] = $db->get_driver();

if ($db->isWritable()) {
$out['db.writable'] = true;
} else {
$out['error'] = $db->getError();
}
$out['db.size'] = $db->size();
$out['version'] = $db->get_version();

} else {
$out['error'] = $db->getError();
}
//echo '<pre>'; var_dump($db);
// Get engine
// Get permissions
// Do a write
// Do a read
// Get tables
// Get size

return response()->json($out);
}

/**
* php information
*
* Retrieve information about php
*
*/
public function phpInfo()
{
ob_start();
phpinfo(11);
$raw = ob_get_clean();
$phpinfo = array('phpinfo' => array());

// Remove credits
$nocreds = preg_replace('#<h1>PHP Credits.*#s', '', $raw);
if (preg_match_all('#(?:<h2>(?:<a name=".*?">)?(.*?)(?:</a>)?</h2>)|(?:<tr(?: class=".*?")?><t[hd](?: class=".*?")?>(.*?)\s*</t[hd]>(?:<t[hd](?: class=".*?")?>(.*?)\s*</t[hd]>(?:<t[hd](?: class=".*?")?>(.*?)\s*</t[hd]>)?)?</tr>)#s', $nocreds, $matches, PREG_SET_ORDER)) {
foreach ($matches as $match) {
if (strlen($match[1])) {
$phpinfo[$match[1]] = array();
} elseif (isset($match[3])) {
$keys1 = array_keys($phpinfo);
$phpinfo[end($keys1)][$match[2]] = isset($match[4]) ? $match[3] . ' ('.$match[4].')' : str_replace(',', ', ', $match[3]);
} else {
$keys1 = array_keys($phpinfo);
$phpinfo[end($keys1)][] = trim(strip_tags($match[2]));
}
}
}
//echo '<pre>';print_r($phpinfo);return;

return response()->json($phpinfo);
}

/**
* Display the Widget Gallery
*/
Expand Down Expand Up @@ -121,16 +47,35 @@ public function widgets()
*/
public function status()
{
$data['page'] = 'clients';
$data['scripts'] = array("clients/client_list.js");
Gate::authorize('global');

$data = [
'connection' => SystemInformation::getDatabaseInformation(),
'php' => SystemInformation::getPhpInformationByFunc(),
];

return view('system.status', $data);
}

/**
* Display database tools
* Get the content of phpinfo() behind an admin gate
*
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Foundation\Application|null
*/
public function php_info()
{
Gate::authorize('global');

return view('system.phpinfo');
}

/**
* Display database migration tools
*/
public function database()
{
Gate::authorize('global');

return view('system.database');
}
}
115 changes: 115 additions & 0 deletions app/SystemInformation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
<?php

namespace App;

use Illuminate\Support\Facades\DB;

/**
* This class provides access to information about the system that MunkiReport is running on.
*
* Various methods are extracted from \Compatibility\Kiss\Database AKA munkireport\lib\Database
*/
class SystemInformation
{
/**
* Get information about the current database and its configuration.
* Also returns some runtime information about the database if it is connectable.
*
* @return array A hash of information about the database. The keys are i18n codes.
* @throws \PDOException if an unsupported attribute was retrieved from the database, in general this should be caught by testing.
*/
public static function getDatabaseInformation(): array
{
$connection = DB::connection(config('database.default'));

$version = $connection->getPdo()?->getAttribute(\PDO::ATTR_SERVER_VERSION);
$info = $connection->getPdo()?->getAttribute(\PDO::ATTR_SERVER_INFO);
$status = $connection->getPdo()?->getAttribute(\PDO::ATTR_CONNECTION_STATUS);
$client = $connection->getPdo()?->getAttribute(\PDO::ATTR_CLIENT_VERSION);

try {
$timeout = $connection->getPdo()?->getAttribute(\PDO::ATTR_TIMEOUT);
} catch (\PDOException $e) {
$timeout = null;
}

$data = [
'db.driver' => $connection->getDriverName(),
'database' => $connection->getDatabaseName(),
'db.prefix' => $connection->getTablePrefix(),
'version' => $version,
'db.method' => $status,
'db.client.version' => $client,
'db.info' => $info,
'timeout' => $timeout,
];

switch ($connection->getDriverName()) {
case 'mysql':
$size = DB::table('information_schema.tables', 't')
->select(DB::raw('SUM(ROUND(((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024 ), 2)) AS size'))
->where('table_schema', '=', $connection->getDatabaseName())
->first()->size;
$data['db.size'] = "{$size} MB";
break;
case 'sqlite':
$pageSize = DB::select('PRAGMA PAGE_SIZE');
$pageCount = DB::select('PRAGMA PAGE_COUNT');
break;
}

return $data;
}

/**
* Get information about the current PHP runtime and its configuration by parsing the HTML output of phpinfo().
*
* This is not very sustainable and some variables may use php functions in future to avoid the HTML output change
* causing breakage.
*
* @return array PHP information scraped from the phpinfo() output buffer.
*/
public static function getPhpInformation(): array
{
ob_start();
phpinfo(11);
$raw = ob_get_clean();
$phpinfo = array('phpinfo' => array());

// Remove credits
$nocreds = preg_replace('#<h1>PHP Credits.*#s', '', $raw);
if (preg_match_all('#(?:<h2>(?:<a name=".*?">)?(.*?)(?:</a>)?</h2>)|(?:<tr(?: class=".*?")?><t[hd](?: class=".*?")?>(.*?)\s*</t[hd]>(?:<t[hd](?: class=".*?")?>(.*?)\s*</t[hd]>(?:<t[hd](?: class=".*?")?>(.*?)\s*</t[hd]>)?)?</tr>)#s', $nocreds, $matches, PREG_SET_ORDER)) {
foreach ($matches as $match) {
if (strlen($match[1])) {
$phpinfo[$match[1]] = array();
} elseif (isset($match[3])) {
$keys1 = array_keys($phpinfo);
$phpinfo[end($keys1)][$match[2]] = isset($match[4]) ? $match[3] . ' ('.$match[4].')' : str_replace(',', ', ', $match[3]);
} else {
$keys1 = array_keys($phpinfo);
$phpinfo[end($keys1)][] = trim(strip_tags($match[2]));
}
}
}

return $phpinfo;
}

/**
* Get information about the current PHP runtime and configuration using runtime function calls instead of
* HTML parsing. Should be used in place of getPhpInformation()
*
* @return array
*/
public static function getPhpInformationByFunc(): array
{
return [
'php.version' => phpversion(),
'php.uname' => php_uname(),
'php.loaded_extensions' => get_loaded_extensions(),
'php.ini_loaded_file' => php_ini_loaded_file(),
'php.ini_scanned_files' => php_ini_scanned_files(),
'php.memory_peak_usage' => memory_get_peak_usage(),
];
}
}
41 changes: 41 additions & 0 deletions app/View/Components/Widget/Detail/Legacy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace App\View\Components\Widget\Detail;

use Illuminate\View\Component;
use Compatibility\Kiss\View;
use munkireport\lib\Widgets;

class Legacy extends Component
{
/**
* @var string Widget name/template name
*/
public $name;

public $data;

/**
* Create a new component instance.
*
* @return void
*/
public function __construct(string $name, ?array $data)
{
$this->name = $name;
$this->data = $data;
}

/**
* Get the view / contents that represent the component.
*
* @return string
*/
public function render(): string
{
$obj = new View();
$widget = app(Widgets::class)->getDetail($this->data);
$output = $obj->viewFetch($widget['file'], $widget['vars'], $widget['path']);
return $output;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace App\View\Components\Widget;
namespace App\View\Components\Widget\Detail;

use Illuminate\View\Component;

Expand All @@ -11,14 +11,22 @@
*/
class Table extends Component
{
/**
* @var string Widget name/template name
*/
public $name;

public $data;

/**
* Create a new component instance.
*
* @return void
*/
public function __construct()
public function __construct(string $name, ?array $data)
{
//
$this->name = $name;
$this->data = $data;
}

/**
Expand All @@ -28,6 +36,6 @@ public function __construct()
*/
public function render()
{
return view('components.widget.table');
return view('components.widget.detail.table', $this->data);
}
}
Loading

0 comments on commit b5dd3f2

Please sign in to comment.