feature/verified (#61)

* add store methods for verification

* add verify rest and auth

* lint: fix double conversion of userID key

* test for middleware, fix log without auth info

* make all scripts with -e
This commit is contained in:
Umputun
2018-05-29 23:07:50 -05:00
committed by GitHub
parent de60edfa61
commit 0363fc4cd9
20 changed files with 260 additions and 59 deletions
+15
View File
@@ -32,6 +32,7 @@ func (a *admin) routes(middlewares ...func(http.Handler) http.Handler) chi.Route
router.Delete("/comment/{id}", a.deleteCommentCtrl)
router.Put("/user/{userid}", a.setBlockCtrl)
router.Delete("/user/{userid}", a.deleteUserCtrl)
router.Put("/verify/{userid}", a.setVerifyCtrl)
router.Get("/export", a.exportCtrl)
router.Put("/pin/{id}", a.setPinCtrl)
router.Get("/blocked", a.blockedUsersCtrl)
@@ -110,6 +111,20 @@ func (a *admin) setReadOnlyCtrl(w http.ResponseWriter, r *http.Request) {
render.JSON(w, r, JSON{"locator": locator, "read-only": roStatus})
}
// PUT /verify?site=siteID&url=post-url&ro=1 - set or reset read-only status for the post
func (a *admin) setVerifyCtrl(w http.ResponseWriter, r *http.Request) {
userID := chi.URLParam(r, "userid")
siteID := r.URL.Query().Get("site")
verifyStatus := r.URL.Query().Get("verified") == "1"
if err := a.dataService.SetVerified(siteID, userID, verifyStatus); err != nil {
rest.SendErrorJSON(w, r, http.StatusBadRequest, err, "can't set verify status")
return
}
a.cache.Flush(siteID, userID)
render.JSON(w, r, JSON{"user": userID, "verified": verifyStatus})
}
// PUT /pin/{id}?site=siteID&url=post-url&pin=1
// mark/unmark comment as a special
func (a *admin) setPinCtrl(w http.ResponseWriter, r *http.Request) {
+38
View File
@@ -275,6 +275,44 @@ func TestAdmin_ReadOnly(t *testing.T) {
assert.False(t, info.ReadOnly)
}
func TestAdmin_Verify(t *testing.T) {
srv, ts := prep(t)
assert.NotNil(t, srv)
defer cleanup(ts)
c1 := store.Comment{Text: "test test #1", Locator: store.Locator{SiteID: "radio-t",
URL: "https://radio-t.com/blah"}, User: store.User{Name: "user1 name", ID: "user1"}}
c2 := store.Comment{Text: "test test #2", ParentID: "p1", Locator: store.Locator{SiteID: "radio-t",
URL: "https://radio-t.com/blah"}, User: store.User{Name: "user2", ID: "user2"}}
_, err := srv.DataService.Create(c1)
assert.Nil(t, err)
_, err = srv.DataService.Create(c2)
assert.Nil(t, err)
verified := srv.DataService.IsVerified("radio-t", "user1")
assert.False(t, verified)
client := http.Client{}
req, err := http.NewRequest(http.MethodPut,
fmt.Sprintf("%s/api/v1/admin/verify/user1?site=radio-t&verified=1", ts.URL), nil)
assert.Nil(t, err)
withBasicAuth(req, "dev", "password")
_, err = client.Do(req)
require.Nil(t, err)
verified = srv.DataService.IsVerified("radio-t", "user1")
assert.True(t, verified)
req, err = http.NewRequest(http.MethodPut,
fmt.Sprintf("%s/api/v1/admin/verify/user1?site=radio-t&verified=0", ts.URL), nil)
assert.Nil(t, err)
withBasicAuth(req, "dev", "password")
_, err = client.Do(req)
require.Nil(t, err)
verified = srv.DataService.IsVerified("radio-t", "user1")
assert.False(t, verified)
}
func TestAdmin_ExportStream(t *testing.T) {
srv, ts := prep(t)
assert.NotNil(t, srv)
+63
View File
@@ -0,0 +1,63 @@
package api
import (
"io/ioutil"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/go-chi/chi"
"github.com/stretchr/testify/assert"
"github.com/umputun/remark/app/rest"
"github.com/umputun/remark/app/store"
"github.com/stretchr/testify/require"
)
func TestMiddleware_AppInfo(t *testing.T) {
router := chi.NewRouter()
router.With(AppInfo("remark42", "12345")).Get("/blah", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
w.Write([]byte("blah blah"))
})
ts := httptest.NewServer(router)
defer ts.Close()
resp, err := http.Get(ts.URL + "/blah")
require.Nil(t, err)
assert.Equal(t, 200, resp.StatusCode)
b, err := ioutil.ReadAll(resp.Body)
assert.NoError(t, err)
assert.Equal(t, "blah blah", string(b))
assert.Equal(t, "remark42", resp.Header.Get("App-Name"))
assert.Equal(t, "12345", resp.Header.Get("App-Version"))
assert.Equal(t, "Umputun", resp.Header.Get("Org"))
}
func TestMiddleware_GetBodyAndUser(t *testing.T) {
req, err := http.NewRequest("GET", "http://example.com/request", strings.NewReader("body"))
require.Nil(t, err)
body, user := getBodyAndUser(req, []LoggerFlag{LogAll})
assert.Equal(t, "body", body)
assert.Equal(t, "", user, "no user")
req = rest.SetUserInfo(req, store.User{ID: "id1", Name: "user1"})
body, user = getBodyAndUser(req, []LoggerFlag{LogAll})
assert.Equal(t, ` - id1 "user1"`, user, "no user")
body, user = getBodyAndUser(req, nil)
assert.Equal(t, "", body)
assert.Equal(t, "", user, "no user")
body, user = getBodyAndUser(req, []LoggerFlag{LogNone})
assert.Equal(t, "", body)
assert.Equal(t, "", user, "no user")
body, user = getBodyAndUser(req, []LoggerFlag{LogUser})
assert.Equal(t, "", body)
assert.Equal(t, ` - id1 "user1"`, user, "no user")
}
+4 -2
View File
@@ -128,11 +128,12 @@ func (s *Rest) routes() chi.Router {
// api routes
router.Route("/api/v1", func(rapi chi.Router) {
rapi.Use(Logger(LogAll), tollbooth_chi.LimitHandler(tollbooth.NewLimiter(10, nil)))
rapi.Use(tollbooth_chi.LimitHandler(tollbooth.NewLimiter(10, nil)))
// open routes
rapi.Group(func(ropen chi.Router) {
ropen.Use(s.Authenticator.Auth(false))
ropen.Use(Logger(LogAll))
ropen.Get("/find", s.findCommentsCtrl)
ropen.Get("/id/{id}", s.commentByIDCtrl)
ropen.Get("/comments", s.findUserCommentsCtrl)
@@ -151,13 +152,14 @@ func (s *Rest) routes() chi.Router {
// protected routes, require auth
rapi.Group(func(rauth chi.Router) {
rauth.Use(s.Authenticator.Auth(true))
rauth.Use(Logger(LogAll))
rauth.Post("/comment", s.createCommentCtrl)
rauth.Put("/comment/{id}", s.updateCommentCtrl)
rauth.Get("/user", s.userInfoCtrl)
rauth.Put("/vote/{id}", s.voteCtrl)
// admin routes, admin users only
rauth.Mount("/admin", s.adminService.routes(s.Authenticator.AdminOnly))
rauth.Mount("/admin", s.adminService.routes(s.Authenticator.AdminOnly, Logger(LogAll)))
})
})