add middleware to check roles

fixes #176
This commit is contained in:
Henry 2021-05-10 09:06:47 +02:00
parent 691f0e75b9
commit 5385ef65bb
3 changed files with 55 additions and 10 deletions

View File

@ -92,7 +92,7 @@ func (h aliasesHandler) revoke(rw http.ResponseWriter, req *http.Request) {
return
}
status := http.StatusTemporaryRedirect
status := http.StatusTemporaryRedirect // TODO: should be SeeOther because it's method POST coming in
err = h.db.Revoke(ctx, aliasName)
if err != nil {
h.flashes.AddError(rw, req, err)

View File

@ -22,6 +22,7 @@ import (
"github.com/ssb-ngi-pointer/go-ssb-room/web"
weberrors "github.com/ssb-ngi-pointer/go-ssb-room/web/errors"
"github.com/ssb-ngi-pointer/go-ssb-room/web/i18n"
"github.com/ssb-ngi-pointer/go-ssb-room/web/members"
"github.com/ssb-ngi-pointer/go-ssb-room/web/router"
)
@ -155,10 +156,11 @@ func Handler(
noticeDB: dbs.Notices,
pinnedDB: dbs.PinnedNotices,
}
mux.HandleFunc("/notice/edit", r.HTML("admin/notice-edit.tmpl", nh.edit))
mux.HandleFunc("/notice/translation/draft", r.HTML("admin/notice-edit.tmpl", nh.draftTranslation))
mux.HandleFunc("/notice/translation/add", nh.addTranslation)
mux.HandleFunc("/notice/save", nh.save)
onlyModsAndAdmins := checkMemberRole(r.Error, roomdb.RoleModerator, roomdb.RoleAdmin)
mux.Handle("/notice/edit", onlyModsAndAdmins(r.HTML("admin/notice-edit.tmpl", nh.edit)))
mux.Handle("/notice/translation/draft", onlyModsAndAdmins(r.HTML("admin/notice-edit.tmpl", nh.draftTranslation)))
mux.Handle("/notice/translation/add", onlyModsAndAdmins(http.HandlerFunc(nh.addTranslation)))
mux.Handle("/notice/save", onlyModsAndAdmins(http.HandlerFunc(nh.save)))
// path:/ matches everything that isn't registerd (ie. its the "Not Found handler")
mux.HandleFunc("/", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
@ -168,6 +170,35 @@ func Handler(
return customStripPrefix("/admin", mux)
}
func checkMemberRole(eh render.ErrorHandlerFunc, roles ...roomdb.Role) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
currentMember := members.FromContext(req.Context())
if currentMember == nil {
err := weberrors.ErrRedirect{Path: "/admin/dashboard", Reason: fmt.Errorf("not an member")}
eh(rw, req, http.StatusSeeOther, err)
return
}
var roleMatched = false
for _, r := range roles {
if currentMember.Role == r {
roleMatched = true
break
}
}
if !roleMatched {
err := weberrors.ErrRedirect{Path: "/admin/dashboard", Reason: weberrors.ErrNotAuthorized}
eh(rw, req, http.StatusSeeOther, err)
return
}
next.ServeHTTP(rw, req)
})
}
}
// how many elements does a paginated page have by default
const defaultPageSize = 20

View File

@ -190,18 +190,32 @@ func TestNoticesCreateOnlyModsAndHigher(t *testing.T) {
resp = ts.Client.PostForm(postEndpoint, loginVals)
a.Equal(http.StatusSeeOther, resp.Code, "wrong HTTP status code for sign in")
cnt := ts.MembersDB.GetByIDCallCount()
// now we are logged in, but we shouldn't be able to get the draft page
doc, resp = ts.Client.GetHTML(draftNotice)
a.Equal(http.StatusTemporaryRedirect, resp.Code)
a.Equal(http.StatusSeeOther, resp.Code)
dashboardURL := ts.URLTo(router.AdminDashboard)
a.Equal(dashboardURL.Path, resp.Header().Get("Location"))
a.True(len(resp.Result().Cookies()) > 0, "got a cookie")
webassert.HasFlashMessages(t, ts.Client, dashboardURL, "AdminMemberDetailsAliasRevoked")
webassert.HasFlashMessages(t, ts.Client, dashboardURL, "ErrorNotAuthorized")
a.Equal(cnt+1, ts.MembersDB.GetByIDCallCount())
// also shouldnt be allowed to save/post
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, csrfName: []string{csrfValue}}
resp = ts.Client.PostForm(u, formValues)
a.Equal(http.StatusSeeOther, resp.Code, "POST should work")
a.Equal(0, ts.NoticeDB.SaveCallCount(), "noticedb should not save the notice")
a.Equal(dashboardURL.Path, resp.Header().Get("Location"))
a.True(len(resp.Result().Cookies()) > 0, "got a cookie")
webassert.HasFlashMessages(t, ts.Client, dashboardURL, "ErrorNotAuthorized")
}