feat: frontend
This commit is contained in:
parent
875c0cc258
commit
4a7b66b481
7 changed files with 847 additions and 0 deletions
556
src/static/assets/index/scripts.js
Normal file
556
src/static/assets/index/scripts.js
Normal file
|
|
@ -0,0 +1,556 @@
|
|||
class Auth {
|
||||
constructor() {
|
||||
this.url = "http://localhost:8000"
|
||||
this.settings = {
|
||||
authority: "https://sso.sr2.uk/realms/sr2",
|
||||
client_id: "chris-dev",
|
||||
redirect_uri: this.url + "/signin-callback.html",
|
||||
response_type: "code",
|
||||
scope: "openid email profile",
|
||||
|
||||
response_mode: "fragment",
|
||||
}
|
||||
|
||||
this.user_manager = new oidc.UserManager(this.settings)
|
||||
this.get_user().then(() => {
|
||||
window.is_authenticated = Boolean(this.user);
|
||||
ui.update_auth_button()
|
||||
})
|
||||
}
|
||||
|
||||
async get_user() {
|
||||
this.user = await this.user_manager.getUser()
|
||||
}
|
||||
|
||||
async login() {
|
||||
try {
|
||||
this.user = await this.user_manager.signinPopup();
|
||||
window.is_authenticated = Boolean(auth.user);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async logout() {
|
||||
try {
|
||||
this.user = await this.user_manager.signoutPopup();
|
||||
window.is_authenticated = Boolean(auth.user);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class UI {
|
||||
constructor() {
|
||||
this.auth_button = document.getElementById("auth_button");
|
||||
|
||||
this.blocked_domains = document.getElementById("blocked_domains")
|
||||
this.timer_status = document.getElementById("timer_status")
|
||||
this.overall_status = document.getElementById("overall_status")
|
||||
this.last_update_complete_time = document.getElementById("last_update_complete_time")
|
||||
this.last_update_duration = document.getElementById("last_update_duration")
|
||||
|
||||
this.manual_update_btn = document.getElementById("manual_update_btn")
|
||||
this.start_timer_btn = document.getElementById("start_timer_btn")
|
||||
this.stop_timer_btn = document.getElementById("stop_timer_btn")
|
||||
|
||||
this.domain_search_btn = document.getElementById("domain_search_btn")
|
||||
|
||||
this.false_positive_load_btn = document.getElementById("false_positive_load_btn")
|
||||
this.event_container = document.getElementById("events_container")
|
||||
|
||||
this.create_listeners()
|
||||
}
|
||||
|
||||
create_listeners() {
|
||||
this.auth_button.addEventListener("click", this.onclick_auth_button)
|
||||
|
||||
this.manual_update_btn.addEventListener("click", this.onclick_manual_update_btn)
|
||||
this.start_timer_btn.addEventListener("click", this.onclick_start_timer_btn)
|
||||
this.stop_timer_btn.addEventListener("click", this.onclick_stop_timer_btn)
|
||||
|
||||
this.domain_search_btn.addEventListener("click", this.onclick_domain_search_btn)
|
||||
|
||||
this.false_positive_load_btn.addEventListener("click", this.onclick_false_positive_load_btn)
|
||||
this.event_container.addEventListener("click", this.onclick_event_button)
|
||||
|
||||
document.getElementById("modal_button").addEventListener("click", this.onclick_modal_button)
|
||||
}
|
||||
|
||||
open_modal(title, message) {
|
||||
document.getElementById("modal_title").innerText = title;
|
||||
document.getElementById("modal_message").innerText = message;
|
||||
|
||||
document.getElementById("modal_backdrop").style.display = "flex";
|
||||
}
|
||||
|
||||
set_loading(button_id, loading) {
|
||||
const button = document.getElementById(button_id);
|
||||
|
||||
button.disabled = loading;
|
||||
|
||||
if (loading) {
|
||||
button.dataset.original_text = button.innerText;
|
||||
button.innerText = "Loading...";
|
||||
} else {
|
||||
button.innerText = button.dataset.original_text;
|
||||
}
|
||||
}
|
||||
|
||||
sync_timer_buttons() {
|
||||
this.start_timer_btn.disabled = timer_running;
|
||||
this.stop_timer_btn.disabled = !timer_running;
|
||||
}
|
||||
|
||||
render_search_results(results) {
|
||||
const container = document.getElementById("domain_search_results");
|
||||
const result_count = Object.keys(results).length;
|
||||
if (!result_count) {
|
||||
container.innerHTML = `<div class="search-result">No results found.</div>`;
|
||||
return;
|
||||
}
|
||||
container.innerHTML = "";
|
||||
for (const [key, value] of Object.entries(results)) {
|
||||
const row = document.createElement("div");
|
||||
row.className = "search-result";
|
||||
row.innerHTML = `
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
${key}
|
||||
</div>
|
||||
|
||||
<div class="col-4 ${ui.event_status_class(value)}">
|
||||
${value}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
container.appendChild(row);
|
||||
}
|
||||
}
|
||||
|
||||
onclick_auth_button() {
|
||||
if (is_authenticated) {
|
||||
auth.logout().then(() => {
|
||||
ui.update_auth_button()
|
||||
})
|
||||
} else {
|
||||
auth.login().then(() => {
|
||||
ui.update_auth_button()
|
||||
})
|
||||
}
|
||||
ui.update_auth_button()
|
||||
}
|
||||
|
||||
update_auth_button() {
|
||||
const button = document.getElementById("auth_button");
|
||||
|
||||
if (is_authenticated) {
|
||||
button.innerText = "Logged In";
|
||||
button.className = "button default-dm success";
|
||||
} else {
|
||||
button.innerText = "Logged Out";
|
||||
button.className = "button default-dm secondary";
|
||||
}
|
||||
}
|
||||
|
||||
event_status_class(value) {
|
||||
switch (value.toUpperCase()) {
|
||||
case "ALLOWED":
|
||||
return "status-good";
|
||||
case "IGNORED":
|
||||
return "status-warning";
|
||||
default:
|
||||
return "status-bad";
|
||||
}
|
||||
}
|
||||
|
||||
update_metrics(metrics){
|
||||
this.blocked_domains.innerHTML = metrics.blocked_domain_count;
|
||||
|
||||
let date
|
||||
let pretty_length
|
||||
if(!metrics.last_update_complete_time){
|
||||
date = "No update since last restart"
|
||||
pretty_length = ""
|
||||
} else {
|
||||
date = new Date(metrics.last_update_complete_time * 1000).toLocaleString();
|
||||
pretty_length = `${Math.round(metrics.last_update_length)} seconds`
|
||||
}
|
||||
this.last_update_complete_time.innerHTML = date;
|
||||
this.last_update_duration.innerHTML = pretty_length;
|
||||
|
||||
let timer_value = ""
|
||||
switch (metrics.TIMER_STATE) {
|
||||
case 0:
|
||||
timer_value = "RUNNING"
|
||||
window.timer_running = true;
|
||||
break;
|
||||
case 1:
|
||||
timer_value = "STOPPING"
|
||||
window.timer_running = true;
|
||||
break;
|
||||
case 2:
|
||||
timer_value = "STOPPED"
|
||||
window.timer_running = false;
|
||||
break;
|
||||
}
|
||||
this.timer_status.innerHTML = timer_value;
|
||||
this.timer_status.className = timer_running ? "status-good" : "status-warning";
|
||||
this.sync_timer_buttons()
|
||||
|
||||
let overall_status = ""
|
||||
switch (metrics.MISP_STATE) {
|
||||
case 0:
|
||||
overall_status = "IDLE"
|
||||
break;
|
||||
case 1:
|
||||
overall_status = "FETCHING"
|
||||
break;
|
||||
case 2:
|
||||
overall_status = "UPDATING"
|
||||
break;
|
||||
case 3:
|
||||
overall_status = "RELOADING"
|
||||
break;
|
||||
case 4:
|
||||
overall_status = "ERROR"
|
||||
break;
|
||||
}
|
||||
this.overall_status.innerHTML = overall_status;
|
||||
}
|
||||
|
||||
render_false_positive_controls(domain_data) {
|
||||
document.getElementById("false_positive_actions").style.display = "block";
|
||||
const always_allow_btn = document.getElementById("always_allow_btn");
|
||||
|
||||
always_allow_btn.innerText = domain_data.always_allow ? "Enabled" : "Disabled";
|
||||
always_allow_btn.className = domain_data.always_allow ? "button default-dm success" : "button default-dm secondary";
|
||||
always_allow_btn.dataset.domain = domain_data.domain;
|
||||
always_allow_btn.dataset.always_allow = domain_data.always_allow;
|
||||
|
||||
always_allow_btn.addEventListener("click", ui.onclick_always_allow_btn)
|
||||
|
||||
ui.event_container.innerHTML = "";
|
||||
|
||||
domain_data.events.forEach(event => {
|
||||
const button = document.createElement("button");
|
||||
|
||||
button.className = `button event-btn ${event.ignored ? "default-dm warning" : "default-dm danger" }`;
|
||||
button.innerText = event.id;
|
||||
button.dataset.id = event.id;
|
||||
button.dataset.ignored = event.ignored
|
||||
button.dataset.domain = domain_data.domain;
|
||||
|
||||
ui.event_container.appendChild(button);
|
||||
});
|
||||
}
|
||||
|
||||
async onclick_manual_update_btn() {
|
||||
ui.set_loading("manual_update_btn", true);
|
||||
try {
|
||||
const data = await api.manual_update()
|
||||
if(data.state==="Starting"){
|
||||
ui.open_modal(
|
||||
"Update Triggered",
|
||||
"Manual update process successfully started."
|
||||
);
|
||||
} else {
|
||||
throw new Error()
|
||||
}
|
||||
} catch (error) {
|
||||
ui.open_modal(
|
||||
"Update Failed",
|
||||
"Failed to trigger update process."
|
||||
);
|
||||
} finally {
|
||||
ui.set_loading("manual_update_btn", false);
|
||||
}
|
||||
}
|
||||
|
||||
async onclick_start_timer_btn() {
|
||||
ui.set_loading("start_timer_btn", true);
|
||||
try {
|
||||
const data = await api.start_timer()
|
||||
api.update_metrics()
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
ui.set_loading("start_timer_btn", false);
|
||||
}
|
||||
}
|
||||
|
||||
async onclick_stop_timer_btn() {
|
||||
ui.set_loading("stop_timer_btn", true);
|
||||
try {
|
||||
const data = await api.stop_timer()
|
||||
api.update_metrics()
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
ui.set_loading("stop_timer_btn", false);
|
||||
}
|
||||
}
|
||||
|
||||
async onclick_domain_search_btn(){
|
||||
ui.set_loading("domain_search_btn", true);
|
||||
try {
|
||||
const data = await api.domain_search()
|
||||
ui.render_search_results(data)
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
ui.set_loading("domain_search_btn", false);
|
||||
}
|
||||
}
|
||||
|
||||
async load_false_positive_controls(){
|
||||
ui.set_loading("false_positive_load_btn", true);
|
||||
try {
|
||||
const data = await api.load_domain_fp()
|
||||
const parsed_data= {
|
||||
domain: data.domain,
|
||||
always_allow: data.always_allowed,
|
||||
events: []
|
||||
}
|
||||
|
||||
data.events.forEach(event => {
|
||||
parsed_data.events.push({"id": event, "ignored": data.ignored_events.includes(event)});
|
||||
})
|
||||
|
||||
ui.render_false_positive_controls(parsed_data)
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
ui.set_loading("false_positive_load_btn", false);
|
||||
}
|
||||
}
|
||||
|
||||
async onclick_false_positive_load_btn(){
|
||||
await ui.load_false_positive_controls()
|
||||
}
|
||||
|
||||
async onclick_event_button(event){
|
||||
if (event.target === event.currentTarget) return;
|
||||
const event_id = event.target.dataset.id;
|
||||
const domain = event.target.dataset.domain;
|
||||
const ignored = event.target.dataset.ignored === "true";
|
||||
try {
|
||||
if(ignored){
|
||||
await api.reinstate_event(domain, event_id)
|
||||
} else {
|
||||
await api.ignore_event(domain, event_id)
|
||||
}
|
||||
await ui.load_false_positive_controls()
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async onclick_always_allow_btn(event){
|
||||
const domain = event.target.dataset.domain;
|
||||
const always_allowed = event.target.dataset.always_allow === "true";
|
||||
try {
|
||||
await api.change_always_allow(domain, always_allowed)
|
||||
await ui.load_false_positive_controls()
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
onclick_modal_button() {
|
||||
document.getElementById("modal_backdrop").style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
class API {
|
||||
constructor() {
|
||||
const self = this
|
||||
this.update_metrics()
|
||||
this.metrics_timer = setInterval(self.update_metrics, 5000)
|
||||
}
|
||||
|
||||
update_metrics() {
|
||||
axios.get(`misp/dashboard_metrics`)
|
||||
.then(response => {
|
||||
ui.update_metrics(response.data);
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
|
||||
async manual_update(published_timestamp = null){
|
||||
const user = await auth.get_user()
|
||||
return axios.put(
|
||||
`misp/manual_update`,
|
||||
{
|
||||
"published_timestamp": published_timestamp
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
"Authorization": `Bearer ${user?.access_token}`
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
.then(response => {
|
||||
return response.data
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
|
||||
async start_timer(){
|
||||
const user = await auth.get_user()
|
||||
return axios.put(
|
||||
`control/start_timer`,
|
||||
{},
|
||||
{
|
||||
headers: {
|
||||
"Authorization": `Bearer ${user?.access_token}`
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
.then(response => {
|
||||
return response.data
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
|
||||
async stop_timer(){
|
||||
const user = await auth.get_user()
|
||||
return axios.put(
|
||||
`control/stop_timer`,
|
||||
{},
|
||||
{
|
||||
headers: {
|
||||
"Authorization": `Bearer ${user?.access_token}`
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
.then(response => {
|
||||
return response.data
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
|
||||
async domain_search(){
|
||||
const user = await auth.get_user()
|
||||
const search_term = document.getElementById("domain_search_input").value
|
||||
return axios.get(
|
||||
`misp/domain/search?domain=${search_term}`,
|
||||
{},
|
||||
{
|
||||
headers: {
|
||||
"Authorization": `Bearer ${user?.access_token}`
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
.then(response => {
|
||||
return response.data
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
|
||||
async load_domain_fp(){
|
||||
const user = await auth.get_user()
|
||||
const search_term = document.getElementById("false_positive_domain").value
|
||||
return axios.get(
|
||||
`/misp/domain/details/${search_term}`,
|
||||
{},
|
||||
{
|
||||
headers: {
|
||||
"Authorization": `Bearer ${user?.access_token}`
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
.then(response => {
|
||||
return response.data
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
|
||||
async ignore_event(domain, event_id){
|
||||
const user = await auth.get_user()
|
||||
return axios.patch(
|
||||
`/misp/domain/events/${domain}/ignore?event=${event_id}`,
|
||||
{},
|
||||
{
|
||||
headers: {
|
||||
"Authorization": `Bearer ${user?.access_token}`
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
.then(response => {
|
||||
return response.data
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
|
||||
async reinstate_event(domain, event_id){
|
||||
const user = await auth.get_user()
|
||||
return axios.patch(
|
||||
`/misp/domain/events/${domain}/reinstate?event=${event_id}`,
|
||||
{},
|
||||
{
|
||||
headers: {
|
||||
"Authorization": `Bearer ${user?.access_token}`
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
.then(response => {
|
||||
return response.data
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
|
||||
async change_always_allow(domain, currently_allowed){
|
||||
const user = await auth.get_user()
|
||||
return axios.patch(
|
||||
`/misp/domain/always_allowed/${domain}?allow=${!currently_allowed}`,
|
||||
{},
|
||||
{
|
||||
headers: {
|
||||
"Authorization": `Bearer ${user?.access_token}`
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
.then(response => {
|
||||
return response.data
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
window.onload = () => {
|
||||
window.ui = new UI()
|
||||
window.auth = new Auth()
|
||||
window.api = new API()
|
||||
|
||||
window.timer_running = false;
|
||||
|
||||
ui.sync_timer_buttons();
|
||||
}
|
||||
120
src/static/assets/index/styles.css
Normal file
120
src/static/assets/index/styles.css
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
body {
|
||||
margin: 0;
|
||||
padding: 24px;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 48px;
|
||||
}
|
||||
|
||||
#auth_button {
|
||||
max-height: 2.5rem;
|
||||
}
|
||||
|
||||
.card {
|
||||
border: 1px solid #333;
|
||||
border-radius: 8px;
|
||||
padding: 18px;
|
||||
margin-bottom: 20px;
|
||||
background-color: light-dark(#eee, #171717);
|
||||
}
|
||||
|
||||
.card h2 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.label {
|
||||
display: block;
|
||||
margin-bottom: 6px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.input {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
border: 1px solid #444;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.button {
|
||||
padding: 10px 14px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.button:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.status-good {
|
||||
color: #4ade80;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.status-bad {
|
||||
color: #f87171;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.status-warning {
|
||||
color: #facc15;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.summary-row {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.search-results {
|
||||
margin-top: 12px;
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
border: 1px solid #333;
|
||||
}
|
||||
|
||||
.search-result {
|
||||
padding: 10px;
|
||||
border-bottom: 1px solid #333;
|
||||
}
|
||||
|
||||
.event-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.event-btn {
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
.top-bar {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.modal-backdrop {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.65);
|
||||
display: none;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modal {
|
||||
width: 400px;
|
||||
background: #1c1c1c;
|
||||
border: 1px solid #444;
|
||||
border-radius: 8px;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
margin-top: 20px;
|
||||
text-align: right;
|
||||
}
|
||||
105
src/static/index.html
Normal file
105
src/static/index.html
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>Title</title>
|
||||
<link rel="stylesheet" href="/libraries/luxgrid_combined.min.css"/>
|
||||
<link rel="stylesheet" href="/assets/index/styles.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="row top-bar">
|
||||
<div class="col-2 justify-start">Logo</div>
|
||||
<div class="col-8 text-center title">Title</div>
|
||||
<div class="col-2 justify-end">
|
||||
<button id="auth_button" class="button default-dm success">Logged In</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h2>System Status</h2>
|
||||
<div class="row">
|
||||
<div class="col-3 summary-row">
|
||||
<div class="label">Total Blocked Domains</div>
|
||||
<div id="blocked_domains"></div>
|
||||
</div>
|
||||
<div class="col-3 summary-row">
|
||||
<div class="label">Timer Status</div>
|
||||
<div id="timer_status" class="status-warning"></div>
|
||||
</div>
|
||||
<div class="col-3 summary-row">
|
||||
<div class="label">Overall Status</div>
|
||||
<div id="overall_status" class="status-good"></div>
|
||||
</div>
|
||||
<div class="col-3 summary-row">
|
||||
<div class="label">Last Update</div>
|
||||
<div id="last_update_complete_time"></div>
|
||||
<div id="last_update_duration"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h2>Actions</h2>
|
||||
<div class="row">
|
||||
<div class="col-4">
|
||||
<button id="manual_update_btn" class="button default-dm primary w-100">Manual Update</button>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<button id="start_timer_btn" class="button default-dm success w-100" disabled>Start Timer</button>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<button id="stop_timer_btn" class="button default-dm danger w-100">Stop Timer</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h2>Domain Search</h2>
|
||||
<label class="label">Search</label>
|
||||
<input id="domain_search_input" class="input" type="text" placeholder="partial domain"/>
|
||||
<div style="margin-top:12px;">
|
||||
<button id="domain_search_btn" class="button default-dm primary">Search</button>
|
||||
</div>
|
||||
<div id="domain_search_results" class="search-results"></div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h2>False Positive Handling</h2>
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
<label class="label">Domain</label>
|
||||
<input id="false_positive_domain" class="input" type="text" placeholder="domain to manage"/>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<label class="label"> </label>
|
||||
<button id="false_positive_load_btn" class="button default-dm primary w-100">Load</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="false_positive_actions" style="display:none; margin-top:20px;">
|
||||
<div class="row align-center">
|
||||
<div class="col-4">
|
||||
<div class="label">Always Allow</div>
|
||||
</div>
|
||||
<div class="col-8">
|
||||
<button id="always_allow_btn" class="button default-dm secondary">Disabled</button>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-top:20px;">
|
||||
<div class="label">Events</div>
|
||||
<div id="events_container" class="event-grid"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="modal_backdrop" class="modal-backdrop">
|
||||
<div class="modal">
|
||||
<h3 id="modal_title">Status</h3>
|
||||
<div id="modal_message"></div>
|
||||
<div class="modal-footer">
|
||||
<button id="modal_button" class="button default-dm primary">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/libraries/axios.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/oidc-client-ts/3.3.0/browser/oidc-client-ts.min.js" integrity="sha512-c2vT43K5Ap/b44ZVGj+uRqqM/RQFtqludEYk8ztxzAPWcPJaKPSGpJRcbo1c2/PdszmNUvPqOzWERCKqT+P1Xg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<script src="/assets/index/scripts.js" type="module"></script>
|
||||
</body>
|
||||
</html>
|
||||
5
src/static/libraries/axios.min.js
vendored
Normal file
5
src/static/libraries/axios.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/static/libraries/luxgrid_combined.min.css
vendored
Normal file
1
src/static/libraries/luxgrid_combined.min.css
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
body,button,input,select,textarea{color:light-dark(black,var(--dm-text-colour))}.col,[class*=col-]{padding-left:15px;padding-right:15px;box-sizing:border-box;min-width:8.33%}:root{color-scheme:light dark;--dm-text-colour:#e0e0e0;--primary-bg:#007bff;--secondary-bg:#6c757d;--success-bg:#28a745;--danger-bg:#dc3545;--warning-bg:#ffc107;--info-bg:#17a2b8;--light-bg:#f8f9fa;--dark-bg:#343a40;--light-bg-text:#212529;--dark-bg-text:white}.danger,.info,.light,.primary,.secondary,.success,.warning{color:var(--light-bg-text)}body{background-color:light-dark(white,#121212)}button{background-color:light-dark(#f0f0f0,#333);border-color:light-dark(white,#555);border-radius:2px}button:hover{background-color:light-dark(#e5e5e5,#555);border-color:light-dark(white,#666)}input,select,textarea{background-color:light-dark(#fafafa,#1e1e1e);border-style:solid;border-width:1px;border-color:light-dark(black,#333)}input:focus,select:focus,textarea:focus{border-color:light-dark(black,#036);border-radius:2px;outline:solid 2px}h1,h2,h3,h4,h5,h6{color:light-dark(black,#fff)}.default{background-color:var(--base-bg-colour)}.default-dm{background-color:light-dark(var(--base-bg-colour),oklch(from var(--base-bg-colour) clamp(0,l + .22,1) clamp(0,c - .02,1) h))}.lighten{background-color:oklch(from var(--base-bg-colour) clamp(0,l + .27,1) c h)}.darken{background-color:oklch(from var(--base-bg-colour) clamp(0,l - .09,1) c h)}.subtle{background-color:rgba(from var(--base-bg-colour) r g b / .6)}.primary{--base-bg-colour:var(--primary-bg)}.secondary{--base-bg-colour:var(--secondary-bg)}.success{--base-bg-colour:var(--success-bg)}.danger{--base-bg-colour:var(--danger-bg)}.warning{--base-bg-colour:var(--warning-bg)}.info{--base-bg-colour:var(--info-bg)}.light{--base-bg-colour:var(--light-bg)}.dark{--base-bg-colour:var(--dark-bg);color:var(--dark-bg-text)}.container{width:100%;margin-left:auto;margin-right:auto;padding-left:15px;padding-right:15px;box-sizing:border-box}.row{display:flex;margin-bottom:5px;flex-wrap:wrap}.col{flex:1;max-width:100%}.col-1{width:8.33%}.col-2{width:16.66%}.col-3,.w-25{width:25%}.col-4{width:33.33%}.col-5{width:41.66%}.col-6,.w-50{width:50%}.col-7{width:58.33%}.col-8{width:66.66%}.col-9,.w-75{width:75%}.col-10{width:83.33%}.col-11{width:91.66%}.col-12,.w-100{width:100%}@media (min-width:576px){.col-sm-1{width:8.33%}.col-sm-2{width:16.66%}.col-sm-3{width:25%}.col-sm-4{width:33.33%}.col-sm-5{width:41.66%}.col-sm-6{width:50%}.col-sm-7{width:58.33%}.col-sm-8{width:66.66%}.col-sm-9{width:75%}.col-sm-10{width:83.33%}.col-sm-11{width:91.66%}.col-sm-12{width:100%}}@media (min-width:768px){.col-md-1{width:8.33%}.col-md-2{width:16.66%}.col-md-3{width:25%}.col-md-4{width:33.33%}.col-md-5{width:41.66%}.col-md-6{width:50%}.col-md-7{width:58.33%}.col-md-8{width:66.66%}.col-md-9{width:75%}.col-md-10{width:83.33%}.col-md-11{width:91.66%}.col-md-12{width:100%}}@media (min-width:992px){.col-lg-1{width:8.33%}.col-lg-2{width:16.66%}.col-lg-3{width:25%}.col-lg-4{width:33.33%}.col-lg-5{width:41.66%}.col-lg-6{width:50%}.col-lg-7{width:58.33%}.col-lg-8{width:66.66%}.col-lg-9{width:75%}.col-lg-10{width:83.33%}.col-lg-11{width:91.66%}.col-lg-12{width:100%}}@media (min-width:1200px){.col-xl-1{width:8.33%}.col-xl-2{width:16.66%}.col-xl-3{width:25%}.col-xl-4{width:33.33%}.col-xl-5{width:41.66%}.col-xl-6{width:50%}.col-xl-7{width:58.33%}.col-xl-8{width:66.66%}.col-xl-9{width:75%}.col-xl-10{width:83.33%}.col-xl-11{width:91.66%}.col-xl-12{width:100%}}.axis-vert{flex-direction:column}.axis-horz{flex-direction:row}.justify-start{display:flex;justify-content:flex-start}.justify-end{display:flex;justify-content:flex-end}.justify-center{display:flex;justify-content:center}.justify-between{display:flex;justify-content:space-between}.justify-around{display:flex;justify-content:space-around}.justify-evenly{display:flex;justify-content:space-evenly}.align-start{display:flex;align-items:flex-start}.align-end{display:flex;align-items:flex-end}.align-center{display:flex;align-items:center}.h-25{height:25%}.h-50{height:50%}.h-75{height:75%}.h-100{height:100%}.vh-25{height:25vh}.vh-50{height:50vh}.vh-75{height:75vh}.vh-100{height:100vh}.vw-25{width:25vw}.vw-50{width:50vw}.vw-75{width:75vw}.vw-100{width:100vw}.text-center{text-align:center}.text-left{text-align:start}.text-right{text-align:end}
|
||||
30
src/static/signin-callback.html
Normal file
30
src/static/signin-callback.html
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/oidc-client-ts/3.3.0/browser/oidc-client-ts.min.js"></script>
|
||||
|
||||
<script>
|
||||
const url = "http://localhost:8000"
|
||||
const settings = {
|
||||
authority: "https://sso.sr2.uk/realms/sr2",
|
||||
client_id: "chris-dev",
|
||||
redirect_uri: url + "/",
|
||||
response_type: "code",
|
||||
scope: "openid email profile",
|
||||
|
||||
response_mode: "fragment",
|
||||
}
|
||||
|
||||
const user_manager = new oidc.UserManager(settings)
|
||||
|
||||
user_manager.signinPopupCallback()
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
30
src/static/signout-callback.html
Normal file
30
src/static/signout-callback.html
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/oidc-client-ts/3.3.0/browser/oidc-client-ts.min.js"></script>
|
||||
|
||||
<script>
|
||||
const url = "http://localhost:8000"
|
||||
const settings = {
|
||||
authority: "https://sso.sr2.uk/realms/sr2",
|
||||
client_id: "chris-dev",
|
||||
redirect_uri: url + "/",
|
||||
response_type: "code",
|
||||
scope: "openid email profile",
|
||||
|
||||
response_mode: "fragment",
|
||||
}
|
||||
|
||||
const user_manager = new oidc.UserManager(settings)
|
||||
|
||||
user_manager.signoutPopupCallback()
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue