356 lines
11 KiB
Go
356 lines
11 KiB
Go
// SPDX-FileCopyrightText: 2021 The NGI Pointer Secure-Scuttlebutt Team of 2020/2021
|
|
//
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package admin
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"testing"
|
|
|
|
"github.com/ssb-ngi-pointer/go-ssb-room/v2/roomdb"
|
|
"github.com/ssb-ngi-pointer/go-ssb-room/v2/web/router"
|
|
"github.com/ssb-ngi-pointer/go-ssb-room/v2/web/webassert"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
// Verifies that the notice.go save handler is like, actually, called.
|
|
func TestNoticeSaveActuallyCalled(t *testing.T) {
|
|
ts := newSession(t)
|
|
a := assert.New(t)
|
|
|
|
id := []string{"1"}
|
|
title := []string{"SSB Breaking News: This Test Is Great"}
|
|
content := []string{"Absolutely Thrilling Content"}
|
|
language := []string{"en-GB"}
|
|
|
|
// POST a correct request to the save handler, and verify that the save was handled using the mock database)
|
|
u := ts.URLTo(router.AdminNoticeSave)
|
|
formValues := url.Values{"id": id, "title": title, "content": content, "language": language}
|
|
resp := ts.Client.PostForm(u, formValues)
|
|
a.Equal(http.StatusSeeOther, resp.Code, "POST should work")
|
|
a.Equal(1, ts.NoticeDB.SaveCallCount(), "noticedb should have saved after POST completed")
|
|
}
|
|
|
|
// Verifies that the notices.go:save handler refuses requests missing required parameters
|
|
func TestNoticeSaveRefusesIncomplete(t *testing.T) {
|
|
ts := newSession(t)
|
|
a := assert.New(t)
|
|
|
|
// notice values we are selectively omitting in the tests below
|
|
id := []string{"1"}
|
|
title := []string{"SSB Breaking News: This Test Is Great"}
|
|
content := []string{"Absolutely Thrilling Content"}
|
|
language := []string{"pt"}
|
|
|
|
/* save without id */
|
|
u := ts.URLTo(router.AdminNoticeSave)
|
|
emptyParams := url.Values{}
|
|
resp := ts.Client.PostForm(u, emptyParams)
|
|
a.Equal(http.StatusSeeOther, resp.Code, "saving without id should not work")
|
|
|
|
loc := resp.Header().Get("Location")
|
|
|
|
noticesList := ts.URLTo(router.CompleteNoticeList)
|
|
a.Equal(noticesList.String(), loc)
|
|
|
|
// we should get noticesList here but
|
|
// due to issue #35 we cant get /notices/list in package admin tests
|
|
// but it doesn't really matter since the flash messages are rendered on whatever page the client goes to next
|
|
sigh := ts.URLTo(router.AdminDashboard)
|
|
|
|
webassert.HasFlashMessages(t, ts.Client, sigh, "ErrorBadRequest")
|
|
|
|
/* save without title */
|
|
formValues := url.Values{"id": id, "content": content, "language": language}
|
|
resp = ts.Client.PostForm(u, formValues)
|
|
a.Equal(http.StatusSeeOther, resp.Code, "saving without title should not work")
|
|
webassert.HasFlashMessages(t, ts.Client, sigh, "ErrorBadRequest")
|
|
|
|
/* save without content */
|
|
formValues = url.Values{"id": id, "title": title, "language": language}
|
|
resp = ts.Client.PostForm(u, formValues)
|
|
a.Equal(http.StatusSeeOther, resp.Code, "saving without content should not work")
|
|
webassert.HasFlashMessages(t, ts.Client, sigh, "ErrorBadRequest")
|
|
|
|
/* save without language */
|
|
formValues = url.Values{"id": id, "title": title, "content": content}
|
|
resp = ts.Client.PostForm(u, formValues)
|
|
a.Equal(http.StatusSeeOther, resp.Code, "saving without language should not work")
|
|
webassert.HasFlashMessages(t, ts.Client, sigh, "ErrorBadRequest")
|
|
|
|
a.Equal(0, ts.NoticeDB.SaveCallCount(), "noticedb should never save incomplete requests")
|
|
}
|
|
|
|
// Verifies that /translation/add only accepts POST requests
|
|
func TestNoticeAddLanguageOnlyAllowsPost(t *testing.T) {
|
|
ts := newSession(t)
|
|
a := assert.New(t)
|
|
// instantiate the ts.URLTo helper (constructs urls for us!)
|
|
|
|
// verify that a GET request is no bueno
|
|
u := ts.URLTo(router.AdminNoticeAddTranslation, "name", roomdb.NoticeNews.String())
|
|
_, resp := ts.Client.GetHTML(u)
|
|
a.Equal(http.StatusBadRequest, resp.Code, "GET should not be allowed for this route")
|
|
|
|
// next up, we verify that a correct POST request actually works:
|
|
id := []string{"1"}
|
|
title := []string{"Bom Dia! SSB Breaking News: This Test Is Great"}
|
|
content := []string{"conteúdo muito bom"}
|
|
language := []string{"pt"}
|
|
|
|
formValues := url.Values{"name": []string{roomdb.NoticeNews.String()}, "id": id, "title": title, "content": content, "language": language}
|
|
resp = ts.Client.PostForm(u, formValues)
|
|
a.Equal(http.StatusSeeOther, resp.Code)
|
|
webassert.HasFlashMessages(t, ts.Client, ts.URLTo(router.AdminDashboard), "NoticeUpdated")
|
|
}
|
|
|
|
// Verifies that the "add a translation" page contains all the required form fields (id/title/content/language)
|
|
func TestNoticeDraftLanguageIncludesAllFields(t *testing.T) {
|
|
ts := newSession(t)
|
|
a := assert.New(t)
|
|
// instantiate the ts.URLTo helper (constructs urls for us!)
|
|
|
|
// to test translations we first need to add a notice to the notice mockdb
|
|
notice := roomdb.Notice{
|
|
ID: 1,
|
|
Title: "News",
|
|
Content: "Breaking News: This Room Has News",
|
|
Language: "en-GB",
|
|
}
|
|
// make sure we return a notice when accessing pinned notices (which are the only notices with translations at writing (2021-03-11)
|
|
ts.PinnedDB.GetReturns(¬ice, nil)
|
|
|
|
u := ts.URLTo(router.AdminNoticeDraftTranslation, "name", roomdb.NoticeNews.String())
|
|
html, resp := ts.Client.GetHTML(u)
|
|
form := html.Find("form")
|
|
a.Equal(http.StatusOK, resp.Code, "Wrong HTTP status code")
|
|
// FormElement defaults to input if tag omitted
|
|
webassert.ElementsInForm(t, form, []webassert.FormElement{
|
|
{Name: "title"},
|
|
{Name: "language"},
|
|
{Tag: "textarea", Name: "content"},
|
|
})
|
|
}
|
|
|
|
func TestNoticeEditFormIncludesAllFields(t *testing.T) {
|
|
ts := newSession(t)
|
|
a := assert.New(t)
|
|
// instantiate the ts.URLTo helper (constructs urls for us!)
|
|
|
|
// Create mock notice data to operate on
|
|
notice := roomdb.Notice{
|
|
ID: 1,
|
|
Title: "News",
|
|
Content: "Breaking News: This Room Has News",
|
|
Language: "en-GB",
|
|
}
|
|
ts.NoticeDB.GetByIDReturns(notice, nil)
|
|
|
|
u := ts.URLTo(router.AdminNoticeEdit, "id", 1)
|
|
html, resp := ts.Client.GetHTML(u)
|
|
form := html.Find("form")
|
|
|
|
a.Equal(http.StatusOK, resp.Code, "Wrong HTTP status code")
|
|
// check for all the form elements & verify their initial contents are set correctly
|
|
// FormElement defaults to input if tag omitted
|
|
webassert.ElementsInForm(t, form, []webassert.FormElement{
|
|
{Name: "title", Value: notice.Title},
|
|
{Name: "language", Value: notice.Language},
|
|
{Name: "id", Value: fmt.Sprintf("%d", notice.ID), Type: "hidden"},
|
|
{Tag: "textarea", Name: "content"},
|
|
})
|
|
}
|
|
|
|
func TestNoticesRoleRightsEditing(t *testing.T) {
|
|
ts := newSession(t)
|
|
|
|
dashboardURL := ts.URLTo(router.AdminDashboard)
|
|
editURL := ts.URLTo(router.AdminNoticeEdit, "id", 1)
|
|
saveURL := ts.URLTo(router.AdminNoticeSave)
|
|
|
|
formValues := url.Values{
|
|
"id": []string{"1"},
|
|
"title": []string{"SSB Breaking News: This Test Is Great"},
|
|
"content": []string{"Absolutely Thrilling Content"},
|
|
"language": []string{"en-GB"},
|
|
}
|
|
|
|
canSeeEditForm := func(t *testing.T, shouldWork bool) {
|
|
a := assert.New(t)
|
|
|
|
doc, resp := ts.Client.GetHTML(editURL)
|
|
|
|
if shouldWork {
|
|
a.Equal(http.StatusOK, resp.Code, "unexpected status code")
|
|
form := doc.Find("form")
|
|
action, has := form.Attr("action")
|
|
a.True(has, "no action on a form?!")
|
|
a.Equal(saveURL.String(), action)
|
|
} else {
|
|
a.Equal(http.StatusSeeOther, resp.Code, "unexpected status code")
|
|
webassert.HasFlashMessages(t, ts.Client, dashboardURL, "ErrorNotAuthorized")
|
|
}
|
|
}
|
|
|
|
totalSaveCallCount := 0
|
|
canSaveNotice := func(t *testing.T, shouldWork bool) {
|
|
a := assert.New(t)
|
|
|
|
// POST a correct request to the save handler, and verify that the save was handled using the mock database)
|
|
resp := ts.Client.PostForm(saveURL, formValues)
|
|
a.Equal(http.StatusSeeOther, resp.Code, "should have redirected")
|
|
|
|
var wantLabel string
|
|
if shouldWork {
|
|
totalSaveCallCount++
|
|
wantLabel = "NoticeUpdated"
|
|
} else {
|
|
wantLabel = "ErrorNotAuthorized"
|
|
}
|
|
webassert.HasFlashMessages(t, ts.Client, dashboardURL, wantLabel)
|
|
a.Equal(totalSaveCallCount, ts.NoticeDB.SaveCallCount(), "call count missmatch")
|
|
}
|
|
|
|
memberUser := roomdb.Member{
|
|
ID: 7331,
|
|
Role: roomdb.RoleMember,
|
|
PubKey: generatePubKey(),
|
|
}
|
|
modUser := roomdb.Member{
|
|
ID: 9001,
|
|
Role: roomdb.RoleModerator,
|
|
PubKey: generatePubKey(),
|
|
}
|
|
adminUser := roomdb.Member{
|
|
ID: 1337,
|
|
Role: roomdb.RoleAdmin,
|
|
PubKey: generatePubKey(),
|
|
}
|
|
|
|
/* test invite creation under various restricted mode with the roles member, mod, admin */
|
|
for _, mode := range roomdb.AllPrivacyModes {
|
|
t.Run(mode.String(), func(t *testing.T) {
|
|
ts.ConfigDB.GetPrivacyModeReturns(mode, nil)
|
|
|
|
// members can only invite in community rooms
|
|
t.Run("members", func(t *testing.T) {
|
|
ts.User = memberUser
|
|
canSeeEditForm(t, mode == roomdb.ModeCommunity)
|
|
canSaveNotice(t, mode == roomdb.ModeCommunity)
|
|
})
|
|
|
|
// mods & admins can always invite
|
|
t.Run("mods", func(t *testing.T) {
|
|
ts.User = modUser
|
|
canSeeEditForm(t, true)
|
|
canSaveNotice(t, true)
|
|
})
|
|
|
|
t.Run("admins", func(t *testing.T) {
|
|
ts.User = adminUser
|
|
canSeeEditForm(t, true)
|
|
canSaveNotice(t, true)
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNoticesRoleRightsAddingTranslation(t *testing.T) {
|
|
ts := newSession(t)
|
|
|
|
dashboardURL := ts.URLTo(router.AdminDashboard)
|
|
draftTrURL := ts.URLTo(router.AdminNoticeDraftTranslation, "name", "NoticeNews")
|
|
addTrURL := ts.URLTo(router.AdminNoticeAddTranslation)
|
|
|
|
formValues := url.Values{
|
|
"id": []string{"1"},
|
|
"title": []string{"SSB Breaking News: This Test Is Great"},
|
|
"content": []string{"Absolutely Thrilling Content"},
|
|
"language": []string{"en-GB"},
|
|
|
|
"name": []string{"NoticeNews"},
|
|
}
|
|
|
|
canSeeAddTranslationForm := func(t *testing.T, shouldWork bool) {
|
|
a := assert.New(t)
|
|
|
|
doc, resp := ts.Client.GetHTML(draftTrURL)
|
|
|
|
if shouldWork {
|
|
a.Equal(http.StatusOK, resp.Code, "unexpected status code")
|
|
form := doc.Find("form")
|
|
action, has := form.Attr("action")
|
|
a.True(has, "no action on a form?!")
|
|
a.Equal(addTrURL.String(), action)
|
|
} else {
|
|
a.Equal(http.StatusSeeOther, resp.Code, "unexpected status code")
|
|
webassert.HasFlashMessages(t, ts.Client, dashboardURL, "ErrorNotAuthorized")
|
|
}
|
|
}
|
|
|
|
totalAddCallCount := 0
|
|
canAddNewTranslation := func(t *testing.T, shouldWork bool) {
|
|
a := assert.New(t)
|
|
|
|
// POST a correct request to the save handler, and verify that the save was handled using the mock database)
|
|
resp := ts.Client.PostForm(addTrURL, formValues)
|
|
a.Equal(http.StatusSeeOther, resp.Code, "should have redirected")
|
|
|
|
var wantLabel string
|
|
if shouldWork {
|
|
totalAddCallCount++
|
|
wantLabel = "NoticeUpdated"
|
|
} else {
|
|
wantLabel = "ErrorNotAuthorized"
|
|
}
|
|
webassert.HasFlashMessages(t, ts.Client, dashboardURL, wantLabel)
|
|
a.Equal(totalAddCallCount, ts.PinnedDB.SetCallCount(), "call count missmatch")
|
|
}
|
|
|
|
memberUser := roomdb.Member{
|
|
ID: 7331,
|
|
Role: roomdb.RoleMember,
|
|
PubKey: generatePubKey(),
|
|
}
|
|
modUser := roomdb.Member{
|
|
ID: 9001,
|
|
Role: roomdb.RoleModerator,
|
|
PubKey: generatePubKey(),
|
|
}
|
|
adminUser := roomdb.Member{
|
|
ID: 1337,
|
|
Role: roomdb.RoleAdmin,
|
|
PubKey: generatePubKey(),
|
|
}
|
|
|
|
/* test invite creation under various restricted mode with the roles member, mod, admin */
|
|
for _, mode := range roomdb.AllPrivacyModes {
|
|
t.Run(mode.String(), func(t *testing.T) {
|
|
ts.ConfigDB.GetPrivacyModeReturns(mode, nil)
|
|
|
|
// members can only invite in community rooms
|
|
t.Run("members", func(t *testing.T) {
|
|
ts.User = memberUser
|
|
canSeeAddTranslationForm(t, mode == roomdb.ModeCommunity)
|
|
canAddNewTranslation(t, mode == roomdb.ModeCommunity)
|
|
})
|
|
|
|
// mods & admins can always invite
|
|
t.Run("mods", func(t *testing.T) {
|
|
ts.User = modUser
|
|
canSeeAddTranslationForm(t, true)
|
|
canAddNewTranslation(t, true)
|
|
})
|
|
|
|
t.Run("admins", func(t *testing.T) {
|
|
ts.User = adminUser
|
|
canSeeAddTranslationForm(t, true)
|
|
canAddNewTranslation(t, true)
|
|
})
|
|
})
|
|
}
|
|
}
|