Initial commit of a log capture and reporting feature

This adds a new section to the admin panel called "Activity", that
supplies charts, graphs and details about messages entering and leaving
the host.

A new daemon captures details of system mail activity by monitoring
the /var/log/mail.log file, summarizing it into a sqllite database
that's kept in user-data.
This commit is contained in:
downtownallday committed 2021-01-11 18:02:07 -05:00
1 parent 73a2b72243
commit 2a0e50c8d4
108 files changed
+9027 -6

No files matched your search

+92
View File
@@ -0,0 +1,92 @@
class Me {
/* construct with return value from GET /me */
constructor(me) {
Object.assign(this, me);
}
is_authenticated() {
return this.api_key || this.user_id;
}
get_email() {
return this.user_email || this.user_id;
}
};
/*
* axios interceptors for authentication
*/
function init_axios_interceptors() {
// requests: attach non-session based auth (admin panel)
axios.interceptors.request.use(request => {
var api_credentials = null;
// code from templates/index.html for "recall saved user
// credentials" (but, without the split(':'))
if (typeof sessionStorage != 'undefined' && sessionStorage.getItem("miab-cp-credentials"))
api_credentials = sessionStorage.getItem("miab-cp-credentials");
else if (typeof localStorage != 'undefined' && localStorage.getItem("miab-cp-credentials"))
api_credentials = localStorage.getItem("miab-cp-credentials");
// end
if (api_credentials) {
request.headers.authorization = 'Basic ' + window.btoa(api_credentials);
}
return request;
});
// reponses: redirect on authorization failure
axios.interceptors.response.use(
response => {
if (response.data &&
response.data.status === 'invalid' &&
response.config.headers.authorization)
{
var url = response.config.url;
if (response.config.baseURL) {
var sep = ( response.config.baseURL.substr(-1) != '/' ?
'/' : '' );
url = response.config.baseURL + sep + url;
}
if (url == '/admin/me')
{
// non-session/admin login
throw new AuthenticationError(
null,
'not authenticated',
response
);
}
}
return response;
},
error => {
const auth_required_msg = 'Authentication required - you have been logged out of the server';
if (! error.response) {
throw error;
}
if (error.response.status == 403 &&
error.response.data == 'login_required')
{
// session login
throw new AuthenticationError(error, auth_required_msg);
}
else if ((error.response.status == 403 ||
error.response.status == 401) &&
error.response.data &&
error.response.data.status == 'error')
{
// admin
throw new AuthenticationError(error, auth_required_msg);
}
throw error;
}
);
}
+18
View File
@@ -0,0 +1,18 @@
class ValueError extends Error {
constructor(msg) {
super(msg);
}
};
class AssertionError extends Error {
}
class AuthenticationError extends Error {
constructor(caused_by_error, msg, response) {
super(msg);
this.caused_by = caused_by_error;
this.response = response;
if (!response && caused_by_error)
this.response = caused_by_error.response;
}
};
+11
View File
@@ -0,0 +1,11 @@
<div class="text-center">
<h2 class="mb-0">{{ header_text }}</h2>
<small class="text-white-50">from the <a href="https://github.com/downtownallday/mailinabox-ldap/" target="_blank" class="text-white-50">MiaB-LDAP project</a></small>
<div class="d-flex align-items-center justify-content-between" style="margin-top:-1.5rem">
<div class="ml-1" style="min-width:1em">
<spinner v-show="loading_counter > 0"></spinner>
</div>
<slot name="links"><div>&nbsp;</div></slot>
</div>
</div>
+19
View File
@@ -0,0 +1,19 @@
Vue.component('spinner', {
template: '<span class="spinner-border spinner-border-sm"></span>'
});
Vue.component('page-header', function(resolve, reject) {
axios.get('ui-common/page-header.html').then((response) => { resolve({
props: {
header_text: { type: String, required: true },
loading_counter: { type: Number, required: true }
},
template: response.data
})}).catch((e) => {
reject(e);
});
});
+8
View File
@@ -0,0 +1,8 @@
<div>
<div class="bg-dark text-white p-1">
<slot name="header"></slot>
</div>
<div class="bg-light text-dark p-1">
<slot></slot>
</div>
</div>
+10
View File
@@ -0,0 +1,10 @@
Vue.component('page-layout', function(resolve, reject) {
axios.get('ui-common/page-layout.html').then((response) => { resolve({
template: response.data,
})}).catch((e) => {
reject(e);
});
});
+1
View File
@@ -0,0 +1 @@
node_modules/
+35
View File
@@ -0,0 +1,35 @@
#!/bin/bash
#
# install bootstrap sources
#
if [ ! -e "node_modules/bootstrap" ]; then
npm install bootstrap
if [ $? -ne 0 ]; then
echo "Installing bootstrap using npm failed. Is npm install on your system?"
exit 1
fi
fi
#
# install sass compiler
#
compiler="/usr/bin/sassc"
if [ ! -x "$compiler" ]; then
sudo apt-get install sassc || exit 1
fi
#
# compile our theme
#
b_dir="node_modules/bootstrap/scss"
$compiler -I "$b_dir" --sourcemap --style compressed theme.scss ../ui-bootstrap.css
if [ $? -eq 0 ]; then
echo "SUCCESS - files:"
ls -sh ../ui-bootstrap.*
fi
+14
View File
@@ -0,0 +1,14 @@
{
"name": "theme",
"version": "1.0.0",
"description": "",
"dependencies": {
"bootstrap": "^4.5.3"
},
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "GPL-3.0-or-later"
}
+95
View File
@@ -0,0 +1,95 @@
/* variable overrides */
$white: #fff;
$gray-100: #f8f9fa;
$gray-200: #e9ecef;
$gray-300: #dee2e6;
$gray-400: #ced4da;
$gray-500: #adb5bd;
$gray-600: #6c757d;
$gray-700: #495057;
$gray-800: #343a40;
$gray-900: #212529;
$black: #000;
$blue: cadetblue;
$primary: #446599; //#96a5b2;
$secondary: $gray-600; //#d8dfe5; //#f5f5f5;
$success: #b7dfb8;
$info: #ffd6b0;
$warning: #f0e68c;
$danger: #a91409;
$light: $gray-100;
$dark: #303e45;
$body-bg: $gray-100; //$blue;
$body-color: $dark;
$card-color: $gray-900;
$card-spacer-x: 0.75rem;
$card-spacer-y: 0.25rem;
$table-color: $dark;
$table-cell-padding: 0.375rem; // .75rem;
$table-cell-padding-sm: 0.15rem; // .3rem;
$font-size-base: 0.85rem; // Assumes the browser default, typically `16px`
$input-btn-padding-y: .25rem; // .375rem !default;
$input-btn-padding-x: .5rem; // .75rem !default;
$input-btn-padding-y-sm: .12rem; // .25rem !default;
$input-btn-padding-x-sm: .25rem; // .5rem !default;
//$input-btn-padding-y-lg: .5rem !default;
//$input-btn-padding-x-lg: 1rem !default;
$alert-padding-y: .25rem;
$alert-padding-x: .75rem;
// $list-group-item-padding-y: .75rem !default;
// $list-group-item-padding-x: 1.25rem !default;
$nav-link-padding-y: 0.20rem;
/* bootstrap styles that we want */
@import "functions";
@import "variables";
@import "mixins";
@import "root";
@import "reboot";
@import "type";
@import "images";
@import "code";
@import "grid";
@import "tables";
@import "forms";
@import "buttons";
@import "transitions";
@import "dropdown";
@import "button-group";
@import "input-group";
/* @import "custom-forms"; */
@import "nav";
@import "navbar";
@import "card";
@import "breadcrumb";
@import "pagination";
@import "badge";
/* @import "jumbotron"; */
@import "alert";
@import "progress";
/* @import "media"; */
@import "list-group";
@import "close";
@import "toasts";
@import "modal";
@import "tooltip";
@import "popover";
/* @import "carousel"; */
@import "spinners";
@import "utilities";
/* @import "print"; */
+3
View File
@@ -0,0 +1,3 @@
:root{--blue: #5f9ea0;--indigo: #6610f2;--purple: #6f42c1;--pink: #e83e8c;--red: #dc3545;--orange: #fd7e14;--yellow: #ffc107;--green: #28a745;--teal: #20c997;--cyan: #17a2b8;--white: #fff;--gray: #6c757d;--gray-dark: #343a40;--primary: #446599;--secondary: #6c757d;--success: #b7dfb8;--info: #ffd6b0;--warning: khaki;--danger: #a91409;--light: #f8f9fa;--dark: #303e45;--breakpoint-xs: 0;--breakpoint-sm: 576px;--breakpoint-md: 768px;--breakpoint-lg: 992px;--breakpoint-xl: 1200px;--font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}*,*::before,*::after{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:.85rem;font-weight:400;line-height:1.5;color:#303e45;text-align:left;background-color:#f8f9fa}[tabindex="-1"]:focus:not(:focus-visible){outline:0 !important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[title],abbr[data-original-title]{text-decoration:underline;text-decoration:underline dotted;cursor:help;border-bottom:0;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul,dl{margin-top:0;margin-bottom:1rem}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#446599;text-decoration:none;background-color:transparent}a:hover{color:#2c4264;text-decoration:underline}a:not([href]):not([class]){color:inherit;text-decoration:none}a:not([href]):not([class]):hover{color:inherit;text-decoration:none}pre,code,kbd,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.375rem;padding-bottom:.375rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit;text-align:-webkit-match-parent}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}input,button,select,optgroup,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role="button"]{cursor:pointer}select{word-wrap:normal}button,[type="button"],[type="reset"],[type="submit"]{-webkit-appearance:button}button:not(:disabled),[type="button"]:not(:disabled),[type="reset"]:not(:disabled),[type="submit"]:not(:disabled){cursor:pointer}button::-moz-focus-inner,[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner{padding:0;border-style:none}input[type="radio"],input[type="checkbox"]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{outline-offset:-2px;-webkit-appearance:none}[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none !important}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}h1,.h1{font-size:2.125rem}h2,.h2{font-size:1.7rem}h3,.h3{font-size:1.4875rem}h4,.h4{font-size:1.275rem}h5,.h5{font-size:1.0625rem}h6,.h6{font-size:.85rem}.lead{font-size:1.0625rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,0.1)}small,.small{font-size:80%;font-weight:400}mark,.mark{padding:.2em;bacLine truncated
/*# sourceMappingURL=ui-bootstrap.css.map */
+91
View File
@@ -0,0 +1,91 @@
{
"version": 3,
"file": "ui-bootstrap.css",
"sources": [
"theme/theme.scss",
"theme/node_modules/bootstrap/scss/_functions.scss",
"theme/node_modules/bootstrap/scss/_variables.scss",
"theme/node_modules/bootstrap/scss/_mixins.scss",
"theme/node_modules/bootstrap/scss/vendor/_rfs.scss",
"theme/node_modules/bootstrap/scss/mixins/_deprecate.scss",
"theme/node_modules/bootstrap/scss/mixins/_breakpoints.scss",
"theme/node_modules/bootstrap/scss/mixins/_hover.scss",
"theme/node_modules/bootstrap/scss/mixins/_image.scss",
"theme/node_modules/bootstrap/scss/mixins/_badge.scss",
"theme/node_modules/bootstrap/scss/mixins/_resize.scss",
"theme/node_modules/bootstrap/scss/mixins/_screen-reader.scss",
"theme/node_modules/bootstrap/scss/mixins/_size.scss",
"theme/node_modules/bootstrap/scss/mixins/_reset-text.scss",
"theme/node_modules/bootstrap/scss/mixins/_text-emphasis.scss",
"theme/node_modules/bootstrap/scss/mixins/_text-hide.scss",
"theme/node_modules/bootstrap/scss/mixins/_text-truncate.scss",
"theme/node_modules/bootstrap/scss/mixins/_visibility.scss",
"theme/node_modules/bootstrap/scss/mixins/_alert.scss",
"theme/node_modules/bootstrap/scss/mixins/_buttons.scss",
"theme/node_modules/bootstrap/scss/mixins/_caret.scss",
"theme/node_modules/bootstrap/scss/mixins/_pagination.scss",
"theme/node_modules/bootstrap/scss/mixins/_lists.scss",
"theme/node_modules/bootstrap/scss/mixins/_list-group.scss",
"theme/node_modules/bootstrap/scss/mixins/_nav-divider.scss",
"theme/node_modules/bootstrap/scss/mixins/_forms.scss",
"theme/node_modules/bootstrap/scss/mixins/_table-row.scss",
"theme/node_modules/bootstrap/scss/mixins/_background-variant.scss",
"theme/node_modules/bootstrap/scss/mixins/_border-radius.scss",
"theme/node_modules/bootstrap/scss/mixins/_box-shadow.scss",
"theme/node_modules/bootstrap/scss/mixins/_gradients.scss",
"theme/node_modules/bootstrap/scss/mixins/_transition.scss",
"theme/node_modules/bootstrap/scss/mixins/_clearfix.scss",
"theme/node_modules/bootstrap/scss/mixins/_grid-framework.scss",
"theme/node_modules/bootstrap/scss/mixins/_grid.scss",
"theme/node_modules/bootstrap/scss/mixins/_float.scss",
"theme/node_modules/bootstrap/scss/_root.scss",
"theme/node_modules/bootstrap/scss/_reboot.scss",
"theme/node_modules/bootstrap/scss/_type.scss",
"theme/node_modules/bootstrap/scss/_images.scss",
"theme/node_modules/bootstrap/scss/_code.scss",
"theme/node_modules/bootstrap/scss/_grid.scss",
"theme/node_modules/bootstrap/scss/_tables.scss",
"theme/node_modules/bootstrap/scss/_forms.scss",
"theme/node_modules/bootstrap/scss/_buttons.scss",
"theme/node_modules/bootstrap/scss/_transitions.scss",
"theme/node_modules/bootstrap/scss/_dropdown.scss",
"theme/node_modules/bootstrap/scss/_button-group.scss",
"theme/node_modules/bootstrap/scss/_input-group.scss",
"theme/node_modules/bootstrap/scss/_nav.scss",
"theme/node_modules/bootstrap/scss/_navbar.scss",
"theme/node_modules/bootstrap/scss/_card.scss",
"theme/node_modules/bootstrap/scss/_breadcrumb.scss",
"theme/node_modules/bootstrap/scss/_pagination.scss",
"theme/node_modules/bootstrap/scss/_badge.scss",
"theme/node_modules/bootstrap/scss/_alert.scss",
"theme/node_modules/bootstrap/scss/_progress.scss",
"theme/node_modules/bootstrap/scss/_list-group.scss",
"theme/node_modules/bootstrap/scss/_close.scss",
"theme/node_modules/bootstrap/scss/_toasts.scss",
"theme/node_modules/bootstrap/scss/_modal.scss",
"theme/node_modules/bootstrap/scss/_tooltip.scss",
"theme/node_modules/bootstrap/scss/_popover.scss",
"theme/node_modules/bootstrap/scss/_spinners.scss",
"theme/node_modules/bootstrap/scss/_utilities.scss",
"theme/node_modules/bootstrap/scss/utilities/_align.scss",
"theme/node_modules/bootstrap/scss/utilities/_background.scss",
"theme/node_modules/bootstrap/scss/utilities/_borders.scss",
"theme/node_modules/bootstrap/scss/utilities/_clearfix.scss",
"theme/node_modules/bootstrap/scss/utilities/_display.scss",
"theme/node_modules/bootstrap/scss/utilities/_embed.scss",
"theme/node_modules/bootstrap/scss/utilities/_flex.scss",
"theme/node_modules/bootstrap/scss/utilities/_float.scss",
"theme/node_modules/bootstrap/scss/utilities/_interactions.scss",
"theme/node_modules/bootstrap/scss/utilities/_overflow.scss",
"theme/node_modules/bootstrap/scss/utilities/_position.scss",
"theme/node_modules/bootstrap/scss/utilities/_screenreaders.scss",
"theme/node_modules/bootstrap/scss/utilities/_shadows.scss",
"theme/node_modules/bootstrap/scss/utilities/_sizing.scss",
"theme/node_modules/bootstrap/scss/utilities/_spacing.scss",
"theme/node_modules/bootstrap/scss/utilities/_stretched-link.scss",
"theme/node_modules/bootstrap/scss/utilities/_text.scss",
"theme/node_modules/bootstrap/scss/utilities/_visibility.scss"
],
"names": [],
"mappings": "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 truncated
}
+30
View File
@@ -0,0 +1,30 @@
:hover {
--hover-bg-color: #ccc;
}
/* fix visibility of calendar icon in bootstrap vue component */
.b-form-datepicker g {
fill: var(--dark);
}
/* make table header sticky at 0 */
.sticky-table-header-0 thead {
position: sticky;
background-color: #fff;
top: 0;
}
.cursor-pointer {
cursor:pointer;
}
.cursor-default {
cursor:default;
}
.clickme {
cursor:pointer;
}
.clickme:hover {
background-color: var(--hover-bg-color);
}