This is an automated email from the ASF dual-hosted git repository.

sebb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-ponymail-foal.git


The following commit(s) were added to refs/heads/master by this push:
     new fd5f490  Tests of management interface
fd5f490 is described below

commit fd5f49099d7e034e6c8188f7f4436ae061724986
Author: Sebb <[email protected]>
AuthorDate: Sat Jan 29 16:49:19 2022 +0000

    Tests of management interface
---
 .github/workflows/integration-tests.yml            |   1 +
 test/itest_integration.py                          | 246 ++++++++++++++++-----
 .../resources/dev_ponymail_apache_org_2020-10.mbox | 120 ++++++++++
 3 files changed, 316 insertions(+), 51 deletions(-)

diff --git a/.github/workflows/integration-tests.yml 
b/.github/workflows/integration-tests.yml
index 96efada..8a4a50a 100644
--- a/.github/workflows/integration-tests.yml
+++ b/.github/workflows/integration-tests.yml
@@ -75,6 +75,7 @@ jobs:
         # The early messages were under incubator ...
         tools/import-mbox.py --source 
test/resources/users_ponymail_apache_org_2019-09.mbox --private --lid 
users.ponymail.apache.org
         tools/import-mbox.py --source 
test/resources/users_ponymail_apache_org_2022-01.mbox
+        tools/import-mbox.py --source 
test/resources/dev_ponymail_apache_org_2020-10.mbox
     - name: Server
       run: |
         cd server
diff --git a/test/itest_integration.py b/test/itest_integration.py
index 89900d4..010e11d 100644
--- a/test/itest_integration.py
+++ b/test/itest_integration.py
@@ -15,6 +15,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import time
 import pytest
 import random
 import requests
@@ -22,6 +23,12 @@ import requests
 # Run as: python3 -m pytest [-s] test/itest_integration.py
 
 API_BASE='http://localhost:8080/api'
+TEST_DOMAIN = 'ponymail.apache.org'
+TEST_LIST = 'users'
+TEST_LIST2 = 'dev'
+DOCUMENT_HIDE_TEST = "c396ps3p5pb05srb4269dzcg9j7sof42"
+DOCUMENT_EDIT_TEST = "ffc3s2wzpn4n4pfonk9rffs4mnbk3l65" # dev list
+DOCUMENT_EDIT_SOURCE = 
"a05f5a472b5e7e6d0ea10162fa9d2b499861258c142dbb7f402454ad23b4af46"
 
 # Emulate how test auth is used by GUI
 def get_cookies(user='user'):
@@ -37,77 +44,108 @@ def get_cookies(user='user'):
     assert 'credentials' in jzon['login']
     return cookies
 
-def check_access(email, cookies):
-        # check email accessibility
-        mid = email['mid']
+def check_email(email, cookies):
+    # check email accessibility
+    mid = email['mid']
+    private = email['private']
+
+    # access by Permalink
+    res = requests.get(
+        f"{API_BASE}/email.lua",
+        params={"id": mid},
+        cookies=cookies
+    )
+    assert res.status_code == 200, mid
+    jzon = res.json()
+    assert mid == jzon['mid']
+    assert mid in jzon['permalinks']
+
+    # check email access by message-id
+    msgid = jzon['message-id']
+    listid = jzon['list_raw']
+    res = requests.get(
+        f"{API_BASE}/email.lua",
+        params={"id": msgid, "listid": listid},
+        cookies=cookies
+    )
+    assert res.status_code == 200, msgid
+    if private:
+        # should not be visible without cookies
         res = requests.get(
             f"{API_BASE}/email.lua",
-            params={"id": mid},
-            cookies=cookies
+            params={"id": mid}
         )
-        assert res.status_code == 200
-        jzon = res.json()
-        assert mid == jzon['mid']
-        assert mid in jzon['permalinks']
-        # check email access by message-id
-        msgid = jzon['message-id']
-        listid = jzon['list_raw']
+        assert res.status_code == 404, mid
         res = requests.get(
             f"{API_BASE}/email.lua",
-            params={"id": msgid, "listid": listid},
-            cookies=cookies
+            params={"id": msgid, "listid": listid}
         )
-        assert res.status_code == 200
-        if email['private']:
-            # should not be visible without cookies
-            res = requests.get(
-                f"{API_BASE}/email.lua",
-                params={"id": mid}
-            )
-            assert res.status_code == 404
-            res = requests.get(
-                f"{API_BASE}/email.lua",
-                params={"id": msgid, "listid": listid}
-            )
-            assert res.status_code == 404
-        # check source accessibility
+        assert res.status_code == 404, msgid
+    return mid, msgid, listid, private
+
+def check_source(mid, msgid, listid, private, cookies):
+    res = requests.get(
+        f"{API_BASE}/source.lua",
+        params={"id": mid},
+        cookies=cookies
+    )
+    assert res.status_code == 200, mid
+    res = requests.get(
+        f"{API_BASE}/source.lua",
+        params={"id": msgid, "listid": listid},
+        cookies=cookies
+    )
+    assert res.status_code == 200, mid
+    if private:
+        # should not be visible without cookies
         res = requests.get(
             f"{API_BASE}/source.lua",
-            params={"id": mid},
-            cookies=cookies
+            params={"id": mid}
         )
-        assert res.status_code == 200
+        assert res.status_code == 404, mid
         res = requests.get(
             f"{API_BASE}/source.lua",
-            params={"id": msgid, "listid": listid},
-            cookies=cookies
+            params={"id": msgid, "listid": listid}
         )
-        assert res.status_code == 200
-        if email['private']:
-            # should not be visible without cookies
-            res = requests.get(
-                f"{API_BASE}/source.lua",
-                params={"id": mid}
-            )
-            assert res.status_code == 404
-            res = requests.get(
-                f"{API_BASE}/source.lua",
-                params={"id": msgid, "listid": listid}
-            )
-            assert res.status_code == 404
+        assert res.status_code == 404, mid
+
+def check_access(email, cookies):
+        mid, msgid, listid, private = check_email(email, cookies)
+        check_source(mid, msgid, listid, private, cookies)
+
+def test_setup():
+    # ensure test conditions are correct at the start
+    import yaml
+    yaml = yaml.safe_load(open("server/ponymail.yaml"))
+    dburl = yaml['database']['dburl']
+    from requests.compat import urljoin
+    path = urljoin(dburl, "ponymail-auditlog/_delete_by_query")
+    res = requests.post(
+        path,
+        json={ "query": { "match_all": {} }},
+        headers={"Content-Type": 'application/json'}
+        )
+    assert res.status_code == 200
+    path = urljoin(dburl, f"ponymail-source/_update/{DOCUMENT_EDIT_SOURCE}")
+    res = requests.post(
+        path,
+        json={ "doc": {"deleted": False} },
+        headers={"Content-Type": 'application/json'}
+        )
+    assert res.status_code == 200
 
 def test_lists():
     jzon = requests.get(f"{API_BASE}/preferences").json()
     # print(jzon)
     lists = jzon['lists']
-    assert 'ponymail.apache.org' in lists
-    assert 'users' in lists['ponymail.apache.org']
+    assert TEST_DOMAIN in lists
+    assert TEST_LIST in lists[TEST_DOMAIN]
     assert len(lists) == 1 # only expecting one domain
 
 def test_public_stats():
     jzon = requests.get(
         f"{API_BASE}/stats.lua",
-        params={"list": 'users', "domain": 'ponymail.apache.org', 
"emailsOnly": True, "d": 'gte=0d'}
+        params={"list": TEST_LIST, "domain": TEST_DOMAIN, "emailsOnly": True, 
"d": 'gte=0d'}
     ).json()
     assert jzon['firstYear'] == 2022
     assert jzon['firstMonth'] == 1
@@ -123,7 +161,7 @@ def test_public_stats():
     # Check we cannot see the private emails
     jzon = requests.get(
         f"{API_BASE}/stats.lua",
-        params={"list": 'users', "domain": 'ponymail.apache.org', 
"emailsOnly": True, "d": '2019-09'}
+        params={"list": TEST_LIST, "domain": TEST_DOMAIN, "emailsOnly": True, 
"d": '2019-09'}
         ).json()
     assert jzon['hits'] == 0
 
@@ -132,7 +170,7 @@ def test_private_stats():
     # only fetch the private mail stats
     jzon = requests.get(
         f"{API_BASE}/stats.lua",
-        params={"list": 'users', "domain": 'ponymail.apache.org', 
"emailsOnly": True, "d": '2019-09'},
+        params={"list": TEST_LIST, "domain": TEST_DOMAIN, "emailsOnly": True, 
"d": '2019-09'},
         cookies=cookies
     ).json()
     # The earlier mails are private
@@ -197,3 +235,109 @@ def test_mgmt_validation():
         {"action": 'edit', "document": '1234', "from": 'sender', "subject": 
'Test Email', "list": 'abc', "body": 'body'},
         admin_cookies, 404)
     assert "Email not found!" in text
+
+def test_mgmt_log_before():
+    admin_cookies = get_cookies('admin')
+    jzon = mgmt_get_json({"action": 'log'}, admin_cookies)
+    assert len(jzon['entries']) == 0
+
+def test_mgmt_hiding():
+    admin_cookies = get_cookies('admin')
+
+    # reset in case of earlier failure
+    text = mgmt_get_text({"action": 'unhide', "document": DOCUMENT_HIDE_TEST}, 
admin_cookies)
+    assert text == "Unhid 1 emails from archives."
+
+    jzon = requests.get(
+        f"{API_BASE}/stats.lua",
+        params={"list": TEST_LIST, "domain": TEST_DOMAIN, "emailsOnly": True, 
"d": 'gte=0d'}
+    ).json()
+
+    assert jzon['hits'] == 6
+
+    check_access({"mid": DOCUMENT_HIDE_TEST, "private": False}, admin_cookies)
+
+    text = mgmt_get_text({"action": 'hide', "document": DOCUMENT_HIDE_TEST}, 
admin_cookies)
+    assert text == "Hid 1 emails from archives."
+
+    jzon = requests.get(
+        f"{API_BASE}/stats.lua",
+        params={"list": TEST_LIST, "domain": TEST_DOMAIN, "emailsOnly": True, 
"d": 'gte=0d'}
+    ).json()
+    assert jzon['hits'] == 5
+
+
+
+    text = mgmt_get_text({"action": 'unhide', "document": DOCUMENT_HIDE_TEST}, 
admin_cookies)
+    assert text == "Unhid 1 emails from archives."
+
+    jzon = requests.get(
+        f"{API_BASE}/stats.lua",
+        params={"list": TEST_LIST, "domain": TEST_DOMAIN, "emailsOnly": True, 
"d": 'gte=0d'}
+    ).json()
+    assert jzon['hits'] == 6
+
+    check_access({"mid": DOCUMENT_HIDE_TEST, "private": False}, None)
+
+def test_mgmt_edit():
+    """This test causes the source for an entry to be hidden"""
+    admin_cookies = get_cookies('admin')
+
+    test_list_id = f"<{TEST_LIST2}.{TEST_DOMAIN}>"
+    jzon = requests.get(
+        f"{API_BASE}/stats.lua",
+        params={"list": TEST_LIST2, "domain": TEST_DOMAIN, "emailsOnly": True, 
"d": 'gte=0d'}
+    ).json()
+
+    assert jzon['hits'] == 1
+
+    email = jzon['emails'][0]
+    check_access(email, None) # should be fully accessible
+
+    res = requests.get(
+        f"{API_BASE}/mbox.lua",
+        params={"list": TEST_LIST2, "domain": TEST_DOMAIN, "d": '2020-10'}
+    )
+    assert res.status_code == 200
+    assert res.text.startswith('From dev-return-')
+
+    # N.B. use variable body so it is always changed, even after a reset
+    text = mgmt_get_text(
+        {
+            "action": 'edit', "document": DOCUMENT_EDIT_TEST,
+            "from": '', "subject": '', "list": test_list_id, "body": 
time.time(), "private": False,
+        },
+        admin_cookies
+        )
+    assert text == "Email successfully saved"
+
+    jzon = requests.get(
+        f"{API_BASE}/stats.lua",
+        params={"list": TEST_LIST2, "domain": TEST_DOMAIN, "emailsOnly": True, 
"d": 'gte=0d'}
+    ).json()
+
+    assert jzon['hits'] == 1 # mbox entry still accessible
+
+    check_email(email, None)
+    check_access(email, admin_cookies) # but the source needs admin
+
+    # check that cannot see mbox
+    res = requests.get(
+        f"{API_BASE}/mbox.lua",
+        params={"list": TEST_LIST2, "domain": TEST_DOMAIN, "d": '2020-10'}
+    )
+    assert res.status_code == 200
+    assert len(res.text) <= 1 # probably just LF
+
+    res = requests.get(
+        f"{API_BASE}/mbox.lua",
+        params={"list": TEST_LIST2, "domain": TEST_DOMAIN, "d": '2020-10'},
+        cookies=admin_cookies
+    )
+    assert res.status_code == 200
+    assert res.text.startswith('From dev-return-')
+
+def test_mgmt_log_after():
+    admin_cookies = get_cookies('admin')
+    jzon = mgmt_get_json({"action": 'log'}, admin_cookies)
+    assert len(jzon['entries']) == 4
diff --git a/test/resources/dev_ponymail_apache_org_2020-10.mbox 
b/test/resources/dev_ponymail_apache_org_2020-10.mbox
new file mode 100644
index 0000000..4015024
--- /dev/null
+++ b/test/resources/dev_ponymail_apache_org_2020-10.mbox
@@ -0,0 +1,120 @@
+From dev-return-1307-archive-asf-public=cust-asf.ponee...@ponymail.apache.org  
Mon Oct  5 04:41:25 2020
+Return-Path: 
<dev-return-1307-archive-asf-public=cust-asf.ponee...@ponymail.apache.org>
+X-Original-To: [email protected]
+Delivered-To: [email protected]
+Received: from mxout1-he-de.apache.org (mxout1-he-de.apache.org 
[95.216.194.37])
+       by mx-eu-01.ponee.io (Postfix) with ESMTPS id E6FDD180654
+       for <[email protected]>; Mon,  5 Oct 2020 06:41:25 
+0200 (CEST)
+Received: from mail.apache.org (mailroute1-lw-us.apache.org [207.244.88.153])
+       by mxout1-he-de.apache.org (ASF Mail Server at mxout1-he-de.apache.org) 
with SMTP id 59A9664274
+       for <[email protected]>; Mon,  5 Oct 2020 04:41:25 
+0000 (UTC)
+Received: (qmail 7680 invoked by uid 500); 5 Oct 2020 04:41:24 -0000
+Mailing-List: contact [email protected]; run by ezmlm
+Precedence: bulk
+List-Help: <mailto:[email protected]>
+List-Unsubscribe: <mailto:[email protected]>
+List-Post: <mailto:[email protected]>
+List-Id: <dev.ponymail.apache.org>
+Reply-To: [email protected]
+Delivered-To: mailing list [email protected]
+Received: (qmail 7503 invoked by uid 99); 5 Oct 2020 04:41:24 -0000
+Received: from spamproc1-he-de.apache.org (HELO spamproc1-he-de.apache.org) 
(116.203.196.100)
+    by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 05 Oct 2020 04:41:24 +0000
+Received: from localhost (localhost [127.0.0.1])
+       by spamproc1-he-de.apache.org (ASF Mail Server at 
spamproc1-he-de.apache.org) with ESMTP id 5676B1FF39B
+       for <[email protected]>; Mon,  5 Oct 2020 04:41:23 +0000 (UTC)
+X-Virus-Scanned: Debian amavisd-new at spamproc1-he-de.apache.org
+X-Spam-Flag: NO
+X-Spam-Score: -7.989
+X-Spam-Level:
+X-Spam-Status: No, score=-7.989 tagged_above=-999 required=6.31
+       tests=[ENV_AND_HDR_SPF_MATCH=-0.5, KAM_DMARC_STATUS=0.01,
+       RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_PASS=-0.001,
+       USER_IN_DEF_SPF_WL=-7.5] autolearn=disabled
+Received: from mx1-ec2-va.apache.org ([116.203.227.195])
+       by localhost (spamproc1-he-de.apache.org [116.203.196.100]) 
(amavisd-new, port 10024)
+       with ESMTP id EhMTXjnR7AGw for <[email protected]>;
+       Mon,  5 Oct 2020 04:41:22 +0000 (UTC)
+Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=3.227.148.255; 
helo=mxout1-ec2-va.apache.org; [email protected]; 
receiver=<UNKNOWN> 
+Received: from mxout1-ec2-va.apache.org (mxout1-ec2-va.apache.org 
[3.227.148.255])
+       by mx1-ec2-va.apache.org (ASF Mail Server at mx1-ec2-va.apache.org) 
with ESMTPS id 8FAB4BC2AF
+       for <[email protected]>; Mon,  5 Oct 2020 04:41:22 
+0000 (UTC)
+Received: from mail.apache.org (mailroute1-lw-us.apache.org [207.244.88.153])
+       by mxout1-ec2-va.apache.org (ASF Mail Server at 
mxout1-ec2-va.apache.org) with SMTP id 7C8B642544
+       for <[email protected]>; Mon,  5 Oct 2020 04:41:22 
+0000 (UTC)
+Received: (qmail 7326 invoked by uid 99); 5 Oct 2020 04:41:22 -0000
+Received: from Unknown (HELO mailrelay1-lw-us.apache.org) (10.10.3.159)
+    by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 05 Oct 2020 04:41:22 +0000
+Received: from macbook-pro-3.hub (unknown [101.114.76.121])
+       by mailrelay1-lw-us.apache.org (ASF Mail Server at 
mailrelay1-lw-us.apache.org) with ESMTPSA id C455E40B90
+       for <[email protected]>; Mon,  5 Oct 2020 04:41:21 
+0000 (UTC)
+Content-Type: text/plain; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: Podling Ponymail Report Reminder - October 2020
+From: [email protected]
+Date: Mon, 05 Oct 2020 04:41:21 -0000
+To: [email protected]
+Message-ID: <[email protected]>
+
+Dear podling,
+
+This email was sent by an automated system on behalf of the Apache
+Incubator PMC. It is an initial reminder to give you plenty of time to
+prepare your quarterly board report.
+
+The board meeting is scheduled for Wed, 21 October 2020.
+The report for your podling will form a part of the Incubator PMC
+report. The Incubator PMC requires your report to be submitted 2 weeks
+before the board meeting, to allow sufficient time for review and
+submission (Wed, October 07).
+
+Please submit your report with sufficient time to allow the Incubator
+PMC, and subsequently board members to review and digest. Again, the
+very latest you should submit your report is 2 weeks prior to the board
+meeting.
+
+Candidate names should not be made public before people are actually
+elected, so please do not include the names of potential committers or
+PPMC members in your report.
+
+Thanks,
+
+The Apache Incubator PMC
+
+Submitting your Report
+
+----------------------
+
+Your report should contain the following:
+
+*   Your project name
+*   A brief description of your project, which assumes no knowledge of
+    the project or necessarily of its field
+*   A list of the three most important issues to address in the move
+    towards graduation.
+*   Any issues that the Incubator PMC or ASF Board might wish/need to be
+    aware of
+*   How has the community developed since the last report
+*   How has the project developed since the last report.
+*   How does the podling rate their own maturity.
+
+This should be appended to the Incubator Wiki page at:
+
+https://cwiki.apache.org/confluence/display/INCUBATOR/October2020
+
+Note: This is manually populated. You may need to wait a little before
+this page is created from a template.
+
+Note: The format of the report has changed to use markdown.
+
+Mentors
+-------
+
+Mentors should review reports for their project(s) and sign them off on
+the Incubator wiki page. Signing off reports shows that you are
+following the project - projects that are not signed may raise alarms
+for the Incubator PMC.
+
+Incubator PMC
+

Reply via email to