MFA fix, added IP blacklist, update webmail client
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
package webui
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestWebmailFolderCreateShowsUpEvenWhenEmpty confirms a freshly created folder is
|
||||
// listed in the sidebar before it holds any messages — the reason
|
||||
// esrv_mailbox_folders exists at all (DistinctFoldersForMailbox alone can't prove a
|
||||
// folder exists until something's actually stored in it).
|
||||
func TestWebmailFolderCreateShowsUpEvenWhenEmpty(t *testing.T) {
|
||||
app := newTestApp(t)
|
||||
mux := app.Mux()
|
||||
domains, _ := app.DB.ListDomains()
|
||||
mailboxID := createTestMailboxWithPassword(t, app, "organizer2@example.com", domains[0].ID, "organizer-password-1!")
|
||||
cookie := webmailLoginSession(t, app, mailboxID)
|
||||
|
||||
req := httptest.NewRequest(http.MethodPost, MailboxPrefix+"/mail/folders/add", strings.NewReader("name=Receipts"))
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.AddCookie(cookie)
|
||||
rec := httptest.NewRecorder()
|
||||
mux.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusFound {
|
||||
t.Fatalf("add folder: status=%d body=%s", rec.Code, rec.Body.String())
|
||||
}
|
||||
|
||||
folders, err := app.DB.ListMailboxFolders(mailboxID)
|
||||
if err != nil || len(folders) != 1 || folders[0] != "Receipts" {
|
||||
t.Fatalf("expected [Receipts] in ListMailboxFolders, got %v (err=%v)", folders, err)
|
||||
}
|
||||
|
||||
inboxReq := httptest.NewRequest(http.MethodGet, MailboxPrefix+"/mail/INBOX", nil)
|
||||
inboxReq.AddCookie(cookie)
|
||||
inboxRec := httptest.NewRecorder()
|
||||
mux.ServeHTTP(inboxRec, inboxReq)
|
||||
if !strings.Contains(inboxRec.Body.String(), `data-folder="Receipts"`) {
|
||||
t.Error("expected the empty new folder to appear in the sidebar")
|
||||
}
|
||||
}
|
||||
|
||||
// TestWebmailFolderCreateRejectsStandardAndDuplicateNames confirms you can't create a
|
||||
// folder that collides with a standard folder or an existing custom one.
|
||||
func TestWebmailFolderCreateRejectsStandardAndDuplicateNames(t *testing.T) {
|
||||
app := newTestApp(t)
|
||||
mux := app.Mux()
|
||||
domains, _ := app.DB.ListDomains()
|
||||
mailboxID := createTestMailboxWithPassword(t, app, "organizer3@example.com", domains[0].ID, "organizer-password-1!")
|
||||
cookie := webmailLoginSession(t, app, mailboxID)
|
||||
|
||||
create := func(name string) {
|
||||
t.Helper()
|
||||
req := httptest.NewRequest(http.MethodPost, MailboxPrefix+"/mail/folders/add", strings.NewReader("name="+name))
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.AddCookie(cookie)
|
||||
rec := httptest.NewRecorder()
|
||||
mux.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusFound {
|
||||
t.Fatalf("create %s: status=%d", name, rec.Code)
|
||||
}
|
||||
}
|
||||
|
||||
create("Sent") // standard folder name — should be rejected, not duplicated
|
||||
create("Work")
|
||||
create("Work") // duplicate — should be rejected, not duplicated
|
||||
|
||||
folders, err := app.DB.ListMailboxFolders(mailboxID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(folders) != 1 || folders[0] != "Work" {
|
||||
t.Fatalf("expected exactly [Work] (Sent rejected as standard, duplicate Work rejected), got %v", folders)
|
||||
}
|
||||
}
|
||||
|
||||
// TestWebmailFolderDeleteMovesMessagesToInboxAndCannotDeleteStandard confirms
|
||||
// deleting a custom folder relocates its messages to INBOX, and that a standard
|
||||
// folder can't be deleted via the same route even if requested directly.
|
||||
func TestWebmailFolderDeleteMovesMessagesToInboxAndCannotDeleteStandard(t *testing.T) {
|
||||
app := newTestApp(t)
|
||||
mux := app.Mux()
|
||||
domains, _ := app.DB.ListDomains()
|
||||
mailboxID := createTestMailboxWithPassword(t, app, "organizer4@example.com", domains[0].ID, "organizer-password-1!")
|
||||
cookie := webmailLoginSession(t, app, mailboxID)
|
||||
|
||||
if err := app.DB.CreateMailboxFolder(mailboxID, "Newsletters"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
raw := "From: a@example.com\r\nTo: organizer4@example.com\r\nSubject: hi\r\n\r\nbody"
|
||||
if _, err := app.Mailstore.StoreMessage(mailboxID, "Newsletters", []byte(raw), "m@example.com", "a@example.com", "hi"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
req := httptest.NewRequest(http.MethodPost, MailboxPrefix+"/mail/folders/Newsletters/remove", nil)
|
||||
req.AddCookie(cookie)
|
||||
rec := httptest.NewRecorder()
|
||||
mux.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusFound {
|
||||
t.Fatalf("delete folder: status=%d", rec.Code)
|
||||
}
|
||||
|
||||
remaining, err := app.DB.ListMailboxFolders(mailboxID)
|
||||
if err != nil || len(remaining) != 0 {
|
||||
t.Fatalf("expected the folder record gone, got %v (err=%v)", remaining, err)
|
||||
}
|
||||
inboxMsgs, err := app.DB.ListMessagesInFolder(mailboxID, "INBOX")
|
||||
if err != nil || len(inboxMsgs) != 1 {
|
||||
t.Fatalf("expected the message relocated to INBOX, got %d (err=%v)", len(inboxMsgs), err)
|
||||
}
|
||||
|
||||
// Attempting to delete a standard folder must be rejected, not silently succeed.
|
||||
stdReq := httptest.NewRequest(http.MethodPost, MailboxPrefix+"/mail/folders/Sent/remove", nil)
|
||||
stdReq.AddCookie(cookie)
|
||||
stdRec := httptest.NewRecorder()
|
||||
mux.ServeHTTP(stdRec, stdReq)
|
||||
if stdRec.Code != http.StatusFound {
|
||||
t.Fatalf("delete standard folder: status=%d", stdRec.Code)
|
||||
}
|
||||
sentReq := httptest.NewRequest(http.MethodGet, MailboxPrefix+"/mail/Sent", nil)
|
||||
sentReq.AddCookie(cookie)
|
||||
sentRec := httptest.NewRecorder()
|
||||
mux.ServeHTTP(sentRec, sentReq)
|
||||
if sentRec.Code != http.StatusOK {
|
||||
t.Fatalf("Sent folder should still exist and render normally, status=%d", sentRec.Code)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user