mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
fix key lang issue + start reports page
*add a workaround to avoid log error when the key send for the i18n is an interpolation literal or any invalid syntaxe * start reports page : format data as table list
This commit is contained in:
parent
e0112c679b
commit
c9ddcb4986
25 changed files with 1253 additions and 35 deletions
|
|
@ -1594,7 +1594,7 @@ body {
|
|||
}
|
||||
|
||||
.table-content-item-wrap {
|
||||
@apply appearance-none pl-1;
|
||||
@apply appearance-none pl-1 pr-2;
|
||||
}
|
||||
|
||||
/** MISC **/
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -8,7 +8,7 @@ import Text from "@components/Widget/Text.vue";
|
|||
import ButtonGroup from "@components/Widget/ButtonGroup.vue";
|
||||
|
||||
/**
|
||||
@name Builder/pLugin.vue
|
||||
@name Builder/PLugin.vue
|
||||
@description This component is lightweight builder containing only the necessary components to create the plugins page.
|
||||
@example
|
||||
[
|
||||
|
|
|
|||
56
vuejs/client/src/components/Builder/Reports.vue
Normal file
56
vuejs/client/src/components/Builder/Reports.vue
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
<script setup>
|
||||
// Containers
|
||||
import Grid from "@components/Widget/Grid.vue";
|
||||
import GridLayout from "@components/Widget/GridLayout.vue";
|
||||
import Title from "@components/Widget/Title.vue";
|
||||
import Table from "@components/Widget/Table.vue";
|
||||
import MessageUnmatch from "@components/Message/Unmatch.vue";
|
||||
|
||||
/**
|
||||
@name Builder/Reports.vue
|
||||
@description This component is lightweight builder containing only the necessary components to create the reports page.
|
||||
@example
|
||||
[
|
||||
{
|
||||
type: "card",
|
||||
gridLayoutClass: "transparent",
|
||||
widgets: [{ type: "MessageUnmatch", data: { text: "reports_not_found" } }],
|
||||
},
|
||||
];
|
||||
@param {array} builder - Array of containers and widgets
|
||||
*/
|
||||
|
||||
const props = defineProps({
|
||||
builder: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- top level grid (layout) -->
|
||||
<GridLayout
|
||||
v-for="(container, index) in props.builder"
|
||||
:key="index"
|
||||
:gridLayoutClass="container.containerClass"
|
||||
:type="container.type"
|
||||
:title="container.title"
|
||||
:link="container.link"
|
||||
:columns="container.containerColumns"
|
||||
:id="container.id"
|
||||
>
|
||||
<!-- widget grid -->
|
||||
<Grid>
|
||||
<!-- widget element -->
|
||||
<template v-for="(widget, index) in container.widgets" :key="index">
|
||||
<MessageUnmatch
|
||||
v-if="widget.type === 'MessageUnmatch'"
|
||||
v-bind="widget.data"
|
||||
/>
|
||||
<Title v-if="widget.type === 'Title'" v-bind="widget.data" />
|
||||
<Table v-if="widget.type === 'Table'" v-bind="widget.data" />
|
||||
</template>
|
||||
</Grid>
|
||||
</GridLayout>
|
||||
</template>
|
||||
|
|
@ -47,14 +47,30 @@ onMounted(() => {
|
|||
<nav>
|
||||
<!-- breadcrumb -->
|
||||
<h2 class="header-title">
|
||||
{{ $t(`dashboard_${header.currPath}`, header.currPath) }}
|
||||
{{
|
||||
$t(
|
||||
`dashboard_${header.currPath}`,
|
||||
$t(
|
||||
"dashboard_placeholder",
|
||||
$t("dashboard_placeholder", header.currPath)
|
||||
)
|
||||
)
|
||||
}}
|
||||
</h2>
|
||||
<ul class="header-breadcrumb-container">
|
||||
<li class="header-breadcrumb-item first">
|
||||
{{ $t("dashboard_bw") }}
|
||||
</li>
|
||||
<li class="header-breadcrumb-item slash mobile active">
|
||||
{{ $t(`dashboard_${header.lastPath}`, header.lastPath) }}
|
||||
{{
|
||||
$t(
|
||||
`dashboard_${header.lastPath}`,
|
||||
$t(
|
||||
"dashboard_placeholder",
|
||||
$t("dashboard_placeholder", header.lastPath)
|
||||
)
|
||||
)
|
||||
}}
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
|
|
|||
|
|
@ -204,7 +204,12 @@ onMounted(() => {
|
|||
:readonly="props.readonly || false"
|
||||
:disabled="props.disabled || false"
|
||||
:placeholder="
|
||||
props.placeholder ? $t(props.placeholder, props.placeholder) : ''
|
||||
props.placeholder
|
||||
? $t(
|
||||
props.placeholder,
|
||||
$t('dashboard_placeholder', props.placeholder)
|
||||
)
|
||||
: ''
|
||||
"
|
||||
:pattern="props.pattern || '(?s).*'"
|
||||
:name="props.name"
|
||||
|
|
|
|||
|
|
@ -90,8 +90,8 @@ onMounted(() => {
|
|||
>
|
||||
{{
|
||||
props.label
|
||||
? $t(props.label, props.label)
|
||||
: $t(props.name, props.name)
|
||||
? $t(props.label, $t("dashboard_placeholder", props.label))
|
||||
: $t(props.name, $t("dashboard_placeholder", props.name))
|
||||
}}
|
||||
</label>
|
||||
<span v-if="props.required" class="input-header-required-sign">*</span>
|
||||
|
|
|
|||
|
|
@ -32,10 +32,10 @@ const gridClass = computed(() => {
|
|||
<ul data-is="list-pairs" v-if="props.pairs" :class="['list-pairs-container']">
|
||||
<li v-for="item in props.pairs" :class="['list-pairs-item', gridClass]">
|
||||
<span class="list-pairs-title">
|
||||
{{ $t(item["key"], item["key"]) }}
|
||||
{{ $t(item["key"], $t("dashboard_placeholder", item["key"])) }}
|
||||
</span>
|
||||
<span class="list-pairs-subtitle">
|
||||
{{ $t(item["value"], item["value"]) }}
|
||||
{{ $t(item["value"], $t("dashboard_placeholder", item["value"])) }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ onMounted(() => {
|
|||
<div :class="[props.type, 'feedback-alert-wrap bg-el']">
|
||||
<div class="feedback-alert-header">
|
||||
<h5 class="feedback-alert-title">
|
||||
{{ $t(props.title, props.title) }}
|
||||
{{ $t(props.title, $t("dashboard_placeholder", props.title)) }}
|
||||
</h5>
|
||||
<button
|
||||
:tabindex="props.tabId"
|
||||
|
|
@ -113,7 +113,9 @@ onMounted(() => {
|
|||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<p class="feedback-alert-text">{{ $t(props.message, props.message) }}</p>
|
||||
<p class="feedback-alert-text">
|
||||
{{ $t(props.message, $t("dashboard_placeholder", props.message)) }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ onMounted(() => {
|
|||
'pointer-events-none',
|
||||
]"
|
||||
:id="`text-${btn.id}`"
|
||||
>{{ $t(props.text, props.text) }}
|
||||
>{{ $t(props.text, $t("dashboard_placeholder", props.text)) }}
|
||||
</span>
|
||||
<Icons
|
||||
v-if="props.iconName"
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ onMounted(() => {
|
|||
:aria-description="$t('dashboard_popover_detail_desc')"
|
||||
>
|
||||
<p :id="`${popover.id}-popover-text`" class="popover-text">
|
||||
{{ $t(props.text, props.text) }}
|
||||
{{ $t(props.text, $t("dashboard_placeholder", props.text)) }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -39,14 +39,10 @@ const status = reactive({
|
|||
});
|
||||
|
||||
const statusDesc = computed(() => {
|
||||
if (props.status === "success")
|
||||
return ["dashboard_status_success", "status active or success."];
|
||||
if (props.status === "error")
|
||||
return ["dashboard_status_error", "status inactive or error."];
|
||||
if (props.status === "warning")
|
||||
return ["dashboard_status_warning", "status warning or alert."];
|
||||
if (props.status === "info")
|
||||
return ["dashboard_status_info", "status loading or waiting or unknown."];
|
||||
if (props.status === "success") return "dashboard_status_success";
|
||||
if (props.status === "error") return "dashboard_status_error";
|
||||
if (props.status === "warning") return "dashboard_status_warning";
|
||||
if (props.status === "info") return "dashboard_status_info";
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
|
|
@ -61,7 +57,7 @@ onMounted(() => {
|
|||
:class="[props.status, 'status-icon']"
|
||||
></div>
|
||||
<p :id="`status-${status.id}`" class="sr-only">
|
||||
{{ $t(statusDesc[0], statusDesc[1]) }}
|
||||
{{ $t(statusDesc) }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -74,6 +74,6 @@ onMounted(() => {
|
|||
v-if="props.subtitle"
|
||||
:class="[subtitle.class, props.color, 'text-el']"
|
||||
>
|
||||
{{ $t(props.subtitle, props.subtitle) }}
|
||||
{{ $t(props.subtitle, $t("dashboard_placeholder", props.subtitle)) }}
|
||||
</component>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ onMounted(() => {
|
|||
v-for="(head, id) in props.header"
|
||||
:class="['table-header-item', `col-span-${props.positions[id]}`]"
|
||||
>
|
||||
{{ $t(head, head) }}
|
||||
{{ $t(head, $t("dashboard_placeholder", head)) }}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ onMounted(() => {
|
|||
ref="textEl"
|
||||
:class="[text.class, props.color, 'text-el']"
|
||||
>
|
||||
{{ $t(props.text, props.text) }}
|
||||
{{ $t(props.text, $t("dashboard_placeholder", props.text)) }}
|
||||
</component>
|
||||
|
||||
<div :class="['flex justify-center items-center']" v-if="props.icon">
|
||||
|
|
@ -89,7 +89,7 @@ onMounted(() => {
|
|||
v-bind="props.attrs"
|
||||
:class="[text.class, props.color, 'text-el', 'ml-2']"
|
||||
>
|
||||
{{ $t(props.text, props.text) }}
|
||||
{{ $t(props.text, $t("dashboard_placeholder", props.text)) }}
|
||||
</component>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -85,6 +85,6 @@ onMounted(() => {
|
|||
v-if="props.title"
|
||||
:class="[props.color, isSubtitleClass, title.class, 'text-el']"
|
||||
>
|
||||
{{ $t(props.title, props.title) }}
|
||||
{{ $t(props.title, $t("dashboard_placeholder", props.title)) }}
|
||||
</component>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"dashboard_placehoder" : "{placeholder}",
|
||||
"dashboard_logo_alt": "BunkerWeb logo image",
|
||||
"dashboard_logo_link_label": "Redirect to home page",
|
||||
"dashboard_bw": "BunkerWeb",
|
||||
|
|
@ -215,5 +216,27 @@
|
|||
"plugins_type_desc": "Only show plugins of the chosen type",
|
||||
"plugins_delete_desc": "Delete plugin",
|
||||
"plugins_modal_delete_title": "Delete plugin",
|
||||
"plugins_modal_delete_confirm": "Are you sure you want to delete the plugin below ?"
|
||||
"plugins_modal_delete_confirm": "Are you sure you want to delete the plugin below ?",
|
||||
"reports_not_found": "No reports found",
|
||||
"reports_search": "Search reports",
|
||||
"reports_search_desc": "Search within report date, ip, url, user agent or data.",
|
||||
"reports_country": "Country",
|
||||
"reports_country_desc": "Country are alpha-2 country code based.",
|
||||
"reports_method": "Method",
|
||||
"reports_method_desc": "Methods are HTTP methods.",
|
||||
"reports_status": "Status",
|
||||
"reports_status_desc": "Status are HTTP status codes.",
|
||||
"reports_reason": "Reason",
|
||||
"reports_reason_desc": "Reason is the plugin name that triggered the report.",
|
||||
"reports_title" :"Reports",
|
||||
"reports_table_title" :"Reports list with date, ip, country, method, url, status code, user agent, reason and data.",
|
||||
"reports_table_date" : "Date",
|
||||
"reports_table_ip": "IP",
|
||||
"reports_table_country" : "Country",
|
||||
"reports_table_method" : "Method",
|
||||
"reports_table_url" : "URL",
|
||||
"reports_table_status_code" : "Status code",
|
||||
"reports_table_cache_user_agent" : "User agent",
|
||||
"reports_table_reason" : "Reason",
|
||||
"reports_table_data": "Data"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"dashboard_placeholder" : "{placeholder}",
|
||||
"dashboard_logo_alt": "BunkerWeb logo image",
|
||||
"dashboard_logo_link_label": "Redirect to home page",
|
||||
"dashboard_bw": "BunkerWeb",
|
||||
|
|
|
|||
22
vuejs/client/src/pages/reports/index.html
Normal file
22
vuejs/client/src/pages/reports/index.html
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/x-icon" href="/images/favicon.ico" />
|
||||
<link rel="stylesheet" href="/css/style.css" />
|
||||
<link rel="stylesheet" href="/css/flag-icons.min.css" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>BunkerWeb | Reports</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="hidden" data-server-global='{"username" : "admin"}'></div>
|
||||
<div class="hidden"
|
||||
data-server-flash='[{"type" : "success", "title" : "title", "message" : "Success feedback"}, {"type" : "error", "title" : "title", "message" : "Error feedback"}, {"type" : "warning", "title" : "title", "message" : "Warning feedback"}, {"type" : "info", "title" : "title", "message" : "Info feedback"}]'>
|
||||
</div>
|
||||
<div class="hidden"
|
||||
data-server-builder='[{"type":"card","containerColumns":{"pc":6,"tablet":6,"mobile":12},"widgets":[{"type":"Instance","data":{"details":[{"key":"instances_hostname","value":"bunkerweb"},{"key":"instances_type","value":"manual"},{"key":"instances_status","value":"instances_active"}],"status":"success","title":"bunkerweb","buttons":[{"attrs":{"data-form-INSTANCE_ID":"bunkerweb","data-form-operation":"reload","data-submit-form":"true"},"text":"action_reload","color":"warning","size":"normal"},{"attrs":{"data-form-INSTANCE_ID":"bunkerweb","data-form-operation":"stop","data-submit-form":"true"},"text":"action_stop","color":"error","size":"normal"}]}}]}]'>
|
||||
</div>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="reports.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
11
vuejs/client/src/pages/reports/reports.js
Normal file
11
vuejs/client/src/pages/reports/reports.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { createApp } from "vue";
|
||||
import { createPinia } from "pinia";
|
||||
import { getI18n } from "@utils/lang.js";
|
||||
import Reports from "./reports.vue";
|
||||
|
||||
const pinia = createPinia();
|
||||
|
||||
createApp(Reports)
|
||||
.use(pinia)
|
||||
.use(getI18n(["dashboard", "action", "inp", "icons", "reports"]))
|
||||
.mount("#app");
|
||||
405
vuejs/client/src/pages/reports/reports.vue
Normal file
405
vuejs/client/src/pages/reports/reports.vue
Normal file
|
|
@ -0,0 +1,405 @@
|
|||
<script setup>
|
||||
import { reactive, onBeforeMount, onMounted } from "vue";
|
||||
import DashboardLayout from "@components/Dashboard/Layout.vue";
|
||||
import BuilderReports from "@components/Builder/Reports.vue";
|
||||
import { useGlobal } from "@utils/global.js";
|
||||
import { useForm } from "@utils/form.js";
|
||||
|
||||
/**
|
||||
@name Page/Reports.vue
|
||||
@description This component is the report page.
|
||||
This page displays global information about reports, and allow to delete or upload some reports.
|
||||
*/
|
||||
|
||||
const reports = reactive({
|
||||
builder: "",
|
||||
});
|
||||
|
||||
onBeforeMount(() => {
|
||||
// Get builder data
|
||||
const dataAtt = "data-server-builder";
|
||||
const dataEl = document.querySelector(`[${dataAtt}]`);
|
||||
const data =
|
||||
dataEl && !dataEl.getAttribute(dataAtt).includes(dataAtt)
|
||||
? JSON.parse(dataEl.getAttribute(dataAtt))
|
||||
: {};
|
||||
reports.builder = data;
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
useGlobal();
|
||||
useForm();
|
||||
});
|
||||
|
||||
const builder = [
|
||||
{
|
||||
type: "card",
|
||||
containerColumns: {
|
||||
pc: 12,
|
||||
tablet: 12,
|
||||
mobile: 12,
|
||||
},
|
||||
widgets: [
|
||||
{
|
||||
type: "Title",
|
||||
data: {
|
||||
title: "reports_title",
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "Table",
|
||||
data: {
|
||||
title: "reports_table_title",
|
||||
minWidth: "lg",
|
||||
header: [
|
||||
"reports_table_date",
|
||||
"reports_table_ip",
|
||||
"reports_table_country",
|
||||
"reports_table_method",
|
||||
"reports_table_url",
|
||||
"reports_table_status_code",
|
||||
"reports_table_cache_user_agent",
|
||||
"reports_table_reason",
|
||||
"reports_table_data",
|
||||
],
|
||||
positions: [1, 1, 1, 1, 2, 1, 2, 1, 2],
|
||||
items: [
|
||||
[
|
||||
{
|
||||
date: "25/06/2024 07:40:23",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "25/06/2024 07:40:23",
|
||||
},
|
||||
},
|
||||
{
|
||||
ip: "172.21.0.1",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "172.21.0.1",
|
||||
},
|
||||
},
|
||||
{
|
||||
country: "local",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "local",
|
||||
},
|
||||
},
|
||||
{
|
||||
method: "GET",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "GET",
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "/admin/login?id=etc/passwd",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "/admin/login?id=etc/passwd",
|
||||
},
|
||||
},
|
||||
{
|
||||
code: "403",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "403",
|
||||
},
|
||||
},
|
||||
{
|
||||
user_agent:
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
||||
},
|
||||
},
|
||||
{
|
||||
reason: "modsecurity",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "modsecurity",
|
||||
},
|
||||
},
|
||||
{
|
||||
data: {
|
||||
text: '{"fesfesfsefesfesfesfesfesfesfesfesfesfsefes": "fesfs"}',
|
||||
},
|
||||
type: "Text",
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
date: "25/06/2024 07:40:23",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "25/06/2024 07:40:23",
|
||||
},
|
||||
},
|
||||
{
|
||||
ip: "111111",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "111111",
|
||||
},
|
||||
},
|
||||
{
|
||||
country: "fr",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "fr",
|
||||
},
|
||||
},
|
||||
{
|
||||
method: "POST",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "POST",
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "/admin/login?id=e",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "/admin/login?id=e",
|
||||
},
|
||||
},
|
||||
{
|
||||
code: "403",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "403",
|
||||
},
|
||||
},
|
||||
{
|
||||
user_agent:
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
||||
},
|
||||
},
|
||||
{
|
||||
reason: " antibot",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: " antibot",
|
||||
},
|
||||
},
|
||||
{
|
||||
data: {
|
||||
text: "{}",
|
||||
},
|
||||
type: "Text",
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
date: "25/06/2024 07:40:23",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "25/06/2024 07:40:23",
|
||||
},
|
||||
},
|
||||
{
|
||||
ip: "111111",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "111111",
|
||||
},
|
||||
},
|
||||
{
|
||||
country: "fr",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "fr",
|
||||
},
|
||||
},
|
||||
{
|
||||
method: "POST",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "POST",
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "/admin/login?id=e",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "/admin/login?id=e",
|
||||
},
|
||||
},
|
||||
{
|
||||
code: "403",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "403",
|
||||
},
|
||||
},
|
||||
{
|
||||
user_agent:
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
||||
},
|
||||
},
|
||||
{
|
||||
reason: " antibot",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: " antibot",
|
||||
},
|
||||
},
|
||||
{
|
||||
data: {
|
||||
text: "{}",
|
||||
},
|
||||
type: "Text",
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
date: "25/06/2024 07:40:23",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "25/06/2024 07:40:23",
|
||||
},
|
||||
},
|
||||
{
|
||||
ip: "111111",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "111111",
|
||||
},
|
||||
},
|
||||
{
|
||||
country: "fr",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "fr",
|
||||
},
|
||||
},
|
||||
{
|
||||
method: "POST",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "POST",
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "/admin/login?id=e",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "/admin/login?id=e",
|
||||
},
|
||||
},
|
||||
{
|
||||
code: "403",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "403",
|
||||
},
|
||||
},
|
||||
{
|
||||
user_agent:
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
||||
},
|
||||
},
|
||||
{
|
||||
reason: " antibot",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: " antibot",
|
||||
},
|
||||
},
|
||||
{
|
||||
data: {
|
||||
text: "{}",
|
||||
},
|
||||
type: "Text",
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
date: "25/06/2024 07:40:23",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "25/06/2024 07:40:23",
|
||||
},
|
||||
},
|
||||
{
|
||||
ip: "111111",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "111111",
|
||||
},
|
||||
},
|
||||
{
|
||||
country: "fr",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "fr",
|
||||
},
|
||||
},
|
||||
{
|
||||
method: "POST",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "POST",
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "/admin/login?id=e",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "/admin/login?id=e",
|
||||
},
|
||||
},
|
||||
{
|
||||
code: "403",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "403",
|
||||
},
|
||||
},
|
||||
{
|
||||
user_agent:
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
||||
},
|
||||
},
|
||||
{
|
||||
reason: " antibot",
|
||||
type: "Text",
|
||||
data: {
|
||||
text: " antibot",
|
||||
},
|
||||
},
|
||||
{
|
||||
data: {
|
||||
text: "{}",
|
||||
},
|
||||
type: "Text",
|
||||
},
|
||||
],
|
||||
],
|
||||
filters: [],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DashboardLayout>
|
||||
<BuilderReports v-if="builder" :builder="builder" />
|
||||
</DashboardLayout>
|
||||
</template>
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import { createI18n } from "vue-i18n";
|
||||
|
||||
import en from "@lang/en.json" assert { type: "json" };
|
||||
import fr from "@lang/fr.json" assert { type: "json" };
|
||||
|
||||
|
|
@ -59,8 +60,12 @@ function getI18n(pagesArr = []) {
|
|||
availableLocales: availablesLangs,
|
||||
fallbackWarn: false,
|
||||
missingWarn: false,
|
||||
warnHtmlMessage: false
|
||||
});
|
||||
warnHtmlMessage: false,
|
||||
silentTranslationWarn: false,
|
||||
missingWarn: false,
|
||||
WarnHtmlInMessageLevel: "off",
|
||||
messageCompiler: false,
|
||||
});
|
||||
|
||||
return i18n;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -334,7 +334,6 @@ def job_builder(jobs):
|
|||
"value": "",
|
||||
"type": "text",
|
||||
"name": "jobs-keyword",
|
||||
"containerClass": "setting",
|
||||
"label": "jobs_search",
|
||||
"placeholder": "inp_keyword",
|
||||
"isClipboard": False,
|
||||
|
|
@ -360,7 +359,6 @@ def job_builder(jobs):
|
|||
"name": "jobs-every",
|
||||
"onlyDown": True,
|
||||
"label": "jobs_interval",
|
||||
"containerClass": "setting",
|
||||
"popovers": [
|
||||
{
|
||||
"text": "jobs_interval_desc",
|
||||
|
|
@ -382,7 +380,6 @@ def job_builder(jobs):
|
|||
"values": ["all", "success", "failed"],
|
||||
"name": "jobs-last-run",
|
||||
"onlyDown": True,
|
||||
"containerClass": "setting",
|
||||
"label": "jobs_reload",
|
||||
"popovers": [
|
||||
{
|
||||
|
|
@ -405,7 +402,6 @@ def job_builder(jobs):
|
|||
"values": ["all", "success", "failed"],
|
||||
"name": "jobs-success",
|
||||
"onlyDown": True,
|
||||
"containerClass": "setting",
|
||||
"label": "jobs_success",
|
||||
"popovers": [
|
||||
{
|
||||
|
|
|
|||
370
vuejs/tests/reports.json
Normal file
370
vuejs/tests/reports.json
Normal file
|
|
@ -0,0 +1,370 @@
|
|||
[
|
||||
{
|
||||
"type": "card",
|
||||
"containerColumns": {
|
||||
"pc": 12,
|
||||
"tablet": 12,
|
||||
"mobile": 12
|
||||
},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Title",
|
||||
"data": {
|
||||
"title": "reports_title"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Table",
|
||||
"data": {
|
||||
"title": "reports_table_title",
|
||||
"minWidth": "lg",
|
||||
"header": [
|
||||
"reports_table_date",
|
||||
"reports_table_ip",
|
||||
"reports_table_country",
|
||||
"reports_table_method",
|
||||
"reports_table_url",
|
||||
"reports_table_status_code",
|
||||
"reports_table_cache_user_agent",
|
||||
"reports_table_reason",
|
||||
"reports_table_data"
|
||||
],
|
||||
"positions": [
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
2
|
||||
],
|
||||
"items": [
|
||||
[
|
||||
{
|
||||
"date": "25/06/2024 07:40:23",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "25/06/2024 07:40:23"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ip": "172.21.0.1",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "172.21.0.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"country": "local",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "local"
|
||||
}
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "GET"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/admin/login?id=etc/passwd",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "/admin/login?id=etc/passwd"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "403",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "403"
|
||||
}
|
||||
},
|
||||
{
|
||||
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36"
|
||||
}
|
||||
},
|
||||
{
|
||||
"reason": "modsecurity",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "modsecurity"
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text": "{\"fesfesfsefesfesfesfesfesfesfesfesfesfsefes\": \"fesfs\"}"
|
||||
},
|
||||
"type": "Text"
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"date": "25/06/2024 07:40:23",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "25/06/2024 07:40:23"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ip": "111111",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "111111"
|
||||
}
|
||||
},
|
||||
{
|
||||
"country": "fr",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "fr"
|
||||
}
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "POST"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/admin/login?id=e",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "/admin/login?id=e"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "403",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "403"
|
||||
}
|
||||
},
|
||||
{
|
||||
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36"
|
||||
}
|
||||
},
|
||||
{
|
||||
"reason": " antibot",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": " antibot"
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text": "{}"
|
||||
},
|
||||
"type": "Text"
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"date": "25/06/2024 07:40:23",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "25/06/2024 07:40:23"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ip": "111111",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "111111"
|
||||
}
|
||||
},
|
||||
{
|
||||
"country": "fr",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "fr"
|
||||
}
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "POST"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/admin/login?id=e",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "/admin/login?id=e"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "403",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "403"
|
||||
}
|
||||
},
|
||||
{
|
||||
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36"
|
||||
}
|
||||
},
|
||||
{
|
||||
"reason": " antibot",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": " antibot"
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text": "{}"
|
||||
},
|
||||
"type": "Text"
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"date": "25/06/2024 07:40:23",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "25/06/2024 07:40:23"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ip": "111111",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "111111"
|
||||
}
|
||||
},
|
||||
{
|
||||
"country": "fr",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "fr"
|
||||
}
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "POST"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/admin/login?id=e",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "/admin/login?id=e"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "403",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "403"
|
||||
}
|
||||
},
|
||||
{
|
||||
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36"
|
||||
}
|
||||
},
|
||||
{
|
||||
"reason": " antibot",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": " antibot"
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text": "{}"
|
||||
},
|
||||
"type": "Text"
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"date": "25/06/2024 07:40:23",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "25/06/2024 07:40:23"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ip": "111111",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "111111"
|
||||
}
|
||||
},
|
||||
{
|
||||
"country": "fr",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "fr"
|
||||
}
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "POST"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/admin/login?id=e",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "/admin/login?id=e"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "403",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "403"
|
||||
}
|
||||
},
|
||||
{
|
||||
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36"
|
||||
}
|
||||
},
|
||||
{
|
||||
"reason": " antibot",
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": " antibot"
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text": "{}"
|
||||
},
|
||||
"type": "Text"
|
||||
}
|
||||
]
|
||||
],
|
||||
"filters": []
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
310
vuejs/tests/reports.py
Normal file
310
vuejs/tests/reports.py
Normal file
|
|
@ -0,0 +1,310 @@
|
|||
import json
|
||||
|
||||
|
||||
reports = [
|
||||
{
|
||||
"url": "/admin/login?id=etc/passwd",
|
||||
"ip": "172.21.0.1",
|
||||
"reason": "modsecurity",
|
||||
"country": "local",
|
||||
"status": 403,
|
||||
"method": "GET",
|
||||
"date": "25/06/2024 07:40:23",
|
||||
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
||||
"data": {"fesfesfsefesfesfesfesfesfesfesfesfesfsefes": "fesfs"},
|
||||
},
|
||||
{
|
||||
"url": "/admin/login?id=e",
|
||||
"ip": "111111",
|
||||
"reason": " antibot",
|
||||
"country": "fr",
|
||||
"status": 403,
|
||||
"method": "POST",
|
||||
"date": "25/06/2024 07:40:23",
|
||||
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
||||
"data": {},
|
||||
},
|
||||
{
|
||||
"url": "/admin/login?id=e",
|
||||
"ip": "111111",
|
||||
"reason": " antibot",
|
||||
"country": "fr",
|
||||
"status": 403,
|
||||
"method": "POST",
|
||||
"date": "25/06/2024 07:40:23",
|
||||
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
||||
"data": {},
|
||||
},
|
||||
{
|
||||
"url": "/admin/login?id=e",
|
||||
"ip": "111111",
|
||||
"reason": " antibot",
|
||||
"country": "fr",
|
||||
"status": 403,
|
||||
"method": "POST",
|
||||
"date": "25/06/2024 07:40:23",
|
||||
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
||||
"data": {},
|
||||
},
|
||||
{
|
||||
"url": "/admin/login?id=e",
|
||||
"ip": "111111",
|
||||
"reason": " antibot",
|
||||
"country": "fr",
|
||||
"status": 403,
|
||||
"method": "POST",
|
||||
"date": "25/06/2024 07:40:23",
|
||||
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
||||
"data": {},
|
||||
},
|
||||
]
|
||||
|
||||
# Reoder reports to get in order "date", "ip", "country", "method", "url", "code", "user_agent", "reason", "data"
|
||||
for report in reports:
|
||||
report["date"] = report.pop("date")
|
||||
report["ip"] = report.pop("ip")
|
||||
report["country"] = report.pop("country")
|
||||
report["method"] = report.pop("method")
|
||||
report["url"] = report.pop("url")
|
||||
report["code"] = report.pop("status")
|
||||
report["user_agent"] = report.pop("user_agent")
|
||||
report["reason"] = report.pop("reason")
|
||||
report["data"] = report.pop("data")
|
||||
|
||||
|
||||
def get_reports_filter(reports):
|
||||
|
||||
if len(reports) <= 5:
|
||||
return []
|
||||
|
||||
total_countries = ["all"]
|
||||
total_methods = ["all"]
|
||||
total_status = ["all"]
|
||||
total_reasons = ["all"]
|
||||
|
||||
for report in reports:
|
||||
if report.get("country") and report.get("country") not in total_countries:
|
||||
total_countries.append(report.get("country"))
|
||||
|
||||
if report.get("method") and report.get("method") not in total_methods:
|
||||
total_methods.append(report.get("method"))
|
||||
|
||||
if report.get("status") and report.get("status") not in total_status:
|
||||
total_status.append(str(report.get("status")))
|
||||
|
||||
if report.get("reason") and report.get("reason") not in total_reasons:
|
||||
total_reasons.append(report.get("reason"))
|
||||
|
||||
filters = []
|
||||
|
||||
filters.append(
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "keyword",
|
||||
"type": "keyword",
|
||||
"value": "",
|
||||
"keys": ["url", "ip", "date", "user_agent"],
|
||||
"field": {
|
||||
"id": "reports-keyword",
|
||||
"value": "",
|
||||
"type": "text",
|
||||
"name": "reports-keyword",
|
||||
"label": "reports_search",
|
||||
"placeholder": "inp_keyword",
|
||||
"isClipboard": False,
|
||||
"popovers": [
|
||||
{
|
||||
"text": "reports_search_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
if len(total_countries) > 1:
|
||||
filters.append(
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "country",
|
||||
"type": "select",
|
||||
"value": "all",
|
||||
"keys": ["country"],
|
||||
"field": {
|
||||
"id": "reports-country",
|
||||
"value": "all",
|
||||
"values": total_countries,
|
||||
"name": "reports-country",
|
||||
"onlyDown": True,
|
||||
"label": "reports_country",
|
||||
"popovers": [
|
||||
{
|
||||
"text": "reports_country_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
if len(total_methods) > 1:
|
||||
filters.append(
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "method",
|
||||
"type": "select",
|
||||
"value": "all",
|
||||
"keys": ["method"],
|
||||
"field": {
|
||||
"id": "reports-method",
|
||||
"value": "all",
|
||||
"values": total_methods,
|
||||
"name": "reports-method",
|
||||
"onlyDown": True,
|
||||
"label": "reports_method",
|
||||
"popovers": [
|
||||
{
|
||||
"text": "reports_method_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
if len(total_status) > 1:
|
||||
filters.append(
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "status",
|
||||
"type": "select",
|
||||
"value": "all",
|
||||
"keys": ["status"],
|
||||
"field": {
|
||||
"id": "reports-status",
|
||||
"value": "all",
|
||||
"values": total_status,
|
||||
"name": "reports-status",
|
||||
"onlyDown": True,
|
||||
"label": "reports_status",
|
||||
"popovers": [
|
||||
{
|
||||
"text": "reports_status_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
if len(total_reasons) > 1:
|
||||
filters.append(
|
||||
{
|
||||
"filter": "table",
|
||||
"filterName": "reason",
|
||||
"type": "select",
|
||||
"value": "all",
|
||||
"keys": ["reason"],
|
||||
"field": {
|
||||
"id": "reports-reason",
|
||||
"value": "all",
|
||||
"values": total_reasons,
|
||||
"name": "reports-reason",
|
||||
"onlyDown": True,
|
||||
"label": "reports_reason",
|
||||
"popovers": [
|
||||
{
|
||||
"text": "reports_reason_desc",
|
||||
"iconName": "info",
|
||||
},
|
||||
],
|
||||
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
|
||||
},
|
||||
},
|
||||
)
|
||||
return filters
|
||||
|
||||
|
||||
def get_reports_list(reports):
|
||||
data = []
|
||||
# loop on each dict
|
||||
for report in reports:
|
||||
item = []
|
||||
for k, v in report.items():
|
||||
item.append(
|
||||
{
|
||||
k: json.dumps(v) if isinstance(v, dict) else str(v),
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": json.dumps(v) if isinstance(v, dict) else str(v),
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
data.append(item)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def reports_builder(reports, data=None):
|
||||
|
||||
if not reports:
|
||||
return [
|
||||
{
|
||||
"type": "void",
|
||||
"widgets": [
|
||||
{"type": "MessageUnmatch", "data": {"text": "reports_not_found"}}
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
filters = get_reports_filter(reports)
|
||||
|
||||
reports_list = get_reports_list(reports)
|
||||
|
||||
builder = [
|
||||
{
|
||||
"type": "card",
|
||||
"containerColumns": {"pc": 12, "tablet": 12, "mobile": 12},
|
||||
"widgets": [
|
||||
{
|
||||
"type": "Title",
|
||||
"data": {"title": "reports_title"},
|
||||
},
|
||||
{
|
||||
"type": "Table",
|
||||
"data": {
|
||||
"title": "reports_table_title",
|
||||
"minWidth": "lg",
|
||||
"header": [
|
||||
"reports_table_date",
|
||||
"reports_table_ip",
|
||||
"reports_table_country",
|
||||
"reports_table_method",
|
||||
"reports_table_url",
|
||||
"reports_table_status_code",
|
||||
"reports_table_cache_user_agent",
|
||||
"reports_table_reason",
|
||||
"reports_table_data",
|
||||
],
|
||||
"positions": [1, 1, 1, 1, 2, 1, 2, 1, 2],
|
||||
"items": reports_list,
|
||||
"filters": filters,
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
|
||||
return builder
|
||||
|
||||
|
||||
output = reports_builder(reports)
|
||||
|
||||
# store on a file
|
||||
with open("reports.json", "w") as f:
|
||||
json.dump(output, f, indent=4)
|
||||
Loading…
Reference in a new issue