diff --git a/app/main.go b/app/main.go index 2c68dd31..6beedbcb 100644 --- a/app/main.go +++ b/app/main.go @@ -16,9 +16,10 @@ import ( ) var opts struct { - DBFile string `long:"db" env:"BOLTDB_FILE" default:"/tmp/remark.db" description:"bolt file name"` - SiteURL string `long:"site-url" env:"REMARK_URL" default:"http://remark.umputun.com:8080" description:"url to remark"` - Admins []string `long:"admin" env:"ADMIN" default:"umputun@gmail.com" description:"admin(s) names" env-delim:","` + BoltPath string `long:"bolt" env:"BOLTDB_PATH" default:"/tmp" description:"parent dir for bolt files"` + Sites []string `long:"site" env:"SITE" default:"demo" description:"site names" env-delim:","` + RemarkURL string `long:"url" env:"REMARK_URL" default:"http://remark.umputun.com:8080" description:"url to remark"` + Admins []string `long:"admin" env:"ADMIN" default:"umputun@gmail.com" description:"admin(s) names" env-delim:","` DevMode bool `long:"dev" env:"DEV" description:"development mode, no auth enforced"` Dbg bool `long:"dbg" env:"DEBUG" description:"debug mode"` @@ -37,7 +38,7 @@ var opts struct { ImportCommand struct { Provider string `long:"provider" default:"disqus" description:"provider type"` - SiteID string `long:"site" default:"site" description:"site ID"` + SiteID string `long:"site" default:"demo" description:"site ID"` InputFile string `long:"file" default:"disqus.xml" description:"input file"` } `command:"import" description:"import comments from external sources"` } @@ -54,7 +55,11 @@ func main() { setupLog(opts.Dbg) log.Print("[INFO] started remark") - dataStore, err := store.NewBoltDB(opts.DBFile) + boltSites := []store.BoltSite{} + for _, site := range opts.Sites { + boltSites = append(boltSites, store.BoltSite{SiteID: site, FileName: fmt.Sprintf("%s/%s.db", opts.BoltPath, site)}) + } + dataStore, err := store.NewBoltDB(boltSites...) if err != nil { log.Fatalf("[ERROR] can't initialize data store, %+v", err) } @@ -87,13 +92,13 @@ func main() { Cid: opts.ServerCommand.GoogleCID, Csecret: opts.ServerCommand.GoogleCSEC, SessionStore: sessionStore, - SiteURL: opts.SiteURL, + RemarkURL: opts.RemarkURL, }), AuthGithub: auth.NewGithub(auth.Params{ Cid: opts.ServerCommand.GithubCID, Csecret: opts.ServerCommand.GithubCSEC, SessionStore: sessionStore, - SiteURL: opts.SiteURL, + RemarkURL: opts.RemarkURL, }), } diff --git a/app/migrator/remark_test.go b/app/migrator/remark_test.go index 00800e26..e5ad31eb 100644 --- a/app/migrator/remark_test.go +++ b/app/migrator/remark_test.go @@ -33,7 +33,7 @@ func TestRemark_Export(t *testing.T) { func prep(t *testing.T) *store.BoltDB { os.Remove(testDb) - b, err := store.NewBoltDB(testDb) + b, err := store.NewBoltDB(store.BoltSite{SiteID: "radio-t", FileName: testDb}) assert.Nil(t, err) comment := store.Comment{ diff --git a/app/rest/admin.go b/app/rest/admin.go index 841c21c7..0b6f716d 100644 --- a/app/rest/admin.go +++ b/app/rest/admin.go @@ -30,14 +30,14 @@ func (a *admin) routes() chi.Router { return router } -// DELETE /comment/{id}?url=post-url +// DELETE /comment/{id}?site=siteID&url=post-url func (a *admin) deleteCommentCtrl(w http.ResponseWriter, r *http.Request) { id := chi.URLParam(r, "id") + locator := store.Locator{SiteID: r.URL.Query().Get("site"), URL: r.URL.Query().Get("url")} log.Printf("[INFO] delete comment %s", id) - url := r.URL.Query().Get("url") - err := a.dataService.Delete(store.Locator{URL: url}, id) + err := a.dataService.Delete(locator, id) if err != nil { log.Printf("[WARN] can't delete comment, %s", err) httpError(w, r, http.StatusInternalServerError, err, "can't delete comment") @@ -45,7 +45,7 @@ func (a *admin) deleteCommentCtrl(w http.ResponseWriter, r *http.Request) { } a.respCache.Flush() render.Status(r, http.StatusOK) - render.JSON(w, r, JSON{"id": id, "url": url}) + render.JSON(w, r, JSON{"id": id, "loc": locator}) } // PUT /user/{userid}?site=side-id&block=1 @@ -62,18 +62,18 @@ func (a *admin) setBlockCtrl(w http.ResponseWriter, r *http.Request) { render.JSON(w, r, JSON{"user_id": userID, "site_id": siteID, "block": blockStatus}) } -// PUT /pin/{id}?url=post-url&pin=1 +// PUT /pin/{id}?site=siteID&url=post-url&pin=1 func (a *admin) setPinCtrl(w http.ResponseWriter, r *http.Request) { commentID := chi.URLParam(r, "id") - url := r.URL.Query().Get("url") + locator := store.Locator{SiteID: r.URL.Query().Get("site"), URL: r.URL.Query().Get("url")} pinStatus := r.URL.Query().Get("pin") == "1" - if err := a.dataService.SetPin(store.Locator{URL: url}, commentID, pinStatus); err != nil { + if err := a.dataService.SetPin(locator, commentID, pinStatus); err != nil { httpError(w, r, http.StatusBadRequest, err, "can't set pin status") return } a.respCache.Flush() - render.JSON(w, r, JSON{"id": commentID, "url": url, "pin": pinStatus}) + render.JSON(w, r, JSON{"id": commentID, "loc": locator, "pin": pinStatus}) } // GET /export?site=site-id @@ -84,5 +84,5 @@ func (a *admin) exportCtrl(w http.ResponseWriter, r *http.Request) { } } func (a *admin) checkBlocked(locator store.Locator, user store.User) bool { - return a.dataService.IsBlocked(store.Locator{}, user.ID) + return a.dataService.IsBlocked(locator, user.ID) } diff --git a/app/rest/auth/auth.go b/app/rest/auth/auth.go index ed0645b0..c60203f9 100644 --- a/app/rest/auth/auth.go +++ b/app/rest/auth/auth.go @@ -37,7 +37,7 @@ type Params struct { Cid string Csecret string SessionStore *sessions.FilesystemStore - SiteURL string + RemarkURL string } // newProvider makes auth for given provider diff --git a/app/rest/auth/providers.go b/app/rest/auth/providers.go index 96fa06f7..b564a45d 100644 --- a/app/rest/auth/providers.go +++ b/app/rest/auth/providers.go @@ -14,7 +14,7 @@ func NewGoogle(p Params) *Provider { return initProvider(p, Provider{ Name: "google", Endpoint: google.Endpoint, - RedirectURL: p.SiteURL + "/auth/google", + RedirectURL: p.RemarkURL + "/auth/google", Scopes: []string{"https://www.googleapis.com/auth/userinfo.email"}, InfoURL: "https://www.googleapis.com/oauth2/v3/userinfo", FilesystemStore: p.SessionStore, @@ -39,7 +39,7 @@ func NewGithub(p Params) *Provider { return initProvider(p, Provider{ Name: "github", Endpoint: github.Endpoint, - RedirectURL: p.SiteURL + "/auth/github", + RedirectURL: p.RemarkURL + "/auth/github", Scopes: []string{"user:email"}, InfoURL: "https://api.github.com/user", FilesystemStore: p.SessionStore, diff --git a/app/rest/server.go b/app/rest/server.go index 3b3f48c0..5c558742 100644 --- a/app/rest/server.go +++ b/app/rest/server.go @@ -150,19 +150,19 @@ func (s *Server) createCommentCtrl(w http.ResponseWriter, r *http.Request) { s.respCache.Flush() render.Status(r, http.StatusAccepted) - render.JSON(w, r, JSON{"id": id, "url": comment.Locator.URL}) + render.JSON(w, r, JSON{"id": id, "loc": comment.Locator}) } -// DELETE /comment/{id}?url=post-url +// DELETE /comment/{id}?site=siteID&url=post-url func (s *Server) deleteCommentCtrl(w http.ResponseWriter, r *http.Request) { id := chi.URLParam(r, "id") log.Printf("[DEBUG] delete comment %s", id) - url := r.URL.Query().Get("url") - err := s.DataService.Delete(store.Locator{URL: url}, id) + locator := store.Locator{SiteID: r.URL.Query().Get("site"), URL: r.URL.Query().Get("url")} + err := s.DataService.Delete(locator, id) if err != nil { - log.Printf("[WARN] can't delete comment, %s", err) + log.Printf("[WARN] can't delete comment %s %+v, %s", id, locator, err) httpError(w, r, http.StatusInternalServerError, err, "can't delete comment") return } @@ -170,13 +170,13 @@ func (s *Server) deleteCommentCtrl(w http.ResponseWriter, r *http.Request) { s.respCache.Flush() render.Status(r, http.StatusOK) - render.JSON(w, r, JSON{"id": id, "url": url}) + render.JSON(w, r, JSON{"id": id, "loc": locator}) } -// GET /find?url=post-url&format=tree&sort=-time +// GET /find?site=siteID&url=post-url&format=tree&sort=-time func (s *Server) findCommentsCtrl(w http.ResponseWriter, r *http.Request) { - url := r.URL.Query().Get("url") - log.Printf("[DEBUG] get comments for %s", url) + locator := store.Locator{SiteID: r.URL.Query().Get("site"), URL: r.URL.Query().Get("url")} + log.Printf("[DEBUG] get comments for %+v", locator) cacheKey := r.URL.String() if comments, ok := s.respCache.Get(cacheKey); ok { @@ -185,9 +185,9 @@ func (s *Server) findCommentsCtrl(w http.ResponseWriter, r *http.Request) { return } - comments, err := s.DataService.Find(store.Request{Locator: store.Locator{URL: url}, Sort: r.URL.Query().Get("sort")}) + comments, err := s.DataService.Find(store.Request{Locator: locator, Sort: r.URL.Query().Get("sort")}) if err != nil { - log.Printf("[WARN] can't get comments for %s, %s", url, err) + log.Printf("[WARN] can't get comments for %+v, %s", locator, err) httpError(w, r, http.StatusInternalServerError, err, "can't load comments comment") return } @@ -201,7 +201,7 @@ func (s *Server) findCommentsCtrl(w http.ResponseWriter, r *http.Request) { renderJSONWithHTML(w, r, comments) } -// GET /last/{max}?url=abc +// GET /last/{max}?site=siteID func (s *Server) lastCommentsCtrl(w http.ResponseWriter, r *http.Request) { max, err := strconv.Atoi(chi.URLParam(r, "max")) @@ -216,7 +216,7 @@ func (s *Server) lastCommentsCtrl(w http.ResponseWriter, r *http.Request) { return } - comments, err := s.DataService.Last(store.Locator{}, max) + comments, err := s.DataService.Last(store.Locator{SiteID: r.URL.Query().Get("site")}, max) if err != nil { log.Printf("[WARN] can't get last comments, %s", err) httpError(w, r, http.StatusInternalServerError, err, "can't get last comments") @@ -228,15 +228,15 @@ func (s *Server) lastCommentsCtrl(w http.ResponseWriter, r *http.Request) { renderJSONWithHTML(w, r, comments) } -// GET /id/{id}?url=post-url +// GET /id/{id}?site=siteID&url=post-url func (s *Server) commentByIDCtrl(w http.ResponseWriter, r *http.Request) { id := chi.URLParam(r, "id") - url := r.URL.Query().Get("url") + locator := store.Locator{SiteID: r.URL.Query().Get("site"), URL: r.URL.Query().Get("url")} - log.Printf("[DEBUG] get comments by id %s, %s", id, url) + log.Printf("[DEBUG] get comments by id %s, %+v", id, locator) - comment, err := s.DataService.GetByID(store.Locator{URL: url}, id) + comment, err := s.DataService.GetByID(locator, id) if err != nil { log.Printf("[WARN] can't get comment, %s", err) httpError(w, r, http.StatusInternalServerError, err, "can't get comment by id") @@ -246,7 +246,7 @@ func (s *Server) commentByIDCtrl(w http.ResponseWriter, r *http.Request) { renderJSONWithHTML(w, r, comment) } -// GET /comments?user=id +// GET /comments?site=siteID&user=id func (s *Server) findUserCommentsCtrl(w http.ResponseWriter, r *http.Request) { userID := r.URL.Query().Get("user") @@ -260,7 +260,7 @@ func (s *Server) findUserCommentsCtrl(w http.ResponseWriter, r *http.Request) { return } - comments, err := s.DataService.GetByUser(store.Locator{}, userID) + comments, err := s.DataService.GetByUser(store.Locator{SiteID: r.URL.Query().Get("site")}, userID) if err != nil { log.Printf("[WARN] can't get comment, %s", err) httpError(w, r, http.StatusBadRequest, err, "can't get comment by user id") @@ -282,18 +282,18 @@ func (s *Server) userInfoCtrl(w http.ResponseWriter, r *http.Request) { render.JSON(w, r, user) } -// GET /count?url=post-url +// GET /count?site=siteID&url=post-url func (s *Server) countCtrl(w http.ResponseWriter, r *http.Request) { - url := r.URL.Query().Get("url") - count, err := s.DataService.Count(store.Locator{URL: url}) + locator := store.Locator{SiteID: r.URL.Query().Get("site"), URL: r.URL.Query().Get("url")} + count, err := s.DataService.Count(locator) if err != nil { httpError(w, r, http.StatusBadRequest, err, "can't get count") return } - render.JSON(w, r, JSON{"count": count, "url": url}) + render.JSON(w, r, JSON{"count": count, "loc": locator}) } -// PUT /vote/{id}?url=post-url&vote=1 +// PUT /vote/{id}?site=siteID&url=post-url&vote=1 func (s *Server) voteCtrl(w http.ResponseWriter, r *http.Request) { user, err := auth.GetUserInfo(r) @@ -301,14 +301,13 @@ func (s *Server) voteCtrl(w http.ResponseWriter, r *http.Request) { httpError(w, r, http.StatusUnauthorized, err, "can't get user info") return } - + locator := store.Locator{SiteID: r.URL.Query().Get("site"), URL: r.URL.Query().Get("url")} id := chi.URLParam(r, "id") log.Printf("[DEBUG] vote for comment %s", id) - url := r.URL.Query().Get("url") vote := r.URL.Query().Get("vote") == "1" - comment, err := s.DataService.Vote(store.Locator{URL: url}, id, user.ID, vote) + comment, err := s.DataService.Vote(locator, id, user.ID, vote) if err != nil { log.Printf("[WARN] vote rejected for %s - %s, %s", user.ID, id, err) httpError(w, r, http.StatusBadRequest, err, "can't vote for comment") diff --git a/app/store/bolt.go b/app/store/bolt.go index aafbc1dc..eea59447 100644 --- a/app/store/bolt.go +++ b/app/store/bolt.go @@ -21,7 +21,7 @@ import ( // is a bucket with ts:reference // - blocking info sits in "block" bucket. Key is userID, value - ts type BoltDB struct { - *bolt.DB + dbs map[string]*bolt.DB } const ( @@ -32,16 +32,24 @@ const ( userLimit = 100 ) +// BoltSite defines single site param +type BoltSite struct { + FileName string + SiteID string +} + // NewBoltDB makes persistent boltdb-based store -func NewBoltDB(dbFile string) (*BoltDB, error) { - log.Printf("[INFO] bolt store, %s", dbFile) - result := BoltDB{} - db, err := bolt.Open(dbFile, 0600, &bolt.Options{Timeout: 5 * time.Second}) - if err != nil { - return nil, errors.Wrapf(err, "failed to make boltdb for %s", dbFile) +func NewBoltDB(sites ...BoltSite) (*BoltDB, error) { + log.Printf("[INFO] bolt store for sites %+v", sites) + result := BoltDB{dbs: make(map[string]*bolt.DB)} + for _, site := range sites { + db, err := bolt.Open(site.FileName, 0600, &bolt.Options{Timeout: 5 * time.Second}) + if err != nil { + return nil, errors.Wrapf(err, "failed to make boltdb for %s", site.FileName) + } + result.dbs[site.SiteID] = db } - result.DB = db - return &result, err + return &result, nil } // Create saves new comment to store @@ -57,7 +65,11 @@ func (b *BoltDB) Create(comment Comment) (string, error) { comment.Votes = make(map[string]bool) comment = sanitizeComment(comment) // clear potentially dangerous js from all parts of comment - err := b.Update(func(tx *bolt.Tx) error { + bdb, err := b.db(comment.Locator.SiteID) + if err != nil { + return "", err + } + err = bdb.Update(func(tx *bolt.Tx) error { bucket, e := tx.CreateBucketIfNotExists([]byte(comment.Locator.URL)) // bucket per post url if e != nil { return errors.Wrapf(e, "can't make or open bucket", comment.Locator.URL) @@ -112,7 +124,12 @@ func (b *BoltDB) Create(comment Comment) (string, error) { // Delete removes comment locator from the store func (b *BoltDB) Delete(locator Locator, commentID string) error { - return b.Update(func(tx *bolt.Tx) error { + bdb, err := b.db(locator.SiteID) + if err != nil { + return err + } + + return bdb.Update(func(tx *bolt.Tx) error { bucket := tx.Bucket([]byte(locator.URL)) if bucket == nil { return errors.Errorf("no bucket %s in store", locator.URL) @@ -139,7 +156,12 @@ func (b *BoltDB) Delete(locator Locator, commentID string) error { func (b *BoltDB) Find(request Request) ([]Comment, error) { res := []Comment{} - err := b.View(func(tx *bolt.Tx) error { + bdb, err := b.db(request.Locator.SiteID) + if err != nil { + return nil, err + } + + err = bdb.View(func(tx *bolt.Tx) error { bucket := tx.Bucket([]byte(request.Locator.URL)) if bucket == nil { return errors.Errorf("no bucket %s in store", request.Locator.URL) @@ -181,7 +203,12 @@ func (b *BoltDB) Find(request Request) ([]Comment, error) { // GetByID returns comment by id across posts func (b *BoltDB) GetByID(locator Locator, commentID string) (comment Comment, err error) { - err = b.View(func(tx *bolt.Tx) error { + bdb, err := b.db(locator.SiteID) + if err != nil { + return comment, err + } + + err = bdb.View(func(tx *bolt.Tx) error { lastBucket := tx.Bucket([]byte(lastBucketName)) if lastBucket == nil { @@ -224,7 +251,12 @@ func (b *BoltDB) Last(locator Locator, max int) (result []Comment, err error) { max = lastLimit } - err = b.View(func(tx *bolt.Tx) error { + bdb, err := b.db(locator.SiteID) + if err != nil { + return nil, err + } + + err = bdb.View(func(tx *bolt.Tx) error { lastBucket := tx.Bucket([]byte(lastBucketName)) if lastBucket == nil { return errors.Errorf("no bucket %s in store", lastBucketName) @@ -264,7 +296,13 @@ func (b *BoltDB) Last(locator Locator, max int) (result []Comment, err error) { // Count returns number of comments for locator func (b *BoltDB) Count(locator Locator) (count int, err error) { - err = b.View(func(tx *bolt.Tx) error { + + bdb, err := b.db(locator.SiteID) + if err != nil { + return 0, err + } + + err = bdb.View(func(tx *bolt.Tx) error { bucket := tx.Bucket([]byte(locator.URL)) if bucket == nil { return errors.Errorf("no bucket %s in store", locator.URL) @@ -278,7 +316,13 @@ func (b *BoltDB) Count(locator Locator) (count int, err error) { // SetBlock blocks/unblocks user for given site func (b *BoltDB) SetBlock(locator Locator, userID string, status bool) error { - return b.Update(func(tx *bolt.Tx) error { + + bdb, err := b.db(locator.SiteID) + if err != nil { + return err + } + + return bdb.Update(func(tx *bolt.Tx) error { bucket, e := tx.CreateBucketIfNotExists([]byte(blocksBucketName)) if e != nil { @@ -301,7 +345,13 @@ func (b *BoltDB) SetBlock(locator Locator, userID string, status bool) error { // IsBlocked checks if user blocked func (b *BoltDB) IsBlocked(locator Locator, userID string) (result bool) { - _ = b.View(func(tx *bolt.Tx) error { + + bdb, err := b.db(locator.SiteID) + if err != nil { + return false + } + + _ = bdb.View(func(tx *bolt.Tx) error { result = false bucket := tx.Bucket([]byte(blocksBucketName)) if bucket != nil && bucket.Get([]byte(userID)) != nil { @@ -314,7 +364,13 @@ func (b *BoltDB) IsBlocked(locator Locator, userID string) (result bool) { // List returns list of buckets, which is list of all commented posts func (b BoltDB) List(locator Locator) (result []string, err error) { - err = b.View(func(tx *bolt.Tx) error { + + bdb, err := b.db(locator.SiteID) + if err != nil { + return nil, err + } + + err = bdb.View(func(tx *bolt.Tx) error { return tx.ForEach(func(name []byte, _ *bolt.Bucket) error { if string(name) != lastBucketName && string(name) != userBucketName { result = append(result, string(name)) @@ -332,8 +388,12 @@ func (b *BoltDB) GetByUser(locator Locator, userID string) (comments []Comment, comments = []Comment{} commentRefs := []string{} + bdb, err := b.db(locator.SiteID) + if err != nil { + return nil, err + } // get list of references to comments - err = b.View(func(tx *bolt.Tx) error { + err = bdb.View(func(tx *bolt.Tx) error { userBucket := tx.Bucket([]byte(userBucketName)) if userBucket == nil { return errors.Errorf("no bucket %s in store", userBucketName) @@ -375,7 +435,12 @@ func (b *BoltDB) GetByUser(locator Locator, userID string) (comments []Comment, // Get for locator.URL and commentID string func (b *BoltDB) Get(locator Locator, commentID string) (comment Comment, err error) { - err = b.View(func(tx *bolt.Tx) error { + bdb, err := b.db(locator.SiteID) + if err != nil { + return comment, err + } + + err = bdb.View(func(tx *bolt.Tx) error { bucket := tx.Bucket([]byte(locator.URL)) if bucket == nil { return errors.Errorf("no bucket %s in store", locator.URL) @@ -406,7 +471,12 @@ func (b *BoltDB) Put(locator Locator, comment Comment) error { comment.User = curComment.User } - return b.Update(func(tx *bolt.Tx) error { + bdb, err := b.db(locator.SiteID) + if err != nil { + return err + } + + return bdb.Update(func(tx *bolt.Tx) error { bucket := tx.Bucket([]byte(locator.URL)) if bucket == nil { return errors.Errorf("no bucket %s in store", locator.URL) @@ -424,6 +494,13 @@ func (b *BoltDB) Put(locator Locator, comment Comment) error { }) } +func (b *BoltDB) db(siteID string) (*bolt.DB, error) { + if res, ok := b.dbs[siteID]; ok { + return res, nil + } + return nil, errors.Errorf("site %s not found", siteID) +} + // ref represents key:value pair for extra, index-only buckets type ref struct { key string diff --git a/app/store/bolt_test.go b/app/store/bolt_test.go index 3b261436..9c663ee9 100644 --- a/app/store/bolt_test.go +++ b/app/store/bolt_test.go @@ -15,7 +15,7 @@ func TestBoltDB_CreateAndFind(t *testing.T) { defer os.Remove(testDb) b = prep(t) - res, err := b.Find(Request{Locator: Locator{URL: "https://radio-t.com"}}) + res, err := b.Find(Request{Locator: Locator{URL: "https://radio-t.com", SiteID: "radio-t"}}) assert.Nil(t, err) assert.Equal(t, 2, len(res)) assert.Equal(t, `some text, link`, res[0].Text) @@ -27,7 +27,7 @@ func TestBoltDB_Delete(t *testing.T) { defer os.Remove(testDb) b := prep(t) - loc := Locator{URL: "https://radio-t.com"} + loc := Locator{URL: "https://radio-t.com", SiteID: "radio-t"} res, err := b.Find(Request{Locator: loc}) assert.Nil(t, err) assert.Equal(t, 2, len(res)) @@ -49,15 +49,15 @@ func TestBoltDB_GetByID(t *testing.T) { defer os.Remove(testDb) b := prep(t) - res, err := b.Find(Request{Locator: Locator{URL: "https://radio-t.com"}}) + res, err := b.Find(Request{Locator: Locator{URL: "https://radio-t.com", SiteID: "radio-t"}}) assert.Nil(t, err) assert.Equal(t, 2, len(res)) - comment, err := b.GetByID(Locator{URL: "https://radio-t.com"}, res[1].ID) + comment, err := b.GetByID(Locator{URL: "https://radio-t.com", SiteID: "radio-t"}, res[1].ID) assert.Nil(t, err) assert.Equal(t, "some text2", comment.Text) - comment, err = b.GetByID(Locator{URL: "https://radio-t.com"}, "1234567") + comment, err = b.GetByID(Locator{URL: "https://radio-t.com", SiteID: "radio-t"}, "1234567") assert.NotNil(t, err) } @@ -65,12 +65,12 @@ func TestBoltDB_Last(t *testing.T) { defer os.Remove(testDb) b := prep(t) - res, err := b.Last(Locator{URL: "https://radio-t.com"}, 0) + res, err := b.Last(Locator{URL: "https://radio-t.com", SiteID: "radio-t"}, 0) assert.Nil(t, err) assert.Equal(t, 2, len(res)) assert.Equal(t, "some text2", res[0].Text) - res, err = b.Last(Locator{URL: "https://radio-t.com"}, 1) + res, err = b.Last(Locator{URL: "https://radio-t.com", SiteID: "radio-t"}, 1) assert.Nil(t, err) assert.Equal(t, 1, len(res)) assert.Equal(t, "some text2", res[0].Text) @@ -80,7 +80,7 @@ func TestBoltDB_Count(t *testing.T) { defer os.Remove(testDb) b := prep(t) - c, err := b.Count(Locator{URL: "https://radio-t.com"}) + c, err := b.Count(Locator{URL: "https://radio-t.com", SiteID: "radio-t"}) assert.Nil(t, err) assert.Equal(t, 2, c) } @@ -89,15 +89,15 @@ func TestBoltDB_BlockUser(t *testing.T) { defer os.Remove(testDb) b := prep(t) - assert.False(t, b.IsBlocked(Locator{SiteID: "site1"}, "user1"), "nothing blocked") + assert.False(t, b.IsBlocked(Locator{SiteID: "radio-t"}, "user1"), "nothing blocked") - assert.NoError(t, b.SetBlock(Locator{SiteID: "site1"}, "user1", true)) - assert.True(t, b.IsBlocked(Locator{SiteID: "site1"}, "user1"), "user1 blocked") + assert.NoError(t, b.SetBlock(Locator{SiteID: "radio-t"}, "user1", true)) + assert.True(t, b.IsBlocked(Locator{SiteID: "radio-t"}, "user1"), "user1 blocked") - assert.False(t, b.IsBlocked(Locator{SiteID: "site1"}, "user2"), "user2 still unblocked") + assert.False(t, b.IsBlocked(Locator{SiteID: "radio-t"}, "user2"), "user2 still unblocked") - assert.NoError(t, b.SetBlock(Locator{SiteID: "site1"}, "user1", false)) - assert.False(t, b.IsBlocked(Locator{SiteID: "site1"}, "user1"), "user1 unblocked") + assert.NoError(t, b.SetBlock(Locator{SiteID: "radio-t"}, "user1", false)) + assert.False(t, b.IsBlocked(Locator{SiteID: "radio-t"}, "user1"), "user1 unblocked") } @@ -106,12 +106,16 @@ func TestBoltDB_List(t *testing.T) { b := prep(t) // two comments for https://radio-t.com // add one more for https://radio-t.com/2 - comment := Comment{Text: `some text, link`, Timestamp: time.Date(2017, 12, 20, 15, 18, 22, 0, time.Local), - Locator: Locator{URL: "https://radio-t.com/2", SiteID: "radio-t"}, User: User{ID: "user1", Name: "user name"}} + comment := Comment{ + Text: `some text, link`, + Timestamp: time.Date(2017, 12, 20, 15, 18, 22, 0, time.Local), + Locator: Locator{URL: "https://radio-t.com/2", SiteID: "radio-t"}, + User: User{ID: "user1", Name: "user name"}, + } _, err := b.Create(comment) assert.Nil(t, err) - res, err := b.List(Locator{SiteID: "site1"}) + res, err := b.List(Locator{SiteID: "radio-t"}) assert.Nil(t, err) assert.Equal(t, []string{"https://radio-t.com", "https://radio-t.com/2"}, res) } @@ -130,7 +134,7 @@ func TestBoltDB_GetForUser(t *testing.T) { func prep(t *testing.T) *BoltDB { os.Remove(testDb) - b, err := NewBoltDB(testDb) + b, err := NewBoltDB(BoltSite{FileName: "/tmp/test-remark.db", SiteID: "radio-t"}) assert.Nil(t, err) comment := Comment{ diff --git a/app/store/service_test.go b/app/store/service_test.go index 8f89093b..288dcbd3 100644 --- a/app/store/service_test.go +++ b/app/store/service_test.go @@ -11,22 +11,22 @@ func TestService_Vote(t *testing.T) { defer os.Remove(testDb) b := Service{Interface: prep(t)} - res, err := b.Last(Locator{URL: "https://radio-t.com"}, 0) + res, err := b.Last(Locator{URL: "https://radio-t.com", SiteID: "radio-t"}, 0) t.Logf("%+v", res[0]) assert.Nil(t, err) assert.Equal(t, 2, len(res)) assert.Equal(t, 0, res[0].Score) assert.Equal(t, map[string]bool{}, res[0].Votes) - c, err := b.Vote(Locator{URL: "https://radio-t.com"}, res[0].ID, "user1", true) + c, err := b.Vote(Locator{URL: "https://radio-t.com", SiteID: "radio-t"}, res[0].ID, "user1", true) assert.Nil(t, err) assert.Equal(t, 1, c.Score) assert.Equal(t, map[string]bool{"user1": true}, c.Votes) - _, err = b.Vote(Locator{URL: "https://radio-t.com"}, res[0].ID, "user1", true) + _, err = b.Vote(Locator{URL: "https://radio-t.com", SiteID: "radio-t"}, res[0].ID, "user1", true) assert.NotNil(t, err, "double-voting rejected") - res, err = b.Last(Locator{URL: "https://radio-t.com"}, 0) + res, err = b.Last(Locator{URL: "https://radio-t.com", SiteID: "radio-t"}, 0) assert.Nil(t, err) assert.Equal(t, 2, len(res)) assert.Equal(t, 1, res[0].Score) @@ -36,22 +36,22 @@ func TestBoltDB_Pin(t *testing.T) { defer os.Remove(testDb) b := Service{Interface: prep(t)} - res, err := b.Last(Locator{URL: "https://radio-t.com"}, 0) + res, err := b.Last(Locator{URL: "https://radio-t.com", SiteID: "radio-t"}, 0) t.Logf("%+v", res[0]) assert.Nil(t, err) assert.Equal(t, 2, len(res)) assert.Equal(t, false, res[0].Pin) - err = b.SetPin(Locator{URL: "https://radio-t.com"}, res[0].ID, true) + err = b.SetPin(Locator{URL: "https://radio-t.com", SiteID: "radio-t"}, res[0].ID, true) assert.Nil(t, err) - c, err := b.GetByID(Locator{URL: "https://radio-t.com"}, res[0].ID) + c, err := b.GetByID(Locator{URL: "https://radio-t.com", SiteID: "radio-t"}, res[0].ID) assert.Nil(t, err) assert.Equal(t, true, c.Pin) - err = b.SetPin(Locator{URL: "https://radio-t.com"}, res[0].ID, false) + err = b.SetPin(Locator{URL: "https://radio-t.com", SiteID: "radio-t"}, res[0].ID, false) assert.Nil(t, err) - c, err = b.GetByID(Locator{URL: "https://radio-t.com"}, res[0].ID) + c, err = b.GetByID(Locator{URL: "https://radio-t.com", SiteID: "radio-t"}, res[0].ID) assert.Nil(t, err) assert.Equal(t, false, c.Pin) } diff --git a/remark.rest b/remark.rest index 0dc07699..ec267646 100644 --- a/remark.rest +++ b/remark.rest @@ -1,6 +1,6 @@ ### find request with tree -GET https://demo.remark42.com/api/v1/find?url=https://radio-t.com/p/2017/12/16/podcast-576/&sort=time&format=tree" +GET https://demo.remark42.com/api/v1/find?site=demo&url=https://radio-t.com/p/2017/12/16/podcast-576/&sort=time&format=tree" ### find request with plain GET https://demo.remark42.com/api/v1/find?url=https://radio-t.com/p/2017/12/16/podcast-576/&sort=time&format=plain"