fix truncate text tabulator + reports page done

This commit is contained in:
Jordan Blasenhauer 2024-08-13 18:27:33 +02:00
parent f7c5ca3603
commit c4e3a78aad
15 changed files with 863 additions and 1355 deletions

View file

@ -24,7 +24,7 @@ def bans_filters(reasons: Optional[list] = None, remains: Optional[list] = None)
"label": "bans_search_ip", # keep it (a18n)
"value": "",
"inpType": "input",
"columns": {"pc": 3, "tablet": 4, " mobile": 12},
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
},
},
]
@ -43,7 +43,7 @@ def bans_filters(reasons: Optional[list] = None, remains: Optional[list] = None)
"values": ["all"] + reasons, # keep "all" and add your reasons dynamically
"inpType": "select",
"onlyDown": True,
"columns": {"pc": 3, "tablet": 4, " mobile": 12},
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
},
},
)
@ -61,7 +61,7 @@ def bans_filters(reasons: Optional[list] = None, remains: Optional[list] = None)
"values": ["all"] + remains, # keep everything and format bans to fit in one remain category
"inpType": "select",
"onlyDown": True,
"columns": {"pc": 3, "tablet": 4, " mobile": 12},
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
},
},
)
@ -82,7 +82,7 @@ def ban_item(id: str, ip: str, reason: str, ban_start_date: int, ban_end_date: i
hideLabel=True,
value=ban_start_date,
disabled=True, # Readonly
columns={"pc": 12, "tablet": 12, " mobile": 12},
columns={"pc": 12, "tablet": 12, "mobile": 12},
)
),
"ban_end_date": get_fields_from_field(
@ -133,7 +133,7 @@ default_add_ban = [
label="bans_add_ban_ip", # keep it (a18n)
hideLabel=True,
value="",
columns={"pc": 12, "tablet": 12, " mobile": 12},
columns={"pc": 12, "tablet": 12, "mobile": 12},
)
),
"ban_end": get_fields_from_field(

View file

@ -56,7 +56,7 @@ def config_form(
label="configs_filename", # keep it (a18n)
value="" if is_new else filename, # empty if new or replace by the filename value to edit (.conf excluded)
pattern="", # add your pattern if needed
columns={"pc": 3, "tablet": 4, " mobile": 12},
columns={"pc": 3, "tablet": 4, "mobile": 12},
),
# Select between available types
select_widget(
@ -65,7 +65,7 @@ def config_form(
label="configs_types", # keep it (a18n)
value="" if is_new else config_type,
values=types or [], # set all available types like ["http", "modsec"]
columns={"pc": 3, "tablet": 4, " mobile": 12},
columns={"pc": 3, "tablet": 4, "mobile": 12},
onlyDown=True,
),
# Add script on Page.vue to disabled listcheck in case checkbox is checked
@ -76,7 +76,7 @@ def config_form(
name="config-global",
label="configs_global", # keep it (a18n)
value=is_global, # no if new, else it depends of the current conf
columns={"pc": 3, "tablet": 4, " mobile": 12},
columns={"pc": 3, "tablet": 4, "mobile": 12},
),
# Case checkbox is checked, this checklist will be ignored on server
# Combobox ATM but will be replace by a checklist
@ -88,7 +88,7 @@ def config_form(
value="",
values=services or [], # set services list ATM, we will update by a checklist with [{value : "service1", is_check : bool}, ...]
onlyDown=True,
columns={"pc": 3, "tablet": 4, " mobile": 12},
columns={"pc": 3, "tablet": 4, "mobile": 12},
),
# Editor to edit the conf
editor_widget(
@ -96,7 +96,7 @@ def config_form(
name="config-value",
label="configs_value", # keep it (a18n)
value="" if is_new else config_value,
columns={"pc": 3, "tablet": 4, " mobile": 12},
columns={"pc": 3, "tablet": 4, "mobile": 12},
),
input_widget(
id="operation",
@ -104,7 +104,7 @@ def config_form(
label="configs_operation", # keep it (a18n)
value="new" if is_new else "edit",
pattern="", # add your pattern if needed
columns={"pc": 3, "tablet": 4, " mobile": 12},
columns={"pc": 3, "tablet": 4, "mobile": 12},
inpClass="hidden", # hide it
),
button_widget(
@ -129,7 +129,7 @@ def configs_filter(types: list):
"label": "configs_search_name", # keep it (a18n)
"value": "",
"inpType": "input",
"columns": {"pc": 3, "tablet": 4, " mobile": 12},
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
},
},
{
@ -143,7 +143,7 @@ def configs_filter(types: list):
"values": ["all"] + types,
"inpType": "select",
"onlyDown": True,
"columns": {"pc": 3, "tablet": 4, " mobile": 12},
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
},
},
{
@ -157,7 +157,7 @@ def configs_filter(types: list):
"values": ["all", "yes", "no"], # keep
"inpType": "select",
"onlyDown": True,
"columns": {"pc": 3, "tablet": 4, " mobile": 12},
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
},
},
]
@ -209,7 +209,7 @@ def config_item(filename: str, conf_type: str, is_global: str, services: list, d
"label": "configs_search_service", # keep it (a18n)
"value": "",
"inpType": "input",
"columns": {"pc": 3, "tablet": 4, " mobile": 12},
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
},
},
],

View file

@ -1,10 +1,10 @@
from .utils.table import add_column
from .utils.format import get_fields_from_field
from .utils.widgets import datepicker_widget, text_widget, tabulator_widget
from .utils.widgets import datepicker_widget, text_widget, tabulator_widget, title_widget, subtitle_widget, unmatch_widget
from typing import Optional
reports_columns = [
add_column(title="Date", field="date", formatter="fields"),
add_column(title="Date", field="date", formatter="fields", minWidth=250),
add_column(title="IP", field="ip", formatter="text"),
add_column(title="Country", field="country", formatter="text"),
add_column(title="Server name", field="server_name", formatter="text"),
@ -21,38 +21,20 @@ def reports_filters(reasons: Optional[list] = None, countries: Optional[list] =
reports_filters = [
{
"type": "like",
"fields": ["ip"],
"setting": {
"id": "input-search-ip",
"name": "input-search-ip",
"label": "reports_search_ip", # keep it (a18n)
"value": "",
"inpType": "input",
"columns": {"pc": 3, "tablet": 4, " mobile": 12},
},
},
{
"type": "like",
"fields": ["url"],
"setting": {
"id": "input-search-url",
"name": "input-search-url",
"label": "reports_search_url", # keep it (a18n)
"value": "",
"inpType": "input",
"columns": {"pc": 3, "tablet": 4, " mobile": 12},
},
},
{
"type": "like",
"fields": ["user_agent", "data"],
"fields": ["ip", "url", "user_agent", "data"],
"setting": {
"id": "input-search-misc",
"name": "input-search-misc",
"label": "reports_search_misc", # keep it (a18n)
"value": "",
"inpType": "input",
"columns": {"pc": 3, "tablet": 4, " mobile": 12},
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
"popovers": [
{
"iconName": "info",
"text": "reports_search_misc_desc",
}
],
},
},
]
@ -70,7 +52,13 @@ def reports_filters(reasons: Optional[list] = None, countries: Optional[list] =
"values": ["all"] + reasons,
"inpType": "select",
"onlyDown": True,
"columns": {"pc": 3, "tablet": 4, " mobile": 12},
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
"popovers": [
{
"iconName": "info",
"text": "reports_select_reason_desc",
}
],
},
}
)
@ -88,7 +76,13 @@ def reports_filters(reasons: Optional[list] = None, countries: Optional[list] =
"values": ["all"] + countries,
"inpType": "select",
"onlyDown": True,
"columns": {"pc": 3, "tablet": 4, " mobile": 12},
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
"popovers": [
{
"iconName": "info",
"text": "reports_select_country_desc",
}
],
},
}
)
@ -106,7 +100,13 @@ def reports_filters(reasons: Optional[list] = None, countries: Optional[list] =
"values": ["all"] + methods,
"inpType": "select",
"onlyDown": True,
"columns": {"pc": 3, "tablet": 4, " mobile": 12},
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
"popovers": [
{
"iconName": "info",
"text": "reports_select_method_desc",
}
],
},
}
)
@ -124,7 +124,13 @@ def reports_filters(reasons: Optional[list] = None, countries: Optional[list] =
"values": ["all"] + codes,
"inpType": "select",
"onlyDown": True,
"columns": {"pc": 3, "tablet": 4, " mobile": 12},
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
"popovers": [
{
"iconName": "info",
"text": "reports_select_code_desc",
}
],
},
}
)
@ -133,39 +139,51 @@ def reports_filters(reasons: Optional[list] = None, countries: Optional[list] =
# date = timestamp
def report_item(id: int, date: int, ip: str, country: str, method: str, url: str, code: str, user_agent: str, reason: str, data: str) -> dict:
return (
{
"date": get_fields_from_field(
datepicker_widget(
id=f"datepicker-date-{id}",
name=f"datepicker-date-{id}",
label="reports_date", # keep it (a18n)
hideLabel=True,
value=date,
disabled=True, # Readonly
)
),
"ip": text_widget(text=ip)["data"],
"country": text_widget(text=country)["data"],
"method": text_widget(text=method)["data"],
"url": text_widget(text=url)["data"],
"code": text_widget(text=code)["data"],
"user_agent": text_widget(text=user_agent)["data"],
"reason": text_widget(text=reason)["data"],
"data": text_widget(text=data)["data"],
},
)
def report_item(id: int, date: int, ip: str, country: str, method: str, url: str, code: str, user_agent: str, reason: str, data: str, server_name: str) -> dict:
return {
"date": get_fields_from_field(
datepicker_widget(
id=f"datepicker-date-{id}",
name=f"datepicker-date-{id}",
label="reports_date", # keep it (a18n)
hideLabel=True,
value=date,
disabled=True, # Readonly
)
),
"server_name": text_widget(text=server_name)["data"],
"ip": text_widget(text=ip)["data"],
"country": text_widget(text=country)["data"],
"method": text_widget(text=method)["data"],
"url": text_widget(text=url)["data"],
"code": text_widget(text=code)["data"],
"user_agent": text_widget(text=user_agent)["data"],
"reason": text_widget(text=reason)["data"],
"data": text_widget(text=data)["data"],
}
def reports_builder(
reports: list, reasons: Optional[list] = None, countries: Optional[list] = None, methods: Optional[list] = None, codes: Optional[list] = None
) -> str:
if reasons is None or len(reasons) == 0:
return {
"type": "card",
"gridLayoutClass": "transparent",
"widgets": [
unmatch_widget(text="reports_not_found"),
],
}
reports_items = [report_item(**report, id=index) for index, report in enumerate(reports)]
return [
{
"type": "card",
"widgets": [
title_widget("reports_title"), # keep it (a18n)
subtitle_widget("reports_subtitle"), # keep it (a18n)
tabulator_widget(
id="table-core-plugins",
columns=reports_columns,

View file

@ -1,6 +1,11 @@
def add_column(title, field, formatter=""):
# don"t return formatter if ""
if formatter:
return {"title": title, "field": field, "formatter": formatter}
def add_column(title, field, formatter="", minWidth=None):
return {"title": title, "field": field}
col = {"title": title, "field": field}
if formatter:
col["formatter"] = formatter
if minWidth:
col["minWidth"] = minWidth
return col

File diff suppressed because it is too large Load diff

View file

@ -28,7 +28,7 @@ core_pro_filters = [
"label": "plugins_search_name", # keep it (a18n)
"value": "",
"inpType": "input",
"columns": {"pc": 3, "tablet": 4, " mobile": 12},
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
},
},
]
@ -92,7 +92,7 @@ registry_filters = [
"label": "plugins_search_name", # keep it (a18n)
"value": "",
"inpType": "input",
"columns": {"pc": 3, "tablet": 4, " mobile": 12},
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
},
},
{
@ -106,7 +106,7 @@ registry_filters = [
"values": ["all", "pro", "external"],
"inpType": "select",
"onlyDown": True,
"columns": {"pc": 3, "tablet": 4, " mobile": 12},
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
},
},
{
@ -120,7 +120,7 @@ registry_filters = [
"values": ["all", "yes", "no"],
"inpType": "select",
"onlyDown": True,
"columns": {"pc": 3, "tablet": 4, " mobile": 12},
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
},
},
]
@ -135,7 +135,7 @@ registry_items = [
hideLabel=True,
id="checkbox-plugin-id", # replace by plugin_id
name="checkbox-plugin-id", # replace by plugin_id
columns={"pc": 12, "tablet": 12, " mobile": 12},
columns={"pc": 12, "tablet": 12, "mobile": 12},
)["data"],
"name": text(text="Name")["data"],
"description": text(text="Description")["data"],
@ -192,7 +192,7 @@ upload_filters = [
"label": "plugins_search_name", # keep it (a18n)
"value": "",
"inpType": "input",
"columns": {"pc": 3, "tablet": 4, " mobile": 12},
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
},
},
]
@ -207,7 +207,7 @@ upload_items = [
hideLabel=True,
id="checkbox-plugin-id", # replace by plugin_id
name="checkbox-plugin-id", # replace by plugin_id
columns={"pc": 12, "tablet": 12, " mobile": 12},
columns={"pc": 12, "tablet": 12, "mobile": 12},
)["data"],
"name": text(text="Name")["data"],
"description": text(text="Description")["data"],

View file

@ -1,6 +1,6 @@
from utils import save_builder
from pages.reports2 import reports_builder
from pages.reports import reports_builder
reports = [
{
@ -13,6 +13,7 @@ reports = [
"user_agent": "Mozilla/5.0",
"reason": "antibot",
"data": "lore ipsum ad vitam aeternam",
"server_name": "localhost",
},
{
"date": 1723491738000,
@ -24,6 +25,7 @@ reports = [
"user_agent": "Mozilla/0.1",
"reason": "unknown",
"data": "",
"server_name": "localhost",
},
]
@ -46,4 +48,4 @@ reasons = list(reasons)
builder = reports_builder(reports, reasons, countries, methods, codes)
save_builder("reports2", builder, update_page=False)
save_builder(page_name="reports", output=builder, script_name="reports")

View file

@ -26,7 +26,7 @@ def generate_form(
label="users_filename", # keep it (a18n)
value="" if is_new else username,
pattern="", # add your pattern if needed
columns={"pc": 3, "tablet": 4, " mobile": 12},
columns={"pc": 3, "tablet": 4, "mobile": 12},
),
input(
id=f"password-{'new' if is_new else username}",
@ -34,7 +34,7 @@ def generate_form(
label="users_password", # keep it (a18n)
value="" if is_new else password,
pattern="", # add your pattern if needed
columns={"pc": 3, "tablet": 4, " mobile": 12},
columns={"pc": 3, "tablet": 4, "mobile": 12},
),
# Select between available types
select(
@ -46,7 +46,7 @@ def generate_form(
"values": roles,
"inpType": "select",
"onlyDown": True,
"columns": {"pc": 3, "tablet": 4, " mobile": 12},
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
},
),
input(
@ -55,7 +55,7 @@ def generate_form(
label="users_operation", # keep it (a18n)
value="new" if is_new else "edit", # "new" if new or "edit" if edit
pattern="", # add your pattern if needed
columns={"pc": 3, "tablet": 4, " mobile": 12},
columns={"pc": 3, "tablet": 4, "mobile": 12},
inputClass="hidden", # hide it
),
input(
@ -113,7 +113,7 @@ users_filters = [
"label": "users_search_username", # keep it (a18n)
"value": "",
"inpType": "input",
"columns": {"pc": 3, "tablet": 4, " mobile": 12},
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
},
},
{
@ -127,7 +127,7 @@ users_filters = [
"values": ["all", "antibot"], # keep "all" and add your roles
"inpType": "select",
"onlyDown": True,
"columns": {"pc": 3, "tablet": 4, " mobile": 12},
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
},
},
{
@ -141,7 +141,7 @@ users_filters = [
"values": ["all", "yes", "no"], # keep
"inpType": "select",
"onlyDown": True,
"columns": {"pc": 3, "tablet": 4, " mobile": 12},
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
},
},
]
@ -194,7 +194,7 @@ users_items = [
"label": "users_search_service", # keep it (a18n)
"value": "",
"inpType": "input",
"columns": {"pc": 3, "tablet": 4, " mobile": 12},
"columns": {"pc": 3, "tablet": 4, "mobile": 12},
},
},
],

View file

@ -8,6 +8,7 @@ import ButtonGroup from "@components/Widget/ButtonGroup.vue";
import Regular from "@components/Form/Regular.vue";
import Title from "@components/Widget/Title.vue";
import Subtitle from "@components/Widget/Subtitle.vue";
import MessageUnmatch from "@components/Message/Unmatch.vue";
import { useEqualStr } from "@utils/global.js";
/**
@ -65,6 +66,15 @@ const props = defineProps({
<Grid>
<!-- widget element -->
<template v-for="(widget, index) in container.widgets" :key="index">
<Title v-if="useEqualStr(widget.type, 'Title')" v-bind="widget.data" />
<Subtitle
v-if="useEqualStr(widget.type, 'Subtitle')"
v-bind="widget.data"
/>
<MessageUnmatch
v-if="useEqualStr(widget.type, 'MessageUnmatch')"
v-bind="widget.data"
/>
<Tabulator
v-if="useEqualStr(widget.type, 'Tabulator')"
v-bind="widget.data"
@ -81,11 +91,6 @@ const props = defineProps({
v-if="useEqualStr(widget.type, 'ButtonGroup')"
v-bind="widget.data"
/>
<Title v-if="useEqualStr(widget.type, 'Title')" v-bind="widget.data" />
<Subtitle
v-if="useEqualStr(widget.type, 'Subtitle')"
v-bind="widget.data"
/>
</template>
</Grid>
</GridLayout>

View file

@ -2,11 +2,10 @@
// Containers
import Grid from "@components/Widget/Grid.vue";
import GridLayout from "@components/Widget/GridLayout.vue";
import Tabulator from "@components/Widget/Tabulator.vue";
import MessageUnmatch from "@components/Message/Unmatch.vue";
import Title from "@components/Widget/Title.vue";
import Subtitle from "@components/Widget/Subtitle.vue";
import Table from "@components/Widget/Table.vue";
import ListPairs from "@components/List/Pairs.vue";
import MessageUnmatch from "@components/Message/Unmatch.vue";
import { useEqualStr } from "@utils/global.js";
/**
@ -54,18 +53,17 @@ const props = defineProps({
<Grid>
<!-- widget element -->
<template v-for="(widget, index) in container.widgets" :key="index">
<MessageUnmatch
v-if="useEqualStr(widget.type, 'messageunmatch')"
v-bind="widget.data"
/>
<Title v-if="useEqualStr(widget.type, 'title')" v-bind="widget.data" />
<Title v-if="useEqualStr(widget.type, 'Title')" v-bind="widget.data" />
<Subtitle
v-if="useEqualStr(widget.type, 'subtitle')"
v-if="useEqualStr(widget.type, 'Subtitle')"
v-bind="widget.data"
/>
<Table v-if="useEqualStr(widget.type, 'table')" v-bind="widget.data" />
<ListPairs
v-if="useEqualStr(widget.type, 'listpairs')"
<MessageUnmatch
v-if="useEqualStr(widget.type, 'MessageUnmatch')"
v-bind="widget.data"
/>
<Tabulator
v-if="useEqualStr(widget.type, 'Tabulator')"
v-bind="widget.data"
/>
</template>

View file

@ -40,7 +40,7 @@ const tableStore = useTableStore();
* "label": "bans_search_ip", # keep it (a18n)
* "value": "",
* "inpType": "input",
* "columns": {"pc": 3, "tablet": 4, " mobile": 12},
* "columns": {"pc": 3, "tablet": 4, "mobile": 12},
* },
* }];
* @param {string} id - Unique id of the table
@ -137,7 +137,8 @@ const table = reactive({
reactiveData: true, //enable data reactivity
autoResize: true, // prevent auto resizing of table
resizableRows: true, // this option takes a boolean value (default = false)
layout: "fitColumns",
resizableColumnFit: true, //maintain the fit of columns when resizing
layout: "fitDataTable",
};
if (props.rowHeight) opts.rowHeight = props.rowHeight;
@ -235,10 +236,12 @@ onMounted(() => {
extendTabulator();
table.instance = new Tabulator(tableEl.value, table.options);
table.instance.on("tableBuilt", () => {
table.instance.redraw();
a11yTable(table.instance);
// Add table instance to store in order to use it in other components
tableStore.setTable(props.id, table.instance);
setTimeout(() => {
table.instance.redraw();
}, 100);
});
});

View file

@ -245,31 +245,17 @@
"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 ?",
"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",
"reports_total": "Total reports",
"reports_top_status": "Top status code",
"reports_top_reason": "Top reason",
"reports_subtitle": "List of reports catch by BunkerWeb.",
"reports_not_found": "No reports found",
"reports_search_misc": "Search misc",
"reports_search_misc_desc": "Misc will search within ip, url, user agent or data.",
"reports_select_reason": "Select reason",
"reports_select_reason_desc": "Reason is the plugin that triggered the report.",
"reports_select_method": "Select method",
"reports_select_method_desc": "Method is the http method of the request.",
"reports_select_code": "Select code",
"reports_select_code_desc": "Code is the http status code returned by the request.",
"bans_search": "Search bans",
"bans_search_desc": "Search within ban ip, ban start / end date",
"bans_reason": "Reason",

View file

@ -6,8 +6,8 @@ import { useGlobal } from "@utils/global";
/**
* @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.
* @description This component is the reports page.
This page displays reports and forms to manage them.
*/
const reports = reactive({
@ -20,7 +20,7 @@ onBeforeMount(() => {
const dataEl = document.querySelector(`[${dataAtt}]`);
const data =
dataEl && !dataEl.getAttribute(dataAtt).includes(dataAtt)
? JSON.parse(dataEl.getAttribute(dataAtt))
? JSON.parse(atob(dataEl.getAttribute(dataAtt)))
: {};
reports.builder = data;
});
@ -29,589 +29,10 @@ onMounted(() => {
// Set the page title
useGlobal();
});
const builder = [
{
type: "card",
containerColumns: {
pc: 4,
tablet: 6,
mobile: 12,
},
widgets: [
{
type: "Title",
data: {
title: "dashboard_details",
},
},
{
type: "ListPairs",
data: {
pairs: [
{
key: "reports_total",
value: "200",
},
{
key: "reports_top_status",
value: "400",
},
{
key: "reports_top_reason",
value: "antibot",
},
],
},
},
],
},
{
type: "card",
containerColumns: {
pc: 12,
tablet: 12,
mobile: 12,
},
widgets: [
{
type: "Title",
data: {
title: "reports_title",
},
},
{
type: "Table",
data: {
title: "reports_table_title",
minWidth: "xl",
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",
},
},
{
raw_data:
'{"fesfesfsefesfesfesfesfesfesfesfesfesfsefes": "fesfs"}',
type: "Text",
data: {
text: '{"fesfesfsefesfesfesfesfesfesfesfesfesfsefes": "fesfs"}',
},
},
],
[
{
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",
},
},
{
raw_data: "{}",
type: "Text",
data: {
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",
},
},
{
raw_data: "{}",
type: "Text",
data: {
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",
},
},
{
raw_data: "{}",
type: "Text",
data: {
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",
},
},
{
raw_data: "{}",
type: "Text",
data: {
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",
},
},
{
raw_data: "{}",
type: "Text",
data: {
text: "{}",
},
},
],
],
filters: [
{
filter: "table",
filterName: "keyword",
type: "keyword",
value: "",
keys: ["url", "ip", "date", "user_agent", "raw_data"],
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,
},
},
},
{
filter: "table",
filterName: "country",
type: "select",
value: "all",
keys: ["country"],
field: {
id: "reports-country",
value: "all",
values: ["all", "local", "fr"],
name: "reports-country",
onlyDown: true,
label: "reports_country",
popovers: [
{
text: "reports_country_desc",
iconName: "info",
},
],
columns: {
pc: 3,
tablet: 4,
mobile: 12,
},
},
},
{
filter: "table",
filterName: "method",
type: "select",
value: "all",
keys: ["method"],
field: {
id: "reports-method",
value: "all",
values: ["all", "GET", "POST"],
name: "reports-method",
onlyDown: true,
label: "reports_method",
popovers: [
{
text: "reports_method_desc",
iconName: "info",
},
],
columns: {
pc: 3,
tablet: 4,
mobile: 12,
},
},
},
{
filter: "table",
filterName: "reason",
type: "select",
value: "all",
keys: ["reason"],
field: {
id: "reports-reason",
value: "all",
values: ["all", "modsecurity", " antibot"],
name: "reports-reason",
onlyDown: true,
label: "reports_reason",
popovers: [
{
text: "reports_reason_desc",
iconName: "info",
},
],
columns: {
pc: 3,
tablet: 4,
mobile: 12,
},
},
},
],
},
},
],
},
];
</script>
<template>
<DashboardLayout>
<BuilderReports v-if="builder" :builder="builder" />
<BuilderReports v-if="reports.builder" :builder="reports.builder" />
</DashboardLayout>
</template>

View file

@ -1,3 +1,4 @@
<!doctype html>
<html lang="en">
<head>
@ -11,7 +12,7 @@
<body>
<div
class="hidden"
data-server-global='{"username" : "admin", "plugins_page": [{"id" : "antibot", "name": "Antibot"}, {"id": "backup", "name" : "backup"}]}'
data-server-global='{"username" : "admin", "plugins_page": [{"id" : "antibot", "name": "Antibot"}, {"id": "backup", "name" : "backup"} ]}'
></div>
<div
class="hidden"
@ -19,7 +20,7 @@
></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"}]}}]}]'
data-server-builder='W3sidHlwZSI6ICJjYXJkIiwgIndpZGdldHMiOiBbeyJ0eXBlIjogIlRpdGxlIiwgImRhdGEiOiB7InRpdGxlIjogInJlcG9ydHNfdGl0bGUifX0sIHsidHlwZSI6ICJTdWJ0aXRsZSIsICJkYXRhIjogeyJzdWJ0aXRsZSI6ICJyZXBvcnRzX3N1YnRpdGxlIn19LCB7InR5cGUiOiAiVGFidWxhdG9yIiwgImRhdGEiOiB7ImlkIjogInRhYmxlLWNvcmUtcGx1Z2lucyIsICJjb2x1bW5zIjogW3sidGl0bGUiOiAiRGF0ZSIsICJmaWVsZCI6ICJkYXRlIiwgImZvcm1hdHRlciI6ICJmaWVsZHMiLCAibWluV2lkdGgiOiAyNTB9LCB7InRpdGxlIjogIklQIiwgImZpZWxkIjogImlwIiwgImZvcm1hdHRlciI6ICJ0ZXh0In0sIHsidGl0bGUiOiAiQ291bnRyeSIsICJmaWVsZCI6ICJjb3VudHJ5IiwgImZvcm1hdHRlciI6ICJ0ZXh0In0sIHsidGl0bGUiOiAiU2VydmVyIG5hbWUiLCAiZmllbGQiOiAic2VydmVyX25hbWUiLCAiZm9ybWF0dGVyIjogInRleHQifSwgeyJ0aXRsZSI6ICJNZXRob2QiLCAiZmllbGQiOiAibWV0aG9kIiwgImZvcm1hdHRlciI6ICJ0ZXh0In0sIHsidGl0bGUiOiAiVVJMIiwgImZpZWxkIjogInVybCIsICJmb3JtYXR0ZXIiOiAidGV4dCJ9LCB7InRpdGxlIjogIkNvZGUiLCAiZmllbGQiOiAiY29kZSIsICJmb3JtYXR0ZXIiOiAidGV4dCJ9LCB7InRpdGxlIjogIlVzZXIgYWdlbnQiLCAiZmllbGQiOiAidXNlcl9hZ2VudCIsICJmb3JtYXR0ZXIiOiAidGV4dCJ9LCB7InRpdGxlIjogIlJlYXNvbiIsICJmaWVsZCI6ICJyZWFzb24iLCAiZm9ybWF0dGVyIjogInRleHQifSwgeyJ0aXRsZSI6ICJEYXRhIiwgImZpZWxkIjogImRhdGEiLCAiZm9ybWF0dGVyIjogInRleHQifV0sICJpdGVtcyI6IFt7ImRhdGUiOiB7InNldHRpbmciOiB7ImxhYmVsIjogInJlcG9ydHNfZGF0ZSIsICJuYW1lIjogImRhdGVwaWNrZXItZGF0ZS0wIiwgImlkIjogImRhdGVwaWNrZXItZGF0ZS0wIiwgInZhbHVlIjogMTcyMzQ5MTczOTk1NCwgImhpZGVMYWJlbCI6IHRydWUsICJkaXNhYmxlZCI6IHRydWUsICJpbnBUeXBlIjogImRhdGVwaWNrZXIifX0sICJzZXJ2ZXJfbmFtZSI6IHsidGV4dCI6ICJsb2NhbGhvc3QifSwgImlwIjogeyJ0ZXh0IjogIjEyNy4wLjAuMSJ9LCAiY291bnRyeSI6IHsidGV4dCI6ICJFTiJ9LCAibWV0aG9kIjogeyJ0ZXh0IjogIlBPU1QifSwgInVybCI6IHsidGV4dCI6ICIvYWRtaW4ifSwgImNvZGUiOiB7InRleHQiOiAiNDAwIn0sICJ1c2VyX2FnZW50IjogeyJ0ZXh0IjogIk1vemlsbGEvNS4wIn0sICJyZWFzb24iOiB7InRleHQiOiAiYW50aWJvdCJ9LCAiZGF0YSI6IHsidGV4dCI6ICJsb3JlIGlwc3VtIGFkIHZpdGFtIGFldGVybmFtIn19LCB7ImRhdGUiOiB7InNldHRpbmciOiB7ImxhYmVsIjogInJlcG9ydHNfZGF0ZSIsICJuYW1lIjogImRhdGVwaWNrZXItZGF0ZS0xIiwgImlkIjogImRhdGVwaWNrZXItZGF0ZS0xIiwgInZhbHVlIjogMTcyMzQ5MTczODAwMCwgImhpZGVMYWJlbCI6IHRydWUsICJkaXNhYmxlZCI6IHRydWUsICJpbnBUeXBlIjogImRhdGVwaWNrZXIifX0sICJzZXJ2ZXJfbmFtZSI6IHsidGV4dCI6ICJsb2NhbGhvc3QifSwgImlwIjogeyJ0ZXh0IjogIjEyNy4wLjAuMiJ9LCAiY291bnRyeSI6IHsidGV4dCI6ICJFTiJ9LCAibWV0aG9kIjogeyJ0ZXh0IjogIkdFVCJ9LCAidXJsIjogeyJ0ZXh0IjogIi9ldGM/In0sICJjb2RlIjogeyJ0ZXh0IjogIjMwMCJ9LCAidXNlcl9hZ2VudCI6IHsidGV4dCI6ICJNb3ppbGxhLzAuMSJ9LCAicmVhc29uIjogeyJ0ZXh0IjogInVua25vd24ifSwgImRhdGEiOiB7InRleHQiOiAiIn19XSwgImZpbHRlcnMiOiBbeyJ0eXBlIjogImxpa2UiLCAiZmllbGRzIjogWyJpcCIsICJ1cmwiLCAidXNlcl9hZ2VudCIsICJkYXRhIl0sICJzZXR0aW5nIjogeyJpZCI6ICJpbnB1dC1zZWFyY2gtbWlzYyIsICJuYW1lIjogImlucHV0LXNlYXJjaC1taXNjIiwgImxhYmVsIjogInJlcG9ydHNfc2VhcmNoX21pc2MiLCAidmFsdWUiOiAiIiwgImlucFR5cGUiOiAiaW5wdXQiLCAiY29sdW1ucyI6IHsicGMiOiAzLCAidGFibGV0IjogNCwgIm1vYmlsZSI6IDEyfSwgInBvcG92ZXJzIjogW3siaWNvbk5hbWUiOiAiaW5mbyIsICJ0ZXh0IjogInJlcG9ydHNfc2VhcmNoX21pc2NfZGVzYyJ9XX19LCB7InR5cGUiOiAiPSIsICJmaWVsZHMiOiBbInJlYXNvbiJdLCAic2V0dGluZyI6IHsiaWQiOiAic2VsZWN0LXJlYXNvbiIsICJuYW1lIjogInNlbGVjdC1yZWFzb24iLCAibGFiZWwiOiAicmVwb3J0c19zZWxlY3RfcmVhc29uIiwgInZhbHVlIjogImFsbCIsICJ2YWx1ZXMiOiBbImFsbCIsICJhbnRpYm90IiwgInVua25vd24iXSwgImlucFR5cGUiOiAic2VsZWN0IiwgIm9ubHlEb3duIjogdHJ1ZSwgImNvbHVtbnMiOiB7InBjIjogMywgInRhYmxldCI6IDQsICJtb2JpbGUiOiAxMn0sICJwb3BvdmVycyI6IFt7Imljb25OYW1lIjogImluZm8iLCAidGV4dCI6ICJyZXBvcnRzX3NlbGVjdF9yZWFzb25fZGVzYyJ9XX19LCB7InR5cGUiOiAiPSIsICJmaWVsZHMiOiBbIm1ldGhvZCJdLCAic2V0dGluZyI6IHsiaWQiOiAic2VsZWN0LW1ldGhvZCIsICJuYW1lIjogInNlbGVjdC1tZXRob2QiLCAibGFiZWwiOiAicmVwb3J0c19zZWxlY3RfbWV0aG9kIiwgInZhbHVlIjogImFsbCIsICJ2YWx1ZXMiOiBbImFsbCIsICJQT1NUIiwgIkdFVCJdLCAiaW5wVHlwZSI6ICJzZWxlY3QiLCAib25seURvd24iOiB0cnVlLCAiY29sdW1ucyI6IHsicGMiOiAzLCAidGFibGV0IjogNCwgIm1vYmlsZSI6IDEyfSwgInBvcG92ZXJzIjogW3siaWNvbk5hbWUiOiAiaW5mbyIsICJ0ZXh0IjogInJlcG9ydHNfc2VsZWN0X21ldGhvZF9kZXNjIn1dfX0sIHsidHlwZSI6ICI9IiwgImZpZWxkcyI6IFsiY29kZSJdLCAic2V0dGluZyI6IHsiaWQiOiAic2VsZWN0LWNvZGUiLCAibmFtZSI6ICJzZWxlY3QtY29kZSIsICJsYWJlbCI6ICJyZXBvcnRzX3NlbGVjdF9jb2RlIiwgInZhbHVlIjogImFsbCIsICJ2YWx1ZXMiOiBbImFsbCIsICIzMDAiLCAiNDAwIl0sICJpbnBUeXBlIjogInNlbGVjdCIsICJvbmx5RG93biI6IHRydWUsICJjb2x1bW5zIjogeyJwYyI6IDMsICJ0YWJsZXQiOiA0LCAibW9iaWxlIjogMTJ9LCAicG9wb3ZlcnMiOiBbeyJpY29uTmFtZSI6ICJpbmZvIiwgInRleHQiOiAicmVwb3J0c19zZWxlY3RfY29kZV9kZXNjIn1dfX1dfX1dfV0='
></div>
<div id="app"></div>
<script type="module" src="reports.js"></script>

View file

@ -8,6 +8,7 @@ import { contentIndex } from "@utils/tabindex.js";
/**
* @name addColumnsWidth
* @description Add min and max width to the column object in case we have the right format.
* Case already a custom max or min width, will be ignored.
* @param {Object} column - The column object to update in case we have the right format.
* @param {String|Number} [colMinWidth=0] - The minimum width for the column. Case 0 or invalid, will be ignored.
* @param {String|Number} [colMaxWidth=0] - The minimum width for the column. Case 0 or invalid, will be ignored.
@ -15,8 +16,10 @@ import { contentIndex } from "@utils/tabindex.js";
*/
function addColumnsWidth(column, colMinWidth = 0, colMaxWidth = 0) {
try {
if (+colMinWidth > 0) column.minWidth = colMinWidth;
if (+colMaxWidth > 0) column.maxWidth = colMaxWidth;
if (+colMinWidth > 0 && !("minWidth" in column))
column.minWidth = colMinWidth;
if (+colMaxWidth > 0 && !("maxWidth" in column))
column.maxWidth = colMaxWidth;
} catch (e) {
console.error(e);
}