bunch of comments

This commit is contained in:
Umputun
2017-12-31 18:29:09 -06:00
parent 47953a39d2
commit 0d8a758588
6 changed files with 31 additions and 22 deletions
+2
View File
@@ -66,6 +66,7 @@ func main() {
dataStore := makeBoltStore()
if p.Active != nil && p.Command.Find("import") == p.Active {
// import mode
params := migrator.ImportParams{
DataStore: dataStore,
InputFile: opts.ImportCommand.InputFile,
@@ -138,6 +139,7 @@ func makeBoltStore() store.Interface {
return result
}
// mkdir -p for all dirs
func makeDirs(dirs ...string) error {
// exists returns whether the given file or directory exists or not
+8 -3
View File
@@ -17,7 +17,7 @@ import (
"github.com/umputun/remark/app/store"
)
// admin provides router for all requests available for admin only
// admin provides router for all requests available for admin users only
type admin struct {
dataService store.Service
exporter migrator.Exporter
@@ -68,7 +68,8 @@ 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}?site=siteID&url=post-url&pin=1 - mark/unmark comment as a special
// 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) {
commentID := chi.URLParam(r, "id")
locator := store.Locator{SiteID: r.URL.Query().Get("site"), URL: r.URL.Query().Get("url")}
@@ -82,7 +83,8 @@ func (a *admin) setPinCtrl(w http.ResponseWriter, r *http.Request) {
render.JSON(w, r, JSON{"id": commentID, "loc": locator, "pin": pinStatus})
}
// GET /export?site=site-id?mode=file|stream - exports all comments for siteID as json stream or file
// GET /export?site=site-id?mode=file|stream
// exports all comments for siteID as json stream or gz file
func (a *admin) exportCtrl(w http.ResponseWriter, r *http.Request) {
siteID := r.URL.Query().Get("site")
var writer io.Writer = w
@@ -100,6 +102,7 @@ func (a *admin) exportCtrl(w http.ResponseWriter, r *http.Request) {
}
// POST /import?site=site-id
// imports comments from post body.
func (a *admin) importCtrl(w http.ResponseWriter, r *http.Request) {
siteID := r.URL.Query().Get("site")
if err := a.importer.Import(r.Body, siteID); err != nil {
@@ -112,6 +115,8 @@ func (a *admin) checkBlocked(locator store.Locator, user store.User) bool {
return a.dataService.IsBlocked(locator, user.ID)
}
// processes comments and hides text of all comments for blocked users.
// resets score and votes too
func (a *admin) maskBlockedUsers(comments []store.Comment) (res []store.Comment) {
for _, c := range comments {
if a.dataService.IsBlocked(c.Locator, c.User.ID) {
+1
View File
@@ -57,6 +57,7 @@ func (t *Tree) filter(comments []store.Comment, parentID string) (f []store.Comm
return f
}
// sort list of nodes, i.e. top-level comments
func (t *Tree) sortNodes(sortType string) {
sort.Slice(t.Nodes, func(i, j int) bool {
+2 -4
View File
@@ -60,7 +60,7 @@ func Limiter(recSec int, excludeIps ...string) func(http.Handler) http.Handler {
}
}
// AppInfo adds custom app-info to header
// AppInfo adds custom app-info to the response header
func AppInfo(app string, version string) func(http.Handler) http.Handler {
f := func(h http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
@@ -77,7 +77,7 @@ func AppInfo(app string, version string) func(http.Handler) http.Handler {
return f
}
// Ping middleware response with pong. Stops chain if ping request detected
// Ping middleware response with pong to /ping. Stops chain if ping request detected
func Ping(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
@@ -104,10 +104,8 @@ func Recoverer(next http.Handler) http.Handler {
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
}()
next.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
+4 -3
View File
@@ -64,6 +64,7 @@ func (s *Server) Run() {
// If you aren't using gorilla/mux, you need to wrap your handlers with context.ClearHandler
router.Use(context.ClearHandler)
// auth routes for all providers
router.Route("/auth", func(r chi.Router) {
r.Mount("/google", s.AuthGoogle.Routes())
r.Mount("/github", s.AuthGithub.Routes())
@@ -71,6 +72,7 @@ func (s *Server) Run() {
r.Get("/logout", s.AuthGoogle.LogoutHandler) // shortcut, can be any of providers, does the same
})
// api routes
router.Route("/api/v1", func(rapi chi.Router) {
rapi.Get("/find", s.findCommentsCtrl)
rapi.Get("/id/{id}", s.commentByIDCtrl)
@@ -78,13 +80,13 @@ func (s *Server) Run() {
rapi.Get("/last/{max}", s.lastCommentsCtrl)
rapi.Get("/count", s.countCtrl)
// require auth
// protected routes, require auth
rapi.With(auth.Auth(s.SessionStore, s.Admins, maybeDevMode(auth.Full))).Group(func(rauth chi.Router) {
rauth.Post("/comment", s.createCommentCtrl)
rauth.Get("/user", s.userInfoCtrl)
rauth.Put("/vote/{id}", s.voteCtrl)
// require admin
// admin routes, admin users only
s.mod = admin{dataService: s.DataService, exporter: s.Exporter, respCache: s.respCache}
rauth.Mount("/admin", s.mod.routes())
})
@@ -93,7 +95,6 @@ func (s *Server) Run() {
router.Get("/robots.txt", func(w http.ResponseWriter, r *http.Request) {
render.PlainText(w, r, "User-agent: *\nDisallow: /auth/\nDisallow: /api/\n")
})
s.addFileServer(router, "/web", http.Dir(filepath.Join(".", "web")))
+14 -12
View File
@@ -60,24 +60,25 @@ type Interface interface {
// Accessor defines all usual access ops avail for regular user
type Accessor interface {
Create(comment Comment) (commentID string, err error)
Get(locator Locator, commentID string) (comment Comment, err error)
Put(locator Locator, comment Comment) error
Find(request Request) ([]Comment, error)
Last(locator Locator, max int) ([]Comment, error)
GetByID(locator Locator, commentID string) (Comment, error)
GetByUser(locator Locator, userID string) ([]Comment, error)
Count(locator Locator) (int, error)
List(locator Locator) ([]string, error)
Create(comment Comment) (commentID string, err error) // create new comment, avoid dups by ID
Get(locator Locator, commentID string) (comment Comment, err error) // get comment by ID
Put(locator Locator, comment Comment) error // update comment, mutable parts only
Find(request Request) ([]Comment, error) // find comments for request
Last(locator Locator, max int) ([]Comment, error) // last comments for given site
GetByID(locator Locator, commentID string) (Comment, error) // comment by id
GetByUser(locator Locator, userID string) ([]Comment, error) // comment by user
Count(locator Locator) (int, error) // number of comments for the post
List(locator Locator) ([]string, error) // list of commented posts
}
// Admin defines all store ops avail for admin only
type Admin interface {
Delete(locator Locator, commentID string) error
SetBlock(locator Locator, userID string, status bool) error
IsBlocked(locator Locator, userID string) bool
Delete(locator Locator, commentID string) error // delete comment by id
SetBlock(locator Locator, userID string, status bool) error // block or unblock user
IsBlocked(locator Locator, userID string) bool // check if user blocked
}
// makeCommentID generates sha1(random) string
func makeCommentID() string {
b := make([]byte, 64)
if _, err := rand.Read(b); err != nil {
@@ -90,6 +91,7 @@ func makeCommentID() string {
return fmt.Sprintf("%x", s.Sum(nil))
}
// clean dangerous html/js from the comment
func sanitizeComment(comment Comment) Comment {
p := bluemonday.UGCPolicy()
comment.Text = p.Sanitize(comment.Text)