hard body limit, encode disqus imported ID

This commit is contained in:
Umputun
2018-05-08 16:31:23 -05:00
parent e8080e8d7a
commit 1268a8f7c5
9 changed files with 43 additions and 44 deletions
+1 -1
View File
@@ -129,7 +129,7 @@ func (d *Disqus) convert(r io.Reader, siteID string) (ch chan store.Comment) {
ID: comment.UID,
Locator: store.Locator{URL: postsMap[comment.Tid.Val], SiteID: siteID},
User: store.User{
ID: "disqus_" + comment.AuthorUserName,
ID: "disqus_" + store.EncodeID(comment.AuthorUserName),
Name: comment.AuthorName,
IP: comment.IP,
},
+2 -2
View File
@@ -32,7 +32,7 @@ func TestDisqus_Import(t *testing.T) {
assert.Equal(t, "", c.ParentID)
assert.Equal(t, store.Locator{SiteID: "test", URL: "http://radio-t.umputun.com/2011/03/229_8880.html"}, c.Locator)
assert.Equal(t, "Dmitry Noname", c.User.Name)
assert.Equal(t, "disqus_google-74b9e7568ef6860e93862c5d77590123", c.User.ID)
assert.Equal(t, "disqus_8799342cdf328253e03313958ffc6a433659d7ff", c.User.ID)
assert.Equal(t, "89.89.89.139", c.User.IP)
posts, err := dataStore.List("test", 0, 0)
@@ -63,7 +63,7 @@ func TestDisqus_Convert(t *testing.T) {
Text: `<p>The quick brown fox jumps over the lazy dog.</p><p><a href="https://https://radio-t.com" rel="nofollow noopener" title="radio-t">some link</a></p>`,
User: store.User{
Name: "Alexander Blah",
ID: "disqus_facebook-1787732238",
ID: "disqus_328c8b68974aef73785f6b38c3d3fedfdf941434",
IP: "178.178.178.178",
},
}
+6 -4
View File
@@ -41,6 +41,8 @@ type Rest struct {
amdminService admin
}
const hardBodyLimit = 1024 * 64 // limit size of body
var mdExt = blackfriday.NoIntraEmphasis | blackfriday.Tables | blackfriday.FencedCode |
blackfriday.Strikethrough | blackfriday.SpaceHeadings | blackfriday.HardLineBreak |
blackfriday.BackslashLineBreak
@@ -124,7 +126,7 @@ func (s *Rest) Run(port int) {
func (s *Rest) createCommentCtrl(w http.ResponseWriter, r *http.Request) {
comment := store.Comment{}
if err := render.DecodeJSON(r.Body, &comment); err != nil {
if err := render.DecodeJSON(http.MaxBytesReader(w, r.Body, hardBodyLimit), &comment); err != nil {
rest.SendErrorJSON(w, r, http.StatusBadRequest, err, "can't bind comment")
return
}
@@ -166,7 +168,7 @@ func (s *Rest) createCommentCtrl(w http.ResponseWriter, r *http.Request) {
func (s *Rest) previewCommentCtrl(w http.ResponseWriter, r *http.Request) {
comment := store.Comment{}
if err := render.DecodeJSON(r.Body, &comment); err != nil {
if err := render.DecodeJSON(http.MaxBytesReader(w, r.Body, hardBodyLimit), &comment); err != nil {
rest.SendErrorJSON(w, r, http.StatusBadRequest, err, "can't bind comment")
return
}
@@ -195,7 +197,7 @@ func (s *Rest) updateCommentCtrl(w http.ResponseWriter, r *http.Request) {
Summary string
}{}
if err := render.DecodeJSON(r.Body, &edit); err != nil {
if err := render.DecodeJSON(http.MaxBytesReader(w, r.Body, hardBodyLimit), &edit); err != nil {
rest.SendErrorJSON(w, r, http.StatusBadRequest, err, "can't bind comment")
return
}
@@ -397,7 +399,7 @@ func (s *Rest) countCtrl(w http.ResponseWriter, r *http.Request) {
func (s *Rest) countMultiCtrl(w http.ResponseWriter, r *http.Request) {
siteID := r.URL.Query().Get("site")
posts := []string{}
if err := render.DecodeJSON(r.Body, &posts); err != nil {
if err := render.DecodeJSON(http.MaxBytesReader(w, r.Body, hardBodyLimit), &posts); err != nil {
rest.SendErrorJSON(w, r, http.StatusBadRequest, err, "can't get list of posts from request")
return
}
+1 -1
View File
@@ -53,7 +53,7 @@ func (p *AvatarProxy) Put(u store.User) (avatarURL string, err error) {
}()
// get ID and location of locally cached avatar
encID := rest.EncodeID(u.ID)
encID := store.EncodeID(u.ID)
location := p.location(encID) // location adds partion to path
if _, err = os.Stat(location); os.IsNotExist(err) {
+4 -5
View File
@@ -9,7 +9,6 @@ import (
"golang.org/x/oauth2/github"
"golang.org/x/oauth2/google"
"github.com/umputun/remark/app/rest"
"github.com/umputun/remark/app/store"
)
@@ -25,7 +24,7 @@ func NewGoogle(p Params) Provider {
MapUser: func(data userData, _ []byte) store.User {
userInfo := store.User{
// encode email with provider name to avoid collision if same id returned by other provider
ID: "google_" + rest.EncodeID(data.value("email")),
ID: "google_" + store.EncodeID(data.value("email")),
Name: data.value("name"),
Picture: data.value("picture"),
}
@@ -48,7 +47,7 @@ func NewGithub(p Params) Provider {
Store: p.SessionStore,
MapUser: func(data userData, _ []byte) store.User {
userInfo := store.User{
ID: "github_" + rest.EncodeID(data.value("login")),
ID: "github_" + store.EncodeID(data.value("login")),
Name: data.value("name"),
Picture: data.value("avatar_url"),
}
@@ -83,7 +82,7 @@ func NewFacebook(p Params) Provider {
Store: p.SessionStore,
MapUser: func(data userData, bdata []byte) store.User {
userInfo := store.User{
ID: "facebook_" + rest.EncodeID(data.value("id")),
ID: "facebook_" + store.EncodeID(data.value("id")),
Name: data.value("name"),
}
if userInfo.Name == "" {
@@ -113,7 +112,7 @@ func NewDisqus(p Params) Provider {
Store: p.SessionStore,
MapUser: func(data userData, _ []byte) store.User {
userInfo := store.User{
ID: "disqus_" + rest.EncodeID(data.value("login")),
ID: "disqus_" + store.EncodeID(data.value("login")),
Name: data.value("name"),
Picture: data.value("avatar_url"),
}
-15
View File
@@ -2,11 +2,7 @@ package rest
import (
"context"
"crypto/sha1"
"errors"
"fmt"
"hash/crc64"
"log"
"net/http"
"github.com/umputun/remark/app/store"
@@ -35,14 +31,3 @@ func SetUserInfo(r *http.Request, user store.User) *http.Request {
ctx = context.WithValue(ctx, contextKey("user"), user)
return r.WithContext(ctx)
}
// EncodeID hashes user id to sha1
func EncodeID(id string) string {
h := sha1.New()
if _, err := h.Write([]byte(id)); err != nil {
// fail back to crc64
log.Printf("[WARN] can't hash id %s, %s", id, err)
return fmt.Sprintf("%x", crc64.Checksum([]byte(id), crc64.MakeTable(crc64.ECMA)))
}
return fmt.Sprintf("%x", h.Sum(nil))
}
-15
View File
@@ -8,21 +8,6 @@ import (
"github.com/umputun/remark/app/store"
)
func TestEncodeID(t *testing.T) {
tbl := []struct {
id string
hash string
}{
{"myid", "6e34471f84557e1713012d64a7477c71bfdac631"},
{"", "da39a3ee5e6b4b0d3255bfef95601890afd80709"},
{"blah blah", "135a1e01bae742c4a576b20fd41a683f6483ca43"},
}
for i, tt := range tbl {
assert.Equal(t, tt.hash, EncodeID(tt.id), "case #%d", i)
}
}
func TestGetUserInfo(t *testing.T) {
r, err := http.NewRequest("GET", "http://blah.com", nil)
assert.Nil(t, err)
+14 -1
View File
@@ -4,6 +4,7 @@ import (
"crypto/hmac"
"crypto/sha1"
"fmt"
"hash/crc64"
"html/template"
"log"
"strconv"
@@ -95,7 +96,7 @@ func (c *Comment) Sanitize() {
// c.Text = strings.Replace(c.Text, "\t", "", -1)
}
// hashIP replace sensitive fields with hashes
// hashIP replace sensitive fields with hmac
func (u *User) hashIP(secret string) {
hashVal := func(val string) string {
@@ -112,3 +113,15 @@ func (u *User) hashIP(secret string) {
u.IP = hashVal(u.IP)
}
// EncodeID hashes id to sha1. The function intentionally left outside of User struct because in some cases
// we need hashing for parts of id, in some others hasing for non-User values.
func EncodeID(id string) string {
h := sha1.New()
if _, err := h.Write([]byte(id)); err != nil {
// fail back to crc64
log.Printf("[WARN] can't hash id %s, %s", id, err)
return fmt.Sprintf("%x", crc64.Checksum([]byte(id), crc64.MakeTable(crc64.ECMA)))
}
return fmt.Sprintf("%x", h.Sum(nil))
}
+15
View File
@@ -58,3 +58,18 @@ func TestComment_PrepareUntrusted(t *testing.T) {
assert.Equal(t, User{ID: "username"}, comment.User)
}
func TestComment_EncodeID(t *testing.T) {
tbl := []struct {
id string
hash string
}{
{"myid", "6e34471f84557e1713012d64a7477c71bfdac631"},
{"", "da39a3ee5e6b4b0d3255bfef95601890afd80709"},
{"blah blah", "135a1e01bae742c4a576b20fd41a683f6483ca43"},
}
for i, tt := range tbl {
assert.Equal(t, tt.hash, EncodeID(tt.id), "case #%d", i)
}
}