From 1955e20f933e8c526f8f51be394b8960253697a9 Mon Sep 17 00:00:00 2001 From: Umputun Date: Wed, 7 Mar 2018 21:59:48 -0600 Subject: [PATCH] encode user id --- app/rest/auth/avatar.go | 13 +------------ app/rest/auth/avatar_test.go | 2 ++ app/rest/auth/providers.go | 10 ++++------ app/rest/user.go | 15 +++++++++++++++ app/store/bolt.go | 21 +++++++++++++++------ 5 files changed, 37 insertions(+), 24 deletions(-) diff --git a/app/rest/auth/avatar.go b/app/rest/auth/avatar.go index 7e6a41f9..300fd5a4 100644 --- a/app/rest/auth/avatar.go +++ b/app/rest/auth/avatar.go @@ -1,7 +1,6 @@ package auth import ( - "crypto/sha1" "fmt" "hash/crc64" "io" @@ -54,7 +53,7 @@ func (p *AvatarProxy) Put(u store.User) (avatarURL string, err error) { }() // get ID and location of locally cached avatar - encID := p.encodeID(u.ID) + encID := rest.EncodeID(u.ID) location := p.location(encID) // location adds partion to path if _, err = os.Stat(location); os.IsNotExist(err) { @@ -126,16 +125,6 @@ func (p *AvatarProxy) Default() string { return strings.TrimRight(p.RemarkURL, "/") + p.RoutePath + "/" + p.DefaultAvatar } -// encodeID hashes user id to sha1 -func (p *AvatarProxy) encodeID(id string) string { - h := sha1.New() - if _, err := h.Write([]byte(id)); err != nil { - log.Printf("[WARN] can't hash id %s, %s", id, err) - return id - } - return fmt.Sprintf("%x", h.Sum(nil)) -} - // get location for user id by adding partion to final path in order to keep files // in different subdirectories and avoid too many files in a single place. // the end result is a full path like this - /tmp/avatars.test/92 diff --git a/app/rest/auth/avatar_test.go b/app/rest/auth/avatar_test.go index 128617f1..a0631210 100644 --- a/app/rest/auth/avatar_test.go +++ b/app/rest/auth/avatar_test.go @@ -51,6 +51,7 @@ func TestPutDefault(t *testing.T) { assert.Equal(t, int64(10), fi.Size()) } + func TestRoutes(t *testing.T) { p := AvatarProxy{StorePath: "/tmp/avatars.test", RoutePath: "/avatar", DefaultAvatar: "default.image"} os.MkdirAll("/tmp/avatars.test", 0700) @@ -77,6 +78,7 @@ func TestRoutes(t *testing.T) { assert.NoError(t, err) assert.Equal(t, int64(8432), sz) } + func TestRoutesDefault(t *testing.T) { p := AvatarProxy{StorePath: "/tmp/avatars.test", RoutePath: "/avatar", DefaultAvatar: "default.image"} os.MkdirAll("/tmp/avatars.test", 0700) diff --git a/app/rest/auth/providers.go b/app/rest/auth/providers.go index 8e1a4e31..5b933e2d 100644 --- a/app/rest/auth/providers.go +++ b/app/rest/auth/providers.go @@ -8,6 +8,7 @@ import ( "golang.org/x/oauth2/github" "golang.org/x/oauth2/google" + "github.com/umputun/remark/app/rest" "github.com/umputun/remark/app/store" ) @@ -22,7 +23,7 @@ func NewGoogle(p Params) Provider { Store: p.SessionStore, MapUser: func(data userData, _ []byte) store.User { userInfo := store.User{ - ID: data.value("email"), + ID: rest.EncodeID("google_" + data.value("email")), Name: data.value("name"), Picture: data.value("picture"), Profile: data.value("profile"), @@ -30,7 +31,6 @@ func NewGoogle(p Params) Provider { if userInfo.Name == "" { userInfo.Name = strings.Split(userInfo.ID, "@")[0] } - userInfo.ID = "google_" + userInfo.ID return userInfo }, }) @@ -47,7 +47,7 @@ func NewGithub(p Params) Provider { Store: p.SessionStore, MapUser: func(data userData, _ []byte) store.User { userInfo := store.User{ - ID: data.value("login"), + ID: rest.EncodeID("github_" + data.value("login")), Name: data.value("name"), Picture: data.value("avatar_url"), Profile: data.value("html_url"), @@ -55,7 +55,6 @@ func NewGithub(p Params) Provider { if userInfo.Name == "" { userInfo.Name = userInfo.ID } - userInfo.ID = "github_" + userInfo.ID return userInfo }, }) @@ -84,13 +83,12 @@ func NewFacebook(p Params) Provider { Store: p.SessionStore, MapUser: func(data userData, bdata []byte) store.User { userInfo := store.User{ - ID: data.value("id"), + ID: rest.EncodeID("facebook_" + data.value("id")), Name: data.value("name"), } if userInfo.Name == "" { userInfo.Name = userInfo.ID } - userInfo.ID = "facebook_" + userInfo.ID uinfoJSON := uinfo{} if err := json.Unmarshal(bdata, &uinfoJSON); err == nil { diff --git a/app/rest/user.go b/app/rest/user.go index cb321838..40492c8d 100644 --- a/app/rest/user.go +++ b/app/rest/user.go @@ -1,7 +1,11 @@ package rest import ( + "crypto/sha1" "errors" + "fmt" + "hash/crc64" + "log" "net/http" "github.com/umputun/remark/app/store" @@ -24,3 +28,14 @@ func GetUserInfo(r *http.Request) (user store.User, err error) { return store.User{}, errors.New("user can't be parsed") } + +// 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)) +} diff --git a/app/store/bolt.go b/app/store/bolt.go index 3c3dcbd2..2a8f37fa 100644 --- a/app/store/bolt.go +++ b/app/store/bolt.go @@ -116,9 +116,10 @@ func (b *BoltDB) Create(comment Comment) (commentID string, err error) { return errors.Wrapf(e, "failed to put key %s to bucket %s", comment.ID, comment.Locator.URL) } + ref := b.makeRef(comment) + // add reference to comment to "last" bucket lastBkt := tx.Bucket([]byte(lastBucketName)) - ref := b.makeRef(comment) commentTs := []byte(comment.Timestamp.Format(tsNano)) e = lastBkt.Put(commentTs, ref) if e != nil { @@ -126,17 +127,16 @@ func (b *BoltDB) Create(comment Comment) (commentID string, err error) { } // add reference to commentID to "users" bucket - usersBkt := tx.Bucket([]byte(userBucketName)) - // get bucket for userID - userIDBkt, e := usersBkt.CreateBucketIfNotExists([]byte(comment.User.ID)) + userBkt, e := b.getUserBucket(tx, comment.User.ID) if e != nil { return errors.Wrapf(e, "can't get bucket %s", comment.User.ID) } // put into individual user's bucket with ts as a key - if e = userIDBkt.Put(commentTs, ref); e != nil { + if e = userBkt.Put(commentTs, ref); e != nil { return errors.Wrapf(e, "failed to put user comment %s for %s", comment.ID, comment.User.ID) } + // increment comments count for post url if _, e = b.count(tx, comment.Locator.URL, 1); e != nil { return errors.Wrapf(e, "failed to increment count for %s", comment.Locator) } @@ -181,6 +181,7 @@ func (b *BoltDB) Delete(locator Locator, commentID string) error { return errors.Wrapf(err, "can't delete key %s from bucket %s", commentID, lastBucketName) } + // decrement comments count for post url if _, e = b.count(tx, comment.Locator.URL, -1); e != nil { return errors.Wrapf(e, "failed to decrement count for %s", comment.Locator) } @@ -370,7 +371,6 @@ func (b BoltDB) List(siteID string, limit, skip int) (list []PostInfo, err error if limit > 0 && len(list) >= limit { break } - } return nil }) @@ -496,6 +496,15 @@ func (b *BoltDB) makePostBucket(tx *bolt.Tx, postURL string) (*bolt.Bucket, erro return res, nil } +func (b *BoltDB) getUserBucket(tx *bolt.Tx, userID string) (*bolt.Bucket, error) { + usersBkt := tx.Bucket([]byte(userBucketName)) + userIDBkt, e := usersBkt.CreateBucketIfNotExists([]byte(userID)) // get bucket for userID + if e != nil { + return nil, errors.Wrapf(e, "can't get bucket %s", userID) + } + return userIDBkt, nil +} + // save comment to key for bucket. Should run in update tx func (b *BoltDB) save(bkt *bolt.Bucket, key []byte, comment Comment) (err error) { jdata, jerr := json.Marshal(&comment)