aboutsummaryrefslogtreecommitdiffhomepage
path: root/ui
diff options
context:
space:
mode:
authorGravatar Frédéric Guillot <fred@miniflux.net>2018-11-11 11:28:29 -0800
committerGravatar Frédéric Guillot <fred@miniflux.net>2018-11-11 11:29:12 -0800
commit5a69a61d4841a35d7ddcb761a688db8c688314d6 (patch)
treeb807ee1da5b0705e7649f70742d8198f351c1224 /ui
parent0925899cee9362cf09e982487bd480e2b09041f4 (diff)
Move UI middlewares and routes to ui package
Diffstat (limited to 'ui')
-rw-r--r--ui/about.go13
-rw-r--r--ui/bookmark_entries.go19
-rw-r--r--ui/category_create.go13
-rw-r--r--ui/category_edit.go15
-rw-r--r--ui/category_entries.go21
-rw-r--r--ui/category_list.go15
-rw-r--r--ui/category_remove.go11
-rw-r--r--ui/category_save.go19
-rw-r--r--ui/category_update.go21
-rw-r--r--ui/entry_bookmark.go25
-rw-r--r--ui/entry_category.go25
-rw-r--r--ui/entry_feed.go25
-rw-r--r--ui/entry_read.go23
-rw-r--r--ui/entry_save.go9
-rw-r--r--ui/entry_scraper.go7
-rw-r--r--ui/entry_search.go25
-rw-r--r--ui/entry_toggle_bookmark.go5
-rw-r--r--ui/entry_unread.go27
-rw-r--r--ui/entry_update_status.go5
-rw-r--r--ui/feed_edit.go17
-rw-r--r--ui/feed_entries.go21
-rw-r--r--ui/feed_icon.go5
-rw-r--r--ui/feed_list.go15
-rw-r--r--ui/feed_refresh.go16
-rw-r--r--ui/feed_remove.go7
-rw-r--r--ui/feed_update.go21
-rw-r--r--ui/handler.go (renamed from ui/controller.go)19
-rw-r--r--ui/history_entries.go19
-rw-r--r--ui/history_flush.go7
-rw-r--r--ui/integration_pocket.go32
-rw-r--r--ui/integration_show.go17
-rw-r--r--ui/integration_update.go17
-rw-r--r--ui/login_check.go21
-rw-r--r--ui/login_show.go9
-rw-r--r--ui/logout.go15
-rw-r--r--ui/middleware.go149
-rw-r--r--ui/oauth2_callback.go41
-rw-r--r--ui/oauth2_redirect.go11
-rw-r--r--ui/oauth2_unlink.go19
-rw-r--r--ui/opml_export.go5
-rw-r--r--ui/opml_import.go13
-rw-r--r--ui/opml_upload.go19
-rw-r--r--ui/pagination.go4
-rw-r--r--ui/proxy.go3
-rw-r--r--ui/search_entries.go19
-rw-r--r--ui/session_list.go15
-rw-r--r--ui/session_remove.go7
-rw-r--r--ui/settings_show.go15
-rw-r--r--ui/settings_update.go21
-rw-r--r--ui/static_app_icon.go3
-rw-r--r--ui/static_favicon.go3
-rw-r--r--ui/static_javascript.go3
-rw-r--r--ui/static_manifest.go11
-rw-r--r--ui/static_stylesheet.go3
-rw-r--r--ui/subscription_add.go15
-rw-r--r--ui/subscription_bookmarklet.go15
-rw-r--r--ui/subscription_choose.go19
-rw-r--r--ui/subscription_submit.go25
-rw-r--r--ui/ui.go133
-rw-r--r--ui/unread_entries.go19
-rw-r--r--ui/unread_mark_all_read.go7
-rw-r--r--ui/user_create.go13
-rw-r--r--ui/user_edit.go14
-rw-r--r--ui/user_list.go15
-rw-r--r--ui/user_remove.go11
-rw-r--r--ui/user_save.go19
-rw-r--r--ui/user_update.go21
67 files changed, 738 insertions, 533 deletions
diff --git a/ui/about.go b/ui/about.go
index abc39a0..5bb9f6b 100644
--- a/ui/about.go
+++ b/ui/about.go
@@ -14,22 +14,21 @@ import (
"miniflux.app/version"
)
-// About shows the about page.
-func (c *Controller) About(w http.ResponseWriter, r *http.Request) {
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) showAboutPage(w http.ResponseWriter, r *http.Request) {
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
view.Set("version", version.Version)
view.Set("build_date", version.BuildDate)
view.Set("menu", "settings")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
html.OK(w, r, view.Render("about"))
}
diff --git a/ui/bookmark_entries.go b/ui/bookmark_entries.go
index 5e6bb45..f2c36b2 100644
--- a/ui/bookmark_entries.go
+++ b/ui/bookmark_entries.go
@@ -15,16 +15,15 @@ import (
"miniflux.app/ui/view"
)
-// ShowStarredPage renders the page with all starred entries.
-func (c *Controller) ShowStarredPage(w http.ResponseWriter, r *http.Request) {
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) showStarredPage(w http.ResponseWriter, r *http.Request) {
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
offset := request.QueryIntParam(r, "offset", 0)
- builder := c.store.NewEntryQueryBuilder(user.ID)
+ builder := h.store.NewEntryQueryBuilder(user.ID)
builder.WithoutStatus(model.EntryStatusRemoved)
builder.WithStarred()
builder.WithOrder(model.DefaultSortingOrder)
@@ -44,17 +43,17 @@ func (c *Controller) ShowStarredPage(w http.ResponseWriter, r *http.Request) {
return
}
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
view.Set("total", count)
view.Set("entries", entries)
- view.Set("pagination", c.getPagination(route.Path(c.router, "starred"), count, offset))
+ view.Set("pagination", getPagination(route.Path(h.router, "starred"), count, offset))
view.Set("menu", "starred")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
- view.Set("hasSaveEntry", c.store.HasSaveEntry(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
+ view.Set("hasSaveEntry", h.store.HasSaveEntry(user.ID))
html.OK(w, r, view.Render("bookmark_entries"))
}
diff --git a/ui/category_create.go b/ui/category_create.go
index bd5039f..d8fe2cf 100644
--- a/ui/category_create.go
+++ b/ui/category_create.go
@@ -13,20 +13,19 @@ import (
"miniflux.app/ui/view"
)
-// CreateCategory shows the form to create a new category.
-func (c *Controller) CreateCategory(w http.ResponseWriter, r *http.Request) {
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) showCreateCategoryPage(w http.ResponseWriter, r *http.Request) {
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
view.Set("menu", "categories")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
html.OK(w, r, view.Render("create_category"))
}
diff --git a/ui/category_edit.go b/ui/category_edit.go
index e0375be..344cfe4 100644
--- a/ui/category_edit.go
+++ b/ui/category_edit.go
@@ -14,19 +14,18 @@ import (
"miniflux.app/ui/view"
)
-// EditCategory shows the form to modify a category.
-func (c *Controller) EditCategory(w http.ResponseWriter, r *http.Request) {
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+func (h *handler) showEditCategoryPage(w http.ResponseWriter, r *http.Request) {
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
- user, err := c.store.UserByID(request.UserID(r))
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
categoryID := request.RouteInt64Param(r, "categoryID")
- category, err := c.store.Category(request.UserID(r), categoryID)
+ category, err := h.store.Category(request.UserID(r), categoryID)
if err != nil {
html.ServerError(w, r, err)
return
@@ -45,8 +44,8 @@ func (c *Controller) EditCategory(w http.ResponseWriter, r *http.Request) {
view.Set("category", category)
view.Set("menu", "categories")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
html.OK(w, r, view.Render("edit_category"))
}
diff --git a/ui/category_entries.go b/ui/category_entries.go
index fe5f638..19b17b9 100644
--- a/ui/category_entries.go
+++ b/ui/category_entries.go
@@ -15,16 +15,15 @@ import (
"miniflux.app/ui/view"
)
-// CategoryEntries shows all entries for the given category.
-func (c *Controller) CategoryEntries(w http.ResponseWriter, r *http.Request) {
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) showCategoryEntriesPage(w http.ResponseWriter, r *http.Request) {
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
categoryID := request.RouteInt64Param(r, "categoryID")
- category, err := c.store.Category(request.UserID(r), categoryID)
+ category, err := h.store.Category(request.UserID(r), categoryID)
if err != nil {
html.ServerError(w, r, err)
return
@@ -36,7 +35,7 @@ func (c *Controller) CategoryEntries(w http.ResponseWriter, r *http.Request) {
}
offset := request.QueryIntParam(r, "offset", 0)
- builder := c.store.NewEntryQueryBuilder(user.ID)
+ builder := h.store.NewEntryQueryBuilder(user.ID)
builder.WithCategoryID(category.ID)
builder.WithOrder(model.DefaultSortingOrder)
builder.WithDirection(user.EntryDirection)
@@ -56,17 +55,17 @@ func (c *Controller) CategoryEntries(w http.ResponseWriter, r *http.Request) {
return
}
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
view.Set("category", category)
view.Set("total", count)
view.Set("entries", entries)
- view.Set("pagination", c.getPagination(route.Path(c.router, "categoryEntries", "categoryID", category.ID), count, offset))
+ view.Set("pagination", getPagination(route.Path(h.router, "categoryEntries", "categoryID", category.ID), count, offset))
view.Set("menu", "categories")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
- view.Set("hasSaveEntry", c.store.HasSaveEntry(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
+ view.Set("hasSaveEntry", h.store.HasSaveEntry(user.ID))
html.OK(w, r, view.Render("category_entries"))
}
diff --git a/ui/category_list.go b/ui/category_list.go
index f4a3651..3137b95 100644
--- a/ui/category_list.go
+++ b/ui/category_list.go
@@ -13,28 +13,27 @@ import (
"miniflux.app/ui/view"
)
-// CategoryList shows the page with all categories.
-func (c *Controller) CategoryList(w http.ResponseWriter, r *http.Request) {
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) showCategoryListPage(w http.ResponseWriter, r *http.Request) {
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
- categories, err := c.store.CategoriesWithFeedCount(user.ID)
+ categories, err := h.store.CategoriesWithFeedCount(user.ID)
if err != nil {
html.ServerError(w, r, err)
return
}
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
view.Set("categories", categories)
view.Set("total", len(categories))
view.Set("menu", "categories")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
html.OK(w, r, view.Render("categories"))
}
diff --git a/ui/category_remove.go b/ui/category_remove.go
index f8a38dc..8e616fc 100644
--- a/ui/category_remove.go
+++ b/ui/category_remove.go
@@ -12,16 +12,15 @@ import (
"miniflux.app/http/route"
)
-// RemoveCategory deletes a category from the database.
-func (c *Controller) RemoveCategory(w http.ResponseWriter, r *http.Request) {
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) removeCategory(w http.ResponseWriter, r *http.Request) {
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
categoryID := request.RouteInt64Param(r, "categoryID")
- category, err := c.store.Category(request.UserID(r), categoryID)
+ category, err := h.store.Category(request.UserID(r), categoryID)
if err != nil {
html.ServerError(w, r, err)
return
@@ -32,10 +31,10 @@ func (c *Controller) RemoveCategory(w http.ResponseWriter, r *http.Request) {
return
}
- if err := c.store.RemoveCategory(user.ID, category.ID); err != nil {
+ if err := h.store.RemoveCategory(user.ID, category.ID); err != nil {
html.ServerError(w, r, err)
return
}
- html.Redirect(w, r, route.Path(c.router, "categories"))
+ html.Redirect(w, r, route.Path(h.router, "categories"))
}
diff --git a/ui/category_save.go b/ui/category_save.go
index d115d0a..dd71528 100644
--- a/ui/category_save.go
+++ b/ui/category_save.go
@@ -17,9 +17,8 @@ import (
"miniflux.app/ui/view"
)
-// SaveCategory validate and save the new category into the database.
-func (c *Controller) SaveCategory(w http.ResponseWriter, r *http.Request) {
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) saveCategory(w http.ResponseWriter, r *http.Request) {
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
@@ -27,13 +26,13 @@ func (c *Controller) SaveCategory(w http.ResponseWriter, r *http.Request) {
categoryForm := form.NewCategoryForm(r)
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
view.Set("form", categoryForm)
view.Set("menu", "categories")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
if err := categoryForm.Validate(); err != nil {
view.Set("errorMessage", err.Error())
@@ -41,7 +40,7 @@ func (c *Controller) SaveCategory(w http.ResponseWriter, r *http.Request) {
return
}
- duplicateCategory, err := c.store.CategoryByTitle(user.ID, categoryForm.Title)
+ duplicateCategory, err := h.store.CategoryByTitle(user.ID, categoryForm.Title)
if err != nil {
html.ServerError(w, r, err)
return
@@ -58,12 +57,12 @@ func (c *Controller) SaveCategory(w http.ResponseWriter, r *http.Request) {
UserID: user.ID,
}
- if err = c.store.CreateCategory(&category); err != nil {
+ if err = h.store.CreateCategory(&category); err != nil {
logger.Error("[Controller:CreateCategory] %v", err)
view.Set("errorMessage", "error.unable_to_create_category")
html.OK(w, r, view.Render("create_category"))
return
}
- html.Redirect(w, r, route.Path(c.router, "categories"))
+ html.Redirect(w, r, route.Path(h.router, "categories"))
}
diff --git a/ui/category_update.go b/ui/category_update.go
index 6ef5648..1d20648 100644
--- a/ui/category_update.go
+++ b/ui/category_update.go
@@ -16,16 +16,15 @@ import (
"miniflux.app/ui/view"
)
-// UpdateCategory validates and updates a category.
-func (c *Controller) UpdateCategory(w http.ResponseWriter, r *http.Request) {
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) updateCategory(w http.ResponseWriter, r *http.Request) {
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
categoryID := request.RouteInt64Param(r, "categoryID")
- category, err := c.store.Category(request.UserID(r), categoryID)
+ category, err := h.store.Category(request.UserID(r), categoryID)
if err != nil {
html.ServerError(w, r, err)
return
@@ -38,14 +37,14 @@ func (c *Controller) UpdateCategory(w http.ResponseWriter, r *http.Request) {
categoryForm := form.NewCategoryForm(r)
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
view.Set("form", categoryForm)
view.Set("category", category)
view.Set("menu", "categories")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
if err := categoryForm.Validate(); err != nil {
view.Set("errorMessage", err.Error())
@@ -53,13 +52,13 @@ func (c *Controller) UpdateCategory(w http.ResponseWriter, r *http.Request) {
return
}
- if c.store.AnotherCategoryExists(user.ID, category.ID, categoryForm.Title) {
+ if h.store.AnotherCategoryExists(user.ID, category.ID, categoryForm.Title) {
view.Set("errorMessage", "error.category_already_exists")
html.OK(w, r, view.Render("edit_category"))
return
}
- err = c.store.UpdateCategory(categoryForm.Merge(category))
+ err = h.store.UpdateCategory(categoryForm.Merge(category))
if err != nil {
logger.Error("[Controller:UpdateCategory] %v", err)
view.Set("errorMessage", "error.unable_to_update_category")
@@ -67,5 +66,5 @@ func (c *Controller) UpdateCategory(w http.ResponseWriter, r *http.Request) {
return
}
- html.Redirect(w, r, route.Path(c.router, "categories"))
+ html.Redirect(w, r, route.Path(h.router, "categories"))
}
diff --git a/ui/entry_bookmark.go b/ui/entry_bookmark.go
index 895c2bc..a07859d 100644
--- a/ui/entry_bookmark.go
+++ b/ui/entry_bookmark.go
@@ -16,16 +16,15 @@ import (
"miniflux.app/ui/view"
)
-// ShowStarredEntry shows a single feed entry in "starred" mode.
-func (c *Controller) ShowStarredEntry(w http.ResponseWriter, r *http.Request) {
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) showStarredEntryPage(w http.ResponseWriter, r *http.Request) {
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
entryID := request.RouteInt64Param(r, "entryID")
- builder := c.store.NewEntryQueryBuilder(user.ID)
+ builder := h.store.NewEntryQueryBuilder(user.ID)
builder.WithEntryID(entryID)
builder.WithoutStatus(model.EntryStatusRemoved)
@@ -41,7 +40,7 @@ func (c *Controller) ShowStarredEntry(w http.ResponseWriter, r *http.Request) {
}
if entry.Status == model.EntryStatusUnread {
- err = c.store.SetEntriesStatus(user.ID, []int64{entry.ID}, model.EntryStatusRead)
+ err = h.store.SetEntriesStatus(user.ID, []int64{entry.ID}, model.EntryStatusRead)
if err != nil {
html.ServerError(w, r, err)
return
@@ -50,7 +49,7 @@ func (c *Controller) ShowStarredEntry(w http.ResponseWriter, r *http.Request) {
entry.Status = model.EntryStatusRead
}
- entryPaginationBuilder := storage.NewEntryPaginationBuilder(c.store, user.ID, entry.ID, user.EntryDirection)
+ entryPaginationBuilder := storage.NewEntryPaginationBuilder(h.store, user.ID, entry.ID, user.EntryDirection)
entryPaginationBuilder.WithStarred()
prevEntry, nextEntry, err := entryPaginationBuilder.Entries()
if err != nil {
@@ -60,16 +59,16 @@ func (c *Controller) ShowStarredEntry(w http.ResponseWriter, r *http.Request) {
nextEntryRoute := ""
if nextEntry != nil {
- nextEntryRoute = route.Path(c.router, "starredEntry", "entryID", nextEntry.ID)
+ nextEntryRoute = route.Path(h.router, "starredEntry", "entryID", nextEntry.ID)
}
prevEntryRoute := ""
if prevEntry != nil {
- prevEntryRoute = route.Path(c.router, "starredEntry", "entryID", prevEntry.ID)
+ prevEntryRoute = route.Path(h.router, "starredEntry", "entryID", prevEntry.ID)
}
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
view.Set("entry", entry)
view.Set("prevEntry", prevEntry)
view.Set("nextEntry", nextEntry)
@@ -77,9 +76,9 @@ func (c *Controller) ShowStarredEntry(w http.ResponseWriter, r *http.Request) {
view.Set("prevEntryRoute", prevEntryRoute)
view.Set("menu", "starred")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
- view.Set("hasSaveEntry", c.store.HasSaveEntry(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
+ view.Set("hasSaveEntry", h.store.HasSaveEntry(user.ID))
html.OK(w, r, view.Render("entry"))
}
diff --git a/ui/entry_category.go b/ui/entry_category.go
index d11248b..c260257 100644
--- a/ui/entry_category.go
+++ b/ui/entry_category.go
@@ -16,9 +16,8 @@ import (
"miniflux.app/ui/view"
)
-// ShowCategoryEntry shows a single feed entry in "category" mode.
-func (c *Controller) ShowCategoryEntry(w http.ResponseWriter, r *http.Request) {
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) showCategoryEntryPage(w http.ResponseWriter, r *http.Request) {
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
@@ -27,7 +26,7 @@ func (c *Controller) ShowCategoryEntry(w http.ResponseWriter, r *http.Request) {
categoryID := request.RouteInt64Param(r, "categoryID")
entryID := request.RouteInt64Param(r, "entryID")
- builder := c.store.NewEntryQueryBuilder(user.ID)
+ builder := h.store.NewEntryQueryBuilder(user.ID)
builder.WithCategoryID(categoryID)
builder.WithEntryID(entryID)
builder.WithoutStatus(model.EntryStatusRemoved)
@@ -44,7 +43,7 @@ func (c *Controller) ShowCategoryEntry(w http.ResponseWriter, r *http.Request) {
}
if entry.Status == model.EntryStatusUnread {
- err = c.store.SetEntriesStatus(user.ID, []int64{entry.ID}, model.EntryStatusRead)
+ err = h.store.SetEntriesStatus(user.ID, []int64{entry.ID}, model.EntryStatusRead)
if err != nil {
html.ServerError(w, r, err)
return
@@ -53,7 +52,7 @@ func (c *Controller) ShowCategoryEntry(w http.ResponseWriter, r *http.Request) {
entry.Status = model.EntryStatusRead
}
- entryPaginationBuilder := storage.NewEntryPaginationBuilder(c.store, user.ID, entry.ID, user.EntryDirection)
+ entryPaginationBuilder := storage.NewEntryPaginationBuilder(h.store, user.ID, entry.ID, user.EntryDirection)
entryPaginationBuilder.WithCategoryID(categoryID)
prevEntry, nextEntry, err := entryPaginationBuilder.Entries()
if err != nil {
@@ -63,16 +62,16 @@ func (c *Controller) ShowCategoryEntry(w http.ResponseWriter, r *http.Request) {
nextEntryRoute := ""
if nextEntry != nil {
- nextEntryRoute = route.Path(c.router, "categoryEntry", "categoryID", categoryID, "entryID", nextEntry.ID)
+ nextEntryRoute = route.Path(h.router, "categoryEntry", "categoryID", categoryID, "entryID", nextEntry.ID)
}
prevEntryRoute := ""
if prevEntry != nil {
- prevEntryRoute = route.Path(c.router, "categoryEntry", "categoryID", categoryID, "entryID", prevEntry.ID)
+ prevEntryRoute = route.Path(h.router, "categoryEntry", "categoryID", categoryID, "entryID", prevEntry.ID)
}
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
view.Set("entry", entry)
view.Set("prevEntry", prevEntry)
view.Set("nextEntry", nextEntry)
@@ -80,9 +79,9 @@ func (c *Controller) ShowCategoryEntry(w http.ResponseWriter, r *http.Request) {
view.Set("prevEntryRoute", prevEntryRoute)
view.Set("menu", "categories")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
- view.Set("hasSaveEntry", c.store.HasSaveEntry(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
+ view.Set("hasSaveEntry", h.store.HasSaveEntry(user.ID))
html.OK(w, r, view.Render("entry"))
}
diff --git a/ui/entry_feed.go b/ui/entry_feed.go
index 9c28c67..e4ea585 100644
--- a/ui/entry_feed.go
+++ b/ui/entry_feed.go
@@ -16,9 +16,8 @@ import (
"miniflux.app/ui/view"
)
-// ShowFeedEntry shows a single feed entry in "feed" mode.
-func (c *Controller) ShowFeedEntry(w http.ResponseWriter, r *http.Request) {
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) showFeedEntryPage(w http.ResponseWriter, r *http.Request) {
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
@@ -27,7 +26,7 @@ func (c *Controller) ShowFeedEntry(w http.ResponseWriter, r *http.Request) {
entryID := request.RouteInt64Param(r, "entryID")
feedID := request.RouteInt64Param(r, "feedID")
- builder := c.store.NewEntryQueryBuilder(user.ID)
+ builder := h.store.NewEntryQueryBuilder(user.ID)
builder.WithFeedID(feedID)
builder.WithEntryID(entryID)
builder.WithoutStatus(model.EntryStatusRemoved)
@@ -44,7 +43,7 @@ func (c *Controller) ShowFeedEntry(w http.ResponseWriter, r *http.Request) {
}
if entry.Status == model.EntryStatusUnread {
- err = c.store.SetEntriesStatus(user.ID, []int64{entry.ID}, model.EntryStatusRead)
+ err = h.store.SetEntriesStatus(user.ID, []int64{entry.ID}, model.EntryStatusRead)
if err != nil {
html.ServerError(w, r, err)
return
@@ -53,7 +52,7 @@ func (c *Controller) ShowFeedEntry(w http.ResponseWriter, r *http.Request) {
entry.Status = model.EntryStatusRead
}
- entryPaginationBuilder := storage.NewEntryPaginationBuilder(c.store, user.ID, entry.ID, user.EntryDirection)
+ entryPaginationBuilder := storage.NewEntryPaginationBuilder(h.store, user.ID, entry.ID, user.EntryDirection)
entryPaginationBuilder.WithFeedID(feedID)
prevEntry, nextEntry, err := entryPaginationBuilder.Entries()
if err != nil {
@@ -63,16 +62,16 @@ func (c *Controller) ShowFeedEntry(w http.ResponseWriter, r *http.Request) {
nextEntryRoute := ""
if nextEntry != nil {
- nextEntryRoute = route.Path(c.router, "feedEntry", "feedID", feedID, "entryID", nextEntry.ID)
+ nextEntryRoute = route.Path(h.router, "feedEntry", "feedID", feedID, "entryID", nextEntry.ID)
}
prevEntryRoute := ""
if prevEntry != nil {
- prevEntryRoute = route.Path(c.router, "feedEntry", "feedID", feedID, "entryID", prevEntry.ID)
+ prevEntryRoute = route.Path(h.router, "feedEntry", "feedID", feedID, "entryID", prevEntry.ID)
}
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
view.Set("entry", entry)
view.Set("prevEntry", prevEntry)
view.Set("nextEntry", nextEntry)
@@ -80,9 +79,9 @@ func (c *Controller) ShowFeedEntry(w http.ResponseWriter, r *http.Request) {
view.Set("prevEntryRoute", prevEntryRoute)
view.Set("menu", "feeds")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
- view.Set("hasSaveEntry", c.store.HasSaveEntry(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
+ view.Set("hasSaveEntry", h.store.HasSaveEntry(user.ID))
html.OK(w, r, view.Render("entry"))
}
diff --git a/ui/entry_read.go b/ui/entry_read.go
index 208ae3b..df79d44 100644
--- a/ui/entry_read.go
+++ b/ui/entry_read.go
@@ -16,16 +16,15 @@ import (
"miniflux.app/ui/view"
)
-// ShowReadEntry shows a single feed entry in "history" mode.
-func (c *Controller) ShowReadEntry(w http.ResponseWriter, r *http.Request) {
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) showReadEntryPage(w http.ResponseWriter, r *http.Request) {
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
entryID := request.RouteInt64Param(r, "entryID")
- builder := c.store.NewEntryQueryBuilder(user.ID)
+ builder := h.store.NewEntryQueryBuilder(user.ID)
builder.WithEntryID(entryID)
builder.WithoutStatus(model.EntryStatusRemoved)
@@ -40,7 +39,7 @@ func (c *Controller) ShowReadEntry(w http.ResponseWriter, r *http.Request) {
return
}
- entryPaginationBuilder := storage.NewEntryPaginationBuilder(c.store, user.ID, entry.ID, user.EntryDirection)
+ entryPaginationBuilder := storage.NewEntryPaginationBuilder(h.store, user.ID, entry.ID, user.EntryDirection)
entryPaginationBuilder.WithStatus(model.EntryStatusRead)
prevEntry, nextEntry, err := entryPaginationBuilder.Entries()
if err != nil {
@@ -50,16 +49,16 @@ func (c *Controller) ShowReadEntry(w http.ResponseWriter, r *http.Request) {
nextEntryRoute := ""
if nextEntry != nil {
- nextEntryRoute = route.Path(c.router, "readEntry", "entryID", nextEntry.ID)
+ nextEntryRoute = route.Path(h.router, "readEntry", "entryID", nextEntry.ID)
}
prevEntryRoute := ""
if prevEntry != nil {
- prevEntryRoute = route.Path(c.router, "readEntry", "entryID", prevEntry.ID)
+ prevEntryRoute = route.Path(h.router, "readEntry", "entryID", prevEntry.ID)
}
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
view.Set("entry", entry)
view.Set("prevEntry", prevEntry)
view.Set("nextEntry", nextEntry)
@@ -67,9 +66,9 @@ func (c *Controller) ShowReadEntry(w http.ResponseWriter, r *http.Request) {
view.Set("prevEntryRoute", prevEntryRoute)
view.Set("menu", "history")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
- view.Set("hasSaveEntry", c.store.HasSaveEntry(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
+ view.Set("hasSaveEntry", h.store.HasSaveEntry(user.ID))
html.OK(w, r, view.Render("entry"))
}
diff --git a/ui/entry_save.go b/ui/entry_save.go
index 93910c0..86d5b4d 100644
--- a/ui/entry_save.go
+++ b/ui/entry_save.go
@@ -13,10 +13,9 @@ import (
"miniflux.app/model"
)
-// SaveEntry send the link to external services.
-func (c *Controller) SaveEntry(w http.ResponseWriter, r *http.Request) {
+func (h *handler) saveEntry(w http.ResponseWriter, r *http.Request) {
entryID := request.RouteInt64Param(r, "entryID")
- builder := c.store.NewEntryQueryBuilder(request.UserID(r))
+ builder := h.store.NewEntryQueryBuilder(request.UserID(r))
builder.WithEntryID(entryID)
builder.WithoutStatus(model.EntryStatusRemoved)
@@ -31,14 +30,14 @@ func (c *Controller) SaveEntry(w http.ResponseWriter, r *http.Request) {
return
}
- settings, err := c.store.Integration(request.UserID(r))
+ settings, err := h.store.Integration(request.UserID(r))
if err != nil {
json.ServerError(w, r, err)
return
}
go func() {
- integration.SendEntry(c.cfg, entry, settings)
+ integration.SendEntry(h.cfg, entry, settings)
}()
json.Created(w, r, map[string]string{"message": "saved"})
diff --git a/ui/entry_scraper.go b/ui/entry_scraper.go
index c35d949..519bfd2 100644
--- a/ui/entry_scraper.go
+++ b/ui/entry_scraper.go
@@ -14,10 +14,9 @@ import (
"miniflux.app/reader/scraper"
)
-// FetchContent downloads the original HTML page and returns relevant contents.
-func (c *Controller) FetchContent(w http.ResponseWriter, r *http.Request) {
+func (h *handler) fetchContent(w http.ResponseWriter, r *http.Request) {
entryID := request.RouteInt64Param(r, "entryID")
- builder := c.store.NewEntryQueryBuilder(request.UserID(r))
+ builder := h.store.NewEntryQueryBuilder(request.UserID(r))
builder.WithEntryID(entryID)
builder.WithoutStatus(model.EntryStatusRemoved)
@@ -39,7 +38,7 @@ func (c *Controller) FetchContent(w http.ResponseWriter, r *http.Request) {
}
entry.Content = sanitizer.Sanitize(entry.URL, content)
- c.store.UpdateEntryContent(entry)
+ h.store.UpdateEntryContent(entry)
json.OK(w, r, map[string]string{"content": entry.Content})
}
diff --git a/ui/entry_search.go b/ui/entry_search.go
index d083b35..252b306 100644
--- a/ui/entry_search.go
+++ b/ui/entry_search.go
@@ -17,9 +17,8 @@ import (
"miniflux.app/ui/view"
)
-// ShowSearchEntry shows a single entry in "search" mode.
-func (c *Controller) ShowSearchEntry(w http.ResponseWriter, r *http.Request) {
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) showSearchEntryPage(w http.ResponseWriter, r *http.Request) {
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
@@ -27,7 +26,7 @@ func (c *Controller) ShowSearchEntry(w http.ResponseWriter, r *http.Request) {
entryID := request.RouteInt64Param(r, "entryID")
searchQuery := request.QueryStringParam(r, "q", "")
- builder := c.store.NewEntryQueryBuilder(user.ID)
+ builder := h.store.NewEntryQueryBuilder(user.ID)
builder.WithSearchQuery(searchQuery)
builder.WithEntryID(entryID)
builder.WithoutStatus(model.EntryStatusRemoved)
@@ -44,7 +43,7 @@ func (c *Controller) ShowSearchEntry(w http.ResponseWriter, r *http.Request) {
}
if entry.Status == model.EntryStatusUnread {
- err = c.store.SetEntriesStatus(user.ID, []int64{entry.ID}, model.EntryStatusRead)
+ err = h.store.SetEntriesStatus(user.ID, []int64{entry.ID}, model.EntryStatusRead)
if err != nil {
logger.Error("[Controller:ShowSearchEntry] %v", err)
html.ServerError(w, r, err)
@@ -54,7 +53,7 @@ func (c *Controller) ShowSearchEntry(w http.ResponseWriter, r *http.Request) {
entry.Status = model.EntryStatusRead
}
- entryPaginationBuilder := storage.NewEntryPaginationBuilder(c.store, user.ID, entry.ID, user.EntryDirection)
+ entryPaginationBuilder := storage.NewEntryPaginationBuilder(h.store, user.ID, entry.ID, user.EntryDirection)
entryPaginationBuilder.WithSearchQuery(searchQuery)
prevEntry, nextEntry, err := entryPaginationBuilder.Entries()
if err != nil {
@@ -64,16 +63,16 @@ func (c *Controller) ShowSearchEntry(w http.ResponseWriter, r *http.Request) {
nextEntryRoute := ""
if nextEntry != nil {
- nextEntryRoute = route.Path(c.router, "searchEntry", "entryID", nextEntry.ID)
+ nextEntryRoute = route.Path(h.router, "searchEntry", "entryID", nextEntry.ID)
}
prevEntryRoute := ""
if prevEntry != nil {
- prevEntryRoute = route.Path(c.router, "searchEntry", "entryID", prevEntry.ID)
+ prevEntryRoute = route.Path(h.router, "searchEntry", "entryID", prevEntry.ID)
}
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
view.Set("searchQuery", searchQuery)
view.Set("entry", entry)
view.Set("prevEntry", prevEntry)
@@ -82,9 +81,9 @@ func (c *Controller) ShowSearchEntry(w http.ResponseWriter, r *http.Request) {
view.Set("prevEntryRoute", prevEntryRoute)
view.Set("menu", "search")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
- view.Set("hasSaveEntry", c.store.HasSaveEntry(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
+ view.Set("hasSaveEntry", h.store.HasSaveEntry(user.ID))
html.OK(w, r, view.Render("entry"))
}
diff --git a/ui/entry_toggle_bookmark.go b/ui/entry_toggle_bookmark.go
index 9f7a3e7..3e638a1 100644
--- a/ui/entry_toggle_bookmark.go
+++ b/ui/entry_toggle_bookmark.go
@@ -11,10 +11,9 @@ import (
"miniflux.app/http/response/json"
)
-// ToggleBookmark handles Ajax request to toggle bookmark value.
-func (c *Controller) ToggleBookmark(w http.ResponseWriter, r *http.Request) {
+func (h *handler) toggleBookmark(w http.ResponseWriter, r *http.Request) {
entryID := request.RouteInt64Param(r, "entryID")
- if err := c.store.ToggleBookmark(request.UserID(r), entryID); err != nil {
+ if err := h.store.ToggleBookmark(request.UserID(r), entryID); err != nil {
json.ServerError(w, r, err)
return
}
diff --git a/ui/entry_unread.go b/ui/entry_unread.go
index 37e9592..fb8d45c 100644
--- a/ui/entry_unread.go
+++ b/ui/entry_unread.go
@@ -16,16 +16,15 @@ import (
"miniflux.app/ui/view"
)
-// ShowUnreadEntry shows a single feed entry in "unread" mode.
-func (c *Controller) ShowUnreadEntry(w http.ResponseWriter, r *http.Request) {
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) showUnreadEntryPage(w http.ResponseWriter, r *http.Request) {
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
entryID := request.RouteInt64Param(r, "entryID")
- builder := c.store.NewEntryQueryBuilder(user.ID)
+ builder := h.store.NewEntryQueryBuilder(user.ID)
builder.WithEntryID(entryID)
builder.WithoutStatus(model.EntryStatusRemoved)
@@ -42,14 +41,14 @@ func (c *Controller) ShowUnreadEntry(w http.ResponseWriter, r *http.Request) {
// Make sure we always get the pagination in unread mode even if the page is refreshed.
if entry.Status == model.EntryStatusRead {
- err = c.store.SetEntriesStatus(user.ID, []int64{entry.ID}, model.EntryStatusUnread)
+ err = h.store.SetEntriesStatus(user.ID, []int64{entry.ID}, model.EntryStatusUnread)
if err != nil {
html.ServerError(w, r, err)
return
}
}
- entryPaginationBuilder := storage.NewEntryPaginationBuilder(c.store, user.ID, entry.ID, user.EntryDirection)
+ entryPaginationBuilder := storage.NewEntryPaginationBuilder(h.store, user.ID, entry.ID, user.EntryDirection)
entryPaginationBuilder.WithStatus(model.EntryStatusUnread)
prevEntry, nextEntry, err := entryPaginationBuilder.Entries()
if err != nil {
@@ -59,24 +58,24 @@ func (c *Controller) ShowUnreadEntry(w http.ResponseWriter, r *http.Request) {
nextEntryRoute := ""
if nextEntry != nil {
- nextEntryRoute = route.Path(c.router, "unreadEntry", "entryID", nextEntry.ID)
+ nextEntryRoute = route.Path(h.router, "unreadEntry", "entryID", nextEntry.ID)
}
prevEntryRoute := ""
if prevEntry != nil {
- prevEntryRoute = route.Path(c.router, "unreadEntry", "entryID", prevEntry.ID)
+ prevEntryRoute = route.Path(h.router, "unreadEntry", "entryID", prevEntry.ID)
}
// Always mark the entry as read after fetching the pagination.
- err = c.store.SetEntriesStatus(user.ID, []int64{entry.ID}, model.EntryStatusRead)
+ err = h.store.SetEntriesStatus(user.ID, []int64{entry.ID}, model.EntryStatusRead)
if err != nil {
html.ServerError(w, r, err)
return
}
entry.Status = model.EntryStatusRead
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
view.Set("entry", entry)
view.Set("prevEntry", prevEntry)
view.Set("nextEntry", nextEntry)
@@ -84,11 +83,11 @@ func (c *Controller) ShowUnreadEntry(w http.ResponseWriter, r *http.Request) {
view.Set("prevEntryRoute", prevEntryRoute)
view.Set("menu", "unread")
view.Set("user", user)
- view.Set("hasSaveEntry", c.store.HasSaveEntry(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
+ view.Set("hasSaveEntry", h.store.HasSaveEntry(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
// Fetching the counter here avoid to be off by one.
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
html.OK(w, r, view.Render("entry"))
}
diff --git a/ui/entry_update_status.go b/ui/entry_update_status.go
index 6c5cb12..ac1c284 100644
--- a/ui/entry_update_status.go
+++ b/ui/entry_update_status.go
@@ -12,8 +12,7 @@ import (
"miniflux.app/http/response/json"
)
-// UpdateEntriesStatus updates the status for a list of entries.
-func (c *Controller) UpdateEntriesStatus(w http.ResponseWriter, r *http.Request) {
+func (h *handler) updateEntriesStatus(w http.ResponseWriter, r *http.Request) {
entryIDs, status, err := decodeEntryStatusPayload(r.Body)
if err != nil {
json.BadRequest(w, r, err)
@@ -25,7 +24,7 @@ func (c *Controller) UpdateEntriesStatus(w http.ResponseWriter, r *http.Request)
return
}
- err = c.store.SetEntriesStatus(request.UserID(r), entryIDs, status)
+ err = h.store.SetEntriesStatus(request.UserID(r), entryIDs, status)
if err != nil {
json.ServerError(w, r, err)
return
diff --git a/ui/feed_edit.go b/ui/feed_edit.go
index 330817b..a195613 100644
--- a/ui/feed_edit.go
+++ b/ui/feed_edit.go
@@ -15,16 +15,15 @@ import (
"miniflux.app/ui/view"
)
-// EditFeed shows the form to modify a subscription.
-func (c *Controller) EditFeed(w http.ResponseWriter, r *http.Request) {
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) showEditFeedPage(w http.ResponseWriter, r *http.Request) {
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
feedID := request.RouteInt64Param(r, "feedID")
- feed, err := c.store.FeedByID(user.ID, feedID)
+ feed, err := h.store.FeedByID(user.ID, feedID)
if err != nil {
html.ServerError(w, r, err)
return
@@ -35,7 +34,7 @@ func (c *Controller) EditFeed(w http.ResponseWriter, r *http.Request) {
return
}
- categories, err := c.store.Categories(user.ID)
+ categories, err := h.store.Categories(user.ID)
if err != nil {
html.ServerError(w, r, err)
return
@@ -54,15 +53,15 @@ func (c *Controller) EditFeed(w http.ResponseWriter, r *http.Request) {
Password: feed.Password,
}
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
view.Set("form", feedForm)
view.Set("categories", categories)
view.Set("feed", feed)
view.Set("menu", "feeds")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
view.Set("defaultUserAgent", client.DefaultUserAgent)
html.OK(w, r, view.Render("edit_feed"))
diff --git a/ui/feed_entries.go b/ui/feed_entries.go
index 685b5c1..46fec9a 100644
--- a/ui/feed_entries.go
+++ b/ui/feed_entries.go
@@ -15,16 +15,15 @@ import (
"miniflux.app/ui/view"
)
-// ShowFeedEntries shows all entries for the given feed.
-func (c *Controller) ShowFeedEntries(w http.ResponseWriter, r *http.Request) {
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) showFeedEntriesPage(w http.ResponseWriter, r *http.Request) {
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
feedID := request.RouteInt64Param(r, "feedID")
- feed, err := c.store.FeedByID(user.ID, feedID)
+ feed, err := h.store.FeedByID(user.ID, feedID)
if err != nil {
html.ServerError(w, r, err)
return
@@ -36,7 +35,7 @@ func (c *Controller) ShowFeedEntries(w http.ResponseWriter, r *http.Request) {
}
offset := request.QueryIntParam(r, "offset", 0)
- builder := c.store.NewEntryQueryBuilder(user.ID)
+ builder := h.store.NewEntryQueryBuilder(user.ID)
builder.WithFeedID(feed.ID)
builder.WithoutStatus(model.EntryStatusRemoved)
builder.WithOrder(model.DefaultSortingOrder)
@@ -56,17 +55,17 @@ func (c *Controller) ShowFeedEntries(w http.ResponseWriter, r *http.Request) {
return
}
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
view.Set("feed", feed)
view.Set("entries", entries)
view.Set("total", count)
- view.Set("pagination", c.getPagination(route.Path(c.router, "feedEntries", "feedID", feed.ID), count, offset))
+ view.Set("pagination", getPagination(route.Path(h.router, "feedEntries", "feedID", feed.ID), count, offset))
view.Set("menu", "feeds")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
- view.Set("hasSaveEntry", c.store.HasSaveEntry(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
+ view.Set("hasSaveEntry", h.store.HasSaveEntry(user.ID))
html.OK(w, r, view.Render("feed_entries"))
}
diff --git a/ui/feed_icon.go b/ui/feed_icon.go
index 63aa050..4b5f30f 100644
--- a/ui/feed_icon.go
+++ b/ui/feed_icon.go
@@ -13,10 +13,9 @@ import (
"miniflux.app/http/response/html"
)
-// ShowIcon shows the feed icon.
-func (c *Controller) ShowIcon(w http.ResponseWriter, r *http.Request) {
+func (h *handler) showIcon(w http.ResponseWriter, r *http.Request) {
iconID := request.RouteInt64Param(r, "iconID")
- icon, err := c.store.IconByID(iconID)
+ icon, err := h.store.IconByID(iconID)
if err != nil {
html.ServerError(w, r, err)
return
diff --git a/ui/feed_list.go b/ui/feed_list.go
index ac5a97c..0c2c546 100644
--- a/ui/feed_list.go
+++ b/ui/feed_list.go
@@ -13,28 +13,27 @@ import (
"miniflux.app/ui/view"
)
-// ShowFeedsPage shows the page with all subscriptions.
-func (c *Controller) ShowFeedsPage(w http.ResponseWriter, r *http.Request) {
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) showFeedsPage(w http.ResponseWriter, r *http.Request) {
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
- feeds, err := c.store.Feeds(user.ID)
+ feeds, err := h.store.Feeds(user.ID)
if err != nil {
html.ServerError(w, r, err)
return
}
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
view.Set("feeds", feeds)
view.Set("total", len(feeds))
view.Set("menu", "feeds")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
html.OK(w, r, view.Render("feeds"))
}
diff --git a/ui/feed_refresh.go b/ui/feed_refresh.go
index 0da4eb8..1b9dc3c 100644
--- a/ui/feed_refresh.go
+++ b/ui/feed_refresh.go
@@ -13,28 +13,26 @@ import (
"miniflux.app/logger"
)
-// RefreshFeed refresh a subscription and redirect to the feed entries page.
-func (c *Controller) RefreshFeed(w http.ResponseWriter, r *http.Request) {
+func (h *handler) refreshFeed(w http.ResponseWriter, r *http.Request) {
feedID := request.RouteInt64Param(r, "feedID")
- if err := c.feedHandler.RefreshFeed(request.UserID(r), feedID); err != nil {
+ if err := h.feedHandler.RefreshFeed(request.UserID(r), feedID); err != nil {
logger.Error("[Controller:RefreshFeed] %v", err)
}
- html.Redirect(w, r, route.Path(c.router, "feedEntries", "feedID", feedID))
+ html.Redirect(w, r, route.Path(h.router, "feedEntries", "feedID", feedID))
}
-// RefreshAllFeeds refresh all feeds in the background for the current user.
-func (c *Controller) RefreshAllFeeds(w http.ResponseWriter, r *http.Request) {
+func (h *handler) refreshAllFeeds(w http.ResponseWriter, r *http.Request) {
userID := request.UserID(r)
- jobs, err := c.store.NewUserBatch(userID, c.store.CountFeeds(userID))
+ jobs, err := h.store.NewUserBatch(userID, h.store.CountFeeds(userID))
if err != nil {
html.ServerError(w, r, err)
return
}
go func() {
- c.pool.Push(jobs)
+ h.pool.Push(jobs)
}()
- html.Redirect(w, r, route.Path(c.router, "feeds"))
+ html.Redirect(w, r, route.Path(h.router, "feeds"))
}
diff --git a/ui/feed_remove.go b/ui/feed_remove.go
index 41fc5b0..c70d77a 100644
--- a/ui/feed_remove.go
+++ b/ui/feed_remove.go
@@ -12,13 +12,12 @@ import (
"miniflux.app/http/route"
)
-// RemoveFeed deletes a subscription from the database and redirect to the list of feeds page.
-func (c *Controller) RemoveFeed(w http.ResponseWriter, r *http.Request) {
+func (h *handler) removeFeed(w http.ResponseWriter, r *http.Request) {
feedID := request.RouteInt64Param(r, "feedID")
- if err := c.store.RemoveFeed(request.UserID(r), feedID); err != nil {
+ if err := h.store.RemoveFeed(request.UserID(r), feedID); err != nil {
html.ServerError(w, r, err)
return
}
- html.Redirect(w, r, route.Path(c.router, "feeds"))
+ html.Redirect(w, r, route.Path(h.router, "feeds"))
}
diff --git a/ui/feed_update.go b/ui/feed_update.go
index 66b6d40..936fd1f 100644
--- a/ui/feed_update.go
+++ b/ui/feed_update.go
@@ -17,16 +17,15 @@ import (
"miniflux.app/ui/view"
)
-// UpdateFeed update a subscription and redirect to the feed entries page.
-func (c *Controller) UpdateFeed(w http.ResponseWriter, r *http.Request) {
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) updateFeed(w http.ResponseWriter, r *http.Request) {
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
feedID := request.RouteInt64Param(r, "feedID")
- feed, err := c.store.FeedByID(user.ID, feedID)
+ feed, err := h.store.FeedByID(user.ID, feedID)
if err != nil {
html.ServerError(w, r, err)
return
@@ -37,7 +36,7 @@ func (c *Controller) UpdateFeed(w http.ResponseWriter, r *http.Request) {
return
}
- categories, err := c.store.Categories(user.ID)
+ categories, err := h.store.Categories(user.ID)
if err != nil {
html.ServerError(w, r, err)
return
@@ -45,15 +44,15 @@ func (c *Controller) UpdateFeed(w http.ResponseWriter, r *http.Request) {
feedForm := form.NewFeedForm(r)
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
view.Set("form", feedForm)
view.Set("categories", categories)
view.Set("feed", feed)
view.Set("menu", "feeds")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
view.Set("defaultUserAgent", client.DefaultUserAgent)
if err := feedForm.ValidateModification(); err != nil {
@@ -62,7 +61,7 @@ func (c *Controller) UpdateFeed(w http.ResponseWriter, r *http.Request) {
return
}
- err = c.store.UpdateFeed(feedForm.Merge(feed))
+ err = h.store.UpdateFeed(feedForm.Merge(feed))
if err != nil {
logger.Error("[Controller:EditFeed] %v", err)
view.Set("errorMessage", "error.unable_to_update_feed")
@@ -70,5 +69,5 @@ func (c *Controller) UpdateFeed(w http.ResponseWriter, r *http.Request) {
return
}
- html.Redirect(w, r, route.Path(c.router, "feedEntries", "feedID", feed.ID))
+ html.Redirect(w, r, route.Path(h.router, "feedEntries", "feedID", feed.ID))
}
diff --git a/ui/controller.go b/ui/handler.go
index b08c253..39fe560 100644
--- a/ui/controller.go
+++ b/ui/handler.go
@@ -14,24 +14,11 @@ import (
"github.com/gorilla/mux"
)
-// Controller contains all HTTP handlers for the user interface.
-type Controller struct {
+type handler struct {
+ router *mux.Router
cfg *config.Config
store *storage.Storage
+ tpl *template.Engine
pool *scheduler.WorkerPool
feedHandler *feed.Handler
- tpl *template.Engine
- router *mux.Router
-}
-
-// NewController returns a new Controller.
-func NewController(cfg *config.Config, store *storage.Storage, pool *scheduler.WorkerPool, feedHandler *feed.Handler, tpl *template.Engine, router *mux.Router) *Controller {
- return &Controller{
- cfg: cfg,
- store: store,
- pool: pool,
- feedHandler: feedHandler,
- tpl: tpl,
- router: router,
- }
}
diff --git a/ui/history_entries.go b/ui/history_entries.go
index 8449240..131879c 100644
--- a/ui/history_entries.go
+++ b/ui/history_entries.go
@@ -15,16 +15,15 @@ import (
"miniflux.app/ui/view"
)
-// ShowHistoryPage renders the page with all read entries.
-func (c *Controller) ShowHistoryPage(w http.ResponseWriter, r *http.Request) {
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) showHistoryPage(w http.ResponseWriter, r *http.Request) {
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
offset := request.QueryIntParam(r, "offset", 0)
- builder := c.store.NewEntryQueryBuilder(user.ID)
+ builder := h.store.NewEntryQueryBuilder(user.ID)
builder.WithStatus(model.EntryStatusRead)
builder.WithOrder(model.DefaultSortingOrder)
builder.WithDirection(user.EntryDirection)
@@ -43,16 +42,16 @@ func (c *Controller) ShowHistoryPage(w http.ResponseWriter, r *http.Request) {
return
}
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
view.Set("entries", entries)
view.Set("total", count)
- view.Set("pagination", c.getPagination(route.Path(c.router, "history"), count, offset))
+ view.Set("pagination", getPagination(route.Path(h.router, "history"), count, offset))
view.Set("menu", "history")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
- view.Set("hasSaveEntry", c.store.HasSaveEntry(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
+ view.Set("hasSaveEntry", h.store.HasSaveEntry(user.ID))
html.OK(w, r, view.Render("history_entries"))
}
diff --git a/ui/history_flush.go b/ui/history_flush.go
index 6c6907b..d0b8f62 100644
--- a/ui/history_flush.go
+++ b/ui/history_flush.go
@@ -12,13 +12,12 @@ import (
"miniflux.app/http/route"
)
-// FlushHistory changes all "read" items to "removed".
-func (c *Controller) FlushHistory(w http.ResponseWriter, r *http.Request) {
- err := c.store.FlushHistory(request.UserID(r))
+func (h *handler) flushHistory(w http.ResponseWriter, r *http.Request) {
+ err := h.store.FlushHistory(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
- html.Redirect(w, r, route.Path(c.router, "history"))
+ html.Redirect(w, r, route.Path(h.router, "history"))
}
diff --git a/ui/integration_pocket.go b/ui/integration_pocket.go
index 47a975c..8f8c680 100644
--- a/ui/integration_pocket.go
+++ b/ui/integration_pocket.go
@@ -16,29 +16,28 @@ import (
"miniflux.app/ui/session"
)
-// PocketAuthorize redirects the end-user to Pocket website to authorize the application.
-func (c *Controller) PocketAuthorize(w http.ResponseWriter, r *http.Request) {
+func (h *handler) pocketAuthorize(w http.ResponseWriter, r *http.Request) {
printer := locale.NewPrinter(request.UserLanguage(r))
- user, err := c.store.UserByID(request.UserID(r))
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
- integration, err := c.store.Integration(user.ID)
+ integration, err := h.store.Integration(user.ID)
if err != nil {
html.ServerError(w, r, err)
return
}
- sess := session.New(c.store, request.SessionID(r))
- connector := pocket.NewConnector(c.cfg.PocketConsumerKey(integration.PocketConsumerKey))
- redirectURL := c.cfg.BaseURL() + route.Path(c.router, "pocketCallback")
+ sess := session.New(h.store, request.SessionID(r))
+ connector := pocket.NewConnector(h.cfg.PocketConsumerKey(integration.PocketConsumerKey))
+ redirectURL := h.cfg.BaseURL() + route.Path(h.router, "pocketCallback")
requestToken, err := connector.RequestToken(redirectURL)
if err != nil {
logger.Error("[Pocket:Authorize] %v", err)
sess.NewFlashErrorMessage(printer.Printf("error.pocket_request_token"))
- html.Redirect(w, r, route.Path(c.router, "integrations"))
+ html.Redirect(w, r, route.Path(h.router, "integrations"))
return
}
@@ -46,41 +45,40 @@ func (c *Controller) PocketAuthorize(w http.ResponseWriter, r *http.Request) {
html.Redirect(w, r, connector.AuthorizationURL(requestToken, redirectURL))
}
-// PocketCallback saves the personal access token after the authorization step.
-func (c *Controller) PocketCallback(w http.ResponseWriter, r *http.Request) {
+func (h *handler) pocketCallback(w http.ResponseWriter, r *http.Request) {
printer := locale.NewPrinter(request.UserLanguage(r))
- sess := session.New(c.store, request.SessionID(r))
+ sess := session.New(h.store, request.SessionID(r))
- user, err := c.store.UserByID(request.UserID(r))
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
- integration, err := c.store.Integration(user.ID)
+ integration, err := h.store.Integration(user.ID)
if err != nil {
html.ServerError(w, r, err)
return
}
- connector := pocket.NewConnector(c.cfg.PocketConsumerKey(integration.PocketConsumerKey))
+ connector := pocket.NewConnector(h.cfg.PocketConsumerKey(integration.PocketConsumerKey))
accessToken, err := connector.AccessToken(request.PocketRequestToken(r))
if err != nil {
logger.Error("[Pocket:Callback] %v", err)
sess.NewFlashErrorMessage(printer.Printf("error.pocket_access_token"))
- html.Redirect(w, r, route.Path(c.router, "integrations"))
+ html.Redirect(w, r, route.Path(h.router, "integrations"))
return
}
sess.SetPocketRequestToken("")
integration.PocketAccessToken = accessToken
- err = c.store.UpdateIntegration(integration)
+ err = h.store.UpdateIntegration(integration)
if err != nil {
html.ServerError(w, r, err)
return
}
sess.NewFlashMessage(printer.Printf("alert.pocket_linked"))
- html.Redirect(w, r, route.Path(c.router, "integrations"))
+ html.Redirect(w, r, route.Path(h.router, "integrations"))
}
diff --git a/ui/integration_show.go b/ui/integration_show.go
index 3cea830..c7f2740 100644
--- a/ui/integration_show.go
+++ b/ui/integration_show.go
@@ -14,15 +14,14 @@ import (
"miniflux.app/ui/view"
)
-// ShowIntegrations renders the page with all external integrations.
-func (c *Controller) ShowIntegrations(w http.ResponseWriter, r *http.Request) {
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) showIntegrationPage(w http.ResponseWriter, r *http.Request) {
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
- integration, err := c.store.Integration(user.ID)
+ integration, err := h.store.Integration(user.ID)
if err != nil {
html.ServerError(w, r, err)
return
@@ -53,14 +52,14 @@ func (c *Controller) ShowIntegrations(w http.ResponseWriter, r *http.Request) {
PocketConsumerKey: integration.PocketConsumerKey,
}
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
view.Set("form", integrationForm)
view.Set("menu", "settings")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
- view.Set("hasPocketConsumerKeyConfigured", c.cfg.PocketConsumerKey("") != "")
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
+ view.Set("hasPocketConsumerKeyConfigured", h.cfg.PocketConsumerKey("") != "")
html.OK(w, r, view.Render("integrations"))
}
diff --git a/ui/integration_update.go b/ui/integration_update.go
index 5661daf..16fdb0f 100644
--- a/ui/integration_update.go
+++ b/ui/integration_update.go
@@ -17,17 +17,16 @@ import (
"miniflux.app/ui/session"
)
-// UpdateIntegration updates integration settings.
-func (c *Controller) UpdateIntegration(w http.ResponseWriter, r *http.Request) {
+func (h *handler) updateIntegration(w http.ResponseWriter, r *http.Request) {
printer := locale.NewPrinter(request.UserLanguage(r))
- sess := session.New(c.store, request.SessionID(r))
- user, err := c.store.UserByID(request.UserID(r))
+ sess := session.New(h.store, request.SessionID(r))
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
- integration, err := c.store.Integration(user.ID)
+ integration, err := h.store.Integration(user.ID)
if err != nil {
html.ServerError(w, r, err)
return
@@ -36,9 +35,9 @@ func (c *Controller) UpdateIntegration(w http.ResponseWriter, r *http.Request) {
integrationForm := form.NewIntegrationForm(r)
integrationForm.Merge(integration)
- if integration.FeverUsername != "" && c.store.HasDuplicateFeverUsername(user.ID, integration.FeverUsername) {
+ if integration.FeverUsername != "" && h.store.HasDuplicateFeverUsername(user.ID, integration.FeverUsername) {
sess.NewFlashErrorMessage(printer.Printf("error.duplicate_fever_username"))
- html.Redirect(w, r, route.Path(c.router, "integrations"))
+ html.Redirect(w, r, route.Path(h.router, "integrations"))
return
}
@@ -48,12 +47,12 @@ func (c *Controller) UpdateIntegration(w http.ResponseWriter, r *http.Request) {
integration.FeverToken = ""
}
- err = c.store.UpdateIntegration(integration)
+ err = h.store.UpdateIntegration(integration)
if err != nil {
html.ServerError(w, r, err)
return
}
sess.NewFlashMessage(printer.Printf("alert.prefs_saved"))
- html.Redirect(w, r, route.Path(c.router, "integrations"))
+ html.Redirect(w, r, route.Path(h.router, "integrations"))
}
diff --git a/ui/login_check.go b/ui/login_check.go
index 73a1736..acc762a 100644
--- a/ui/login_check.go
+++ b/ui/login_check.go
@@ -13,13 +13,12 @@ import (
"miniflux.app/ui/view"
)
-// CheckLogin validates the username/password and redirects the user to the unread page.
-func (c *Controller) CheckLogin(w http.ResponseWriter, r *http.Request) {
+func (h *handler) checkLogin(w http.ResponseWriter, r *http.Request) {
clientIP := request.ClientIP(r)
- sess := session.New(c.store, request.SessionID(r))
+ sess := session.New(h.store, request.SessionID(r))
authForm := form.NewAuthForm(r)
- view := view.New(c.tpl, r, sess)
+ view := view.New(h.tpl, r, sess)
view.Set("errorMessage", "error.bad_credentials")
view.Set("form", authForm)
@@ -29,22 +28,22 @@ func (c *Controller) CheckLogin(w http.ResponseWriter, r *http.Request) {
return
}
- if err := c.store.CheckPassword(authForm.Username, authForm.Password); err != nil {
+ if err := h.store.CheckPassword(authForm.Username, authForm.Password); err != nil {
logger.Error("[Controller:CheckLogin] [ClientIP=%s] %v", clientIP, err)
html.OK(w, r, view.Render("login"))
return
}
- sessionToken, userID, err := c.store.CreateUserSession(authForm.Username, r.UserAgent(), clientIP)
+ sessionToken, userID, err := h.store.CreateUserSession(authForm.Username, r.UserAgent(), clientIP)
if err != nil {
html.ServerError(w, r, err)
return
}
logger.Info("[Controller:CheckLogin] username=%s just logged in", authForm.Username)
- c.store.SetLastLogin(userID)
+ h.store.SetLastLogin(userID)
- user, err := c.store.UserByID(userID)
+ user, err := h.store.UserByID(userID)
if err != nil {
html.ServerError(w, r, err)
return
@@ -56,9 +55,9 @@ func (c *Controller) CheckLogin(w http.ResponseWriter, r *http.Request) {
http.SetCookie(w, cookie.New(
cookie.CookieUserSessionID,
sessionToken,
- c.cfg.IsHTTPS,
- c.cfg.BasePath(),
+ h.cfg.IsHTTPS,
+ h.cfg.BasePath(),
))
- html.Redirect(w, r, route.Path(c.router, "unread"))
+ html.Redirect(w, r, route.Path(h.router, "unread"))
}
diff --git a/ui/login_show.go b/ui/login_show.go
index 890f9db..ea458f4 100644
--- a/ui/login_show.go
+++ b/ui/login_show.go
@@ -14,14 +14,13 @@ import (
"miniflux.app/ui/view"
)
-// ShowLoginPage shows the login form.
-func (c *Controller) ShowLoginPage(w http.ResponseWriter, r *http.Request) {
+func (h *handler) showLoginPage(w http.ResponseWriter, r *http.Request) {
if request.IsAuthenticated(r) {
- html.Redirect(w, r, route.Path(c.router, "unread"))
+ html.Redirect(w, r, route.Path(h.router, "unread"))
return
}
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
html.OK(w, r, view.Render("login"))
}
diff --git a/ui/logout.go b/ui/logout.go
index 59f8af2..ecb08b9 100644
--- a/ui/logout.go
+++ b/ui/logout.go
@@ -15,10 +15,9 @@ import (
"miniflux.app/ui/session"
)
-// Logout destroy the session and redirects the user to the login page.
-func (c *Controller) Logout(w http.ResponseWriter, r *http.Request) {
- sess := session.New(c.store, request.SessionID(r))
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) logout(w http.ResponseWriter, r *http.Request) {
+ sess := session.New(h.store, request.SessionID(r))
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
@@ -27,15 +26,15 @@ func (c *Controller) Logout(w http.ResponseWriter, r *http.Request) {
sess.SetLanguage(user.Language)
sess.SetTheme(user.Theme)
- if err := c.store.RemoveUserSessionByToken(user.ID, request.UserSessionToken(r)); err != nil {
+ if err := h.store.RemoveUserSessionByToken(user.ID, request.UserSessionToken(r)); err != nil {
logger.Error("[Controller:Logout] %v", err)
}
http.SetCookie(w, cookie.Expired(
cookie.CookieUserSessionID,
- c.cfg.IsHTTPS,
- c.cfg.BasePath(),
+ h.cfg.IsHTTPS,
+ h.cfg.BasePath(),
))
- html.Redirect(w, r, route.Path(c.router, "login"))
+ html.Redirect(w, r, route.Path(h.router, "login"))
}
diff --git a/ui/middleware.go b/ui/middleware.go
new file mode 100644
index 0000000..6ec68ee
--- /dev/null
+++ b/ui/middleware.go
@@ -0,0 +1,149 @@
+// Copyright 2018 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 ui // import "miniflux.app/ui"
+
+import (
+ "context"
+ "errors"
+ "net/http"
+
+ "miniflux.app/config"
+ "miniflux.app/http/cookie"
+ "miniflux.app/http/request"
+ "miniflux.app/http/response/html"
+ "miniflux.app/http/route"
+ "miniflux.app/storage"
+ "miniflux.app/logger"
+ "miniflux.app/model"
+
+ "github.com/gorilla/mux"
+)
+
+type middleware struct {
+ router *mux.Router
+ cfg *config.Config
+ store *storage.Storage
+}
+
+func newMiddleware(router *mux.Router, cfg *config.Config, store *storage.Storage) *middleware {
+ return &middleware{router, cfg, store}
+}
+
+func (m *middleware) handleUserSession(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ session := m.getUserSessionFromCookie(r)
+
+ if session == nil {
+ logger.Debug("[UserSession] Session not found")
+ if m.isPublicRoute(r) {
+ next.ServeHTTP(w, r)
+ } else {
+ html.Redirect(w, r, route.Path(m.router, "login"))
+ }
+ } else {
+ logger.Debug("[UserSession] %s", session)
+
+ ctx := r.Context()
+ ctx = context.WithValue(ctx, request.UserIDContextKey, session.UserID)
+ ctx = context.WithValue(ctx, request.IsAuthenticatedContextKey, true)
+ ctx = context.WithValue(ctx, request.UserSessionTokenContextKey, session.Token)
+
+ next.ServeHTTP(w, r.WithContext(ctx))
+ }
+ })
+}
+
+func (m *middleware) handleAppSession(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ var err error
+ session := m.getAppSessionValueFromCookie(r)
+
+ if session == nil {
+ logger.Debug("[AppSession] Session not found")
+
+ session, err = m.store.CreateSession()
+ if err != nil {
+ html.ServerError(w, r, err)
+ return
+ }
+
+ http.SetCookie(w, cookie.New(cookie.CookieSessionID, session.ID, m.cfg.IsHTTPS, m.cfg.BasePath()))
+ } else {
+ logger.Debug("[AppSession] %s", session)
+ }
+
+ if r.Method == "POST" {
+ formValue := r.FormValue("csrf")
+ headerValue := r.Header.Get("X-Csrf-Token")
+
+ if session.Data.CSRF != formValue && session.Data.CSRF != headerValue {
+ logger.Error(`[AppSession] Invalid or missing CSRF token: Form="%s", Header="%s"`, formValue, headerValue)
+ html.BadRequest(w, r, errors.New("Invalid or missing CSRF"))
+ return
+ }
+ }
+
+ ctx := r.Context()
+ ctx = context.WithValue(ctx, request.SessionIDContextKey, session.ID)
+ ctx = context.WithValue(ctx, request.CSRFContextKey, session.Data.CSRF)
+ ctx = context.WithValue(ctx, request.OAuth2StateContextKey, session.Data.OAuth2State)
+ ctx = context.WithValue(ctx, request.FlashMessageContextKey, session.Data.FlashMessage)
+ ctx = context.WithValue(ctx, request.FlashErrorMessageContextKey, session.Data.FlashErrorMessage)
+ ctx = context.WithValue(ctx, request.UserLanguageContextKey, session.Data.Language)
+ ctx = context.WithValue(ctx, request.UserThemeContextKey, session.Data.Theme)
+ ctx = context.WithValue(ctx, request.PocketRequestTokenContextKey, session.Data.PocketRequestToken)
+ next.ServeHTTP(w, r.WithContext(ctx))
+ })
+}
+
+func (m *middleware) getAppSessionValueFromCookie(r *http.Request) *model.Session {
+ cookieValue := request.CookieValue(r, cookie.CookieSessionID)
+ if cookieValue == "" {
+ return nil
+ }
+
+ session, err := m.store.Session(cookieValue)
+ if err != nil {
+ logger.Error("[AppSession] %v", err)
+ return nil
+ }
+
+ return session
+}
+
+func (m *middleware) isPublicRoute(r *http.Request) bool {
+ route := mux.CurrentRoute(r)
+ switch route.GetName() {
+ case "login",
+ "checkLogin",
+ "stylesheet",
+ "javascript",
+ "oauth2Redirect",
+ "oauth2Callback",
+ "appIcon",
+ "favicon",
+ "webManifest",
+ "robots",
+ "healthcheck":
+ return true
+ default:
+ return false
+ }
+}
+
+func (m *middleware) getUserSessionFromCookie(r *http.Request) *model.UserSession {
+ cookieValue := request.CookieValue(r, cookie.CookieUserSessionID)
+ if cookieValue == "" {
+ return nil
+ }
+
+ session, err := m.store.UserSessionByToken(cookieValue)
+ if err != nil {
+ logger.Error("[UserSession] %v", err)
+ return nil
+ }
+
+ return session
+}
diff --git a/ui/oauth2_callback.go b/ui/oauth2_callback.go
index 0aecd1c..bd7c999 100644
--- a/ui/oauth2_callback.go
+++ b/ui/oauth2_callback.go
@@ -17,51 +17,50 @@ import (
"miniflux.app/ui/session"
)
-// OAuth2Callback receives the authorization code and create a new session.
-func (c *Controller) OAuth2Callback(w http.ResponseWriter, r *http.Request) {
+func (h *handler) oauth2Callback(w http.ResponseWriter, r *http.Request) {
clientIP := request.ClientIP(r)
printer := locale.NewPrinter(request.UserLanguage(r))
- sess := session.New(c.store, request.SessionID(r))
+ sess := session.New(h.store, request.SessionID(r))
provider := request.RouteStringParam(r, "provider")
if provider == "" {
logger.Error("[OAuth2] Invalid or missing provider")
- html.Redirect(w, r, route.Path(c.router, "login"))
+ html.Redirect(w, r, route.Path(h.router, "login"))
return
}
code := request.QueryStringParam(r, "code", "")
if code == "" {
logger.Error("[OAuth2] No code received on callback")
- html.Redirect(w, r, route.Path(c.router, "login"))
+ html.Redirect(w, r, route.Path(h.router, "login"))
return
}
state := request.QueryStringParam(r, "state", "")
if state == "" || state != request.OAuth2State(r) {
logger.Error(`[OAuth2] Invalid state value: got "%s" instead of "%s"`, state, request.OAuth2State(r))
- html.Redirect(w, r, route.Path(c.router, "login"))
+ html.Redirect(w, r, route.Path(h.router, "login"))
return
}
- authProvider, err := getOAuth2Manager(c.cfg).Provider(provider)
+ authProvider, err := getOAuth2Manager(h.cfg).Provider(provider)
if err != nil {
logger.Error("[OAuth2] %v", err)
- html.Redirect(w, r, route.Path(c.router, "login"))
+ html.Redirect(w, r, route.Path(h.router, "login"))
return
}
profile, err := authProvider.GetProfile(code)
if err != nil {
logger.Error("[OAuth2] %v", err)
- html.Redirect(w, r, route.Path(c.router, "login"))
+ html.Redirect(w, r, route.Path(h.router, "login"))
return
}
logger.Info("[OAuth2] [ClientIP=%s] Successful auth for %s", clientIP, profile)
if request.IsAuthenticated(r) {
- user, err := c.store.UserByExtraField(profile.Key, profile.ID)
+ user, err := h.store.UserByExtraField(profile.Key, profile.ID)
if err != nil {
html.ServerError(w, r, err)
return
@@ -70,28 +69,28 @@ func (c *Controller) OAuth2Callback(w http.ResponseWriter, r *http.Request) {
if user != nil {
logger.Error("[OAuth2] User #%d cannot be associated because %s is already associated", request.UserID(r), user.Username)
sess.NewFlashErrorMessage(printer.Printf("error.duplicate_linked_account"))
- html.Redirect(w, r, route.Path(c.router, "settings"))
+ html.Redirect(w, r, route.Path(h.router, "settings"))
return
}
- if err := c.store.UpdateExtraField(request.UserID(r), profile.Key, profile.ID); err != nil {
+ if err := h.store.UpdateExtraField(request.UserID(r), profile.Key, profile.ID); err != nil {
html.ServerError(w, r, err)
return
}
sess.NewFlashMessage(printer.Printf("alert.account_linked"))
- html.Redirect(w, r, route.Path(c.router, "settings"))
+ html.Redirect(w, r, route.Path(h.router, "settings"))
return
}
- user, err := c.store.UserByExtraField(profile.Key, profile.ID)
+ user, err := h.store.UserByExtraField(profile.Key, profile.ID)
if err != nil {
html.ServerError(w, r, err)
return
}
if user == nil {
- if !c.cfg.IsOAuth2UserCreationAllowed() {
+ if !h.cfg.IsOAuth2UserCreationAllowed() {
html.Forbidden(w, r)
return
}
@@ -101,13 +100,13 @@ func (c *Controller) OAuth2Callback(w http.ResponseWriter, r *http.Request) {
user.IsAdmin = false
user.Extra[profile.Key] = profile.ID
- if err := c.store.CreateUser(user); err != nil {
+ if err := h.store.CreateUser(user); err != nil {
html.ServerError(w, r, err)
return
}
}
- sessionToken, _, err := c.store.CreateUserSession(user.Username, r.UserAgent(), clientIP)
+ sessionToken, _, err := h.store.CreateUserSession(user.Username, r.UserAgent(), clientIP)
if err != nil {
html.ServerError(w, r, err)
return
@@ -115,16 +114,16 @@ func (c *Controller) OAuth2Callback(w http.ResponseWriter, r *http.Request) {
logger.Info("[OAuth2] [ClientIP=%s] username=%s (%s) just logged in", clientIP, user.Username, profile)
- c.store.SetLastLogin(user.ID)
+ h.store.SetLastLogin(user.ID)
sess.SetLanguage(user.Language)
sess.SetTheme(user.Theme)
http.SetCookie(w, cookie.New(
cookie.CookieUserSessionID,
sessionToken,
- c.cfg.IsHTTPS,
- c.cfg.BasePath(),
+ h.cfg.IsHTTPS,
+ h.cfg.BasePath(),
))
- html.Redirect(w, r, route.Path(c.router, "unread"))
+ html.Redirect(w, r, route.Path(h.router, "unread"))
}
diff --git a/ui/oauth2_redirect.go b/ui/oauth2_redirect.go
index e54309a..85116cf 100644
--- a/ui/oauth2_redirect.go
+++ b/ui/oauth2_redirect.go
@@ -14,21 +14,20 @@ import (
"miniflux.app/ui/session"
)
-// OAuth2Redirect redirects the user to the consent page to ask for permission.
-func (c *Controller) OAuth2Redirect(w http.ResponseWriter, r *http.Request) {
- sess := session.New(c.store, request.SessionID(r))
+func (h *handler) oauth2Redirect(w http.ResponseWriter, r *http.Request) {
+ sess := session.New(h.store, request.SessionID(r))
provider := request.RouteStringParam(r, "provider")
if provider == "" {
logger.Error("[OAuth2] Invalid or missing provider: %s", provider)
- html.Redirect(w, r, route.Path(c.router, "login"))
+ html.Redirect(w, r, route.Path(h.router, "login"))
return
}
- authProvider, err := getOAuth2Manager(c.cfg).Provider(provider)
+ authProvider, err := getOAuth2Manager(h.cfg).Provider(provider)
if err != nil {
logger.Error("[OAuth2] %v", err)
- html.Redirect(w, r, route.Path(c.router, "login"))
+ html.Redirect(w, r, route.Path(h.router, "login"))
return
}
diff --git a/ui/oauth2_unlink.go b/ui/oauth2_unlink.go
index 8e38ddc..3283f89 100644
--- a/ui/oauth2_unlink.go
+++ b/ui/oauth2_unlink.go
@@ -15,26 +15,25 @@ import (
"miniflux.app/ui/session"
)
-// OAuth2Unlink unlink an account from the external provider.
-func (c *Controller) OAuth2Unlink(w http.ResponseWriter, r *http.Request) {
+func (h *handler) oauth2Unlink(w http.ResponseWriter, r *http.Request) {
printer := locale.NewPrinter(request.UserLanguage(r))
provider := request.RouteStringParam(r, "provider")
if provider == "" {
logger.Info("[OAuth2] Invalid or missing provider")
- html.Redirect(w, r, route.Path(c.router, "login"))
+ html.Redirect(w, r, route.Path(h.router, "login"))
return
}
- authProvider, err := getOAuth2Manager(c.cfg).Provider(provider)
+ authProvider, err := getOAuth2Manager(h.cfg).Provider(provider)
if err != nil {
logger.Error("[OAuth2] %v", err)
- html.Redirect(w, r, route.Path(c.router, "settings"))
+ html.Redirect(w, r, route.Path(h.router, "settings"))
return
}
- sess := session.New(c.store, request.SessionID(r))
+ sess := session.New(h.store, request.SessionID(r))
- hasPassword, err := c.store.HasPassword(request.UserID(r))
+ hasPassword, err := h.store.HasPassword(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
@@ -42,15 +41,15 @@ func (c *Controller) OAuth2Unlink(w http.ResponseWriter, r *http.Request) {
if !hasPassword {
sess.NewFlashErrorMessage(printer.Printf("error.unlink_account_without_password"))
- html.Redirect(w, r, route.Path(c.router, "settings"))
+ html.Redirect(w, r, route.Path(h.router, "settings"))
return
}
- if err := c.store.RemoveExtraField(request.UserID(r), authProvider.GetUserExtraKey()); err != nil {
+ if err := h.store.RemoveExtraField(request.UserID(r), authProvider.GetUserExtraKey()); err != nil {
html.ServerError(w, r, err)
return
}
sess.NewFlashMessage(printer.Printf("alert.account_unlinked"))
- html.Redirect(w, r, route.Path(c.router, "settings"))
+ html.Redirect(w, r, route.Path(h.router, "settings"))
}
diff --git a/ui/opml_export.go b/ui/opml_export.go
index 55ceb56..4eb6d2c 100644
--- a/ui/opml_export.go
+++ b/ui/opml_export.go
@@ -13,9 +13,8 @@ import (
"miniflux.app/reader/opml"
)
-// Export generates the OPML file.
-func (c *Controller) Export(w http.ResponseWriter, r *http.Request) {
- opml, err := opml.NewHandler(c.store).Export(request.UserID(r))
+func (h *handler) exportFeeds(w http.ResponseWriter, r *http.Request) {
+ opml, err := opml.NewHandler(h.store).Export(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
diff --git a/ui/opml_import.go b/ui/opml_import.go
index 9a763ca..06f54bb 100644
--- a/ui/opml_import.go
+++ b/ui/opml_import.go
@@ -13,20 +13,19 @@ import (
"miniflux.app/ui/view"
)
-// Import shows the import form.
-func (c *Controller) Import(w http.ResponseWriter, r *http.Request) {
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) showImportPage(w http.ResponseWriter, r *http.Request) {
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
view.Set("menu", "feeds")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
html.OK(w, r, view.Render("import"))
}
diff --git a/ui/opml_upload.go b/ui/opml_upload.go
index 538f822..82e2ac8 100644
--- a/ui/opml_upload.go
+++ b/ui/opml_upload.go
@@ -16,9 +16,8 @@ import (
"miniflux.app/ui/view"
)
-// UploadOPML handles OPML file importation.
-func (c *Controller) UploadOPML(w http.ResponseWriter, r *http.Request) {
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) uploadOPML(w http.ResponseWriter, r *http.Request) {
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
@@ -27,7 +26,7 @@ func (c *Controller) UploadOPML(w http.ResponseWriter, r *http.Request) {
file, fileHeader, err := r.FormFile("file")
if err != nil {
logger.Error("[Controller:UploadOPML] %v", err)
- html.Redirect(w, r, route.Path(c.router, "import"))
+ html.Redirect(w, r, route.Path(h.router, "import"))
return
}
defer file.Close()
@@ -39,12 +38,12 @@ func (c *Controller) UploadOPML(w http.ResponseWriter, r *http.Request) {
fileHeader.Size,
)
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
view.Set("menu", "feeds")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
if fileHeader.Size == 0 {
view.Set("errorMessage", "error.empty_file")
@@ -52,11 +51,11 @@ func (c *Controller) UploadOPML(w http.ResponseWriter, r *http.Request) {
return
}
- if impErr := opml.NewHandler(c.store).Import(user.ID, file); impErr != nil {
+ if impErr := opml.NewHandler(h.store).Import(user.ID, file); impErr != nil {
view.Set("errorMessage", impErr)
html.OK(w, r, view.Render("import"))
return
}
- html.Redirect(w, r, route.Path(c.router, "feeds"))
+ html.Redirect(w, r, route.Path(h.router, "feeds"))
}
diff --git a/ui/pagination.go b/ui/pagination.go
index 5fdf715..7534431 100644
--- a/ui/pagination.go
+++ b/ui/pagination.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
-package ui // import "miniflux.app/ui"
+package ui // import "miniflux.app/ui"
const (
nbItemsPerPage = 100
@@ -20,7 +20,7 @@ type pagination struct {
SearchQuery string
}
-func (c *Controller) getPagination(route string, total, offset int) pagination {
+func getPagination(route string, total, offset int) pagination {
nextOffset := 0
prevOffset := 0
showNext := (total - offset) > nbItemsPerPage
diff --git a/ui/proxy.go b/ui/proxy.go
index 050c070..e9f8ec0 100644
--- a/ui/proxy.go
+++ b/ui/proxy.go
@@ -18,8 +18,7 @@ import (
"miniflux.app/http/response/html"
)
-// ImageProxy fetch an image from a remote server and sent it back to the browser.
-func (c *Controller) ImageProxy(w http.ResponseWriter, r *http.Request) {
+func (h *handler) imageProxy(w http.ResponseWriter, r *http.Request) {
// If we receive a "If-None-Match" header, we assume the image is already stored in browser cache.
if r.Header.Get("If-None-Match") != "" {
w.WriteHeader(http.StatusNotModified)
diff --git a/ui/search_entries.go b/ui/search_entries.go
index 1304ef2..be97da0 100644
--- a/ui/search_entries.go
+++ b/ui/search_entries.go
@@ -15,9 +15,8 @@ import (
"miniflux.app/ui/view"
)
-// ShowSearchEntries shows all entries for the given feed.
-func (c *Controller) ShowSearchEntries(w http.ResponseWriter, r *http.Request) {
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) showSearchEntriesPage(w http.ResponseWriter, r *http.Request) {
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
@@ -25,7 +24,7 @@ func (c *Controller) ShowSearchEntries(w http.ResponseWriter, r *http.Request) {
searchQuery := request.QueryStringParam(r, "q", "")
offset := request.QueryIntParam(r, "offset", 0)
- builder := c.store.NewEntryQueryBuilder(user.ID)
+ builder := h.store.NewEntryQueryBuilder(user.ID)
builder.WithSearchQuery(searchQuery)
builder.WithoutStatus(model.EntryStatusRemoved)
builder.WithOrder(model.DefaultSortingOrder)
@@ -45,9 +44,9 @@ func (c *Controller) ShowSearchEntries(w http.ResponseWriter, r *http.Request) {
return
}
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
- pagination := c.getPagination(route.Path(c.router, "searchEntries"), count, offset)
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
+ pagination := getPagination(route.Path(h.router, "searchEntries"), count, offset)
pagination.SearchQuery = searchQuery
view.Set("searchQuery", searchQuery)
@@ -56,9 +55,9 @@ func (c *Controller) ShowSearchEntries(w http.ResponseWriter, r *http.Request) {
view.Set("pagination", pagination)
view.Set("menu", "search")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
- view.Set("hasSaveEntry", c.store.HasSaveEntry(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
+ view.Set("hasSaveEntry", h.store.HasSaveEntry(user.ID))
html.OK(w, r, view.Render("search_entries"))
}
diff --git a/ui/session_list.go b/ui/session_list.go
index 76e693a..28da202 100644
--- a/ui/session_list.go
+++ b/ui/session_list.go
@@ -13,18 +13,17 @@ import (
"miniflux.app/ui/view"
)
-// ShowSessions shows the list of active user sessions.
-func (c *Controller) ShowSessions(w http.ResponseWriter, r *http.Request) {
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+func (h *handler) showSessionsPage(w http.ResponseWriter, r *http.Request) {
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
- user, err := c.store.UserByID(request.UserID(r))
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
- sessions, err := c.store.UserSessions(user.ID)
+ sessions, err := h.store.UserSessions(user.ID)
if err != nil {
html.ServerError(w, r, err)
return
@@ -36,8 +35,8 @@ func (c *Controller) ShowSessions(w http.ResponseWriter, r *http.Request) {
view.Set("sessions", sessions)
view.Set("menu", "settings")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
html.OK(w, r, view.Render("sessions"))
}
diff --git a/ui/session_remove.go b/ui/session_remove.go
index cc62612..e84a7a2 100644
--- a/ui/session_remove.go
+++ b/ui/session_remove.go
@@ -13,13 +13,12 @@ import (
"miniflux.app/logger"
)
-// RemoveSession remove a user session.
-func (c *Controller) RemoveSession(w http.ResponseWriter, r *http.Request) {
+func (h *handler) removeSession(w http.ResponseWriter, r *http.Request) {
sessionID := request.RouteInt64Param(r, "sessionID")
- err := c.store.RemoveUserSessionByID(request.UserID(r), sessionID)
+ err := h.store.RemoveUserSessionByID(request.UserID(r), sessionID)
if err != nil {
logger.Error("[Controller:RemoveSession] %v", err)
}
- html.Redirect(w, r, route.Path(c.router, "sessions"))
+ html.Redirect(w, r, route.Path(h.router, "sessions"))
}
diff --git a/ui/settings_show.go b/ui/settings_show.go
index 4f4756d..39d85ca 100644
--- a/ui/settings_show.go
+++ b/ui/settings_show.go
@@ -16,12 +16,11 @@ import (
"miniflux.app/ui/view"
)
-// ShowSettings shows the settings page.
-func (c *Controller) ShowSettings(w http.ResponseWriter, r *http.Request) {
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+func (h *handler) showSettingsPage(w http.ResponseWriter, r *http.Request) {
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
- user, err := c.store.UserByID(request.UserID(r))
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
@@ -35,7 +34,7 @@ func (c *Controller) ShowSettings(w http.ResponseWriter, r *http.Request) {
EntryDirection: user.EntryDirection,
}
- timezones, err := c.store.Timezones()
+ timezones, err := h.store.Timezones()
if err != nil {
html.ServerError(w, r, err)
return
@@ -47,8 +46,8 @@ func (c *Controller) ShowSettings(w http.ResponseWriter, r *http.Request) {
view.Set("timezones", timezones)
view.Set("menu", "settings")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
html.OK(w, r, view.Render("settings"))
}
diff --git a/ui/settings_update.go b/ui/settings_update.go
index 466bb78..3497dd9 100644
--- a/ui/settings_update.go
+++ b/ui/settings_update.go
@@ -18,18 +18,17 @@ import (
"miniflux.app/ui/view"
)
-// UpdateSettings update the settings.
-func (c *Controller) UpdateSettings(w http.ResponseWriter, r *http.Request) {
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+func (h *handler) updateSettings(w http.ResponseWriter, r *http.Request) {
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
- user, err := c.store.UserByID(request.UserID(r))
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
- timezones, err := c.store.Timezones()
+ timezones, err := h.store.Timezones()
if err != nil {
html.ServerError(w, r, err)
return
@@ -43,8 +42,8 @@ func (c *Controller) UpdateSettings(w http.ResponseWriter, r *http.Request) {
view.Set("timezones", timezones)
view.Set("menu", "settings")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
if err := settingsForm.Validate(); err != nil {
view.Set("errorMessage", err.Error())
@@ -52,13 +51,13 @@ func (c *Controller) UpdateSettings(w http.ResponseWriter, r *http.Request) {
return
}
- if c.store.AnotherUserExists(user.ID, settingsForm.Username) {
+ if h.store.AnotherUserExists(user.ID, settingsForm.Username) {
view.Set("errorMessage", "error.user_already_exists")
html.OK(w, r, view.Render("settings"))
return
}
- err = c.store.UpdateUser(settingsForm.Merge(user))
+ err = h.store.UpdateUser(settingsForm.Merge(user))
if err != nil {
logger.Error("[Controller:UpdateSettings] %v", err)
view.Set("errorMessage", "error.unable_to_update_user")
@@ -69,5 +68,5 @@ func (c *Controller) UpdateSettings(w http.ResponseWriter, r *http.Request) {
sess.SetLanguage(user.Language)
sess.SetTheme(user.Theme)
sess.NewFlashMessage(locale.NewPrinter(request.UserLanguage(r)).Printf("alert.prefs_saved"))
- html.Redirect(w, r, route.Path(c.router, "settings"))
+ html.Redirect(w, r, route.Path(h.router, "settings"))
}
diff --git a/ui/static_app_icon.go b/ui/static_app_icon.go
index 9e2a448..ea0290b 100644
--- a/ui/static_app_icon.go
+++ b/ui/static_app_icon.go
@@ -15,8 +15,7 @@ import (
"miniflux.app/ui/static"
)
-// AppIcon shows application icons.
-func (c *Controller) AppIcon(w http.ResponseWriter, r *http.Request) {
+func (h *handler) showAppIcon(w http.ResponseWriter, r *http.Request) {
filename := request.RouteStringParam(r, "filename")
etag, found := static.BinariesChecksums[filename]
if !found {
diff --git a/ui/static_favicon.go b/ui/static_favicon.go
index 1266a19..80060a5 100644
--- a/ui/static_favicon.go
+++ b/ui/static_favicon.go
@@ -14,8 +14,7 @@ import (
"miniflux.app/ui/static"
)
-// Favicon shows the application favicon.
-func (c *Controller) Favicon(w http.ResponseWriter, r *http.Request) {
+func (h *handler) showFavicon(w http.ResponseWriter, r *http.Request) {
etag, found := static.BinariesChecksums["favicon.ico"]
if !found {
html.NotFound(w, r)
diff --git a/ui/static_javascript.go b/ui/static_javascript.go
index ff7fd16..de6b342 100644
--- a/ui/static_javascript.go
+++ b/ui/static_javascript.go
@@ -14,8 +14,7 @@ import (
"miniflux.app/ui/static"
)
-// Javascript renders application client side code.
-func (c *Controller) Javascript(w http.ResponseWriter, r *http.Request) {
+func (h *handler) showJavascript(w http.ResponseWriter, r *http.Request) {
filename := request.RouteStringParam(r, "name")
etag, found := static.JavascriptsChecksums[filename]
if !found {
diff --git a/ui/static_manifest.go b/ui/static_manifest.go
index 51369a2..50e7e98 100644
--- a/ui/static_manifest.go
+++ b/ui/static_manifest.go
@@ -13,8 +13,7 @@ import (
"miniflux.app/model"
)
-// WebManifest renders web manifest file.
-func (c *Controller) WebManifest(w http.ResponseWriter, r *http.Request) {
+func (h *handler) showWebManifest(w http.ResponseWriter, r *http.Request) {
type webManifestIcon struct {
Source string `json:"src"`
Sizes string `json:"sizes"`
@@ -38,13 +37,13 @@ func (c *Controller) WebManifest(w http.ResponseWriter, r *http.Request) {
ShortName: "Miniflux",
Description: "Minimalist Feed Reader",
Display: "minimal-ui",
- StartURL: route.Path(c.router, "unread"),
+ StartURL: route.Path(h.router, "unread"),
ThemeColor: themeColor,
BackgroundColor: themeColor,
Icons: []webManifestIcon{
- webManifestIcon{Source: route.Path(c.router, "appIcon", "filename", "icon-120.png"), Sizes: "120x120", Type: "image/png"},
- webManifestIcon{Source: route.Path(c.router, "appIcon", "filename", "icon-192.png"), Sizes: "192x192", Type: "image/png"},
- webManifestIcon{Source: route.Path(c.router, "appIcon", "filename", "icon-512.png"), Sizes: "512x512", Type: "image/png"},
+ webManifestIcon{Source: route.Path(h.router, "appIcon", "filename", "icon-120.png"), Sizes: "120x120", Type: "image/png"},
+ webManifestIcon{Source: route.Path(h.router, "appIcon", "filename", "icon-192.png"), Sizes: "192x192", Type: "image/png"},
+ webManifestIcon{Source: route.Path(h.router, "appIcon", "filename", "icon-512.png"), Sizes: "512x512", Type: "image/png"},
},
}
diff --git a/ui/static_stylesheet.go b/ui/static_stylesheet.go
index 9a21bc6..506caf4 100644
--- a/ui/static_stylesheet.go
+++ b/ui/static_stylesheet.go
@@ -14,8 +14,7 @@ import (
"miniflux.app/ui/static"
)
-// Stylesheet renders the CSS.
-func (c *Controller) Stylesheet(w http.ResponseWriter, r *http.Request) {
+func (h *handler) showStylesheet(w http.ResponseWriter, r *http.Request) {
filename := request.RouteStringParam(r, "name")
etag, found := static.StylesheetsChecksums[filename]
if !found {
diff --git a/ui/subscription_add.go b/ui/subscription_add.go
index 3056eec..db539c8 100644
--- a/ui/subscription_add.go
+++ b/ui/subscription_add.go
@@ -14,18 +14,17 @@ import (
"miniflux.app/ui/view"
)
-// AddSubscription shows the form to add a new feed.
-func (c *Controller) AddSubscription(w http.ResponseWriter, r *http.Request) {
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+func (h *handler) showAddSubscriptionPage(w http.ResponseWriter, r *http.Request) {
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
- user, err := c.store.UserByID(request.UserID(r))
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
- categories, err := c.store.Categories(user.ID)
+ categories, err := h.store.Categories(user.ID)
if err != nil {
html.ServerError(w, r, err)
return
@@ -34,8 +33,8 @@ func (c *Controller) AddSubscription(w http.ResponseWriter, r *http.Request) {
view.Set("categories", categories)
view.Set("menu", "feeds")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
view.Set("defaultUserAgent", client.DefaultUserAgent)
html.OK(w, r, view.Render("add_subscription"))
diff --git a/ui/subscription_bookmarklet.go b/ui/subscription_bookmarklet.go
index 5c0e08c..060aa48 100644
--- a/ui/subscription_bookmarklet.go
+++ b/ui/subscription_bookmarklet.go
@@ -15,18 +15,17 @@ import (
"miniflux.app/ui/view"
)
-// Bookmarklet prefill the form to add a subscription from the URL provided by the bookmarklet.
-func (c *Controller) Bookmarklet(w http.ResponseWriter, r *http.Request) {
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+func (h *handler) bookmarklet(w http.ResponseWriter, r *http.Request) {
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
- user, err := c.store.UserByID(request.UserID(r))
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
- categories, err := c.store.Categories(user.ID)
+ categories, err := h.store.Categories(user.ID)
if err != nil {
html.ServerError(w, r, err)
return
@@ -38,8 +37,8 @@ func (c *Controller) Bookmarklet(w http.ResponseWriter, r *http.Request) {
view.Set("categories", categories)
view.Set("menu", "feeds")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
view.Set("defaultUserAgent", client.DefaultUserAgent)
html.OK(w, r, view.Render("add_subscription"))
diff --git a/ui/subscription_choose.go b/ui/subscription_choose.go
index 4f701c8..b554b03 100644
--- a/ui/subscription_choose.go
+++ b/ui/subscription_choose.go
@@ -16,18 +16,17 @@ import (
"miniflux.app/ui/view"
)
-// ChooseSubscription shows a page to choose a subscription.
-func (c *Controller) ChooseSubscription(w http.ResponseWriter, r *http.Request) {
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+func (h *handler) showChooseSubscriptionPage(w http.ResponseWriter, r *http.Request) {
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
- user, err := c.store.UserByID(request.UserID(r))
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
- categories, err := c.store.Categories(user.ID)
+ categories, err := h.store.Categories(user.ID)
if err != nil {
html.ServerError(w, r, err)
return
@@ -36,8 +35,8 @@ func (c *Controller) ChooseSubscription(w http.ResponseWriter, r *http.Request)
view.Set("categories", categories)
view.Set("menu", "feeds")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
view.Set("defaultUserAgent", client.DefaultUserAgent)
subscriptionForm := form.NewSubscriptionForm(r)
@@ -48,7 +47,7 @@ func (c *Controller) ChooseSubscription(w http.ResponseWriter, r *http.Request)
return
}
- feed, err := c.feedHandler.CreateFeed(
+ feed, err := h.feedHandler.CreateFeed(
user.ID,
subscriptionForm.CategoryID,
subscriptionForm.URL,
@@ -64,5 +63,5 @@ func (c *Controller) ChooseSubscription(w http.ResponseWriter, r *http.Request)
return
}
- html.Redirect(w, r, route.Path(c.router, "feedEntries", "feedID", feed.ID))
+ html.Redirect(w, r, route.Path(h.router, "feedEntries", "feedID", feed.ID))
}
diff --git a/ui/subscription_submit.go b/ui/subscription_submit.go
index bdf6a59..8d3c7ed 100644
--- a/ui/subscription_submit.go
+++ b/ui/subscription_submit.go
@@ -18,18 +18,17 @@ import (
"miniflux.app/ui/view"
)
-// SubmitSubscription try to find a feed from the URL provided by the user.
-func (c *Controller) SubmitSubscription(w http.ResponseWriter, r *http.Request) {
- sess := session.New(c.store, request.SessionID(r))
- v := view.New(c.tpl, r, sess)
+func (h *handler) submitSubscription(w http.ResponseWriter, r *http.Request) {
+ sess := session.New(h.store, request.SessionID(r))
+ v := view.New(h.tpl, r, sess)
- user, err := c.store.UserByID(request.UserID(r))
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
- categories, err := c.store.Categories(user.ID)
+ categories, err := h.store.Categories(user.ID)
if err != nil {
html.ServerError(w, r, err)
return
@@ -38,8 +37,8 @@ func (c *Controller) SubmitSubscription(w http.ResponseWriter, r *http.Request)
v.Set("categories", categories)
v.Set("menu", "feeds")
v.Set("user", user)
- v.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- v.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
+ v.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ v.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
v.Set("defaultUserAgent", client.DefaultUserAgent)
subscriptionForm := form.NewSubscriptionForm(r)
@@ -73,7 +72,7 @@ func (c *Controller) SubmitSubscription(w http.ResponseWriter, r *http.Request)
v.Set("errorMessage", "error.subscription_not_found")
html.OK(w, r, v.Render("add_subscription"))
case n == 1:
- feed, err := c.feedHandler.CreateFeed(
+ feed, err := h.feedHandler.CreateFeed(
user.ID,
subscriptionForm.CategoryID,
subscriptions[0].URL,
@@ -89,15 +88,15 @@ func (c *Controller) SubmitSubscription(w http.ResponseWriter, r *http.Request)
return
}
- html.Redirect(w, r, route.Path(c.router, "feedEntries", "feedID", feed.ID))
+ html.Redirect(w, r, route.Path(h.router, "feedEntries", "feedID", feed.ID))
case n > 1:
- v := view.New(c.tpl, r, sess)
+ v := view.New(h.tpl, r, sess)
v.Set("subscriptions", subscriptions)
v.Set("form", subscriptionForm)
v.Set("menu", "feeds")
v.Set("user", user)
- v.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- v.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
+ v.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ v.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
html.OK(w, r, v.Render("choose_subscription"))
}
diff --git a/ui/ui.go b/ui/ui.go
new file mode 100644
index 0000000..3577636
--- /dev/null
+++ b/ui/ui.go
@@ -0,0 +1,133 @@
+// Copyright 2018 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 ui // import "miniflux.app/ui"
+
+import (
+ "net/http"
+
+ "miniflux.app/config"
+ "miniflux.app/reader/feed"
+ "miniflux.app/scheduler"
+ "miniflux.app/storage"
+ "miniflux.app/template"
+
+ "github.com/gorilla/mux"
+)
+
+// Serve declares all routes for the user interface.
+func Serve(router *mux.Router, cfg *config.Config, store *storage.Storage, pool *scheduler.WorkerPool, feedHandler *feed.Handler) {
+ middleware := newMiddleware(router, cfg, store)
+ handler := &handler{router, cfg, store, template.NewEngine(cfg, router), pool, feedHandler}
+
+ uiRouter := router.NewRoute().Subrouter()
+ uiRouter.Use(middleware.handleAppSession)
+ uiRouter.Use(middleware.handleUserSession)
+
+ // Static assets.
+ uiRouter.HandleFunc("/stylesheets/{name}.css", handler.showStylesheet).Name("stylesheet").Methods("GET")
+ uiRouter.HandleFunc("/{name}.js", handler.showJavascript).Name("javascript").Methods("GET")
+ uiRouter.HandleFunc("/favicon.ico", handler.showFavicon).Name("favicon").Methods("GET")
+ uiRouter.HandleFunc("/icon/{filename}", handler.showAppIcon).Name("appIcon").Methods("GET")
+ uiRouter.HandleFunc("/manifest.json", handler.showWebManifest).Name("webManifest").Methods("GET")
+
+ // New subscription pages.
+ uiRouter.HandleFunc("/subscribe", handler.showAddSubscriptionPage).Name("addSubscription").Methods("GET")
+ uiRouter.HandleFunc("/subscribe", handler.submitSubscription).Name("submitSubscription").Methods("POST")
+ uiRouter.HandleFunc("/subscriptions", handler.showChooseSubscriptionPage).Name("chooseSubscription").Methods("POST")
+ uiRouter.HandleFunc("/bookmarklet", handler.bookmarklet).Name("bookmarklet").Methods("GET")
+
+ // Unread page.
+ uiRouter.HandleFunc("/mark-all-as-read", handler.markAllAsRead).Name("markAllAsRead").Methods("GET")
+ uiRouter.HandleFunc("/unread", handler.showUnreadPage).Name("unread").Methods("GET")
+ uiRouter.HandleFunc("/unread/entry/{entryID}", handler.showUnreadEntryPage).Name("unreadEntry").Methods("GET")
+
+ // History pages.
+ uiRouter.HandleFunc("/history", handler.showHistoryPage).Name("history").Methods("GET")
+ uiRouter.HandleFunc("/history/entry/{entryID}", handler.showReadEntryPage).Name("readEntry").Methods("GET")
+ uiRouter.HandleFunc("/history/flush", handler.flushHistory).Name("flushHistory").Methods("GET")
+
+ // Bookmark pages.
+ uiRouter.HandleFunc("/starred", handler.showStarredPage).Name("starred").Methods("GET")
+ uiRouter.HandleFunc("/starred/entry/{entryID}", handler.showStarredEntryPage).Name("starredEntry").Methods("GET")
+
+ // Search pages.
+ uiRouter.HandleFunc("/search", handler.showSearchEntriesPage).Name("searchEntries").Methods("GET")
+ uiRouter.HandleFunc("/search/entry/{entryID}", handler.showSearchEntryPage).Name("searchEntry").Methods("GET")
+
+ // Feed listing pages.
+ uiRouter.HandleFunc("/feeds", handler.showFeedsPage).Name("feeds").Methods("GET")
+ uiRouter.HandleFunc("/feeds/refresh", handler.refreshAllFeeds).Name("refreshAllFeeds").Methods("GET")
+
+ // Individual feed pages.
+ uiRouter.HandleFunc("/feed/{feedID}/refresh", handler.refreshFeed).Name("refreshFeed").Methods("GET")
+ uiRouter.HandleFunc("/feed/{feedID}/edit", handler.showEditFeedPage).Name("editFeed").Methods("GET")
+ uiRouter.HandleFunc("/feed/{feedID}/remove", handler.removeFeed).Name("removeFeed").Methods("POST")
+ uiRouter.HandleFunc("/feed/{feedID}/update", handler.updateFeed).Name("updateFeed").Methods("POST")
+ uiRouter.HandleFunc("/feed/{feedID}/entries", handler.showFeedEntriesPage).Name("feedEntries").Methods("GET")
+ uiRouter.HandleFunc("/feed/{feedID}/entry/{entryID}", handler.showFeedEntryPage).Name("feedEntry").Methods("GET")
+ uiRouter.HandleFunc("/feed/icon/{iconID}", handler.showIcon).Name("icon").Methods("GET")
+
+ // Category pages.
+ uiRouter.HandleFunc("/category/{categoryID}/entry/{entryID}", handler.showCategoryEntryPage).Name("categoryEntry").Methods("GET")
+ uiRouter.HandleFunc("/categories", handler.showCategoryListPage).Name("categories").Methods("GET")
+ uiRouter.HandleFunc("/category/create", handler.showCreateCategoryPage).Name("createCategory").Methods("GET")
+ uiRouter.HandleFunc("/category/save", handler.saveCategory).Name("saveCategory").Methods("POST")
+ uiRouter.HandleFunc("/category/{categoryID}/entries", handler.showCategoryEntriesPage).Name("categoryEntries").Methods("GET")
+ uiRouter.HandleFunc("/category/{categoryID}/edit", handler.showEditCategoryPage).Name("editCategory").Methods("GET")
+ uiRouter.HandleFunc("/category/{categoryID}/update", handler.updateCategory).Name("updateCategory").Methods("POST")
+ uiRouter.HandleFunc("/category/{categoryID}/remove", handler.removeCategory).Name("removeCategory").Methods("POST")
+
+ // Entry pages.
+ uiRouter.HandleFunc("/entry/status", handler.updateEntriesStatus).Name("updateEntriesStatus").Methods("POST")
+ uiRouter.HandleFunc("/entry/save/{entryID}", handler.saveEntry).Name("saveEntry").Methods("POST")
+ uiRouter.HandleFunc("/entry/download/{entryID}", handler.fetchContent).Name("fetchContent").Methods("POST")
+ uiRouter.HandleFunc("/proxy/{encodedURL}", handler.imageProxy).Name("proxy").Methods("GET")
+ uiRouter.HandleFunc("/entry/bookmark/{entryID}", handler.toggleBookmark).Name("toggleBookmark").Methods("POST")
+
+ // User pages.
+ uiRouter.HandleFunc("/users", handler.showUsersPage).Name("users").Methods("GET")
+ uiRouter.HandleFunc("/user/create", handler.showCreateUserPage).Name("createUser").Methods("GET")
+ uiRouter.HandleFunc("/user/save", handler.saveUser).Name("saveUser").Methods("POST")
+ uiRouter.HandleFunc("/users/{userID}/edit", handler.showEditUserPage).Name("editUser").Methods("GET")
+ uiRouter.HandleFunc("/users/{userID}/update", handler.updateUser).Name("updateUser").Methods("POST")
+ uiRouter.HandleFunc("/users/{userID}/remove", handler.removeUser).Name("removeUser").Methods("POST")
+
+ // Settings pages.
+ uiRouter.HandleFunc("/settings", handler.showSettingsPage).Name("settings").Methods("GET")
+ uiRouter.HandleFunc("/settings", handler.updateSettings).Name("updateSettings").Methods("POST")
+ uiRouter.HandleFunc("/integrations", handler.showIntegrationPage).Name("integrations").Methods("GET")
+ uiRouter.HandleFunc("/integration", handler.updateIntegration).Name("updateIntegration").Methods("POST")
+ uiRouter.HandleFunc("/integration/pocket/authorize", handler.pocketAuthorize).Name("pocketAuthorize").Methods("GET")
+ uiRouter.HandleFunc("/integration/pocket/callback", handler.pocketCallback).Name("pocketCallback").Methods("GET")
+ uiRouter.HandleFunc("/about", handler.showAboutPage).Name("about").Methods("GET")
+
+ // Session pages.
+ uiRouter.HandleFunc("/sessions", handler.showSessionsPage).Name("sessions").Methods("GET")
+ uiRouter.HandleFunc("/sessions/{sessionID}/remove", handler.removeSession).Name("removeSession").Methods("POST")
+
+ // OPML pages.
+ uiRouter.HandleFunc("/export", handler.exportFeeds).Name("export").Methods("GET")
+ uiRouter.HandleFunc("/import", handler.showImportPage).Name("import").Methods("GET")
+ uiRouter.HandleFunc("/upload", handler.uploadOPML).Name("uploadOPML").Methods("POST")
+
+ // OAuth2 flow.
+ uiRouter.HandleFunc("/oauth2/{provider}/unlink", handler.oauth2Unlink).Name("oauth2Unlink").Methods("GET")
+ uiRouter.HandleFunc("/oauth2/{provider}/redirect", handler.oauth2Redirect).Name("oauth2Redirect").Methods("GET")
+ uiRouter.HandleFunc("/oauth2/{provider}/callback", handler.oauth2Callback).Name("oauth2Callback").Methods("GET")
+
+ // Authentication pages.
+ uiRouter.HandleFunc("/login", handler.checkLogin).Name("checkLogin").Methods("POST")
+ uiRouter.HandleFunc("/logout", handler.logout).Name("logout").Methods("GET")
+ uiRouter.HandleFunc("/", handler.showLoginPage).Name("login").Methods("GET")
+
+ router.HandleFunc("/healthcheck", func(w http.ResponseWriter, r *http.Request) {
+ w.Write([]byte("OK"))
+ }).Name("healthcheck")
+
+ router.HandleFunc("/robots.txt", func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "text/plain")
+ w.Write([]byte("User-agent: *\nDisallow: /"))
+ }).Name("robots")
+}
diff --git a/ui/unread_entries.go b/ui/unread_entries.go
index cb02428..c49fc30 100644
--- a/ui/unread_entries.go
+++ b/ui/unread_entries.go
@@ -15,19 +15,18 @@ import (
"miniflux.app/ui/view"
)
-// ShowUnreadPage render the page with all unread entries.
-func (c *Controller) ShowUnreadPage(w http.ResponseWriter, r *http.Request) {
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+func (h *handler) showUnreadPage(w http.ResponseWriter, r *http.Request) {
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
- user, err := c.store.UserByID(request.UserID(r))
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
offset := request.QueryIntParam(r, "offset", 0)
- builder := c.store.NewEntryQueryBuilder(user.ID)
+ builder := h.store.NewEntryQueryBuilder(user.ID)
builder.WithStatus(model.EntryStatusUnread)
countUnread, err := builder.CountEntries()
if err != nil {
@@ -39,7 +38,7 @@ func (c *Controller) ShowUnreadPage(w http.ResponseWriter, r *http.Request) {
offset = 0
}
- builder = c.store.NewEntryQueryBuilder(user.ID)
+ builder = h.store.NewEntryQueryBuilder(user.ID)
builder.WithStatus(model.EntryStatusUnread)
builder.WithOrder(model.DefaultSortingOrder)
builder.WithDirection(user.EntryDirection)
@@ -52,12 +51,12 @@ func (c *Controller) ShowUnreadPage(w http.ResponseWriter, r *http.Request) {
}
view.Set("entries", entries)
- view.Set("pagination", c.getPagination(route.Path(c.router, "unread"), countUnread, offset))
+ view.Set("pagination", getPagination(route.Path(h.router, "unread"), countUnread, offset))
view.Set("menu", "unread")
view.Set("user", user)
view.Set("countUnread", countUnread)
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
- view.Set("hasSaveEntry", c.store.HasSaveEntry(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
+ view.Set("hasSaveEntry", h.store.HasSaveEntry(user.ID))
html.OK(w, r, view.Render("unread_entries"))
}
diff --git a/ui/unread_mark_all_read.go b/ui/unread_mark_all_read.go
index 724da67..c7b9fa0 100644
--- a/ui/unread_mark_all_read.go
+++ b/ui/unread_mark_all_read.go
@@ -13,11 +13,10 @@ import (
"miniflux.app/logger"
)
-// MarkAllAsRead marks all unread entries as read.
-func (c *Controller) MarkAllAsRead(w http.ResponseWriter, r *http.Request) {
- if err := c.store.MarkAllAsRead(request.UserID(r)); err != nil {
+func (h *handler) markAllAsRead(w http.ResponseWriter, r *http.Request) {
+ if err := h.store.MarkAllAsRead(request.UserID(r)); err != nil {
logger.Error("[MarkAllAsRead] %v", err)
}
- html.Redirect(w, r, route.Path(c.router, "unread"))
+ html.Redirect(w, r, route.Path(h.router, "unread"))
}
diff --git a/ui/user_create.go b/ui/user_create.go
index a94d286..c3269b2 100644
--- a/ui/user_create.go
+++ b/ui/user_create.go
@@ -14,12 +14,11 @@ import (
"miniflux.app/ui/view"
)
-// CreateUser shows the user creation form.
-func (c *Controller) CreateUser(w http.ResponseWriter, r *http.Request) {
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+func (h *handler) showCreateUserPage(w http.ResponseWriter, r *http.Request) {
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
- user, err := c.store.UserByID(request.UserID(r))
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
@@ -33,8 +32,8 @@ func (c *Controller) CreateUser(w http.ResponseWriter, r *http.Request) {
view.Set("form", &form.UserForm{})
view.Set("menu", "settings")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
html.OK(w, r, view.Render("create_user"))
}
diff --git a/ui/user_edit.go b/ui/user_edit.go
index 2348a7d..3d0289c 100644
--- a/ui/user_edit.go
+++ b/ui/user_edit.go
@@ -15,11 +15,11 @@ import (
)
// EditUser shows the form to edit a user.
-func (c *Controller) EditUser(w http.ResponseWriter, r *http.Request) {
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+func (h *handler) showEditUserPage(w http.ResponseWriter, r *http.Request) {
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
- user, err := c.store.UserByID(request.UserID(r))
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
@@ -31,7 +31,7 @@ func (c *Controller) EditUser(w http.ResponseWriter, r *http.Request) {
}
userID := request.RouteInt64Param(r, "userID")
- selectedUser, err := c.store.UserByID(userID)
+ selectedUser, err := h.store.UserByID(userID)
if err != nil {
html.ServerError(w, r, err)
return
@@ -51,8 +51,8 @@ func (c *Controller) EditUser(w http.ResponseWriter, r *http.Request) {
view.Set("selected_user", selectedUser)
view.Set("menu", "settings")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
html.OK(w, r, view.Render("edit_user"))
}
diff --git a/ui/user_list.go b/ui/user_list.go
index 3c9e3ed..37850c7 100644
--- a/ui/user_list.go
+++ b/ui/user_list.go
@@ -13,12 +13,11 @@ import (
"miniflux.app/ui/view"
)
-// ShowUsers renders the list of users.
-func (c *Controller) ShowUsers(w http.ResponseWriter, r *http.Request) {
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+func (h *handler) showUsersPage(w http.ResponseWriter, r *http.Request) {
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
- user, err := c.store.UserByID(request.UserID(r))
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
@@ -29,7 +28,7 @@ func (c *Controller) ShowUsers(w http.ResponseWriter, r *http.Request) {
return
}
- users, err := c.store.Users()
+ users, err := h.store.Users()
if err != nil {
html.ServerError(w, r, err)
return
@@ -40,8 +39,8 @@ func (c *Controller) ShowUsers(w http.ResponseWriter, r *http.Request) {
view.Set("users", users)
view.Set("menu", "settings")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
html.OK(w, r, view.Render("users"))
}
diff --git a/ui/user_remove.go b/ui/user_remove.go
index beda7be..6564ca3 100644
--- a/ui/user_remove.go
+++ b/ui/user_remove.go
@@ -12,9 +12,8 @@ import (
"miniflux.app/http/route"
)
-// RemoveUser deletes a user from the database.
-func (c *Controller) RemoveUser(w http.ResponseWriter, r *http.Request) {
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) removeUser(w http.ResponseWriter, r *http.Request) {
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
@@ -26,7 +25,7 @@ func (c *Controller) RemoveUser(w http.ResponseWriter, r *http.Request) {
}
userID := request.RouteInt64Param(r, "userID")
- selectedUser, err := c.store.UserByID(userID)
+ selectedUser, err := h.store.UserByID(userID)
if err != nil {
html.ServerError(w, r, err)
return
@@ -37,10 +36,10 @@ func (c *Controller) RemoveUser(w http.ResponseWriter, r *http.Request) {
return
}
- if err := c.store.RemoveUser(selectedUser.ID); err != nil {
+ if err := h.store.RemoveUser(selectedUser.ID); err != nil {
html.ServerError(w, r, err)
return
}
- html.Redirect(w, r, route.Path(c.router, "users"))
+ html.Redirect(w, r, route.Path(h.router, "users"))
}
diff --git a/ui/user_save.go b/ui/user_save.go
index a4be346..f13ac0a 100644
--- a/ui/user_save.go
+++ b/ui/user_save.go
@@ -16,9 +16,8 @@ import (
"miniflux.app/ui/view"
)
-// SaveUser validate and save the new user into the database.
-func (c *Controller) SaveUser(w http.ResponseWriter, r *http.Request) {
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) saveUser(w http.ResponseWriter, r *http.Request) {
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
@@ -31,12 +30,12 @@ func (c *Controller) SaveUser(w http.ResponseWriter, r *http.Request) {
userForm := form.NewUserForm(r)
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
view.Set("menu", "settings")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
view.Set("form", userForm)
if err := userForm.ValidateCreation(); err != nil {
@@ -45,19 +44,19 @@ func (c *Controller) SaveUser(w http.ResponseWriter, r *http.Request) {
return
}
- if c.store.UserExists(userForm.Username) {
+ if h.store.UserExists(userForm.Username) {
view.Set("errorMessage", "error.user_already_exists")
html.OK(w, r, view.Render("create_user"))
return
}
newUser := userForm.ToUser()
- if err := c.store.CreateUser(newUser); err != nil {
+ if err := h.store.CreateUser(newUser); err != nil {
logger.Error("[Controller:SaveUser] %v", err)
view.Set("errorMessage", "error.unable_to_create_user")
html.OK(w, r, view.Render("create_user"))
return
}
- html.Redirect(w, r, route.Path(c.router, "users"))
+ html.Redirect(w, r, route.Path(h.router, "users"))
}
diff --git a/ui/user_update.go b/ui/user_update.go
index 34567e0..85f1501 100644
--- a/ui/user_update.go
+++ b/ui/user_update.go
@@ -16,9 +16,8 @@ import (
"miniflux.app/ui/view"
)
-// UpdateUser validate and update a user.
-func (c *Controller) UpdateUser(w http.ResponseWriter, r *http.Request) {
- user, err := c.store.UserByID(request.UserID(r))
+func (h *handler) updateUser(w http.ResponseWriter, r *http.Request) {
+ user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
@@ -30,7 +29,7 @@ func (c *Controller) UpdateUser(w http.ResponseWriter, r *http.Request) {
}
userID := request.RouteInt64Param(r, "userID")
- selectedUser, err := c.store.UserByID(userID)
+ selectedUser, err := h.store.UserByID(userID)
if err != nil {
html.ServerError(w, r, err)
return
@@ -43,12 +42,12 @@ func (c *Controller) UpdateUser(w http.ResponseWriter, r *http.Request) {
userForm := form.NewUserForm(r)
- sess := session.New(c.store, request.SessionID(r))
- view := view.New(c.tpl, r, sess)
+ sess := session.New(h.store, request.SessionID(r))
+ view := view.New(h.tpl, r, sess)
view.Set("menu", "settings")
view.Set("user", user)
- view.Set("countUnread", c.store.CountUnreadEntries(user.ID))
- view.Set("countErrorFeeds", c.store.CountErrorFeeds(user.ID))
+ view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
+ view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
view.Set("selected_user", selectedUser)
view.Set("form", userForm)
@@ -58,19 +57,19 @@ func (c *Controller) UpdateUser(w http.ResponseWriter, r *http.Request) {
return
}
- if c.store.AnotherUserExists(selectedUser.ID, userForm.Username) {
+ if h.store.AnotherUserExists(selectedUser.ID, userForm.Username) {
view.Set("errorMessage", "error.user_already_exists")
html.OK(w, r, view.Render("edit_user"))
return
}
userForm.Merge(selectedUser)
- if err := c.store.UpdateUser(selectedUser); err != nil {
+ if err := h.store.UpdateUser(selectedUser); err != nil {
logger.Error("[Controller:UpdateUser] %v", err)
view.Set("errorMessage", "error.unable_to_update_user")
html.OK(w, r, view.Render("edit_user"))
return
}
- html.Redirect(w, r, route.Path(c.router, "users"))
+ html.Redirect(w, r, route.Path(h.router, "users"))
}