aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--Makefile14
-rw-r--r--locale/locale.go4
-rw-r--r--locale/translations.go2
-rw-r--r--model/theme.go6
-rw-r--r--model/user.go12
-rw-r--r--reader/feed/handler.go2
-rw-r--r--reader/opml/handler.go6
-rw-r--r--reader/processor/processor.go1
-rw-r--r--reader/rewrite/rewriter.go1
-rw-r--r--server/api/controller/category.go3
-rw-r--r--server/api/controller/feed.go6
-rw-r--r--server/api/controller/user.go9
-rw-r--r--server/api/payload/payload.go7
-rw-r--r--server/core/context.go15
-rw-r--r--server/core/handler.go4
-rw-r--r--server/middleware/basic_auth.go16
-rw-r--r--server/middleware/context_keys.go26
-rw-r--r--server/middleware/csrf.go6
-rw-r--r--server/middleware/middleware.go15
-rw-r--r--server/middleware/session.go11
-rw-r--r--server/route/route.go3
-rw-r--r--server/routes.go4
-rw-r--r--server/static/bin.go2
-rw-r--r--server/static/css.go2
-rw-r--r--server/static/js.go2
-rw-r--r--server/template/common.go2
-rw-r--r--server/template/template.go2
-rw-r--r--server/template/views.go2
-rw-r--r--server/ui/controller/about.go1
-rw-r--r--server/ui/controller/category.go8
-rw-r--r--server/ui/controller/feed.go8
-rw-r--r--server/ui/controller/history.go2
-rw-r--r--server/ui/controller/icon.go6
-rw-r--r--server/ui/controller/oauth2.go2
-rw-r--r--server/ui/controller/opml.go3
-rw-r--r--server/ui/controller/pagination.go16
-rw-r--r--server/ui/controller/session.go7
-rw-r--r--server/ui/controller/settings.go11
-rw-r--r--server/ui/controller/static.go8
-rw-r--r--server/ui/controller/subscription.go2
-rw-r--r--server/ui/controller/unread.go2
-rw-r--r--server/ui/controller/user.go13
-rw-r--r--server/ui/filter/image_proxy_filter.go5
-rw-r--r--server/ui/form/auth.go8
-rw-r--r--server/ui/form/category.go10
-rw-r--r--server/ui/form/feed.go8
-rw-r--r--server/ui/form/settings.go15
-rw-r--r--server/ui/form/subscription.go8
-rw-r--r--server/ui/form/user.go23
-rw-r--r--server/ui/payload/payload.go4
-rw-r--r--sql/sql.go2
-rw-r--r--storage/category.go38
-rw-r--r--storage/feed.go15
-rw-r--r--storage/icon.go15
-rw-r--r--storage/session.go13
-rw-r--r--storage/storage.go8
-rw-r--r--storage/timezone.go8
-rw-r--r--storage/user.go37
59 files changed, 322 insertions, 171 deletions
diff --git a/.travis.yml b/.travis.yml
index 8a3c51f..c872700 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,7 +9,9 @@ go:
- 1.9
before_install:
- npm install -g jshint
+ - go get -u github.com/golang/lint/golint
script:
- jshint server/static/js/app.js
+ - make lint
- make test
- make integration-test
diff --git a/Makefile b/Makefile
index 61ec8c2..0b4be22 100644
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,10 @@
-APP = miniflux
-VERSION = $(shell git rev-parse --short HEAD)
-BUILD_DATE = `date +%FT%T%z`
-DB_URL = postgres://postgres:postgres@localhost/miniflux_test?sslmode=disable
+APP := miniflux
+VERSION := $(shell git rev-parse --short HEAD)
+BUILD_DATE := `date +%FT%T%z`
+PKG_LIST := $(shell go list ./... | grep -v /vendor/)
+DB_URL := postgres://postgres:postgres@localhost/miniflux_test?sslmode=disable
-.PHONY: build-linux build-darwin build run clean test integration-test clean-integration-test
+.PHONY: build-linux build-darwin build run clean test lint integration-test clean-integration-test
build-linux:
@ go generate
@@ -25,6 +26,9 @@ clean:
test:
go test -cover -race ./...
+lint:
+ @ golint -set_exit_status ${PKG_LIST}
+
integration-test:
psql -U postgres -c 'drop database if exists miniflux_test;'
psql -U postgres -c 'create database miniflux_test;'
diff --git a/locale/locale.go b/locale/locale.go
index 257ec2b..c62d6b6 100644
--- a/locale/locale.go
+++ b/locale/locale.go
@@ -24,8 +24,8 @@ func Load() *Translator {
return translator
}
-// GetAvailableLanguages returns the list of available languages.
-func GetAvailableLanguages() map[string]string {
+// AvailableLanguages returns the list of available languages.
+func AvailableLanguages() map[string]string {
return map[string]string{
"en_US": "English",
"fr_FR": "Français",
diff --git a/locale/translations.go b/locale/translations.go
index 766f8ad..b9164fa 100644
--- a/locale/translations.go
+++ b/locale/translations.go
@@ -1,5 +1,5 @@
// Code generated by go generate; DO NOT EDIT.
-// 2017-11-25 15:50:52.572283626 -0800 PST m=+0.030941705
+// 2017-11-27 21:07:53.23444885 -0800 PST m=+0.028635078
package locale
diff --git a/model/theme.go b/model/theme.go
index c9bbc05..85307ce 100644
--- a/model/theme.go
+++ b/model/theme.go
@@ -6,8 +6,8 @@ package model
import "github.com/miniflux/miniflux2/errors"
-// GetThemes returns the list of available themes.
-func GetThemes() map[string]string {
+// Themes returns the list of available themes.
+func Themes() map[string]string {
return map[string]string{
"default": "Default",
"black": "Black",
@@ -16,7 +16,7 @@ func GetThemes() map[string]string {
// ValidateTheme validates theme value.
func ValidateTheme(theme string) error {
- for key := range GetThemes() {
+ for key := range Themes() {
if key == theme {
return nil
}
diff --git a/model/user.go b/model/user.go
index b756f1b..c030d52 100644
--- a/model/user.go
+++ b/model/user.go
@@ -33,11 +33,7 @@ func (u User) ValidateUserCreation() error {
return err
}
- if err := u.ValidatePassword(); err != nil {
- return err
- }
-
- return nil
+ return u.ValidatePassword()
}
// ValidateUserModification validates user for modification.
@@ -54,11 +50,7 @@ func (u User) ValidateUserModification() error {
return err
}
- if err := ValidateTheme(u.Theme); err != nil {
- return err
- }
-
- return nil
+ return ValidateTheme(u.Theme)
}
// ValidateUserLogin validates user credential requirements.
diff --git a/reader/feed/handler.go b/reader/feed/handler.go
index c6dc448..f406c13 100644
--- a/reader/feed/handler.go
+++ b/reader/feed/handler.go
@@ -92,7 +92,7 @@ func (h *Handler) CreateFeed(userID, categoryID int64, url string) (*model.Feed,
func (h *Handler) RefreshFeed(userID, feedID int64) error {
defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Handler:RefreshFeed] feedID=%d", feedID))
- originalFeed, err := h.store.GetFeedById(userID, feedID)
+ originalFeed, err := h.store.FeedByID(userID, feedID)
if err != nil {
return err
}
diff --git a/reader/opml/handler.go b/reader/opml/handler.go
index 8ba2736..9d5fb0f 100644
--- a/reader/opml/handler.go
+++ b/reader/opml/handler.go
@@ -21,7 +21,7 @@ type Handler struct {
// Export exports user feeds to OPML.
func (h *Handler) Export(userID int64) (string, error) {
- feeds, err := h.store.GetFeeds(userID)
+ feeds, err := h.store.Feeds(userID)
if err != nil {
log.Println(err)
return "", errors.New("unable to fetch feeds")
@@ -52,13 +52,13 @@ func (h *Handler) Import(userID int64, data io.Reader) (err error) {
var category *model.Category
if subscription.CategoryName == "" {
- category, err = h.store.GetFirstCategory(userID)
+ category, err = h.store.FirstCategory(userID)
if err != nil {
log.Println(err)
return errors.New("unable to find first category")
}
} else {
- category, err = h.store.GetCategoryByTitle(userID, subscription.CategoryName)
+ category, err = h.store.CategoryByTitle(userID, subscription.CategoryName)
if err != nil {
log.Println(err)
return errors.New("unable to search category by title")
diff --git a/reader/processor/processor.go b/reader/processor/processor.go
index a4f4de1..ef93b9a 100644
--- a/reader/processor/processor.go
+++ b/reader/processor/processor.go
@@ -9,6 +9,7 @@ import (
"github.com/miniflux/miniflux2/reader/sanitizer"
)
+// ItemContentProcessor executes a set of functions to sanitize and alter item contents.
func ItemContentProcessor(url, content string) string {
content = sanitizer.Sanitize(url, content)
return rewrite.Rewriter(url, content)
diff --git a/reader/rewrite/rewriter.go b/reader/rewrite/rewriter.go
index f23c0af..d76feee 100644
--- a/reader/rewrite/rewriter.go
+++ b/reader/rewrite/rewriter.go
@@ -38,6 +38,7 @@ var rewriteRules = []func(string, string) string{
},
}
+// Rewriter modify item contents with a set of rewriting rules.
func Rewriter(url, content string) string {
for _, rewriteRule := range rewriteRules {
content = rewriteRule(url, content)
diff --git a/server/api/controller/category.go b/server/api/controller/category.go
index bf89411..5cf88bd 100644
--- a/server/api/controller/category.go
+++ b/server/api/controller/category.go
@@ -6,6 +6,7 @@ package api
import (
"errors"
+
"github.com/miniflux/miniflux2/server/api/payload"
"github.com/miniflux/miniflux2/server/core"
)
@@ -65,7 +66,7 @@ func (c *Controller) UpdateCategory(ctx *core.Context, request *core.Request, re
// GetCategories is the API handler to get a list of categories for a given user.
func (c *Controller) GetCategories(ctx *core.Context, request *core.Request, response *core.Response) {
- categories, err := c.store.GetCategories(ctx.UserID())
+ categories, err := c.store.Categories(ctx.UserID())
if err != nil {
response.JSON().ServerError(errors.New("Unable to fetch categories"))
return
diff --git a/server/api/controller/feed.go b/server/api/controller/feed.go
index 282e81c..73bf241 100644
--- a/server/api/controller/feed.go
+++ b/server/api/controller/feed.go
@@ -66,7 +66,7 @@ func (c *Controller) UpdateFeed(ctx *core.Context, request *core.Request, respon
return
}
- originalFeed, err := c.store.GetFeedById(userID, feedID)
+ originalFeed, err := c.store.FeedByID(userID, feedID)
if err != nil {
response.JSON().NotFound(errors.New("Unable to find this feed"))
return
@@ -88,7 +88,7 @@ func (c *Controller) UpdateFeed(ctx *core.Context, request *core.Request, respon
// GetFeeds is the API handler that get all feeds that belongs to the given user.
func (c *Controller) GetFeeds(ctx *core.Context, request *core.Request, response *core.Response) {
- feeds, err := c.store.GetFeeds(ctx.UserID())
+ feeds, err := c.store.Feeds(ctx.UserID())
if err != nil {
response.JSON().ServerError(errors.New("Unable to fetch feeds from the database"))
return
@@ -106,7 +106,7 @@ func (c *Controller) GetFeed(ctx *core.Context, request *core.Request, response
return
}
- feed, err := c.store.GetFeedById(userID, feedID)
+ feed, err := c.store.FeedByID(userID, feedID)
if err != nil {
response.JSON().ServerError(errors.New("Unable to fetch this feed"))
return
diff --git a/server/api/controller/user.go b/server/api/controller/user.go
index 3ea6650..fcf24b6 100644
--- a/server/api/controller/user.go
+++ b/server/api/controller/user.go
@@ -6,6 +6,7 @@ package api
import (
"errors"
+
"github.com/miniflux/miniflux2/server/api/payload"
"github.com/miniflux/miniflux2/server/core"
)
@@ -67,7 +68,7 @@ func (c *Controller) UpdateUser(ctx *core.Context, request *core.Request, respon
return
}
- originalUser, err := c.store.GetUserById(userID)
+ originalUser, err := c.store.UserByID(userID)
if err != nil {
response.JSON().BadRequest(errors.New("Unable to fetch this user from the database"))
return
@@ -94,7 +95,7 @@ func (c *Controller) GetUsers(ctx *core.Context, request *core.Request, response
return
}
- users, err := c.store.GetUsers()
+ users, err := c.store.Users()
if err != nil {
response.JSON().ServerError(errors.New("Unable to fetch the list of users"))
return
@@ -116,7 +117,7 @@ func (c *Controller) GetUser(ctx *core.Context, request *core.Request, response
return
}
- user, err := c.store.GetUserById(userID)
+ user, err := c.store.UserByID(userID)
if err != nil {
response.JSON().BadRequest(errors.New("Unable to fetch this user from the database"))
return
@@ -143,7 +144,7 @@ func (c *Controller) RemoveUser(ctx *core.Context, request *core.Request, respon
return
}
- user, err := c.store.GetUserById(userID)
+ user, err := c.store.UserByID(userID)
if err != nil {
response.JSON().ServerError(errors.New("Unable to fetch this user from the database"))
return
diff --git a/server/api/payload/payload.go b/server/api/payload/payload.go
index 4fbc16e..310ba05 100644
--- a/server/api/payload/payload.go
+++ b/server/api/payload/payload.go
@@ -12,11 +12,13 @@ import (
"github.com/miniflux/miniflux2/model"
)
+// EntriesResponse represents the response sent when fetching entries.
type EntriesResponse struct {
Total int `json:"total"`
Entries model.Entries `json:"entries"`
}
+// DecodeUserPayload unserialize JSON user object.
func DecodeUserPayload(data io.Reader) (*model.User, error) {
var user model.User
@@ -28,6 +30,7 @@ func DecodeUserPayload(data io.Reader) (*model.User, error) {
return &user, nil
}
+// DecodeURLPayload unserialize JSON subscription object.
func DecodeURLPayload(data io.Reader) (string, error) {
type payload struct {
URL string `json:"url"`
@@ -42,6 +45,7 @@ func DecodeURLPayload(data io.Reader) (string, error) {
return p.URL, nil
}
+// DecodeEntryStatusPayload unserialize JSON entry statuses object.
func DecodeEntryStatusPayload(data io.Reader) ([]int64, string, error) {
type payload struct {
EntryIDs []int64 `json:"entry_ids"`
@@ -57,6 +61,7 @@ func DecodeEntryStatusPayload(data io.Reader) ([]int64, string, error) {
return p.EntryIDs, p.Status, nil
}
+// DecodeFeedCreationPayload unserialize JSON feed creation object.
func DecodeFeedCreationPayload(data io.Reader) (string, int64, error) {
type payload struct {
FeedURL string `json:"feed_url"`
@@ -72,6 +77,7 @@ func DecodeFeedCreationPayload(data io.Reader) (string, int64, error) {
return p.FeedURL, p.CategoryID, nil
}
+// DecodeFeedModificationPayload unserialize JSON feed object.
func DecodeFeedModificationPayload(data io.Reader) (*model.Feed, error) {
var feed model.Feed
@@ -83,6 +89,7 @@ func DecodeFeedModificationPayload(data io.Reader) (*model.Feed, error) {
return &feed, nil
}
+// DecodeCategoryPayload unserialize JSON category object.
func DecodeCategoryPayload(data io.Reader) (*model.Category, error) {
var category model.Category
diff --git a/server/core/context.go b/server/core/context.go
index 90c4659..217e4d4 100644
--- a/server/core/context.go
+++ b/server/core/context.go
@@ -9,6 +9,7 @@ import (
"net/http"
"github.com/miniflux/miniflux2/model"
+ "github.com/miniflux/miniflux2/server/middleware"
"github.com/miniflux/miniflux2/server/route"
"github.com/miniflux/miniflux2/storage"
@@ -26,7 +27,7 @@ type Context struct {
// IsAdminUser checks if the logged user is administrator.
func (c *Context) IsAdminUser() bool {
- if v := c.request.Context().Value("IsAdminUser"); v != nil {
+ if v := c.request.Context().Value(middleware.IsAdminUserContextKey); v != nil {
return v.(bool)
}
return false
@@ -34,7 +35,7 @@ func (c *Context) IsAdminUser() bool {
// UserTimezone returns the timezone used by the logged user.
func (c *Context) UserTimezone() string {
- if v := c.request.Context().Value("UserTimezone"); v != nil {
+ if v := c.request.Context().Value(middleware.UserTimezoneContextKey); v != nil {
return v.(string)
}
return "UTC"
@@ -42,7 +43,7 @@ func (c *Context) UserTimezone() string {
// IsAuthenticated returns a boolean if the user is authenticated.
func (c *Context) IsAuthenticated() bool {
- if v := c.request.Context().Value("IsAuthenticated"); v != nil {
+ if v := c.request.Context().Value(middleware.IsAuthenticatedContextKey); v != nil {
return v.(bool)
}
return false
@@ -50,7 +51,7 @@ func (c *Context) IsAuthenticated() bool {
// UserID returns the UserID of the logged user.
func (c *Context) UserID() int64 {
- if v := c.request.Context().Value("UserId"); v != nil {
+ if v := c.request.Context().Value(middleware.UserIDContextKey); v != nil {
return v.(int64)
}
return 0
@@ -60,7 +61,7 @@ func (c *Context) UserID() int64 {
func (c *Context) LoggedUser() *model.User {
if c.user == nil {
var err error
- c.user, err = c.store.GetUserById(c.UserID())
+ c.user, err = c.store.UserByID(c.UserID())
if err != nil {
log.Fatalln(err)
}
@@ -81,7 +82,7 @@ func (c *Context) UserLanguage() string {
// CsrfToken returns the current CSRF token.
func (c *Context) CsrfToken() string {
- if v := c.request.Context().Value("CsrfToken"); v != nil {
+ if v := c.request.Context().Value(middleware.CsrfContextKey); v != nil {
return v.(string)
}
@@ -91,7 +92,7 @@ func (c *Context) CsrfToken() string {
// Route returns the path for the given arguments.
func (c *Context) Route(name string, args ...interface{}) string {
- return route.GetRoute(c.router, name, args...)
+ return route.Path(c.router, name, args...)
}
// NewContext creates a new Context.
diff --git a/server/core/handler.go b/server/core/handler.go
index df7e0be..db6204a 100644
--- a/server/core/handler.go
+++ b/server/core/handler.go
@@ -27,7 +27,7 @@ type Handler struct {
translator *locale.Translator
template *template.Engine
router *mux.Router
- middleware *middleware.MiddlewareChain
+ middleware *middleware.Chain
}
// Use is a wrapper around an HTTP handler.
@@ -51,7 +51,7 @@ func (h *Handler) Use(f HandlerFunc) http.Handler {
}
// NewHandler returns a new Handler.
-func NewHandler(store *storage.Storage, router *mux.Router, template *template.Engine, translator *locale.Translator, middleware *middleware.MiddlewareChain) *Handler {
+func NewHandler(store *storage.Storage, router *mux.Router, template *template.Engine, translator *locale.Translator, middleware *middleware.Chain) *Handler {
return &Handler{
store: store,
translator: translator,
diff --git a/server/middleware/basic_auth.go b/server/middleware/basic_auth.go
index 73dfb98..3ad5318 100644
--- a/server/middleware/basic_auth.go
+++ b/server/middleware/basic_auth.go
@@ -6,15 +6,18 @@ package middleware
import (
"context"
- "github.com/miniflux/miniflux2/storage"
"log"
"net/http"
+
+ "github.com/miniflux/miniflux2/storage"
)
+// BasicAuthMiddleware is the middleware for HTTP Basic authentication.
type BasicAuthMiddleware struct {
store *storage.Storage
}
+// Handler executes the middleware.
func (b *BasicAuthMiddleware) Handler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
@@ -35,7 +38,7 @@ func (b *BasicAuthMiddleware) Handler(next http.Handler) http.Handler {
return
}
- user, err := b.store.GetUserByUsername(username)
+ user, err := b.store.UserByUsername(username)
if err != nil || user == nil {
log.Println("[Middleware:BasicAuth] User not found:", username)
w.WriteHeader(http.StatusUnauthorized)
@@ -47,15 +50,16 @@ func (b *BasicAuthMiddleware) Handler(next http.Handler) http.Handler {
b.store.SetLastLogin(user.ID)
ctx := r.Context()
- ctx = context.WithValue(ctx, "UserId", user.ID)
- ctx = context.WithValue(ctx, "UserTimezone", user.Timezone)
- ctx = context.WithValue(ctx, "IsAdminUser", user.IsAdmin)
- ctx = context.WithValue(ctx, "IsAuthenticated", true)
+ ctx = context.WithValue(ctx, UserIDContextKey, user.ID)
+ ctx = context.WithValue(ctx, UserTimezoneContextKey, user.Timezone)
+ ctx = context.WithValue(ctx, IsAdminUserContextKey, user.IsAdmin)
+ ctx = context.WithValue(ctx, IsAuthenticatedContextKey, true)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
+// NewBasicAuthMiddleware returns a new BasicAuthMiddleware.
func NewBasicAuthMiddleware(s *storage.Storage) *BasicAuthMiddleware {
return &BasicAuthMiddleware{store: s}
}
diff --git a/server/middleware/context_keys.go b/server/middleware/context_keys.go
new file mode 100644
index 0000000..c011fbb
--- /dev/null
+++ b/server/middleware/context_keys.go
@@ -0,0 +1,26 @@
+// Copyright 2017 Frédéric Guillot. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+package middleware
+
+type contextKey struct {
+ name string
+}
+
+var (
+ // UserIDContextKey is the context key used to store the user ID.
+ UserIDContextKey = &contextKey{"UserID"}
+
+ // UserTimezoneContextKey is the context key used to store the user timezone.
+ UserTimezoneContextKey = &contextKey{"UserTimezone"}
+
+ // IsAdminUserContextKey is the context key used to store the user role.
+ IsAdminUserContextKey = &contextKey{"IsAdminUser"}
+
+ // IsAuthenticatedContextKey is the context key used to store the authentication flag.
+ IsAuthenticatedContextKey = &contextKey{"IsAuthenticated"}
+
+ // CsrfContextKey is the context key used to store CSRF token.
+ CsrfContextKey = &contextKey{"CSRF"}
+)
diff --git a/server/middleware/csrf.go b/server/middleware/csrf.go
index 74736b5..0c07e42 100644
--- a/server/middleware/csrf.go
+++ b/server/middleware/csrf.go
@@ -6,11 +6,13 @@ package middleware
import (
"context"
- "github.com/miniflux/miniflux2/helper"
"log"
"net/http"
+
+ "github.com/miniflux/miniflux2/helper"
)
+// Csrf is a middleware that handle CSRF tokens.
func Csrf(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var csrfToken string
@@ -32,7 +34,7 @@ func Csrf(next http.Handler) http.Handler {
}
ctx := r.Context()
- ctx = context.WithValue(ctx, "CsrfToken", csrfToken)
+ ctx = context.WithValue(ctx, CsrfContextKey, csrfToken)
w.Header().Add("Vary", "Cookie")
isTokenValid := csrfToken == r.FormValue("csrf") || csrfToken == r.Header.Get("X-Csrf-Token")
diff --git a/server/middleware/middleware.go b/server/middleware/middleware.go
index cab01c8..9853bc3 100644
--- a/server/middleware/middleware.go
+++ b/server/middleware/middleware.go
@@ -8,13 +8,16 @@ import (
"net/http"
)
+// Middleware represents a HTTP middleware.
type Middleware func(http.Handler) http.Handler
-type MiddlewareChain struct {
+// Chain handles a list of middlewares.
+type Chain struct {
middlewares []Middleware
}
-func (m *MiddlewareChain) Wrap(h http.Handler) http.Handler {
+// Wrap adds a HTTP handler into the chain.
+func (m *Chain) Wrap(h http.Handler) http.Handler {
for i := range m.middlewares {
h = m.middlewares[len(m.middlewares)-1-i](h)
}
@@ -22,10 +25,12 @@ func (m *MiddlewareChain) Wrap(h http.Handler) http.Handler {
return h
}
-func (m *MiddlewareChain) WrapFunc(fn http.HandlerFunc) http.Handler {
+// WrapFunc adds a HTTP handler function into the chain.
+func (m *Chain) WrapFunc(fn http.HandlerFunc) http.Handler {
return m.Wrap(fn)
}
-func NewMiddlewareChain(middlewares ...Middleware) *MiddlewareChain {
- return &MiddlewareChain{append(([]Middleware)(nil), middlewares...)}
+// NewChain returns a new Chain.
+func NewChain(middlewares ...Middleware) *Chain {
+ return &Chain{append(([]Middleware)(nil), middlewares...)}
}
diff --git a/server/middleware/session.go b/server/middleware/session.go
index 1ab0d0a..e857c1f 100644
--- a/server/middleware/session.go
+++ b/server/middleware/session.go
@@ -16,11 +16,13 @@ import (
"github.com/gorilla/mux"
)
+// SessionMiddleware represents a session middleware.
type SessionMiddleware struct {
store *storage.Storage
router *mux.Router
}
+// Handler execute the middleware.
func (s *SessionMiddleware) Handler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
session := s.getSessionFromCookie(r)
@@ -30,13 +32,13 @@ func (s *SessionMiddleware) Handler(next http.Handler) http.Handler {
if s.isPublicRoute(r) {
next.ServeHTTP(w, r)
} else {
- http.Redirect(w, r, route.GetRoute(s.router, "login"), http.StatusFound)
+ http.Redirect(w, r, route.Path(s.router, "login"), http.StatusFound)
}
} else {
log.Println("[Middleware:Session]", session)
ctx := r.Context()
- ctx = context.WithValue(ctx, "UserId", session.UserID)
- ctx = context.WithValue(ctx, "IsAuthenticated", true)
+ ctx = context.WithValue(ctx, UserIDContextKey, session.UserID)
+ ctx = context.WithValue(ctx, IsAuthenticatedContextKey, true)
next.ServeHTTP(w, r.WithContext(ctx))
}
@@ -59,7 +61,7 @@ func (s *SessionMiddleware) getSessionFromCookie(r *http.Request) *model.Session
return nil
}
- session, err := s.store.GetSessionByToken(sessionCookie.Value)
+ session, err := s.store.SessionByToken(sessionCookie.Value)
if err != nil {
log.Println(err)
return nil
@@ -68,6 +70,7 @@ func (s *SessionMiddleware) getSessionFromCookie(r *http.Request) *model.Session
return session
}
+// NewSessionMiddleware returns a new SessionMiddleware.
func NewSessionMiddleware(s *storage.Storage, r *mux.Router) *SessionMiddleware {
return &SessionMiddleware{store: s, router: r}
}
diff --git a/server/route/route.go b/server/route/route.go
index 885f0bc..06d095a 100644
--- a/server/route/route.go
+++ b/server/route/route.go
@@ -11,7 +11,8 @@ import (
"github.com/gorilla/mux"
)
-func GetRoute(router *mux.Router, name string, args ...interface{}) string {
+// Path returns the defined route based on given arguments.
+func Path(router *mux.Router, name string, args ...interface{}) string {
route := router.Get(name)
if route == nil {
log.Fatalln("Route not found:", name)
diff --git a/server/routes.go b/server/routes.go
index 8d5a5c5..8c584fa 100644
--- a/server/routes.go
+++ b/server/routes.go
@@ -31,11 +31,11 @@ func getRoutes(cfg *config.Config, store *storage.Storage, feedHandler *feed.Han
apiController := api_controller.NewController(store, feedHandler)
uiController := ui_controller.NewController(cfg, store, pool, feedHandler, opml.NewHandler(store))
- apiHandler := core.NewHandler(store, router, templateEngine, translator, middleware.NewMiddlewareChain(
+ apiHandler := core.NewHandler(store, router, templateEngine, translator, middleware.NewChain(
middleware.NewBasicAuthMiddleware(store).Handler,
))
- uiHandler := core.NewHandler(store, router, templateEngine, translator, middleware.NewMiddlewareChain(
+ uiHandler := core.NewHandler(store, router, templateEngine, translator, middleware.NewChain(
middleware.NewSessionMiddleware(store, router).Handler,
middleware.Csrf,
))
diff --git a/server/static/bin.go b/server/static/bin.go
index 3a5ca06..9987f8a 100644
--- a/server/static/bin.go
+++ b/server/static/bin.go
@@ -1,5 +1,5 @@
// Code generated by go generate; DO NOT EDIT.
-// 2017-11-25 10:47:30.351686806 -0800 PST m=+0.007814912
+// 2017-11-27 21:07:53.21170439 -0800 PST m=+0.005890618
package static
diff --git a/server/static/css.go b/server/static/css.go
index 39da75c..2bb2f39 100644
--- a/server/static/css.go
+++ b/server/static/css.go
@@ -1,5 +1,5 @@
// Code generated by go generate; DO NOT EDIT.
-// 2017-11-25 10:47:30.352812144 -0800 PST m=+0.008940250
+// 2017-11-27 21:07:53.213299146 -0800 PST m=+0.007485374
package static
diff --git a/server/static/js.go b/server/static/js.go
index 5076159..9f7c717 100644
--- a/server/static/js.go
+++ b/server/static/js.go
@@ -1,5 +1,5 @@
// Code generated by go generate; DO NOT EDIT.
-// 2017-11-25 10:47:30.357950671 -0800 PST m=+0.014078777
+// 2017-11-27 21:07:53.215205872 -0800 PST m=+0.009392100
package static
diff --git a/server/template/common.go b/server/template/common.go
index 21f91aa..0a803b2 100644
--- a/server/template/common.go
+++ b/server/template/common.go
@@ -1,5 +1,5 @@
// Code generated by go generate; DO NOT EDIT.
-// 2017-11-25 10:47:30.370347794 -0800 PST m=+0.026475900
+// 2017-11-27 21:07:53.233262137 -0800 PST m=+0.027448365
package template
diff --git a/server/template/template.go b/server/template/template.go
index cf778b3..63a1df8 100644
--- a/server/template/template.go
+++ b/server/template/template.go
@@ -49,7 +49,7 @@ func (e *Engine) parseAll() {
return false
},
"route": func(name string, args ...interface{}) string {
- return route.GetRoute(e.router, name, args...)
+ return route.Path(e.router, name, args...)
},
"noescape": func(str string) template.HTML {
return template.HTML(str)
diff --git a/server/template/views.go b/server/template/views.go
index 9a429a9..8254f8c 100644
--- a/server/template/views.go
+++ b/server/template/views.go
@@ -1,5 +1,5 @@
// Code generated by go generate; DO NOT EDIT.
-// 2017-11-25 17:05:58.40092186 -0800 PST m=+0.019242510
+// 2017-11-27 21:07:53.218349526 -0800 PST m=+0.012535754
package template
diff --git a/server/ui/controller/about.go b/server/ui/controller/about.go
index 5d9a242..0b1e4e4 100644
--- a/server/ui/controller/about.go
+++ b/server/ui/controller/about.go
@@ -9,6 +9,7 @@ import (
"github.com/miniflux/miniflux2/version"
)
+// AboutPage shows the about page.
func (c *Controller) AboutPage(ctx *core.Context, request *core.Request, response *core.Response) {
args, err := c.getCommonTemplateArgs(ctx)
if err != nil {
diff --git a/server/ui/controller/category.go b/server/ui/controller/category.go
index e8ebb03..b718d0d 100644
--- a/server/ui/controller/category.go
+++ b/server/ui/controller/category.go
@@ -22,7 +22,7 @@ func (c *Controller) ShowCategories(ctx *core.Context, request *core.Request, re
}
user := ctx.LoggedUser()
- categories, err := c.store.GetCategoriesWithFeedCount(user.ID)
+ categories, err := c.store.CategoriesWithFeedCount(user.ID)
if err != nil {
response.HTML().ServerError(err)
return
@@ -57,7 +57,7 @@ func (c *Controller) ShowCategoryEntries(ctx *core.Context, request *core.Reques
builder.WithDirection(model.DefaultSortingDirection)
builder.WithoutStatus(model.EntryStatusRemoved)
builder.WithOffset(offset)
- builder.WithLimit(NbItemsPerPage)
+ builder.WithLimit(nbItemsPerPage)
entries, err := builder.GetEntries()
if err != nil {
@@ -110,7 +110,7 @@ func (c *Controller) SaveCategory(ctx *core.Context, request *core.Request, resp
return
}
- duplicateCategory, err := c.store.GetCategoryByTitle(user.ID, categoryForm.Title)
+ duplicateCategory, err := c.store.CategoryByTitle(user.ID, categoryForm.Title)
if err != nil {
response.HTML().ServerError(err)
return
@@ -223,7 +223,7 @@ func (c *Controller) getCategoryFromURL(ctx *core.Context, request *core.Request
}
user := ctx.LoggedUser()
- category, err := c.store.GetCategory(user.ID, categoryID)
+ category, err := c.store.Category(user.ID, categoryID)
if err != nil {
response.HTML().ServerError(err)
return nil, err
diff --git a/server/ui/controller/feed.go b/server/ui/controller/feed.go
index 7ed903e..85a94cf 100644
--- a/server/ui/controller/feed.go
+++ b/server/ui/controller/feed.go
@@ -39,7 +39,7 @@ func (c *Controller) ShowFeedsPage(ctx *core.Context, request *core.Request, res
return
}
- feeds, err := c.store.GetFeeds(user.ID)
+ feeds, err := c.store.Feeds(user.ID)
if err != nil {
response.HTML().ServerError(err)
return
@@ -74,7 +74,7 @@ func (c *Controller) ShowFeedEntries(ctx *core.Context, request *core.Request, r
builder.WithOrder(model.DefaultSortingOrder)
builder.WithDirection(model.DefaultSortingDirection)
builder.WithOffset(offset)
- builder.WithLimit(NbItemsPerPage)
+ builder.WithLimit(nbItemsPerPage)
entries, err := builder.GetEntries()
if err != nil {
@@ -190,7 +190,7 @@ func (c *Controller) getFeedFromURL(request *core.Request, response *core.Respon
return nil, err
}
- feed, err := c.store.GetFeedById(user.ID, feedID)
+ feed, err := c.store.FeedByID(user.ID, feedID)
if err != nil {
response.HTML().ServerError(err)
return nil, err
@@ -210,7 +210,7 @@ func (c *Controller) getFeedFormTemplateArgs(ctx *core.Context, user *model.User
return nil, err
}
- categories, err := c.store.GetCategories(user.ID)
+ categories, err := c.store.Categories(user.ID)
if err != nil {
return nil, err
}
diff --git a/server/ui/controller/history.go b/server/ui/controller/history.go
index 100b12f..9b4e316 100644
--- a/server/ui/controller/history.go
+++ b/server/ui/controller/history.go
@@ -25,7 +25,7 @@ func (c *Controller) ShowHistoryPage(ctx *core.Context, request *core.Request, r
builder.WithOrder(model.DefaultSortingOrder)
builder.WithDirection(model.DefaultSortingDirection)
builder.WithOffset(offset)
- builder.WithLimit(NbItemsPerPage)
+ builder.WithLimit(nbItemsPerPage)
entries, err := builder.GetEntries()
if err != nil {
diff --git a/server/ui/controller/icon.go b/server/ui/controller/icon.go
index 0fd85ca..4f9f247 100644
--- a/server/ui/controller/icon.go
+++ b/server/ui/controller/icon.go
@@ -5,10 +5,12 @@
package controller
import (
- "github.com/miniflux/miniflux2/server/core"
"time"
+
+ "github.com/miniflux/miniflux2/server/core"
)
+// ShowIcon shows the feed icon.
func (c *Controller) ShowIcon(ctx *core.Context, request *core.Request, response *core.Response) {
iconID, err := request.IntegerParam("iconID")
if err != nil {
@@ -16,7 +18,7 @@ func (c *Controller) ShowIcon(ctx *core.Context, request *core.Request, response
return
}
- icon, err := c.store.GetIconByID(iconID)
+ icon, err := c.store.IconByID(iconID)
if err != nil {
response.HTML().ServerError(err)
return
diff --git a/server/ui/controller/oauth2.go b/server/ui/controller/oauth2.go
index c80ec71..2ed928c 100644
--- a/server/ui/controller/oauth2.go
+++ b/server/ui/controller/oauth2.go
@@ -82,7 +82,7 @@ func (c *Controller) OAuth2Callback(ctx *core.Context, request *core.Request, re
return
}
- user, err := c.store.GetUserByExtraField(profile.Key, profile.ID)
+ user, err := c.store.UserByExtraField(profile.Key, profile.ID)
if err != nil {
response.HTML().ServerError(err)
return
diff --git a/server/ui/controller/opml.go b/server/ui/controller/opml.go
index d489032..ebde622 100644
--- a/server/ui/controller/opml.go
+++ b/server/ui/controller/opml.go
@@ -10,6 +10,7 @@ import (
"github.com/miniflux/miniflux2/server/core"
)
+// Export generates the OPML file.
func (c *Controller) Export(ctx *core.Context, request *core.Request, response *core.Response) {
user := ctx.LoggedUser()
opml, err := c.opmlHandler.Export(user.ID)
@@ -21,6 +22,7 @@ func (c *Controller) Export(ctx *core.Context, request *core.Request, response *
response.XML().Download("feeds.opml", opml)
}
+// Import shows the import form.
func (c *Controller) Import(ctx *core.Context, request *core.Request, response *core.Response) {
args, err := c.getCommonTemplateArgs(ctx)
if err != nil {
@@ -33,6 +35,7 @@ func (c *Controller) Import(ctx *core.Context, request *core.Request, response *
}))
}
+// UploadOPML handles OPML file importation.
func (c *Controller) UploadOPML(ctx *core.Context, request *core.Request, response *core.Response) {
file, fileHeader, err := request.File("file")
if err != nil {
diff --git a/server/ui/controller/pagination.go b/server/ui/controller/pagination.go
index b649d90..1d61f74 100644
--- a/server/ui/controller/pagination.go
+++ b/server/ui/controller/pagination.go
@@ -5,10 +5,10 @@
package controller
const (
- NbItemsPerPage = 100
+ nbItemsPerPage = 100
)
-type Pagination struct {
+type pagination struct {
Route string
Total int
Offset int
@@ -19,25 +19,25 @@ type Pagination struct {
PrevOffset int
}
-func (c *Controller) getPagination(route string, total, offset int) Pagination {
+func (c *Controller) getPagination(route string, total, offset int) pagination {
nextOffset := 0
prevOffset := 0
- showNext := (total - offset) > NbItemsPerPage
+ showNext := (total - offset) > nbItemsPerPage
showPrev := offset > 0
if showNext {
- nextOffset = offset + NbItemsPerPage
+ nextOffset = offset + nbItemsPerPage
}
if showPrev {
- prevOffset = offset - NbItemsPerPage
+ prevOffset = offset - nbItemsPerPage
}
- return Pagination{
+ return pagination{
Route: route,
Total: total,
Offset: offset,
- ItemsPerPage: NbItemsPerPage,
+ ItemsPerPage: nbItemsPerPage,
ShowNext: showNext,
NextOffset: nextOffset,
ShowPrev: showPrev,
diff --git a/server/ui/controller/session.go b/server/ui/controller/session.go
index fec754b..ee0c75a 100644
--- a/server/ui/controller/session.go
+++ b/server/ui/controller/session.go
@@ -5,10 +5,12 @@
package controller
import (
- "github.com/miniflux/miniflux2/server/core"
"log"
+
+ "github.com/miniflux/miniflux2/server/core"
)
+// ShowSessions shows the list of active sessions.
func (c *Controller) ShowSessions(ctx *core.Context, request *core.Request, response *core.Response) {
user := ctx.LoggedUser()
args, err := c.getCommonTemplateArgs(ctx)
@@ -17,7 +19,7 @@ func (c *Controller) ShowSessions(ctx *core.Context, request *core.Request, resp
return
}
- sessions, err := c.store.GetSessions(user.ID)
+ sessions, err := c.store.Sessions(user.ID)
if err != nil {
response.HTML().ServerError(err)
return
@@ -31,6 +33,7 @@ func (c *Controller) ShowSessions(ctx *core.Context, request *core.Request, resp
}))
}
+// RemoveSession remove a session.
func (c *Controller) RemoveSession(ctx *core.Context, request *core.Request, response *core.Response) {
user := ctx.LoggedUser()
diff --git a/server/ui/controller/settings.go b/server/ui/controller/settings.go
index 1bd599b..e8ab20b 100644
--- a/server/ui/controller/settings.go
+++ b/server/ui/controller/settings.go
@@ -5,13 +5,15 @@
package controller
import (
+ "log"
+
"github.com/miniflux/miniflux2/locale"
"github.com/miniflux/miniflux2/model"
"github.com/miniflux/miniflux2/server/core"
"github.com/miniflux/miniflux2/server/ui/form"
- "log"
)
+// ShowSettings shows the settings page.
func (c *Controller) ShowSettings(ctx *core.Context, request *core.Request, response *core.Response) {
user := ctx.LoggedUser()
@@ -24,6 +26,7 @@ func (c *Controller) ShowSettings(ctx *core.Context, request *core.Request, resp
response.HTML().Render("settings", args)
}
+// UpdateSettings update the settings.
func (c *Controller) UpdateSettings(ctx *core.Context, request *core.Request, response *core.Response) {
user := ctx.LoggedUser()
@@ -81,9 +84,9 @@ func (c *Controller) getSettingsFormTemplateArgs(ctx *core.Context, user *model.
}
args["menu"] = "settings"
- args["themes"] = model.GetThemes()
- args["languages"] = locale.GetAvailableLanguages()
- args["timezones"], err = c.store.GetTimezones()
+ args["themes"] = model.Themes()
+ args["languages"] = locale.AvailableLanguages()
+ args["timezones"], err = c.store.Timezones()
if err != nil {
return args, err
}
diff --git a/server/ui/controller/static.go b/server/ui/controller/static.go
index 822118a..fba408c 100644
--- a/server/ui/controller/static.go
+++ b/server/ui/controller/static.go
@@ -6,12 +6,14 @@ package controller
import (
"encoding/base64"
- "github.com/miniflux/miniflux2/server/core"
- "github.com/miniflux/miniflux2/server/static"
"log"
"time"
+
+ "github.com/miniflux/miniflux2/server/core"
+ "github.com/miniflux/miniflux2/server/static"
)
+// Stylesheet renders the CSS.
func (c *Controller) Stylesheet(ctx *core.Context, request *core.Request, response *core.Response) {
stylesheet := request.StringParam("name", "white")
body := static.Stylesheets["common"]
@@ -25,10 +27,12 @@ func (c *Controller) Stylesheet(ctx *core.Context, request *core.Request, respon
response.Cache("text/css", etag, []byte(body), 48*time.Hour)
}
+// Javascript renders application client side code.
func (c *Controller) Javascript(ctx *core.Context, request *core.Request, response *core.Response) {
response.Cache("text/javascript", static.JavascriptChecksums["app"], []byte(static.Javascript["app"]), 48*time.Hour)
}
+// Favicon renders the application favicon.
func (c *Controller) Favicon(ctx *core.Context, request *core.Request, response *core.Response) {
blob, err := base64.StdEncoding.DecodeString(static.Binaries["favicon.ico"])
if err != nil {
diff --git a/server/ui/controller/subscription.go b/server/ui/controller/subscription.go
index 342f0c5..8b0caf1 100644
--- a/server/ui/controller/subscription.go
+++ b/server/ui/controller/subscription.go
@@ -135,7 +135,7 @@ func (c *Controller) getSubscriptionFormTemplateArgs(ctx *core.Context, user *mo
return nil, err
}
- categories, err := c.store.GetCategories(user.ID)
+ categories, err := c.store.Categories(user.ID)
if err != nil {
return nil, err
}
diff --git a/server/ui/controller/unread.go b/server/ui/controller/unread.go
index 593ee38..a114250 100644
--- a/server/ui/controller/unread.go
+++ b/server/ui/controller/unread.go
@@ -19,7 +19,7 @@ func (c *Controller) ShowUnreadPage(ctx *core.Context, request *core.Request, re
builder.WithOrder(model.DefaultSortingOrder)
builder.WithDirection(model.DefaultSortingDirection)
builder.WithOffset(offset)
- builder.WithLimit(NbItemsPerPage)
+ builder.WithLimit(nbItemsPerPage)
entries, err := builder.GetEntries()
if err != nil {
diff --git a/server/ui/controller/user.go b/server/ui/controller/user.go
index 1590d96..0d1fbb2 100644
--- a/server/ui/controller/user.go
+++ b/server/ui/controller/user.go
@@ -6,12 +6,14 @@ package controller
import (
"errors"
+ "log"
+
"github.com/miniflux/miniflux2/model"
"github.com/miniflux/miniflux2/server/core"
"github.com/miniflux/miniflux2/server/ui/form"
- "log"
)
+// ShowUsers shows the list of users.
func (c *Controller) ShowUsers(ctx *core.Context, request *core.Request, response *core.Response) {
user := ctx.LoggedUser()
@@ -26,7 +28,7 @@ func (c *Controller) ShowUsers(ctx *core.Context, request *core.Request, respons
return
}
- users, err := c.store.GetUsers()
+ users, err := c.store.Users()
if err != nil {
response.HTML().ServerError(err)
return
@@ -38,6 +40,7 @@ func (c *Controller) ShowUsers(ctx *core.Context, request *core.Request, respons
}))
}
+// CreateUser shows the user creation form.
func (c *Controller) CreateUser(ctx *core.Context, request *core.Request, response *core.Response) {
user := ctx.LoggedUser()
@@ -58,6 +61,7 @@ func (c *Controller) CreateUser(ctx *core.Context, request *core.Request, respon
}))
}
+// SaveUser validate and save the new user into the database.
func (c *Controller) SaveUser(ctx *core.Context, request *core.Request, response *core.Response) {
user := ctx.LoggedUser()
@@ -105,6 +109,7 @@ func (c *Controller) SaveUser(ctx *core.Context, request *core.Request, response
response.Redirect(ctx.Route("users"))
}
+// EditUser shows the form to edit a user.
func (c *Controller) EditUser(ctx *core.Context, request *core.Request, response *core.Response) {
user := ctx.LoggedUser()
@@ -134,6 +139,7 @@ func (c *Controller) EditUser(ctx *core.Context, request *core.Request, response
}))
}
+// UpdateUser validate and update a user.
func (c *Controller) UpdateUser(ctx *core.Context, request *core.Request, response *core.Response) {
user := ctx.LoggedUser()
@@ -189,6 +195,7 @@ func (c *Controller) UpdateUser(ctx *core.Context, request *core.Request, respon
response.Redirect(ctx.Route("users"))
}
+// RemoveUser deletes a user from the database.
func (c *Controller) RemoveUser(ctx *core.Context, request *core.Request, response *core.Response) {
user := ctx.LoggedUser()
if !user.IsAdmin {
@@ -216,7 +223,7 @@ func (c *Controller) getUserFromURL(ctx *core.Context, request *core.Request, re
return nil, err
}
- user, err := c.store.GetUserById(userID)
+ user, err := c.store.UserByID(userID)
if err != nil {
response.HTML().ServerError(err)
return nil, err
diff --git a/server/ui/filter/image_proxy_filter.go b/server/ui/filter/image_proxy_filter.go
index 71da869..8a775fe 100644
--- a/server/ui/filter/image_proxy_filter.go
+++ b/server/ui/filter/image_proxy_filter.go
@@ -6,9 +6,10 @@ package filter
import (
"encoding/base64"
+ "strings"
+
"github.com/miniflux/miniflux2/reader/url"
"github.com/miniflux/miniflux2/server/route"
- "strings"
"github.com/PuerkitoBio/goquery"
"github.com/gorilla/mux"
@@ -24,7 +25,7 @@ func ImageProxyFilter(r *mux.Router, data string) string {
doc.Find("img").Each(func(i int, img *goquery.Selection) {
if srcAttr, ok := img.Attr("src"); ok {
if !url.IsHTTPS(srcAttr) {
- path := route.GetRoute(r, "proxy", "encodedURL", base64.StdEncoding.EncodeToString([]byte(srcAttr)))
+ path := route.Path(r, "proxy", "encodedURL", base64.StdEncoding.EncodeToString([]byte(srcAttr)))
img.SetAttr("src", path)
}
}
diff --git a/server/ui/form/auth.go b/server/ui/form/auth.go
index 3cfc217..6849339 100644
--- a/server/ui/form/auth.go
+++ b/server/ui/form/auth.go
@@ -5,23 +5,27 @@
package form
import (
- "errors"
"net/http"
+
+ "github.com/miniflux/miniflux2/errors"
)
+// AuthForm represents the authentication form.
type AuthForm struct {
Username string
Password string
}
+// Validate makes sure the form values are valid.
func (a AuthForm) Validate() error {
if a.Username == "" || a.Password == "" {
- return errors.New("All fields are mandatory.")
+ return errors.NewLocalizedError("All fields are mandatory.")
}
return nil
}
+// NewAuthForm returns a new AuthForm.
func NewAuthForm(r *http.Request) *AuthForm {
return &AuthForm{
Username: r.FormValue("username"),
diff --git a/server/ui/form/category.go b/server/ui/form/category.go
index 510d1b4..f977b7a 100644
--- a/server/ui/form/category.go
+++ b/server/ui/form/category.go
@@ -5,9 +5,10 @@
package form
import (
- "errors"
- "github.com/miniflux/miniflux2/model"
"net/http"
+
+ "github.com/miniflux/miniflux2/errors"
+ "github.com/miniflux/miniflux2/model"
)
// CategoryForm represents a feed form in the UI
@@ -15,18 +16,21 @@ type CategoryForm struct {
Title string
}
+// Validate makes sure the form values are valid.
func (c CategoryForm) Validate() error {
if c.Title == "" {
- return errors.New("The title is mandatory.")
+ return errors.NewLocalizedError("The title is mandatory.")
}
return nil
}
+// Merge update the given category fields.
func (c CategoryForm) Merge(category *model.Category) *model.Category {
category.Title = c.Title
return category
}
+// NewCategoryForm returns a new CategoryForm.
func NewCategoryForm(r *http.Request) *CategoryForm {
return &CategoryForm{
Title: r.FormValue("title"),
diff --git a/server/ui/form/feed.go b/server/ui/form/feed.go
index e21e6ca..8a8cf20 100644
--- a/server/ui/form/feed.go
+++ b/server/ui/form/feed.go
@@ -5,10 +5,11 @@
package form
import (
- "errors"
- "github.com/miniflux/miniflux2/model"
"net/http"
"strconv"
+
+ "github.com/miniflux/miniflux2/errors"
+ "github.com/miniflux/miniflux2/model"
)
// FeedForm represents a feed form in the UI
@@ -22,11 +23,12 @@ type FeedForm struct {
// ValidateModification validates FeedForm fields
func (f FeedForm) ValidateModification() error {
if f.FeedURL == "" || f.SiteURL == "" || f.Title == "" || f.CategoryID == 0 {
- return errors.New("All fields are mandatory.")
+ return errors.NewLocalizedError("All fields are mandatory.")
}
return nil
}
+// Merge updates the fields of the given feed.
func (f FeedForm) Merge(feed *model.Feed) *model.Feed {
feed.Category.ID = f.CategoryID
feed.Title = f.Title
diff --git a/server/ui/form/settings.go b/server/ui/form/settings.go
index 1e40b97..3d37a0f 100644
--- a/server/ui/form/settings.go
+++ b/server/ui/form/settings.go
@@ -5,11 +5,13 @@
package form
import (
- "errors"
- "github.com/miniflux/miniflux2/model"
"net/http"
+
+ "github.com/miniflux/miniflux2/errors"
+ "github.com/miniflux/miniflux2/model"
)
+// SettingsForm represents the settings form.
type SettingsForm struct {
Username string
Password string
@@ -19,6 +21,7 @@ type SettingsForm struct {
Timezone string
}
+// Merge updates the fields of the given user.
func (s *SettingsForm) Merge(user *model.User) *model.User {
user.Username = s.Username
user.Theme = s.Theme
@@ -32,24 +35,26 @@ func (s *SettingsForm) Merge(user *model.User) *model.User {
return user
}
+// Validate makes sure the form values are valid.
func (s *SettingsForm) Validate() error {
if s.Username == "" || s.Theme == "" || s.Language == "" || s.Timezone == "" {
- return errors.New("The username, theme, language and timezone fields are mandatory.")
+ return errors.NewLocalizedError("The username, theme, language and timezone fields are mandatory.")
}
if s.Password != "" {
if s.Password != s.Confirmation {
- return errors.New("Passwords are not the same.")
+ return errors.NewLocalizedError("Passwords are not the same.")
}
if len(s.Password) < 6 {
- return errors.New("You must use at least 6 characters")
+ return errors.NewLocalizedError("You must use at least 6 characters")
}
}
return nil
}
+// NewSettingsForm returns a new SettingsForm.
func NewSettingsForm(r *http.Request) *SettingsForm {
return &SettingsForm{
Username: r.FormValue("username"),
diff --git a/server/ui/form/subscription.go b/server/ui/form/subscription.go
index 6696b22..ca1c605 100644
--- a/server/ui/form/subscription.go
+++ b/server/ui/form/subscription.go
@@ -5,24 +5,28 @@
package form
import (
- "errors"
"net/http"
"strconv"
+
+ "github.com/miniflux/miniflux2/errors"
)
+// SubscriptionForm represents the subscription form.
type SubscriptionForm struct {
URL string
CategoryID int64
}
+// Validate makes sure the form values are valid.
func (s *SubscriptionForm) Validate() error {
if s.URL == "" || s.CategoryID == 0 {
- return errors.New("The URL and the category are mandatory.")
+ return errors.NewLocalizedError("The URL and the category are mandatory.")
}
return nil
}
+// NewSubscriptionForm returns a new SubscriptionForm.
func NewSubscriptionForm(r *http.Request) *SubscriptionForm {
categoryID, err := strconv.Atoi(r.FormValue("category_id"))
if err != nil {
diff --git a/server/ui/form/user.go b/server/ui/form/user.go
index 1197b48..5319cb8 100644
--- a/server/ui/form/user.go
+++ b/server/ui/form/user.go
@@ -5,11 +5,13 @@
package form
import (
- "errors"
- "github.com/miniflux/miniflux2/model"
"net/http"
+
+ "github.com/miniflux/miniflux2/errors"
+ "github.com/miniflux/miniflux2/model"
)
+// UserForm represents the user form.
type UserForm struct {
Username string
Password string
@@ -17,40 +19,43 @@ type UserForm struct {
IsAdmin bool
}
+// ValidateCreation validates user creation.
func (u UserForm) ValidateCreation() error {
if u.Username == "" || u.Password == "" || u.Confirmation == "" {
- return errors.New("All fields are mandatory.")
+ return errors.NewLocalizedError("All fields are mandatory.")
}
if u.Password != u.Confirmation {
- return errors.New("Passwords are not the same.")
+ return errors.NewLocalizedError("Passwords are not the same.")
}
if len(u.Password) < 6 {
- return errors.New("You must use at least 6 characters.")
+ return errors.NewLocalizedError("You must use at least 6 characters.")
}
return nil
}
+// ValidateModification validates user modification.
func (u UserForm) ValidateModification() error {
if u.Username == "" {
- return errors.New("The username is mandatory.")
+ return errors.NewLocalizedError("The username is mandatory.")
}
if u.Password != "" {
if u.Password != u.Confirmation {
- return errors.New("Passwords are not the same.")
+ return errors.NewLocalizedError("Passwords are not the same.")
}
if len(u.Password) < 6 {
- return errors.New("You must use at least 6 characters.")
+ return errors.NewLocalizedError("You must use at least 6 characters.")
}
}
return nil
}
+// ToUser returns a User from the form values.
func (u UserForm) ToUser() *model.User {
return &model.User{
Username: u.Username,
@@ -59,6 +64,7 @@ func (u UserForm) ToUser() *model.User {
}
}
+// Merge updates the fields of the given user.
func (u UserForm) Merge(user *model.User) *model.User {
user.Username = u.Username
user.IsAdmin = u.IsAdmin
@@ -70,6 +76,7 @@ func (u UserForm) Merge(user *model.User) *model.User {
return user
}
+// NewUserForm returns a new UserForm.
func NewUserForm(r *http.Request) *UserForm {
return &UserForm{
Username: r.FormValue("username"),
diff --git a/server/ui/payload/payload.go b/server/ui/payload/payload.go
index b2fef95..7312fb2 100644
--- a/server/ui/payload/payload.go
+++ b/server/ui/payload/payload.go
@@ -7,10 +7,12 @@ package payload
import (
"encoding/json"
"fmt"
- "github.com/miniflux/miniflux2/model"
"io"
+
+ "github.com/miniflux/miniflux2/model"
)
+// DecodeEntryStatusPayload unserialize JSON request to update entry statuses.
func DecodeEntryStatusPayload(data io.Reader) (entryIDs []int64, status string, err error) {
type payload struct {
EntryIDs []int64 `json:"entry_ids"`
diff --git a/sql/sql.go b/sql/sql.go
index 1a3febd..14457c0 100644
--- a/sql/sql.go
+++ b/sql/sql.go
@@ -1,5 +1,5 @@
// Code generated by go generate; DO NOT EDIT.
-// 2017-11-25 10:47:30.347837046 -0800 PST m=+0.003965152
+// 2017-11-27 21:07:53.208711992 -0800 PST m=+0.002898220
package sql
diff --git a/storage/category.go b/storage/category.go
index e1986b7..5591a89 100644
--- a/storage/category.go
+++ b/storage/category.go
@@ -14,6 +14,7 @@ import (
"github.com/miniflux/miniflux2/model"
)
+// AnotherCategoryExists checks if another category exists with the same title.
func (s *Storage) AnotherCategoryExists(userID, categoryID int64, title string) bool {
defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:AnotherCategoryExists] userID=%d, categoryID=%d, title=%s", userID, categoryID, title))
@@ -23,6 +24,7 @@ func (s *Storage) AnotherCategoryExists(userID, categoryID int64, title string)
return result >= 1
}
+// CategoryExists checks if the given category exists into the database.
func (s *Storage) CategoryExists(userID, categoryID int64) bool {
defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:CategoryExists] userID=%d, categoryID=%d", userID, categoryID))
@@ -32,8 +34,9 @@ func (s *Storage) CategoryExists(userID, categoryID int64) bool {
return result >= 1
}
-func (s *Storage) GetCategory(userID, categoryID int64) (*model.Category, error) {
- defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:GetCategory] userID=%d, getCategory=%d", userID, categoryID))
+// Category returns a category from the database.
+func (s *Storage) Category(userID, categoryID int64) (*model.Category, error) {
+ defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:Category] userID=%d, getCategory=%d", userID, categoryID))
var category model.Category
query := `SELECT id, user_id, title FROM categories WHERE user_id=$1 AND id=$2`
@@ -41,29 +44,31 @@ func (s *Storage) GetCategory(userID, categoryID int64) (*model.Category, error)
if err == sql.ErrNoRows {
return nil, nil
} else if err != nil {
- return nil, fmt.Errorf("Unable to fetch category: %v", err)
+ return nil, fmt.Errorf("unable to fetch category: %v", err)
}
return &category, nil
}
-func (s *Storage) GetFirstCategory(userID int64) (*model.Category, error) {
- defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:GetFirstCategory] userID=%d", userID))
+// FirstCategory returns the first category for the given user.
+func (s *Storage) FirstCategory(userID int64) (*model.Category, error) {
+ defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:FirstCategory] userID=%d", userID))
var category model.Category
- query := `SELECT id, user_id, title FROM categories WHERE user_id=$1 ORDER BY title ASC`
+ query := `SELECT id, user_id, title FROM categories WHERE user_id=$1 ORDER BY title ASC LIMIT 1`
err := s.db.QueryRow(query, userID).Scan(&category.ID, &category.UserID, &category.Title)
if err == sql.ErrNoRows {
return nil, nil
} else if err != nil {
- return nil, fmt.Errorf("Unable to fetch category: %v", err)
+ return nil, fmt.Errorf("unable to fetch category: %v", err)
}
return &category, nil
}
-func (s *Storage) GetCategoryByTitle(userID int64, title string) (*model.Category, error) {
- defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:GetCategoryByTitle] userID=%d, title=%s", userID, title))
+// CategoryByTitle finds a category by the title.
+func (s *Storage) CategoryByTitle(userID int64, title string) (*model.Category, error) {
+ defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:CategoryByTitle] userID=%d, title=%s", userID, title))
var category model.Category
query := `SELECT id, user_id, title FROM categories WHERE user_id=$1 AND title=$2`
@@ -77,10 +82,11 @@ func (s *Storage) GetCategoryByTitle(userID int64, title string) (*model.Categor
return &category, nil
}
-func (s *Storage) GetCategories(userID int64) (model.Categories, error) {
- defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:GetCategories] userID=%d", userID))
+// Categories returns all categories that belongs to the given user.
+func (s *Storage) Categories(userID int64) (model.Categories, error) {
+ defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:Categories] userID=%d", userID))
- query := `SELECT id, user_id, title FROM categories WHERE user_id=$1`
+ query := `SELECT id, user_id, title FROM categories WHERE user_id=$1 ORDER BY title ASC`
rows, err := s.db.Query(query, userID)
if err != nil {
return nil, fmt.Errorf("Unable to fetch categories: %v", err)
@@ -100,8 +106,9 @@ func (s *Storage) GetCategories(userID int64) (model.Categories, error) {
return categories, nil
}
-func (s *Storage) GetCategoriesWithFeedCount(userID int64) (model.Categories, error) {
- defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:GetCategoriesWithFeedCount] userID=%d", userID))
+// CategoriesWithFeedCount returns all categories with the number of feeds.
+func (s *Storage) CategoriesWithFeedCount(userID int64) (model.Categories, error) {
+ defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:CategoriesWithFeedCount] userID=%d", userID))
query := `SELECT
c.id, c.user_id, c.title,
(SELECT count(*) FROM feeds WHERE feeds.category_id=c.id) AS count
@@ -126,6 +133,7 @@ func (s *Storage) GetCategoriesWithFeedCount(userID int64) (model.Categories, er
return categories, nil
}
+// CreateCategory creates a new category.
func (s *Storage) CreateCategory(category *model.Category) error {
defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:CreateCategory] title=%s", category.Title))
@@ -149,6 +157,7 @@ func (s *Storage) CreateCategory(category *model.Category) error {
return nil
}
+// UpdateCategory updates an existing category.
func (s *Storage) UpdateCategory(category *model.Category) error {
defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:UpdateCategory] categoryID=%d", category.ID))
@@ -167,6 +176,7 @@ func (s *Storage) UpdateCategory(category *model.Category) error {
return nil
}
+// RemoveCategory deletes a category.
func (s *Storage) RemoveCategory(userID, categoryID int64) error {
defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:RemoveCategory] userID=%d, categoryID=%d", userID, categoryID))
diff --git a/storage/feed.go b/storage/feed.go
index 4c58160..9d42664 100644
--- a/storage/feed.go
+++ b/storage/feed.go
@@ -14,6 +14,7 @@ import (
"github.com/miniflux/miniflux2/model"
)
+// FeedExists checks if the given feed exists.
func (s *Storage) FeedExists(userID, feedID int64) bool {
defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:FeedExists] userID=%d, feedID=%d", userID, feedID))
@@ -23,6 +24,7 @@ func (s *Storage) FeedExists(userID, feedID int64) bool {
return result >= 1
}
+// FeedURLExists checks if feed URL already exists.
func (s *Storage) FeedURLExists(userID int64, feedURL string) bool {
defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:FeedURLExists] userID=%d, feedURL=%s", userID, feedURL))
@@ -43,8 +45,9 @@ func (s *Storage) CountFeeds(userID int64) int {
return result
}
-func (s *Storage) GetFeeds(userID int64) (model.Feeds, error) {
- defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:GetFeeds] userID=%d", userID))
+// Feeds returns all feeds of the given user.
+func (s *Storage) Feeds(userID int64) (model.Feeds, error) {
+ defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:Feeds] userID=%d", userID))
feeds := make(model.Feeds, 0)
query := `SELECT
@@ -109,8 +112,9 @@ func (s *Storage) GetFeeds(userID int64) (model.Feeds, error) {
return feeds, nil
}
-func (s *Storage) GetFeedById(userID, feedID int64) (*model.Feed, error) {
- defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:GetFeedById] feedID=%d", feedID))
+// FeedByID returns a feed by the ID.
+func (s *Storage) FeedByID(userID, feedID int64) (*model.Feed, error) {
+ defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:FeedByID] feedID=%d", feedID))
var feed model.Feed
feed.Category = &model.Category{UserID: userID}
@@ -149,6 +153,7 @@ func (s *Storage) GetFeedById(userID, feedID int64) (*model.Feed, error) {
return &feed, nil
}
+// CreateFeed creates a new feed.
func (s *Storage) CreateFeed(feed *model.Feed) error {
defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:CreateFeed] feedURL=%s", feed.FeedURL))
sql := `
@@ -184,6 +189,7 @@ func (s *Storage) CreateFeed(feed *model.Feed) error {
return nil
}
+// UpdateFeed updates an existing feed.
func (s *Storage) UpdateFeed(feed *model.Feed) (err error) {
defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:UpdateFeed] feedURL=%s", feed.FeedURL))
@@ -213,6 +219,7 @@ func (s *Storage) UpdateFeed(feed *model.Feed) (err error) {
return nil
}
+// RemoveFeed removes a feed.
func (s *Storage) RemoveFeed(userID, feedID int64) error {
defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:RemoveFeed] userID=%d, feedID=%d", userID, feedID))
diff --git a/storage/icon.go b/storage/icon.go
index 69f9653..e021d29 100644
--- a/storage/icon.go
+++ b/storage/icon.go
@@ -14,6 +14,7 @@ import (
"github.com/miniflux/miniflux2/model"
)
+// HasIcon checks if the given feed has an icon.
func (s *Storage) HasIcon(feedID int64) bool {
var result int
query := `SELECT count(*) as c FROM feed_icons WHERE feed_id=$1`
@@ -21,8 +22,9 @@ func (s *Storage) HasIcon(feedID int64) bool {
return result == 1
}
-func (s *Storage) GetIconByID(iconID int64) (*model.Icon, error) {
- defer helper.ExecutionTime(time.Now(), "[Storage:GetIconByID]")
+// IconByID returns an icon by the ID.
+func (s *Storage) IconByID(iconID int64) (*model.Icon, error) {
+ defer helper.ExecutionTime(time.Now(), "[Storage:IconByID]")
var icon model.Icon
query := `SELECT id, hash, mime_type, content FROM icons WHERE id=$1`
@@ -36,8 +38,9 @@ func (s *Storage) GetIconByID(iconID int64) (*model.Icon, error) {
return &icon, nil
}
-func (s *Storage) GetIconByHash(icon *model.Icon) error {
- defer helper.ExecutionTime(time.Now(), "[Storage:GetIconByHash]")
+// IconByHash returns an icon by the hash (checksum).
+func (s *Storage) IconByHash(icon *model.Icon) error {
+ defer helper.ExecutionTime(time.Now(), "[Storage:IconByHash]")
err := s.db.QueryRow(`SELECT id FROM icons WHERE hash=$1`, icon.Hash).Scan(&icon.ID)
if err == sql.ErrNoRows {
@@ -49,6 +52,7 @@ func (s *Storage) GetIconByHash(icon *model.Icon) error {
return nil
}
+// CreateIcon creates a new icon.
func (s *Storage) CreateIcon(icon *model.Icon) error {
defer helper.ExecutionTime(time.Now(), "[Storage:CreateIcon]")
@@ -73,10 +77,11 @@ func (s *Storage) CreateIcon(icon *model.Icon) error {
return nil
}
+// CreateFeedIcon creates an icon and associate the icon to the given feed.
func (s *Storage) CreateFeedIcon(feed *model.Feed, icon *model.Icon) error {
defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:CreateFeedIcon] feedID=%d", feed.ID))
- err := s.GetIconByHash(icon)
+ err := s.IconByHash(icon)
if err != nil {
return err
}
diff --git a/storage/session.go b/storage/session.go
index 296711d..719fcff 100644
--- a/storage/session.go
+++ b/storage/session.go
@@ -7,11 +7,13 @@ package storage
import (
"database/sql"
"fmt"
+
"github.com/miniflux/miniflux2/helper"
"github.com/miniflux/miniflux2/model"
)
-func (s *Storage) GetSessions(userID int64) (model.Sessions, error) {
+// Sessions returns the list of sessions for the given user.
+func (s *Storage) Sessions(userID int64) (model.Sessions, error) {
query := `SELECT id, user_id, token, created_at, user_agent, ip FROM sessions WHERE user_id=$1 ORDER BY id DESC`
rows, err := s.db.Query(query, userID)
if err != nil {
@@ -41,6 +43,7 @@ func (s *Storage) GetSessions(userID int64) (model.Sessions, error) {
return sessions, nil
}
+// CreateSession creates a new sessions.
func (s *Storage) CreateSession(username, userAgent, ip string) (sessionID string, err error) {
var userID int64
@@ -61,7 +64,8 @@ func (s *Storage) CreateSession(username, userAgent, ip string) (sessionID strin
return token, nil
}
-func (s *Storage) GetSessionByToken(token string) (*model.Session, error) {
+// SessionByToken finds a session by the token.
+func (s *Storage) SessionByToken(token string) (*model.Session, error) {
var session model.Session
query := "SELECT id, user_id, token, created_at, user_agent, ip FROM sessions WHERE token = $1"
@@ -83,6 +87,7 @@ func (s *Storage) GetSessionByToken(token string) (*model.Session, error) {
return &session, nil
}
+// RemoveSessionByToken remove a session by using the token.
func (s *Storage) RemoveSessionByToken(userID int64, token string) error {
result, err := s.db.Exec(`DELETE FROM sessions WHERE user_id=$1 AND token=$2`, userID, token)
if err != nil {
@@ -101,6 +106,7 @@ func (s *Storage) RemoveSessionByToken(userID int64, token string) error {
return nil
}
+// RemoveSessionByID remove a session by using the ID.
func (s *Storage) RemoveSessionByID(userID, sessionID int64) error {
result, err := s.db.Exec(`DELETE FROM sessions WHERE user_id=$1 AND id=$2`, userID, sessionID)
if err != nil {
@@ -119,7 +125,8 @@ func (s *Storage) RemoveSessionByID(userID, sessionID int64) error {
return nil
}
+// FlushAllSessions removes all sessions from the database.
func (s *Storage) FlushAllSessions() (err error) {
- _, err = s.db.Exec(`delete from sessions`)
+ _, err = s.db.Exec(`DELETE FROM sessions`)
return
}
diff --git a/storage/storage.go b/storage/storage.go
index ebefe91..c815a06 100644
--- a/storage/storage.go
+++ b/storage/storage.go
@@ -8,19 +8,23 @@ import (
"database/sql"
"log"
+ // Postgresql driver import
_ "github.com/lib/pq"
)
+// Storage handles all operations related to the database.
type Storage struct {
db *sql.DB
}
+// Close closes all database connections.
func (s *Storage) Close() {
s.db.Close()
}
-func NewStorage(databaseUrl string, maxOpenConns int) *Storage {
- db, err := sql.Open("postgres", databaseUrl)
+// NewStorage returns a new Storage.
+func NewStorage(databaseURL string, maxOpenConns int) *Storage {
+ db, err := sql.Open("postgres", databaseURL)
if err != nil {
log.Fatalf("Unable to connect to the database: %v", err)
}
diff --git a/storage/timezone.go b/storage/timezone.go
index 8edfc1c..257f44f 100644
--- a/storage/timezone.go
+++ b/storage/timezone.go
@@ -6,12 +6,14 @@ package storage
import (
"fmt"
- "github.com/miniflux/miniflux2/helper"
"time"
+
+ "github.com/miniflux/miniflux2/helper"
)
-func (s *Storage) GetTimezones() (map[string]string, error) {
- defer helper.ExecutionTime(time.Now(), "[Storage:GetTimezones]")
+// Timezones returns all timezones supported by the database.
+func (s *Storage) Timezones() (map[string]string, error) {
+ defer helper.ExecutionTime(time.Now(), "[Storage:Timezones]")
timezones := make(map[string]string)
query := `select name from pg_timezone_names() order by name asc`
diff --git a/storage/user.go b/storage/user.go
index d02418e..fdbbfda 100644
--- a/storage/user.go
+++ b/storage/user.go
@@ -19,6 +19,7 @@ import (
"golang.org/x/crypto/bcrypt"
)
+// SetLastLogin updates the last login date of a user.
func (s *Storage) SetLastLogin(userID int64) error {
defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:SetLastLogin] userID=%d", userID))
query := "UPDATE users SET last_login_at=now() WHERE id=$1"
@@ -30,6 +31,7 @@ func (s *Storage) SetLastLogin(userID int64) error {
return nil
}
+// UserExists checks if a user exists by using the given username.
func (s *Storage) UserExists(username string) bool {
defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:UserExists] username=%s", username))
@@ -38,6 +40,7 @@ func (s *Storage) UserExists(username string) bool {
return result >= 1
}
+// AnotherUserExists checks if another user exists with the given username.
func (s *Storage) AnotherUserExists(userID int64, username string) bool {
defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:AnotherUserExists] userID=%d, username=%s", userID, username))
@@ -46,6 +49,7 @@ func (s *Storage) AnotherUserExists(userID int64, username string) bool {
return result >= 1
}
+// CreateUser creates a new user.
func (s *Storage) CreateUser(user *model.User) (err error) {
defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:CreateUser] username=%s", user.Username))
password := ""
@@ -84,6 +88,7 @@ func (s *Storage) CreateUser(user *model.User) (err error) {
return nil
}
+// UpdateExtraField updates an extra field of the given user.
func (s *Storage) UpdateExtraField(userID int64, field, value string) error {
query := fmt.Sprintf(`UPDATE users SET extra = hstore('%s', $1) WHERE id=$2`, field)
_, err := s.db.Exec(query, value, userID)
@@ -93,6 +98,7 @@ func (s *Storage) UpdateExtraField(userID int64, field, value string) error {
return nil
}
+// RemoveExtraField deletes an extra field for the given user.
func (s *Storage) RemoveExtraField(userID int64, field string) error {
query := `UPDATE users SET extra = delete(extra, $1) WHERE id=$2`
_, err := s.db.Exec(query, field, userID)
@@ -102,6 +108,7 @@ func (s *Storage) RemoveExtraField(userID int64, field string) error {
return nil
}
+// UpdateUser updates a user.
func (s *Storage) UpdateUser(user *model.User) error {
defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:UpdateUser] username=%s", user.Username))
user.Username = strings.ToLower(user.Username)
@@ -128,8 +135,9 @@ func (s *Storage) UpdateUser(user *model.User) error {
return nil
}
-func (s *Storage) GetUserById(userID int64) (*model.User, error) {
- defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:GetUserById] userID=%d", userID))
+// UserByID finds a user by the ID.
+func (s *Storage) UserByID(userID int64) (*model.User, error) {
+ defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:UserByID] userID=%d", userID))
var user model.User
var extra hstore.Hstore
@@ -151,8 +159,9 @@ func (s *Storage) GetUserById(userID int64) (*model.User, error) {
return &user, nil
}
-func (s *Storage) GetUserByUsername(username string) (*model.User, error) {
- defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:GetUserByUsername] username=%s", username))
+// UserByUsername finds a user by the username.
+func (s *Storage) UserByUsername(username string) (*model.User, error) {
+ defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:UserByUsername] username=%s", username))
var user model.User
row := s.db.QueryRow("SELECT id, username, is_admin, theme, language, timezone FROM users WHERE username=$1", username)
@@ -166,8 +175,9 @@ func (s *Storage) GetUserByUsername(username string) (*model.User, error) {
return &user, nil
}
-func (s *Storage) GetUserByExtraField(field, value string) (*model.User, error) {
- defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:GetUserByExtraField] field=%s", field))
+// UserByExtraField finds a user by an extra field value.
+func (s *Storage) UserByExtraField(field, value string) (*model.User, error) {
+ defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:UserByExtraField] field=%s", field))
var user model.User
query := `SELECT id, username, is_admin, theme, language, timezone FROM users WHERE extra->$1=$2`
row := s.db.QueryRow(query, field, value)
@@ -181,6 +191,7 @@ func (s *Storage) GetUserByExtraField(field, value string) (*model.User, error)
return &user, nil
}
+// RemoveUser deletes a user.
func (s *Storage) RemoveUser(userID int64) error {
defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:RemoveUser] userID=%d", userID))
@@ -195,14 +206,15 @@ func (s *Storage) RemoveUser(userID int64) error {
}
if count == 0 {
- return errors.New("nothing has been removed.")
+ return errors.New("nothing has been removed")
}
return nil
}
-func (s *Storage) GetUsers() (model.Users, error) {
- defer helper.ExecutionTime(time.Now(), "[Storage:GetUsers]")
+// Users returns all users.
+func (s *Storage) Users() (model.Users, error) {
+ defer helper.ExecutionTime(time.Now(), "[Storage:Users]")
var users model.Users
rows, err := s.db.Query("SELECT id, username, is_admin, theme, language, timezone, last_login_at FROM users ORDER BY username ASC")
@@ -233,6 +245,7 @@ func (s *Storage) GetUsers() (model.Users, error) {
return users, nil
}
+// CheckPassword validate the hashed password.
func (s *Storage) CheckPassword(username, password string) error {
defer helper.ExecutionTime(time.Now(), "[Storage:CheckPassword]")
@@ -241,13 +254,13 @@ func (s *Storage) CheckPassword(username, password string) error {
err := s.db.QueryRow("SELECT password FROM users WHERE username=$1", username).Scan(&hash)
if err == sql.ErrNoRows {
- return fmt.Errorf("Unable to find this user: %s\n", username)
+ return fmt.Errorf("unable to find this user: %s", username)
} else if err != nil {
- return fmt.Errorf("Unable to fetch user: %v\n", err)
+ return fmt.Errorf("unable to fetch user: %v", err)
}
if err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)); err != nil {
- return fmt.Errorf("Invalid password for %s\n", username)
+ return fmt.Errorf("invalid password for %s", username)
}
return nil