Admin Dashboard overview
This commit is contained in:
parent
18bb6bffa7
commit
d38ad87220
@ -21,7 +21,7 @@ namespace Core\API {
|
||||
"allowed_extensions" => new ArrayType("allowed_extensions", Parameter::TYPE_STRING),
|
||||
"trusted_domains" => new ArrayType("trusted_domains", Parameter::TYPE_STRING),
|
||||
"user_registration_enabled" => new Parameter("user_registration_enabled", Parameter::TYPE_BOOLEAN),
|
||||
"captcha_provider" => new StringType("captcha_provider", -1, true, "none", CaptchaProvider::PROVIDERS),
|
||||
"captcha_provider" => new StringType("captcha_provider", -1, true, "disabled", CaptchaProvider::PROVIDERS),
|
||||
"mail_enabled" => new Parameter("mail_enabled", Parameter::TYPE_BOOLEAN),
|
||||
"mail_port" => new IntegerType("mail_port", 1, 65535),
|
||||
"rate_limiting_enabled" => new Parameter("rate_limiting_enabled", Parameter::TYPE_BOOLEAN),
|
||||
|
@ -46,11 +46,12 @@ class Stats extends Request {
|
||||
"server" => [
|
||||
"version" => WEBBASE_VERSION,
|
||||
"server" => $_SERVER["SERVER_SOFTWARE"] ?? "Unknown",
|
||||
"memory_usage" => memory_get_usage(),
|
||||
"load_avg" => $loadAvg,
|
||||
"memoryUsage" => memory_get_usage(),
|
||||
"loadAverage" => $loadAvg,
|
||||
"database" => $this->context->getSQL()->getStatus(),
|
||||
"mail" => $settings->isMailEnabled(),
|
||||
"captcha" => $settings->getCaptchaProvider()?->jsonSerialize()
|
||||
"captcha" => $settings->getCaptchaProvider()?->jsonSerialize(),
|
||||
"rateLimiting" => $settings->isRateLimitingEnabled()
|
||||
],
|
||||
];
|
||||
|
||||
|
@ -1470,6 +1470,10 @@ namespace Core\API\User {
|
||||
'token' => new StringType('token', 36),
|
||||
));
|
||||
$this->userToken = null;
|
||||
$this->rateLimiting = new RateLimiting(
|
||||
new RateLimitRule(10, 30, RateLimitRule::SECOND),
|
||||
new RateLimitRule(30, 1, RateLimitRule::MINUTE),
|
||||
);
|
||||
}
|
||||
|
||||
public function getToken(): ?UserToken {
|
||||
|
@ -109,7 +109,7 @@ class Settings {
|
||||
$settings->timeZone = date_default_timezone_get();
|
||||
|
||||
// captcha
|
||||
$settings->captchaProvider = "none";
|
||||
$settings->captchaProvider = "disabled";
|
||||
$settings->captchaSiteKey = "";
|
||||
$settings->captchaSecretKey = "";
|
||||
|
||||
|
@ -3,6 +3,8 @@
|
||||
return [
|
||||
"title" => "Einstellungen",
|
||||
"information" => "Informationen",
|
||||
"disabled" => "Deaktiviert",
|
||||
"enabled" => "Aktiviert",
|
||||
|
||||
# API Key
|
||||
"api_key" => "API Schlüssel",
|
||||
@ -44,6 +46,8 @@ return [
|
||||
"captcha_provider" => "Captcha Anbieter",
|
||||
"captcha_site_key" => "Öffentlicher Captcha Schlüssel",
|
||||
"captcha_secret_key" => "Geheimer Captcha Schlüssel",
|
||||
"recaptcha" => "Google reCaptcha",
|
||||
"hcaptcha" => "hCaptcha",
|
||||
|
||||
# redis
|
||||
"rate_limit" => "Rate-Limit",
|
||||
|
@ -3,6 +3,8 @@
|
||||
return [
|
||||
"title" => "Settings",
|
||||
"information" => "Information",
|
||||
"disabled" => "Disabled",
|
||||
"enabled" => "Enabled",
|
||||
|
||||
# API Key
|
||||
"api_key" => "API Key",
|
||||
@ -44,6 +46,8 @@ return [
|
||||
"captcha_provider" => "Captcha Provider",
|
||||
"captcha_site_key" => "Captcha Site Key",
|
||||
"captcha_secret_key" => "Secret Captcha Key",
|
||||
"recaptcha" => "Google reCaptcha",
|
||||
"hcaptcha" => "hCaptcha",
|
||||
|
||||
# redis
|
||||
"rate_limit" => "Rate Limiting",
|
||||
|
@ -6,11 +6,11 @@ use Core\Objects\ApiObject;
|
||||
|
||||
abstract class CaptchaProvider extends ApiObject {
|
||||
|
||||
const NONE = "none";
|
||||
const DISABLED = "disabled";
|
||||
const RECAPTCHA = "recaptcha";
|
||||
const HCAPTCHA = "hcaptcha";
|
||||
|
||||
const PROVIDERS = [self::NONE, self::RECAPTCHA, self::HCAPTCHA];
|
||||
const PROVIDERS = [self::DISABLED, self::RECAPTCHA, self::HCAPTCHA];
|
||||
|
||||
private string $siteKey;
|
||||
private string $secretKey;
|
||||
|
@ -2,8 +2,18 @@ import * as React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {useCallback, useContext, useEffect, useState} from "react";
|
||||
import {LocaleContext} from "shared/locale";
|
||||
import {ArrowCircleRight, BugReport, Groups, LibraryBooks, People} from "@mui/icons-material";
|
||||
import {CircularProgress} from "@mui/material";
|
||||
import {humanReadableSize} from "shared/util";
|
||||
import {sprintf} from "sprintf-js";
|
||||
import {
|
||||
ArrowCircleRight,
|
||||
BugReport,
|
||||
CheckCircle,
|
||||
Groups,
|
||||
HighlightOff,
|
||||
LibraryBooks,
|
||||
People
|
||||
} from "@mui/icons-material";
|
||||
import {Box, CircularProgress, Paper, Table, TableBody, TableCell, TableRow} from "@mui/material";
|
||||
|
||||
const StatBox = (props) => <div className={"col-lg-3 col-6"}>
|
||||
<div className={"small-box bg-" + props.color}>
|
||||
@ -24,6 +34,19 @@ const StatBox = (props) => <div className={"col-lg-3 col-6"}>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
const StatusLine = (props) => {
|
||||
const {enabled, text, ...other} = props;
|
||||
if (enabled) {
|
||||
return <Box display="grid" gridTemplateColumns={"30px auto"}>
|
||||
<CheckCircle color={"primary"} title={text} /> {text}
|
||||
</Box>
|
||||
} else {
|
||||
return <Box display="grid" gridTemplateColumns={"30px auto"}>
|
||||
<HighlightOff color={"secondary"} title={text} /> {text}
|
||||
</Box>
|
||||
}
|
||||
}
|
||||
|
||||
export default function Overview(props) {
|
||||
|
||||
const [fetchStats, setFetchStats] = useState(true);
|
||||
@ -32,7 +55,7 @@ export default function Overview(props) {
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
requestModules(props.api, ["general", "admin"], currentLocale).then(data => {
|
||||
requestModules(props.api, ["general", "admin", "settings"], currentLocale).then(data => {
|
||||
if (!data.success) {
|
||||
props.showDialog("Error fetching translations: " + data.msg);
|
||||
}
|
||||
@ -56,12 +79,10 @@ export default function Overview(props) {
|
||||
onFetchStats();
|
||||
}, []);
|
||||
|
||||
/*
|
||||
let loadAvg = this.state.server.load_avg;
|
||||
if (Array.isArray(this.state.server.load_avg)) {
|
||||
loadAvg = this.state.server.load_avg.join(" ");
|
||||
let loadAvg = stats ? stats.server.loadAverage : null;
|
||||
if (Array.isArray(loadAvg)) {
|
||||
loadAvg = loadAvg.map(v => sprintf("%.1f", v)).join(", ");
|
||||
}
|
||||
*/
|
||||
|
||||
return <>
|
||||
<div className={"content-header"}>
|
||||
@ -100,6 +121,59 @@ export default function Overview(props) {
|
||||
link={"/admin/logs"} />
|
||||
</div>
|
||||
</div>
|
||||
<Box m={2} p={2} component={Paper}>
|
||||
<h4>Server Stats</h4><hr />
|
||||
{stats === null ? <CircularProgress /> :
|
||||
<Table>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell>Web-Base Version</TableCell>
|
||||
<TableCell>{stats.server.version}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>Server</TableCell>
|
||||
<TableCell>{stats.server.server ?? "Unknown"}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>Load Average</TableCell>
|
||||
<TableCell>{loadAvg}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>Memory Usage</TableCell>
|
||||
<TableCell>{humanReadableSize(stats.server.memoryUsage)}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>Database</TableCell>
|
||||
<TableCell>{stats.server.database}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>Captcha</TableCell>
|
||||
<TableCell>
|
||||
<StatusLine enabled={!!stats.server.captcha}
|
||||
text={L("settings." + (stats.server.captcha ? stats.server.captcha.name : "disabled"))}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>Mail</TableCell>
|
||||
<TableCell>
|
||||
<StatusLine enabled={!!stats.server.mail}
|
||||
text={L("settings." + (stats.server.mail ? "enabled" : "disabled"))}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>Rate-Limiting</TableCell>
|
||||
<TableCell>
|
||||
<StatusLine enabled={!!stats.server.rateLimiting}
|
||||
text={L("settings." + (stats.server.rateLimiting ? "enabled" : "disabled"))}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
}
|
||||
</Box>
|
||||
</section>
|
||||
</>
|
||||
}
|
||||
|
@ -283,10 +283,16 @@ export default function SettingsView(props) {
|
||||
</FormGroup>
|
||||
];
|
||||
} else if (selectedTab === "captcha") {
|
||||
let captchaOptions = {};
|
||||
["disabled", "recaptcha", "hcaptcha"].reduce((map, key) => {
|
||||
map[key] = L("settings." + key);
|
||||
return map;
|
||||
}, captchaOptions);
|
||||
|
||||
return [
|
||||
renderSelection("captcha_provider", {"none": L("settings.none"), "recaptcha": "Google reCaptcha", "hcaptcha": "hCaptcha"}),
|
||||
renderTextInput("captcha_site_key", settings.captcha_provider === "none"),
|
||||
renderPasswordInput("captcha_secret_key", settings.captcha_provider === "none"),
|
||||
renderSelection("captcha_provider", captchaOptions),
|
||||
renderTextInput("captcha_site_key", settings.captcha_provider === "disabled"),
|
||||
renderPasswordInput("captcha_secret_key", settings.captcha_provider === "disabled"),
|
||||
];
|
||||
} else if (selectedTab === "redis") {
|
||||
return [
|
||||
|
Loading…
Reference in New Issue
Block a user