4
0
Эх сурвалжийг харах

Make sure golint pass on the code base

Frédéric Guillot 8 жил өмнө
parent
commit
bb8e61c7c5
59 өөрчлөгдсөн 322 нэмэгдсэн , 171 устгасан
  1. 2 0
      .travis.yml
  2. 9 5
      Makefile
  3. 2 2
      locale/locale.go
  4. 1 1
      locale/translations.go
  5. 3 3
      model/theme.go
  6. 2 10
      model/user.go
  7. 1 1
      reader/feed/handler.go
  8. 3 3
      reader/opml/handler.go
  9. 1 0
      reader/processor/processor.go
  10. 1 0
      reader/rewrite/rewriter.go
  11. 2 1
      server/api/controller/category.go
  12. 3 3
      server/api/controller/feed.go
  13. 5 4
      server/api/controller/user.go
  14. 7 0
      server/api/payload/payload.go
  15. 8 7
      server/core/context.go
  16. 2 2
      server/core/handler.go
  17. 10 6
      server/middleware/basic_auth.go
  18. 26 0
      server/middleware/context_keys.go
  19. 4 2
      server/middleware/csrf.go
  20. 10 5
      server/middleware/middleware.go
  21. 7 4
      server/middleware/session.go
  22. 2 1
      server/route/route.go
  23. 2 2
      server/routes.go
  24. 1 1
      server/static/bin.go
  25. 1 1
      server/static/css.go
  26. 1 1
      server/static/js.go
  27. 1 1
      server/template/common.go
  28. 1 1
      server/template/template.go
  29. 1 1
      server/template/views.go
  30. 1 0
      server/ui/controller/about.go
  31. 4 4
      server/ui/controller/category.go
  32. 4 4
      server/ui/controller/feed.go
  33. 1 1
      server/ui/controller/history.go
  34. 4 2
      server/ui/controller/icon.go
  35. 1 1
      server/ui/controller/oauth2.go
  36. 3 0
      server/ui/controller/opml.go
  37. 8 8
      server/ui/controller/pagination.go
  38. 5 2
      server/ui/controller/session.go
  39. 7 4
      server/ui/controller/settings.go
  40. 6 2
      server/ui/controller/static.go
  41. 1 1
      server/ui/controller/subscription.go
  42. 1 1
      server/ui/controller/unread.go
  43. 10 3
      server/ui/controller/user.go
  44. 3 2
      server/ui/filter/image_proxy_filter.go
  45. 6 2
      server/ui/form/auth.go
  46. 7 3
      server/ui/form/category.go
  47. 5 3
      server/ui/form/feed.go
  48. 10 5
      server/ui/form/settings.go
  49. 6 2
      server/ui/form/subscription.go
  50. 15 8
      server/ui/form/user.go
  51. 3 1
      server/ui/payload/payload.go
  52. 1 1
      sql/sql.go
  53. 24 14
      storage/category.go
  54. 11 4
      storage/feed.go
  55. 10 5
      storage/icon.go
  56. 10 3
      storage/session.go
  57. 6 2
      storage/storage.go
  58. 5 3
      storage/timezone.go
  59. 25 12
      storage/user.go

+ 2 - 0
.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

+ 9 - 5
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;'

+ 2 - 2
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",

+ 1 - 1
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
 

+ 3 - 3
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
 		}

+ 2 - 10
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.

+ 1 - 1
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
 	}

+ 3 - 3
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")

+ 1 - 0
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)

+ 1 - 0
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)

+ 2 - 1
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

+ 3 - 3
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

+ 5 - 4
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

+ 7 - 0
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
 

+ 8 - 7
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.

+ 2 - 2
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,

+ 10 - 6
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}
 }

+ 26 - 0
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"}
+)

+ 4 - 2
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")

+ 10 - 5
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...)}
 }

+ 7 - 4
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}
 }

+ 2 - 1
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)

+ 2 - 2
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,
 	))

+ 1 - 1
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
 

+ 1 - 1
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
 

+ 1 - 1
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
 

+ 1 - 1
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
 

+ 1 - 1
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)

+ 1 - 1
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
 

+ 1 - 0
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 {

+ 4 - 4
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

+ 4 - 4
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
 	}

+ 1 - 1
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 {

+ 4 - 2
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

+ 1 - 1
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

+ 3 - 0
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 {

+ 8 - 8
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,

+ 5 - 2
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()
 

+ 7 - 4
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
 	}

+ 6 - 2
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 {

+ 1 - 1
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
 	}

+ 1 - 1
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 {

+ 10 - 3
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

+ 3 - 2
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)
 			}
 		}

+ 6 - 2
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"),

+ 7 - 3
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"),

+ 5 - 3
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

+ 10 - 5
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"),

+ 6 - 2
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 {

+ 15 - 8
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"),

+ 3 - 1
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"`

+ 1 - 1
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
 

+ 24 - 14
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))
 

+ 11 - 4
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))
 

+ 10 - 5
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
 	}

+ 10 - 3
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
 }

+ 6 - 2
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)
 	}

+ 5 - 3
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`

+ 25 - 12
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