You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ponymail.apache.org by hu...@apache.org on 2021/03/31 12:01:24 UTC
[incubator-ponymail-foal] branch master updated (55c4bb4 -> 1a1f265)
This is an automated email from the ASF dual-hosted git repository.
humbedooh pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-ponymail-foal.git.
from 55c4bb4 convert to proper List-ID format AFTER asserts
new 5665ef6 assert doc ID is string
new 527ee16 Add audit log plugin for server
new aa8e9da use audit log plugin for writing log entries
new eafb066 add 'log' command for viewing the log
new 4785f21 no need for time, audit log plugin handles it
new 84ee468 PEP8 linting
new 6a18426 fix type test bugs
new 374adfc fix type warnings
new 2fabfdb allow filtering for certain actions
new fe6f4be fix type test warnings
new 78334dc filter to only show edit/remove actions for now
new bd8bfc5 Add a simple starter for viewing audit logs
new 081921c Allow loading more log entries into the viw
new 1a1f265 regenerate
The 14 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
server/endpoints/mgmt.py | 54 ++++++++++++---------------
server/plugins/auditlog.py | 92 ++++++++++++++++++++++++++++++++++++++++++++++
webui/css/scaffolding.css | 18 ++++++++-
webui/js/ponymail.js | 60 ++++++++++++++++++++++++++++++
webui/js/source/mgmt.js | 60 ++++++++++++++++++++++++++++++
5 files changed, 253 insertions(+), 31 deletions(-)
create mode 100644 server/plugins/auditlog.py
[incubator-ponymail-foal] 01/14: assert doc ID is string
Posted by hu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
humbedooh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-ponymail-foal.git
commit 5665ef6572837178714e35b524bd978d1978a67d
Author: Daniel Gruno <hu...@apache.org>
AuthorDate: Wed Mar 31 11:01:32 2021 +0200
assert doc ID is string
---
server/endpoints/mgmt.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/server/endpoints/mgmt.py b/server/endpoints/mgmt.py
index fcc9f02..b93e869 100644
--- a/server/endpoints/mgmt.py
+++ b/server/endpoints/mgmt.py
@@ -41,6 +41,7 @@ async def process(
if action == "delete":
delcount = 0
for doc in docs:
+ assert isinstance(doc, str), "Document ID must be a string"
email = await plugins.mbox.get_email(session, permalink=doc)
if email and isinstance(email, dict) and plugins.aaa.can_access_email(session, email):
email["deleted"] = True
[incubator-ponymail-foal] 10/14: fix type test warnings
Posted by hu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
humbedooh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-ponymail-foal.git
commit fe6f4be0ba7a1e42e72d89e21c8364aafbc94c7d
Author: Daniel Gruno <hu...@apache.org>
AuthorDate: Wed Mar 31 12:43:24 2021 +0200
fix type test warnings
---
server/plugins/auditlog.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/server/plugins/auditlog.py b/server/plugins/auditlog.py
index 51ac108..ad94d16 100644
--- a/server/plugins/auditlog.py
+++ b/server/plugins/auditlog.py
@@ -44,7 +44,7 @@ class AuditLogEntry:
async def view(
- session: plugins.session.SessionObject, page: int = 0, num_entries: int = 50, raw: bool = False, filter: typing.List[str] = []
+ session: plugins.session.SessionObject, page: int = 0, num_entries: int = 50, raw: bool = False, filter: typing.Tuple = ()
) -> typing.AsyncGenerator:
""" Returns N entries from the audit log, paginated """
assert session.database, "No database connection could be found!"
[incubator-ponymail-foal] 11/14: filter to only show edit/remove
actions for now
Posted by hu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
humbedooh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-ponymail-foal.git
commit 78334dc1480d7511fbe2798eda23ad54c5fc3984
Author: Daniel Gruno <hu...@apache.org>
AuthorDate: Wed Mar 31 12:43:48 2021 +0200
filter to only show edit/remove actions for now
---
server/endpoints/mgmt.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/server/endpoints/mgmt.py b/server/endpoints/mgmt.py
index b30ee2f..d800d1d 100644
--- a/server/endpoints/mgmt.py
+++ b/server/endpoints/mgmt.py
@@ -43,7 +43,7 @@ async def process(
numentries = int(indata.get("size", 50))
page = int(indata.get("page", 0))
out = []
- async for entry in plugins.auditlog.view(session, page=page, num_entries=numentries, raw=True):
+ async for entry in plugins.auditlog.view(session, page=page, num_entries=numentries, raw=True, filter=("edit", "delete",)):
out.append(entry)
return {
"entries": out
[incubator-ponymail-foal] 06/14: PEP8 linting
Posted by hu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
humbedooh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-ponymail-foal.git
commit 84ee468a59f7715c21b20a18df2badd543601362
Author: Daniel Gruno <hu...@apache.org>
AuthorDate: Wed Mar 31 12:20:28 2021 +0200
PEP8 linting
---
server/plugins/auditlog.py | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/server/plugins/auditlog.py b/server/plugins/auditlog.py
index 197dd25..0d54ff9 100644
--- a/server/plugins/auditlog.py
+++ b/server/plugins/auditlog.py
@@ -26,7 +26,16 @@ import time
class AuditLogEntry:
- _keys: tuple = ("id", "date", "action", "remote", "author","target", "lid", "log", )
+ _keys: tuple = (
+ "id",
+ "date",
+ "action",
+ "remote",
+ "author",
+ "target",
+ "lid",
+ "log",
+ )
def __init__(self, doc):
for key in self._keys:
@@ -34,13 +43,12 @@ class AuditLogEntry:
setattr(self, key, doc[key])
-async def view(session: plugins.session.SessionObject, page: int = 0, num_entries: int = 50, raw: bool = False) -> typing.List[dict]:
+async def view(
+ session: plugins.session.SessionObject, page: int = 0, num_entries: int = 50, raw: bool = False
+) -> typing.List[dict]:
""" Returns N entries from the audit log, paginated """
res = await session.database.search(
- index=session.database.dbs.auditlog,
- size=num_entries,
- from_=page*num_entries,
- sort="date:desc",
+ index=session.database.dbs.auditlog, size=num_entries, from_=page * num_entries, sort="date:desc",
)
for doc in res["hits"]["hits"]:
doc["_source"]["id"] = doc["_id"]
@@ -49,6 +57,7 @@ async def view(session: plugins.session.SessionObject, page: int = 0, num_entrie
else:
yield AuditLogEntry(doc["_source"])
+
async def add_entry(session: plugins.session.SessionObject, action: str, target: str, lid: str, log: str):
""" Adds an entry to the audit log"""
[incubator-ponymail-foal] 02/14: Add audit log plugin for server
Posted by hu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
humbedooh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-ponymail-foal.git
commit 527ee16c279a9da385eeaa47047de902c977607e
Author: Daniel Gruno <hu...@apache.org>
AuthorDate: Wed Mar 31 12:16:30 2021 +0200
Add audit log plugin for server
This will ONLY have add or view commands, audit log should be
append-only.
---
server/plugins/auditlog.py | 72 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 72 insertions(+)
diff --git a/server/plugins/auditlog.py b/server/plugins/auditlog.py
new file mode 100644
index 0000000..197dd25
--- /dev/null
+++ b/server/plugins/auditlog.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+This is the Audit log library for Pony Mail codename Foal
+It manages viewing and editing the audit log.
+"""
+
+import plugins.session
+import typing
+import time
+
+
+class AuditLogEntry:
+ _keys: tuple = ("id", "date", "action", "remote", "author","target", "lid", "log", )
+
+ def __init__(self, doc):
+ for key in self._keys:
+ if key in doc:
+ setattr(self, key, doc[key])
+
+
+async def view(session: plugins.session.SessionObject, page: int = 0, num_entries: int = 50, raw: bool = False) -> typing.List[dict]:
+ """ Returns N entries from the audit log, paginated """
+ res = await session.database.search(
+ index=session.database.dbs.auditlog,
+ size=num_entries,
+ from_=page*num_entries,
+ sort="date:desc",
+ )
+ for doc in res["hits"]["hits"]:
+ doc["_source"]["id"] = doc["_id"]
+ if raw:
+ yield doc["_source"]
+ else:
+ yield AuditLogEntry(doc["_source"])
+
+async def add_entry(session: plugins.session.SessionObject, action: str, target: str, lid: str, log: str):
+ """ Adds an entry to the audit log"""
+
+ # Default log entries based on type
+ if not log and action == "delete":
+ log = f"Removed email {target} from {lid} archives"
+ if not log and action == "edit":
+ log = f"Modified email {target} from {lid} archives"
+
+ await session.database.index(
+ index=session.database.dbs.auditlog,
+ body={
+ "date": time.strftime("%Y/%m/%d %H:%M:%S", time.gmtime(time.time())),
+ "action": action,
+ "remote": session.remote,
+ "author": f"{session.credentials.uid}@{session.credentials.oauth_provider}",
+ "target": target,
+ "lid": lid,
+ "log": log,
+ },
+ )
[incubator-ponymail-foal] 07/14: fix type test bugs
Posted by hu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
humbedooh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-ponymail-foal.git
commit 6a18426b8fa433dea1de16ede43766512e4eaae0
Author: Daniel Gruno <hu...@apache.org>
AuthorDate: Wed Mar 31 12:24:02 2021 +0200
fix type test bugs
---
server/plugins/auditlog.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/server/plugins/auditlog.py b/server/plugins/auditlog.py
index 0d54ff9..fb5eeae 100644
--- a/server/plugins/auditlog.py
+++ b/server/plugins/auditlog.py
@@ -45,8 +45,9 @@ class AuditLogEntry:
async def view(
session: plugins.session.SessionObject, page: int = 0, num_entries: int = 50, raw: bool = False
-) -> typing.List[dict]:
+) -> typing.AsyncGenerator:
""" Returns N entries from the audit log, paginated """
+ assert session.database, "No database connection could be found!"
res = await session.database.search(
index=session.database.dbs.auditlog, size=num_entries, from_=page * num_entries, sort="date:desc",
)
@@ -66,7 +67,8 @@ async def add_entry(session: plugins.session.SessionObject, action: str, target:
log = f"Removed email {target} from {lid} archives"
if not log and action == "edit":
log = f"Modified email {target} from {lid} archives"
-
+ assert session.credentials, "No session credentials could be found!"
+ assert session.database, "Session not connected to database!"
await session.database.index(
index=session.database.dbs.auditlog,
body={
[incubator-ponymail-foal] 13/14: Allow loading more log entries
into the viw
Posted by hu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
humbedooh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-ponymail-foal.git
commit 081921ca2ec4f58846a9c76a99de4c30ea800d6d
Author: Daniel Gruno <hu...@apache.org>
AuthorDate: Wed Mar 31 14:01:05 2021 +0200
Allow loading more log entries into the viw
---
webui/js/source/mgmt.js | 43 +++++++++++++++++++++++++++++--------------
1 file changed, 29 insertions(+), 14 deletions(-)
diff --git a/webui/js/source/mgmt.js b/webui/js/source/mgmt.js
index 6f087fb..7f725f4 100644
--- a/webui/js/source/mgmt.js
+++ b/webui/js/source/mgmt.js
@@ -1,4 +1,7 @@
let admin_current_email = null;
+let audit_entries = []
+let audit_page = 0;
+let audit_size = 30;
async function POST(url, formdata, state) {
const resp = await fetch(url, {
@@ -136,20 +139,28 @@ function admin_email_preview(stats, json) {
}
function admin_audit_view(state, json) {
+ let headers = ['Date', 'Author','Remote','Action','Target', 'Log'];
let cp = document.getElementById("panel");
- let div = new HTML('div', { style: { margin: '5px'}});
- cp.inject(div);
-
- div.inject(new HTML('h1', {}, "Audit log:"));
- if (json.entries && json.entries.length > 0) {
- let table = new HTML('table', {border: "1", class:"auditlog_entries"});
- let trh = new HTML('tr');
- let headers = ['Date', 'Author','Remote','Action','Target', 'Log'];
- for (let i = 0; i < headers.length; i++) {
- let th = new HTML('th', {}, headers[i] + ":");
- trh.inject(th);
+ let div = document.getElementById('auditlog_entries');
+ if (!div) {
+ div = new HTML('div', { id: "auditlog", style: { margin: '5px'}});
+ cp.inject(div);
+ div.inject(new HTML('h1', {}, "Audit log:"));
+ }
+ let table = document.getElementById('auditlog_entries');
+ if (json.entries && json.entries.length > 0 || table) {
+ if (!table) {
+ table = new HTML('table', {border: "1", id: "auditlog_entries", class:"auditlog_entries"});
+ let trh = new HTML('tr');
+ for (let i = 0; i < headers.length; i++) {
+ let th = new HTML('th', {}, headers[i] + ":");
+ trh.inject(th);
+ }
+ table.inject(trh)
+ div.inject(table);
+ let btn = new HTML('button', {onclick: "admin_audit_next();"}, "Load more entries");
+ div.inject(btn);
}
- table.inject(trh)
for (let i = 0; i < json.entries.length; i++) {
let entry = json.entries[i];
let tr = new HTML('tr', {class: "auditlog_entry"});
@@ -172,12 +183,16 @@ function admin_audit_view(state, json) {
}
table.inject(tr);
}
- div.inject(table);
} else {
div.inject("Audit log is empty");
}
+}
+function admin_audit_next() {
+ audit_page++;
+ GET('%sapi/mgmt.json?action=log&page=%u&size=%u'.format(apiURL, audit_page, audit_size), admin_audit_view, null);
}
+
function admin_init() {
let mid = location.href.split('/').pop();
// Specific email/list handling?
@@ -191,6 +206,6 @@ function admin_init() {
GET('%sapi/email.json?id=%s'.format(apiURL, mid), admin_email_preview, null);
}
} else { // View audit log
- GET('%sapi/mgmt.json?action=log'.format(apiURL), admin_audit_view, null);
+ GET('%sapi/mgmt.json?action=log&page=%s&size=%u'.format(apiURL, audit_page, audit_size), admin_audit_view, null);
}
}
\ No newline at end of file
[incubator-ponymail-foal] 14/14: regenerate
Posted by hu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
humbedooh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-ponymail-foal.git
commit 1a1f2650f0046059bef1170648b99466d91a85b8
Author: Daniel Gruno <hu...@apache.org>
AuthorDate: Wed Mar 31 14:01:10 2021 +0200
regenerate
---
webui/js/ponymail.js | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 60 insertions(+)
diff --git a/webui/js/ponymail.js b/webui/js/ponymail.js
index a5e6d98..23c1624 100644
--- a/webui/js/ponymail.js
+++ b/webui/js/ponymail.js
@@ -2428,6 +2428,9 @@ function listview_threaded_element(thread, idx) {
******************************************/
let admin_current_email = null;
+let audit_entries = []
+let audit_page = 0;
+let audit_size = 30;
async function POST(url, formdata, state) {
const resp = await fetch(url, {
@@ -2564,6 +2567,61 @@ function admin_email_preview(stats, json) {
div.inject(new HTML('small', {}, "Emails that are removed may still be recovered by the base system administrator. For complete expungement, please contact the system administrator."))
}
+function admin_audit_view(state, json) {
+ let headers = ['Date', 'Author','Remote','Action','Target', 'Log'];
+ let cp = document.getElementById("panel");
+ let div = document.getElementById('auditlog_entries');
+ if (!div) {
+ div = new HTML('div', { id: "auditlog", style: { margin: '5px'}});
+ cp.inject(div);
+ div.inject(new HTML('h1', {}, "Audit log:"));
+ }
+ let table = document.getElementById('auditlog_entries');
+ if (json.entries && json.entries.length > 0 || table) {
+ if (!table) {
+ table = new HTML('table', {border: "1", id: "auditlog_entries", class:"auditlog_entries"});
+ let trh = new HTML('tr');
+ for (let i = 0; i < headers.length; i++) {
+ let th = new HTML('th', {}, headers[i] + ":");
+ trh.inject(th);
+ }
+ table.inject(trh)
+ div.inject(table);
+ let btn = new HTML('button', {onclick: "admin_audit_next();"}, "Load more entries");
+ div.inject(btn);
+ }
+ for (let i = 0; i < json.entries.length; i++) {
+ let entry = json.entries[i];
+ let tr = new HTML('tr', {class: "auditlog_entry"});
+ for (let i = 0; i < headers.length; i++) {
+ let key = headers[i].toLowerCase();
+ let value = entry[key];
+ if (key == 'target') {
+ value = new HTML('a', {href: "/admin/" +value}, value);
+ }
+ if (key == 'action') {
+ let action_colors = {
+ edit: 'blue',
+ delete: 'red',
+ default: 'black'
+ };
+ value = new HTML('spam', {style: {color: action_colors[value] ? action_colors[value] : action_colors['default']}}, value);
+ }
+ let th = new HTML('td', {}, value);
+ tr.inject(th);
+ }
+ table.inject(tr);
+ }
+ } else {
+ div.inject("Audit log is empty");
+ }
+}
+
+function admin_audit_next() {
+ audit_page++;
+ GET('%sapi/mgmt.json?action=log&page=%u&size=%u'.format(apiURL, audit_page, audit_size), admin_audit_view, null);
+}
+
function admin_init() {
let mid = location.href.split('/').pop();
// Specific email/list handling?
@@ -2576,6 +2634,8 @@ function admin_init() {
else {
GET('%sapi/email.json?id=%s'.format(apiURL, mid), admin_email_preview, null);
}
+ } else { // View audit log
+ GET('%sapi/mgmt.json?action=log&page=%s&size=%u'.format(apiURL, audit_page, audit_size), admin_audit_view, null);
}
}
[incubator-ponymail-foal] 03/14: use audit log plugin for writing
log entries
Posted by hu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
humbedooh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-ponymail-foal.git
commit aa8e9daede3da9e99e35e76970b9c5525bd3615e
Author: Daniel Gruno <hu...@apache.org>
AuthorDate: Wed Mar 31 12:16:45 2021 +0200
use audit log plugin for writing log entries
---
server/endpoints/mgmt.py | 29 +++++------------------------
1 file changed, 5 insertions(+), 24 deletions(-)
diff --git a/server/endpoints/mgmt.py b/server/endpoints/mgmt.py
index b93e869..f13dd0f 100644
--- a/server/endpoints/mgmt.py
+++ b/server/endpoints/mgmt.py
@@ -21,6 +21,7 @@ import plugins.server
import plugins.session
import plugins.mbox
import plugins.defuzzer
+import plugins.auditlog
import typing
import aiohttp.web
import time
@@ -49,18 +50,7 @@ async def process(
index=session.database.dbs.mbox, body=email, id=email["id"],
)
lid = email.get("list_raw")
- await session.database.index(
- index=session.database.dbs.auditlog,
- body={
- "date": time.strftime("%Y/%m/%d %H:%M:%S", time.gmtime(time.time())),
- "action": "delete",
- "remote": session.remote,
- "author": f"{session.credentials.uid}@{session.credentials.oauth_provider}",
- "target": doc,
- "lid": lid,
- "log": f"Removed email {doc} from {lid} archives",
- },
- )
+ await plugins.auditlog.add_entry(session, action="delete", target=doc, lid=lid, log=f"Removed email {doc} from {lid} archives")
delcount += 1
return aiohttp.web.Response(headers={}, status=200, text=f"Removed {delcount} emails from archives.")
# Editing an email in place
@@ -106,18 +96,9 @@ async def process(
index=session.database.dbs.source, body=source, id=email["id"],
)
- await session.database.index(
- index=session.database.dbs.auditlog,
- body={
- "date": time.strftime("%Y/%m/%d %H:%M:%S", time.gmtime(time.time())),
- "action": "edit",
- "remote": session.remote,
- "author": f"{session.credentials.uid}@{session.credentials.oauth_provider}",
- "target": doc,
- "lid": origin_lid,
- "log": f"Edited email {doc} from {origin_lid} archives ({origin_lid} -> {lid})",
- },
- )
+ await plugins.auditlog.add_entry(session, action="edit", target=doc, lid=lid,
+ log= f"Edited email {doc} from {origin_lid} archives ({origin_lid} -> {lid})")
+
return aiohttp.web.Response(headers={}, status=200, text=f"Email successfully saved")
return aiohttp.web.Response(headers={}, status=404, text=f"Email not found!")
[incubator-ponymail-foal] 04/14: add 'log' command for viewing the
log
Posted by hu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
humbedooh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-ponymail-foal.git
commit eafb066a1f99db99ecc7abd297f79f523022b01d
Author: Daniel Gruno <hu...@apache.org>
AuthorDate: Wed Mar 31 12:17:11 2021 +0200
add 'log' command for viewing the log
---
server/endpoints/mgmt.py | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/server/endpoints/mgmt.py b/server/endpoints/mgmt.py
index f13dd0f..7fafb13 100644
--- a/server/endpoints/mgmt.py
+++ b/server/endpoints/mgmt.py
@@ -38,8 +38,17 @@ async def process(
if not session.credentials.admin or not server.config.ui.mgmt_enabled:
return aiohttp.web.Response(headers={}, status=403, text="You need administrative access to use this feature.")
+ # Viewing audit log?
+ if action == "log":
+ numentries = int(indata.get("size", 50))
+ page = int(indata.get("page", 0))
+ out = []
+ async for entry in plugins.auditlog.view(session, page=page, num_entries=numentries, raw=True):
+ out.append(entry)
+ return out
+
# Deleting/hiding a document?
- if action == "delete":
+ elif action == "delete":
delcount = 0
for doc in docs:
assert isinstance(doc, str), "Document ID must be a string"
[incubator-ponymail-foal] 09/14: allow filtering for certain actions
Posted by hu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
humbedooh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-ponymail-foal.git
commit 2fabfdb30700e07b0b3375c9b3bc6beaed4b4e26
Author: Daniel Gruno <hu...@apache.org>
AuthorDate: Wed Mar 31 12:42:09 2021 +0200
allow filtering for certain actions
---
server/plugins/auditlog.py | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/server/plugins/auditlog.py b/server/plugins/auditlog.py
index fb5eeae..51ac108 100644
--- a/server/plugins/auditlog.py
+++ b/server/plugins/auditlog.py
@@ -44,13 +44,22 @@ class AuditLogEntry:
async def view(
- session: plugins.session.SessionObject, page: int = 0, num_entries: int = 50, raw: bool = False
+ session: plugins.session.SessionObject, page: int = 0, num_entries: int = 50, raw: bool = False, filter: typing.List[str] = []
) -> typing.AsyncGenerator:
""" Returns N entries from the audit log, paginated """
assert session.database, "No database connection could be found!"
- res = await session.database.search(
- index=session.database.dbs.auditlog, size=num_entries, from_=page * num_entries, sort="date:desc",
- )
+ if not filter:
+ res = await session.database.search(
+ index=session.database.dbs.auditlog, size=num_entries, from_=page * num_entries, sort="date:desc",
+ )
+ else:
+ res = await session.database.search(
+ index=session.database.dbs.auditlog, size=num_entries, from_=page * num_entries, sort="date:desc",
+ body={
+ "query": {"bool": {"must": [{"terms": {"action": filter}}]}}
+ },
+ )
+
for doc in res["hits"]["hits"]:
doc["_source"]["id"] = doc["_id"]
if raw:
[incubator-ponymail-foal] 08/14: fix type warnings
Posted by hu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
humbedooh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-ponymail-foal.git
commit 374adfc40d8dad75f556a958dc85402e1ca550e1
Author: Daniel Gruno <hu...@apache.org>
AuthorDate: Wed Mar 31 12:28:04 2021 +0200
fix type warnings
---
server/endpoints/mgmt.py | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/server/endpoints/mgmt.py b/server/endpoints/mgmt.py
index 9818c8b..b30ee2f 100644
--- a/server/endpoints/mgmt.py
+++ b/server/endpoints/mgmt.py
@@ -34,8 +34,9 @@ async def process(
doc = indata.get("document")
if not docs and doc:
docs = [doc]
- if not session.credentials.admin or not server.config.ui.mgmt_enabled:
+ if not session.credentials or not session.credentials.admin or not server.config.ui.mgmt_enabled:
return aiohttp.web.Response(headers={}, status=403, text="You need administrative access to use this feature.")
+ assert session.database, "No session database connection could be found!"
# Viewing audit log?
if action == "log":
@@ -44,7 +45,9 @@ async def process(
out = []
async for entry in plugins.auditlog.view(session, page=page, num_entries=numentries, raw=True):
out.append(entry)
- return out
+ return {
+ "entries": out
+ }
# Deleting/hiding a document?
elif action == "delete":
@@ -57,7 +60,7 @@ async def process(
await session.database.index(
index=session.database.dbs.mbox, body=email, id=email["id"],
)
- lid = email.get("list_raw")
+ lid = email.get("list_raw", "??")
await plugins.auditlog.add_entry(session, action="delete", target=doc, lid=lid, log=f"Removed email {doc} from {lid} archives")
delcount += 1
return aiohttp.web.Response(headers={}, status=200, text=f"Removed {delcount} emails from archives.")
@@ -65,11 +68,12 @@ async def process(
elif action == "edit":
new_from = indata.get("from")
new_subject = indata.get("subject")
- new_list = indata.get("list")
+ new_list = indata.get("list", "")
private = True if indata.get("private", "no") == "yes" else False
- new_body = indata.get("body")
+ new_body = indata.get("body", "")
# Check for consistency so we don't pollute the database
+ assert isinstance(doc, str) and doc, "Document ID is missing or invalid"
assert isinstance(new_from, str), "Author field must be a text string!"
assert isinstance(new_subject, str), "Subject field must be a text string!"
assert isinstance(new_list, str), "List ID field must be a text string!"
[incubator-ponymail-foal] 05/14: no need for time,
audit log plugin handles it
Posted by hu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
humbedooh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-ponymail-foal.git
commit 4785f21e27cc84f4d4afedd2d6da1d22dd1d3187
Author: Daniel Gruno <hu...@apache.org>
AuthorDate: Wed Mar 31 12:19:28 2021 +0200
no need for time, audit log plugin handles it
---
server/endpoints/mgmt.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/server/endpoints/mgmt.py b/server/endpoints/mgmt.py
index 7fafb13..9818c8b 100644
--- a/server/endpoints/mgmt.py
+++ b/server/endpoints/mgmt.py
@@ -24,7 +24,6 @@ import plugins.defuzzer
import plugins.auditlog
import typing
import aiohttp.web
-import time
async def process(
[incubator-ponymail-foal] 12/14: Add a simple starter for viewing
audit logs
Posted by hu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
humbedooh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-ponymail-foal.git
commit bd8bfc51b7288d44eb9f3ea4ae180f0587b3d672
Author: Daniel Gruno <hu...@apache.org>
AuthorDate: Wed Mar 31 13:50:56 2021 +0200
Add a simple starter for viewing audit logs
---
webui/css/scaffolding.css | 18 +++++++++++++++++-
webui/js/source/mgmt.js | 45 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 62 insertions(+), 1 deletion(-)
diff --git a/webui/css/scaffolding.css b/webui/css/scaffolding.css
index 49987ed..d9d7756 100644
--- a/webui/css/scaffolding.css
+++ b/webui/css/scaffolding.css
@@ -1179,4 +1179,20 @@ pre {
.chatty_body a {
word-break: break-all !important;
- }
\ No newline at end of file
+ }
+
+.auditlog_entry:nth-child(odd) {
+ background: #EEE;
+}
+
+.auditlog_entry:nth-child(even) {
+ background: #F8F8F8;
+}
+
+.auditlog_entry td {
+ padding: 2px;
+}
+
+.auditlog_entries th {
+ padding: 2px;
+}
\ No newline at end of file
diff --git a/webui/js/source/mgmt.js b/webui/js/source/mgmt.js
index 0565860..6f087fb 100644
--- a/webui/js/source/mgmt.js
+++ b/webui/js/source/mgmt.js
@@ -135,6 +135,49 @@ function admin_email_preview(stats, json) {
div.inject(new HTML('small', {}, "Emails that are removed may still be recovered by the base system administrator. For complete expungement, please contact the system administrator."))
}
+function admin_audit_view(state, json) {
+ let cp = document.getElementById("panel");
+ let div = new HTML('div', { style: { margin: '5px'}});
+ cp.inject(div);
+
+ div.inject(new HTML('h1', {}, "Audit log:"));
+ if (json.entries && json.entries.length > 0) {
+ let table = new HTML('table', {border: "1", class:"auditlog_entries"});
+ let trh = new HTML('tr');
+ let headers = ['Date', 'Author','Remote','Action','Target', 'Log'];
+ for (let i = 0; i < headers.length; i++) {
+ let th = new HTML('th', {}, headers[i] + ":");
+ trh.inject(th);
+ }
+ table.inject(trh)
+ for (let i = 0; i < json.entries.length; i++) {
+ let entry = json.entries[i];
+ let tr = new HTML('tr', {class: "auditlog_entry"});
+ for (let i = 0; i < headers.length; i++) {
+ let key = headers[i].toLowerCase();
+ let value = entry[key];
+ if (key == 'target') {
+ value = new HTML('a', {href: "/admin/" +value}, value);
+ }
+ if (key == 'action') {
+ let action_colors = {
+ edit: 'blue',
+ delete: 'red',
+ default: 'black'
+ };
+ value = new HTML('spam', {style: {color: action_colors[value] ? action_colors[value] : action_colors['default']}}, value);
+ }
+ let th = new HTML('td', {}, value);
+ tr.inject(th);
+ }
+ table.inject(tr);
+ }
+ div.inject(table);
+ } else {
+ div.inject("Audit log is empty");
+ }
+
+}
function admin_init() {
let mid = location.href.split('/').pop();
// Specific email/list handling?
@@ -147,5 +190,7 @@ function admin_init() {
else {
GET('%sapi/email.json?id=%s'.format(apiURL, mid), admin_email_preview, null);
}
+ } else { // View audit log
+ GET('%sapi/mgmt.json?action=log'.format(apiURL), admin_audit_view, null);
}
}
\ No newline at end of file