diff --git a/backend/app/rest/api/rest.go b/backend/app/rest/api/rest.go index ea33d68f..ccad9e37 100644 --- a/backend/app/rest/api/rest.go +++ b/backend/app/rest/api/rest.go @@ -250,7 +250,7 @@ func (s *Rest) routes() chi.Router { rauth.Put("/comment/{id}", s.updateCommentCtrl) rauth.Post("/comment", s.createCommentCtrl) - rauth.Put("/vote/{id}", s.voteCtrl) + rauth.With(rejectAnonUser).Put("/vote/{id}", s.voteCtrl) rauth.Post("/deleteme", s.deleteMeCtrl) }) }) @@ -346,3 +346,21 @@ func URLKey(r *http.Request) string { } return key } + +// rejectAnonUser is a middleware rejecting anonymous users +func rejectAnonUser(next http.Handler) http.Handler { + fn := func(w http.ResponseWriter, r *http.Request) { + user, err := rest.GetUserInfo(r) + if err != nil { + http.Error(w, "Unauthorized", http.StatusUnauthorized) + return + } + + if strings.HasPrefix(user.ID, "anonymous_") { + http.Error(w, "Access denied", http.StatusForbidden) + return + } + next.ServeHTTP(w, r) + } + return http.HandlerFunc(fn) +} diff --git a/backend/app/rest/api/rest_test.go b/backend/app/rest/api/rest_test.go index 51ba067f..d21b1c6c 100644 --- a/backend/app/rest/api/rest_test.go +++ b/backend/app/rest/api/rest_test.go @@ -24,6 +24,7 @@ import ( "github.com/stretchr/testify/require" "github.com/umputun/remark/backend/app/migrator" + "github.com/umputun/remark/backend/app/rest" "github.com/umputun/remark/backend/app/rest/proxy" "github.com/umputun/remark/backend/app/store" adminstore "github.com/umputun/remark/backend/app/store/admin" @@ -176,6 +177,26 @@ func TestRest_RunAutocertModeHTTPOnly(t *testing.T) { srv.Shutdown() } +func Test_rejectAnonUser(t *testing.T) { + + ts := httptest.NewServer(fakeAuth(rejectAnonUser(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintln(w, "Hello") + })))) + defer ts.Close() + + resp, err := http.Get(ts.URL) + require.NoError(t, err) + assert.Equal(t, http.StatusUnauthorized, resp.StatusCode, "use not logged in") + + resp, err = http.Get(ts.URL + "?fake_id=anonymous_user123&fake_name=test") + require.NoError(t, err) + assert.Equal(t, http.StatusForbidden, resp.StatusCode, "anon rejected") + + resp, err = http.Get(ts.URL + "?fake_id=real_user123&fake_name=test") + require.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode, "real user") +} + func startupT(t *testing.T) (ts *httptest.Server, srv *Rest, teardown func()) { testDb := fmt.Sprintf("/tmp/test-remark-%d.db", rand.Int31()) @@ -242,6 +263,20 @@ func startupT(t *testing.T) (ts *httptest.Server, srv *Rest, teardown func()) { return ts, srv, teardown } +// fake auth middleware make user authed and uses query's fake_id for ID and fake_name for Name +func fakeAuth(next http.Handler) http.Handler { + fn := func(w http.ResponseWriter, r *http.Request) { + if r.URL.Query().Get("fake_id") != "" { + r = rest.SetUserInfo(r, store.User{ + ID: r.URL.Query().Get("fake_id"), + Name: r.URL.Query().Get("fake_name"), + }) + } + next.ServeHTTP(w, r) + } + return http.HandlerFunc(fn) +} + func get(t *testing.T, url string) (string, int) { r, err := http.Get(url) require.Nil(t, err)