ui.go 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
  2. // SPDX-License-Identifier: Apache-2.0
  3. package ui // import "miniflux.app/v2/internal/ui"
  4. import (
  5. "net/http"
  6. "miniflux.app/v2/internal/config"
  7. "miniflux.app/v2/internal/storage"
  8. "miniflux.app/v2/internal/template"
  9. "miniflux.app/v2/internal/worker"
  10. )
  11. // Serve returns an http.Handler that serves the user interface.
  12. // The returned handler expects the base path to be stripped from the request URL.
  13. func Serve(store *storage.Storage, pool *worker.Pool) http.Handler {
  14. basePath := config.Opts.BasePath()
  15. middleware := newMiddleware(basePath, store)
  16. templateEngine := template.NewEngine(basePath)
  17. templateEngine.ParseTemplates()
  18. handler := &handler{basePath, store, templateEngine, pool}
  19. mux := http.NewServeMux()
  20. // Static assets.
  21. mux.HandleFunc("GET /stylesheets/{checksum}/{filename}", handler.showStylesheet)
  22. mux.HandleFunc("GET /js/{checksum}/{filename}", handler.showJavascript)
  23. mux.HandleFunc("GET /icon/{checksum}/{filename}", handler.showAppIcon)
  24. mux.HandleFunc("GET /favicon.ico", handler.showFavicon)
  25. mux.HandleFunc("GET /manifest.json", handler.showWebManifest)
  26. // New subscription pages.
  27. mux.HandleFunc("GET /subscribe", handler.showAddSubscriptionPage)
  28. mux.HandleFunc("POST /subscribe", handler.submitSubscription)
  29. mux.HandleFunc("POST /subscriptions", handler.showChooseSubscriptionPage)
  30. mux.HandleFunc("GET /bookmarklet", handler.bookmarklet)
  31. // Unread page.
  32. mux.HandleFunc("POST /mark-all-as-read", handler.markAllAsRead)
  33. mux.HandleFunc("GET /unread", handler.showUnreadPage)
  34. mux.HandleFunc("GET /unread/entry/{entryID}", handler.showUnreadEntryPage)
  35. // History pages.
  36. mux.HandleFunc("GET /history", handler.showHistoryPage)
  37. mux.HandleFunc("GET /history/entry/{entryID}", handler.showReadEntryPage)
  38. mux.HandleFunc("POST /history/flush", handler.flushHistory)
  39. // Starred pages.
  40. mux.HandleFunc("GET /starred", handler.showStarredPage)
  41. mux.HandleFunc("GET /starred/entry/{entryID}", handler.showStarredEntryPage)
  42. // Search pages.
  43. mux.HandleFunc("GET /search", handler.showSearchPage)
  44. mux.HandleFunc("GET /search/entry/{entryID}", handler.showSearchEntryPage)
  45. // Feed listing pages.
  46. mux.HandleFunc("GET /feeds", handler.showFeedsPage)
  47. mux.HandleFunc("GET /feeds/refresh", handler.refreshAllFeeds)
  48. // Individual feed pages.
  49. mux.HandleFunc("GET /feed/{feedID}/refresh", handler.refreshFeed)
  50. mux.HandleFunc("POST /feed/{feedID}/refresh", handler.refreshFeed)
  51. mux.HandleFunc("GET /feed/{feedID}/edit", handler.showEditFeedPage)
  52. mux.HandleFunc("POST /feed/{feedID}/remove", handler.removeFeed)
  53. mux.HandleFunc("POST /feed/{feedID}/update", handler.updateFeed)
  54. mux.HandleFunc("GET /feed/{feedID}/entries", handler.showFeedEntriesPage)
  55. mux.HandleFunc("GET /feed/{feedID}/entries/all", handler.showFeedEntriesAllPage)
  56. mux.HandleFunc("GET /feed/{feedID}/entry/{entryID}", handler.showFeedEntryPage)
  57. mux.HandleFunc("GET /unread/feed/{feedID}/entry/{entryID}", handler.showUnreadFeedEntryPage)
  58. mux.HandleFunc("POST /feed/{feedID}/mark-all-as-read", handler.markFeedAsRead)
  59. mux.HandleFunc("GET /feed-icon/{externalIconID}", handler.showFeedIcon)
  60. // Category pages.
  61. mux.HandleFunc("GET /category/{categoryID}/entry/{entryID}", handler.showCategoryEntryPage)
  62. mux.HandleFunc("GET /unread/category/{categoryID}/entry/{entryID}", handler.showUnreadCategoryEntryPage)
  63. mux.HandleFunc("GET /starred/category/{categoryID}/entry/{entryID}", handler.showStarredCategoryEntryPage)
  64. mux.HandleFunc("GET /categories", handler.showCategoryListPage)
  65. mux.HandleFunc("GET /category/create", handler.showCreateCategoryPage)
  66. mux.HandleFunc("POST /category/save", handler.saveCategory)
  67. mux.HandleFunc("GET /category/{categoryID}/feeds", handler.showCategoryFeedsPage)
  68. mux.HandleFunc("POST /category/{categoryID}/feed/{feedID}/remove", handler.removeCategoryFeed)
  69. mux.HandleFunc("POST /category/{categoryID}/feed/{feedID}/mark-all-as-read", handler.markCategoryFeedAsRead)
  70. mux.HandleFunc("GET /category/{categoryID}/feeds/refresh", handler.refreshCategoryFeedsPage)
  71. mux.HandleFunc("GET /category/{categoryID}/entries", handler.showCategoryEntriesPage)
  72. mux.HandleFunc("GET /category/{categoryID}/entries/refresh", handler.refreshCategoryEntriesPage)
  73. mux.HandleFunc("GET /category/{categoryID}/entries/all", handler.showCategoryEntriesAllPage)
  74. mux.HandleFunc("GET /category/{categoryID}/entries/starred", handler.showCategoryEntriesStarredPage)
  75. mux.HandleFunc("GET /category/{categoryID}/edit", handler.showEditCategoryPage)
  76. mux.HandleFunc("POST /category/{categoryID}/update", handler.updateCategory)
  77. mux.HandleFunc("POST /category/{categoryID}/remove", handler.removeCategory)
  78. mux.HandleFunc("POST /category/{categoryID}/mark-all-as-read", handler.markCategoryAsRead)
  79. // Tag pages.
  80. mux.HandleFunc("GET /tags/{tagName}/entries/all", handler.showTagEntriesAllPage)
  81. mux.HandleFunc("GET /tags/{tagName}/entry/{entryID}", handler.showTagEntryPage)
  82. // Entry pages.
  83. mux.HandleFunc("POST /entry/status", handler.updateEntriesStatus)
  84. mux.HandleFunc("POST /entry/save/{entryID}", handler.saveEntry)
  85. mux.HandleFunc("POST /entry/enclosure/{enclosureID}/save-progression", handler.saveEnclosureProgression)
  86. mux.HandleFunc("POST /entry/download/{entryID}", handler.fetchContent)
  87. mux.HandleFunc("POST /entry/star/{entryID}", handler.toggleStarred)
  88. // Media proxy.
  89. mux.HandleFunc("GET /proxy/{encodedDigest}/{encodedURL}", handler.mediaProxy)
  90. // Share pages.
  91. mux.HandleFunc("POST /entry/share/{entryID}", handler.createSharedEntry)
  92. mux.HandleFunc("POST /entry/unshare/{entryID}", handler.unshareEntry)
  93. mux.HandleFunc("GET /share/{shareCode}", handler.sharedEntry)
  94. mux.HandleFunc("GET /shares", handler.sharedEntries)
  95. // User pages.
  96. mux.HandleFunc("GET /users", handler.showUsersPage)
  97. mux.HandleFunc("GET /user/create", handler.showCreateUserPage)
  98. mux.HandleFunc("POST /user/save", handler.saveUser)
  99. mux.HandleFunc("GET /users/{userID}/edit", handler.showEditUserPage)
  100. mux.HandleFunc("POST /users/{userID}/update", handler.updateUser)
  101. mux.HandleFunc("POST /users/{userID}/remove", handler.removeUser)
  102. // Settings pages.
  103. mux.HandleFunc("GET /settings", handler.showSettingsPage)
  104. mux.HandleFunc("POST /settings", handler.updateSettings)
  105. mux.HandleFunc("GET /integrations", handler.showIntegrationPage)
  106. mux.HandleFunc("POST /integration", handler.updateIntegration)
  107. mux.HandleFunc("GET /about", handler.showAboutPage)
  108. // Session pages.
  109. mux.HandleFunc("GET /sessions", handler.showSessionsPage)
  110. mux.HandleFunc("POST /sessions/{sessionID}/remove", handler.removeSession)
  111. // API Keys pages.
  112. if config.Opts.HasAPI() {
  113. mux.HandleFunc("GET /keys", handler.showAPIKeysPage)
  114. mux.HandleFunc("POST /keys/{keyID}/delete", handler.deleteAPIKey)
  115. mux.HandleFunc("GET /keys/create", handler.showCreateAPIKeyPage)
  116. mux.HandleFunc("POST /keys/save", handler.saveAPIKey)
  117. }
  118. // OPML pages.
  119. mux.HandleFunc("GET /export", handler.exportFeeds)
  120. mux.HandleFunc("GET /import", handler.showImportPage)
  121. mux.HandleFunc("POST /upload", handler.uploadOPML)
  122. mux.HandleFunc("POST /fetch", handler.fetchOPML)
  123. // OAuth2 flow.
  124. if config.Opts.OAuth2Provider() != "" {
  125. mux.HandleFunc("GET /oauth2/{provider}/unlink", handler.oauth2Unlink)
  126. mux.HandleFunc("GET /oauth2/{provider}/redirect", handler.oauth2Redirect)
  127. mux.HandleFunc("GET /oauth2/{provider}/callback", handler.oauth2Callback)
  128. }
  129. // Offline page.
  130. mux.HandleFunc("GET /offline", handler.showOfflinePage)
  131. // Authentication pages.
  132. mux.HandleFunc("POST /login", handler.checkLogin)
  133. mux.HandleFunc("GET /logout", handler.logout)
  134. mux.Handle("GET /{$}", middleware.handleAuthProxy(http.HandlerFunc(handler.showLoginPage)))
  135. // WebAuthn flow.
  136. if config.Opts.WebAuthn() {
  137. mux.HandleFunc("GET /webauthn/register/begin", handler.beginRegistration)
  138. mux.HandleFunc("POST /webauthn/register/finish", handler.finishRegistration)
  139. mux.HandleFunc("GET /webauthn/login/begin", handler.beginLogin)
  140. mux.HandleFunc("POST /webauthn/login/finish", handler.finishLogin)
  141. mux.HandleFunc("POST /webauthn/deleteall", handler.deleteAllCredentials)
  142. mux.HandleFunc("POST /webauthn/{credentialHandle}/delete", handler.deleteCredential)
  143. mux.HandleFunc("GET /webauthn/{credentialHandle}/rename", handler.renameCredential)
  144. mux.HandleFunc("POST /webauthn/{credentialHandle}/save", handler.saveCredential)
  145. }
  146. // robots.txt
  147. mux.HandleFunc("GET /robots.txt", func(w http.ResponseWriter, r *http.Request) {
  148. w.Header().Set("Content-Type", "text/plain")
  149. w.Write([]byte("User-agent: *\nDisallow: /"))
  150. })
  151. // Apply middleware chain: user session then app session.
  152. return middleware.handleUserSession(middleware.handleAppSession(mux))
  153. }