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