options.go 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835
  1. // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
  2. // SPDX-License-Identifier: Apache-2.0
  3. package config // import "miniflux.app/v2/internal/config"
  4. import (
  5. "fmt"
  6. "net/url"
  7. "sort"
  8. "strings"
  9. "time"
  10. "miniflux.app/v2/internal/crypto"
  11. "miniflux.app/v2/internal/version"
  12. )
  13. const (
  14. defaultHTTPS = false
  15. defaultLogFile = "stderr"
  16. defaultLogDateTime = false
  17. defaultLogFormat = "text"
  18. defaultLogLevel = "info"
  19. defaultHSTS = true
  20. defaultHTTPService = true
  21. defaultSchedulerService = true
  22. defaultDebug = false
  23. defaultTiming = false
  24. defaultBaseURL = "http://localhost"
  25. defaultRootURL = "http://localhost"
  26. defaultBasePath = ""
  27. defaultWorkerPoolSize = 16
  28. defaultPollingFrequency = 60
  29. defaultForceRefreshInterval = 30
  30. defaultBatchSize = 100
  31. defaultPollingScheduler = "round_robin"
  32. defaultSchedulerEntryFrequencyMinInterval = 5
  33. defaultSchedulerEntryFrequencyMaxInterval = 24 * 60
  34. defaultSchedulerEntryFrequencyFactor = 1
  35. defaultSchedulerRoundRobinMinInterval = 60
  36. defaultSchedulerRoundRobinMaxInterval = 1440
  37. defaultPollingParsingErrorLimit = 3
  38. defaultRunMigrations = false
  39. defaultDatabaseURL = "user=postgres password=postgres dbname=miniflux2 sslmode=disable"
  40. defaultDatabaseMaxConns = 20
  41. defaultDatabaseMinConns = 1
  42. defaultDatabaseConnectionLifetime = 5
  43. defaultListenAddr = "127.0.0.1:8080"
  44. defaultCertFile = ""
  45. defaultKeyFile = ""
  46. defaultCertDomain = ""
  47. defaultCleanupFrequencyHours = 24
  48. defaultCleanupArchiveReadDays = 60
  49. defaultCleanupArchiveUnreadDays = 180
  50. defaultCleanupArchiveBatchSize = 10000
  51. defaultCleanupRemoveSessionsDays = 30
  52. defaultMediaProxyHTTPClientTimeout = 120
  53. defaultMediaProxyMode = "http-only"
  54. defaultMediaResourceTypes = "image"
  55. defaultMediaProxyURL = ""
  56. defaultFilterEntryMaxAgeDays = 0
  57. defaultFetchBilibiliWatchTime = false
  58. defaultFetchNebulaWatchTime = false
  59. defaultFetchOdyseeWatchTime = false
  60. defaultFetchYouTubeWatchTime = false
  61. defaultYouTubeApiKey = ""
  62. defaultYouTubeEmbedUrlOverride = "https://www.youtube-nocookie.com/embed/"
  63. defaultCreateAdmin = false
  64. defaultAdminUsername = ""
  65. defaultAdminPassword = ""
  66. defaultOAuth2UserCreation = false
  67. defaultOAuth2ClientID = ""
  68. defaultOAuth2ClientSecret = ""
  69. defaultOAuth2RedirectURL = ""
  70. defaultOAuth2OidcDiscoveryEndpoint = ""
  71. defaultOauth2OidcProviderName = "OpenID Connect"
  72. defaultOAuth2Provider = ""
  73. defaultDisableLocalAuth = false
  74. defaultPocketConsumerKey = ""
  75. defaultHTTPClientTimeout = 20
  76. defaultHTTPClientMaxBodySize = 15
  77. defaultHTTPClientProxy = ""
  78. defaultHTTPServerTimeout = 300
  79. defaultAuthProxyHeader = ""
  80. defaultAuthProxyUserCreation = false
  81. defaultMaintenanceMode = false
  82. defaultMaintenanceMessage = "Miniflux is currently under maintenance"
  83. defaultMetricsCollector = false
  84. defaultMetricsRefreshInterval = 60
  85. defaultMetricsAllowedNetworks = "127.0.0.1/8"
  86. defaultMetricsUsername = ""
  87. defaultMetricsPassword = ""
  88. defaultWatchdog = true
  89. defaultInvidiousInstance = "yewtu.be"
  90. defaultWebAuthn = false
  91. )
  92. var defaultHTTPClientUserAgent = "Mozilla/5.0 (compatible; Miniflux/" + version.Version + "; +https://miniflux.app)"
  93. // Option contains a key to value map of a single option. It may be used to output debug strings.
  94. type Option struct {
  95. Key string
  96. Value interface{}
  97. }
  98. // Options contains configuration options.
  99. type Options struct {
  100. HTTPS bool
  101. logFile string
  102. logDateTime bool
  103. logFormat string
  104. logLevel string
  105. hsts bool
  106. httpService bool
  107. schedulerService bool
  108. serverTimingHeader bool
  109. baseURL string
  110. rootURL string
  111. basePath string
  112. databaseURL string
  113. databaseMaxConns int
  114. databaseMinConns int
  115. databaseConnectionLifetime int
  116. runMigrations bool
  117. listenAddr string
  118. certFile string
  119. certDomain string
  120. certKeyFile string
  121. cleanupFrequencyHours int
  122. cleanupArchiveReadDays int
  123. cleanupArchiveUnreadDays int
  124. cleanupArchiveBatchSize int
  125. cleanupRemoveSessionsDays int
  126. pollingFrequency int
  127. forceRefreshInterval int
  128. batchSize int
  129. pollingScheduler string
  130. schedulerEntryFrequencyMinInterval int
  131. schedulerEntryFrequencyMaxInterval int
  132. schedulerEntryFrequencyFactor int
  133. schedulerRoundRobinMinInterval int
  134. schedulerRoundRobinMaxInterval int
  135. pollingParsingErrorLimit int
  136. workerPoolSize int
  137. createAdmin bool
  138. adminUsername string
  139. adminPassword string
  140. mediaProxyHTTPClientTimeout int
  141. mediaProxyMode string
  142. mediaProxyResourceTypes []string
  143. mediaProxyCustomURL string
  144. fetchBilibiliWatchTime bool
  145. fetchNebulaWatchTime bool
  146. fetchOdyseeWatchTime bool
  147. fetchYouTubeWatchTime bool
  148. filterEntryMaxAgeDays int
  149. youTubeApiKey string
  150. youTubeEmbedUrlOverride string
  151. youTubeEmbedDomain string
  152. oauth2UserCreationAllowed bool
  153. oauth2ClientID string
  154. oauth2ClientSecret string
  155. oauth2RedirectURL string
  156. oidcDiscoveryEndpoint string
  157. oidcProviderName string
  158. oauth2Provider string
  159. disableLocalAuth bool
  160. pocketConsumerKey string
  161. httpClientTimeout int
  162. httpClientMaxBodySize int64
  163. httpClientProxyURL *url.URL
  164. httpClientProxies []string
  165. httpClientUserAgent string
  166. httpServerTimeout int
  167. authProxyHeader string
  168. authProxyUserCreation bool
  169. maintenanceMode bool
  170. maintenanceMessage string
  171. metricsCollector bool
  172. metricsRefreshInterval int
  173. metricsAllowedNetworks []string
  174. metricsUsername string
  175. metricsPassword string
  176. watchdog bool
  177. invidiousInstance string
  178. mediaProxyPrivateKey []byte
  179. webAuthn bool
  180. }
  181. // NewOptions returns Options with default values.
  182. func NewOptions() *Options {
  183. return &Options{
  184. HTTPS: defaultHTTPS,
  185. logFile: defaultLogFile,
  186. logDateTime: defaultLogDateTime,
  187. logFormat: defaultLogFormat,
  188. logLevel: defaultLogLevel,
  189. hsts: defaultHSTS,
  190. httpService: defaultHTTPService,
  191. schedulerService: defaultSchedulerService,
  192. serverTimingHeader: defaultTiming,
  193. baseURL: defaultBaseURL,
  194. rootURL: defaultRootURL,
  195. basePath: defaultBasePath,
  196. databaseURL: defaultDatabaseURL,
  197. databaseMaxConns: defaultDatabaseMaxConns,
  198. databaseMinConns: defaultDatabaseMinConns,
  199. databaseConnectionLifetime: defaultDatabaseConnectionLifetime,
  200. runMigrations: defaultRunMigrations,
  201. listenAddr: defaultListenAddr,
  202. certFile: defaultCertFile,
  203. certDomain: defaultCertDomain,
  204. certKeyFile: defaultKeyFile,
  205. cleanupFrequencyHours: defaultCleanupFrequencyHours,
  206. cleanupArchiveReadDays: defaultCleanupArchiveReadDays,
  207. cleanupArchiveUnreadDays: defaultCleanupArchiveUnreadDays,
  208. cleanupArchiveBatchSize: defaultCleanupArchiveBatchSize,
  209. cleanupRemoveSessionsDays: defaultCleanupRemoveSessionsDays,
  210. pollingFrequency: defaultPollingFrequency,
  211. forceRefreshInterval: defaultForceRefreshInterval,
  212. batchSize: defaultBatchSize,
  213. pollingScheduler: defaultPollingScheduler,
  214. schedulerEntryFrequencyMinInterval: defaultSchedulerEntryFrequencyMinInterval,
  215. schedulerEntryFrequencyMaxInterval: defaultSchedulerEntryFrequencyMaxInterval,
  216. schedulerEntryFrequencyFactor: defaultSchedulerEntryFrequencyFactor,
  217. schedulerRoundRobinMinInterval: defaultSchedulerRoundRobinMinInterval,
  218. schedulerRoundRobinMaxInterval: defaultSchedulerRoundRobinMaxInterval,
  219. pollingParsingErrorLimit: defaultPollingParsingErrorLimit,
  220. workerPoolSize: defaultWorkerPoolSize,
  221. createAdmin: defaultCreateAdmin,
  222. mediaProxyHTTPClientTimeout: defaultMediaProxyHTTPClientTimeout,
  223. mediaProxyMode: defaultMediaProxyMode,
  224. mediaProxyResourceTypes: []string{defaultMediaResourceTypes},
  225. mediaProxyCustomURL: defaultMediaProxyURL,
  226. filterEntryMaxAgeDays: defaultFilterEntryMaxAgeDays,
  227. fetchBilibiliWatchTime: defaultFetchBilibiliWatchTime,
  228. fetchNebulaWatchTime: defaultFetchNebulaWatchTime,
  229. fetchOdyseeWatchTime: defaultFetchOdyseeWatchTime,
  230. fetchYouTubeWatchTime: defaultFetchYouTubeWatchTime,
  231. youTubeApiKey: defaultYouTubeApiKey,
  232. youTubeEmbedUrlOverride: defaultYouTubeEmbedUrlOverride,
  233. oauth2UserCreationAllowed: defaultOAuth2UserCreation,
  234. oauth2ClientID: defaultOAuth2ClientID,
  235. oauth2ClientSecret: defaultOAuth2ClientSecret,
  236. oauth2RedirectURL: defaultOAuth2RedirectURL,
  237. oidcDiscoveryEndpoint: defaultOAuth2OidcDiscoveryEndpoint,
  238. oidcProviderName: defaultOauth2OidcProviderName,
  239. oauth2Provider: defaultOAuth2Provider,
  240. disableLocalAuth: defaultDisableLocalAuth,
  241. pocketConsumerKey: defaultPocketConsumerKey,
  242. httpClientTimeout: defaultHTTPClientTimeout,
  243. httpClientMaxBodySize: defaultHTTPClientMaxBodySize * 1024 * 1024,
  244. httpClientProxyURL: nil,
  245. httpClientProxies: []string{},
  246. httpClientUserAgent: defaultHTTPClientUserAgent,
  247. httpServerTimeout: defaultHTTPServerTimeout,
  248. authProxyHeader: defaultAuthProxyHeader,
  249. authProxyUserCreation: defaultAuthProxyUserCreation,
  250. maintenanceMode: defaultMaintenanceMode,
  251. maintenanceMessage: defaultMaintenanceMessage,
  252. metricsCollector: defaultMetricsCollector,
  253. metricsRefreshInterval: defaultMetricsRefreshInterval,
  254. metricsAllowedNetworks: []string{defaultMetricsAllowedNetworks},
  255. metricsUsername: defaultMetricsUsername,
  256. metricsPassword: defaultMetricsPassword,
  257. watchdog: defaultWatchdog,
  258. invidiousInstance: defaultInvidiousInstance,
  259. mediaProxyPrivateKey: crypto.GenerateRandomBytes(16),
  260. webAuthn: defaultWebAuthn,
  261. }
  262. }
  263. func (o *Options) LogFile() string {
  264. return o.logFile
  265. }
  266. // LogDateTime returns true if the date/time should be displayed in log messages.
  267. func (o *Options) LogDateTime() bool {
  268. return o.logDateTime
  269. }
  270. // LogFormat returns the log format.
  271. func (o *Options) LogFormat() string {
  272. return o.logFormat
  273. }
  274. // LogLevel returns the log level.
  275. func (o *Options) LogLevel() string {
  276. return o.logLevel
  277. }
  278. // SetLogLevel sets the log level.
  279. func (o *Options) SetLogLevel(level string) {
  280. o.logLevel = level
  281. }
  282. // HasMaintenanceMode returns true if maintenance mode is enabled.
  283. func (o *Options) HasMaintenanceMode() bool {
  284. return o.maintenanceMode
  285. }
  286. // MaintenanceMessage returns maintenance message.
  287. func (o *Options) MaintenanceMessage() string {
  288. return o.maintenanceMessage
  289. }
  290. // HasServerTimingHeader returns true if server-timing headers enabled.
  291. func (o *Options) HasServerTimingHeader() bool {
  292. return o.serverTimingHeader
  293. }
  294. // BaseURL returns the application base URL with path.
  295. func (o *Options) BaseURL() string {
  296. return o.baseURL
  297. }
  298. // RootURL returns the base URL without path.
  299. func (o *Options) RootURL() string {
  300. return o.rootURL
  301. }
  302. // BasePath returns the application base path according to the base URL.
  303. func (o *Options) BasePath() string {
  304. return o.basePath
  305. }
  306. // IsDefaultDatabaseURL returns true if the default database URL is used.
  307. func (o *Options) IsDefaultDatabaseURL() bool {
  308. return o.databaseURL == defaultDatabaseURL
  309. }
  310. // DatabaseURL returns the database URL.
  311. func (o *Options) DatabaseURL() string {
  312. return o.databaseURL
  313. }
  314. // DatabaseMaxConns returns the maximum number of database connections.
  315. func (o *Options) DatabaseMaxConns() int {
  316. return o.databaseMaxConns
  317. }
  318. // DatabaseMinConns returns the minimum number of database connections.
  319. func (o *Options) DatabaseMinConns() int {
  320. return o.databaseMinConns
  321. }
  322. // DatabaseConnectionLifetime returns the maximum amount of time a connection may be reused.
  323. func (o *Options) DatabaseConnectionLifetime() time.Duration {
  324. return time.Duration(o.databaseConnectionLifetime) * time.Minute
  325. }
  326. // ListenAddr returns the listen address for the HTTP server.
  327. func (o *Options) ListenAddr() string {
  328. return o.listenAddr
  329. }
  330. // CertFile returns the SSL certificate filename if any.
  331. func (o *Options) CertFile() string {
  332. return o.certFile
  333. }
  334. // CertKeyFile returns the private key filename for custom SSL certificate.
  335. func (o *Options) CertKeyFile() string {
  336. return o.certKeyFile
  337. }
  338. // CertDomain returns the domain to use for Let's Encrypt certificate.
  339. func (o *Options) CertDomain() string {
  340. return o.certDomain
  341. }
  342. // CleanupFrequencyHours returns the interval in hours for cleanup jobs.
  343. func (o *Options) CleanupFrequencyHours() int {
  344. return o.cleanupFrequencyHours
  345. }
  346. // CleanupArchiveReadDays returns the number of days after which marking read items as removed.
  347. func (o *Options) CleanupArchiveReadDays() int {
  348. return o.cleanupArchiveReadDays
  349. }
  350. // CleanupArchiveUnreadDays returns the number of days after which marking unread items as removed.
  351. func (o *Options) CleanupArchiveUnreadDays() int {
  352. return o.cleanupArchiveUnreadDays
  353. }
  354. // CleanupArchiveBatchSize returns the number of entries to archive for each interval.
  355. func (o *Options) CleanupArchiveBatchSize() int {
  356. return o.cleanupArchiveBatchSize
  357. }
  358. // CleanupRemoveSessionsDays returns the number of days after which to remove sessions.
  359. func (o *Options) CleanupRemoveSessionsDays() int {
  360. return o.cleanupRemoveSessionsDays
  361. }
  362. // WorkerPoolSize returns the number of background worker.
  363. func (o *Options) WorkerPoolSize() int {
  364. return o.workerPoolSize
  365. }
  366. // PollingFrequency returns the interval to refresh feeds in the background.
  367. func (o *Options) PollingFrequency() int {
  368. return o.pollingFrequency
  369. }
  370. // ForceRefreshInterval returns the force refresh interval
  371. func (o *Options) ForceRefreshInterval() int {
  372. return o.forceRefreshInterval
  373. }
  374. // BatchSize returns the number of feeds to send for background processing.
  375. func (o *Options) BatchSize() int {
  376. return o.batchSize
  377. }
  378. // PollingScheduler returns the scheduler used for polling feeds.
  379. func (o *Options) PollingScheduler() string {
  380. return o.pollingScheduler
  381. }
  382. // SchedulerEntryFrequencyMaxInterval returns the maximum interval in minutes for the entry frequency scheduler.
  383. func (o *Options) SchedulerEntryFrequencyMaxInterval() int {
  384. return o.schedulerEntryFrequencyMaxInterval
  385. }
  386. // SchedulerEntryFrequencyMinInterval returns the minimum interval in minutes for the entry frequency scheduler.
  387. func (o *Options) SchedulerEntryFrequencyMinInterval() int {
  388. return o.schedulerEntryFrequencyMinInterval
  389. }
  390. // SchedulerEntryFrequencyFactor returns the factor for the entry frequency scheduler.
  391. func (o *Options) SchedulerEntryFrequencyFactor() int {
  392. return o.schedulerEntryFrequencyFactor
  393. }
  394. func (o *Options) SchedulerRoundRobinMinInterval() int {
  395. return o.schedulerRoundRobinMinInterval
  396. }
  397. func (o *Options) SchedulerRoundRobinMaxInterval() int {
  398. return o.schedulerRoundRobinMaxInterval
  399. }
  400. // PollingParsingErrorLimit returns the limit of errors when to stop polling.
  401. func (o *Options) PollingParsingErrorLimit() int {
  402. return o.pollingParsingErrorLimit
  403. }
  404. // IsOAuth2UserCreationAllowed returns true if user creation is allowed for OAuth2 users.
  405. func (o *Options) IsOAuth2UserCreationAllowed() bool {
  406. return o.oauth2UserCreationAllowed
  407. }
  408. // OAuth2ClientID returns the OAuth2 Client ID.
  409. func (o *Options) OAuth2ClientID() string {
  410. return o.oauth2ClientID
  411. }
  412. // OAuth2ClientSecret returns the OAuth2 client secret.
  413. func (o *Options) OAuth2ClientSecret() string {
  414. return o.oauth2ClientSecret
  415. }
  416. // OAuth2RedirectURL returns the OAuth2 redirect URL.
  417. func (o *Options) OAuth2RedirectURL() string {
  418. return o.oauth2RedirectURL
  419. }
  420. // OIDCDiscoveryEndpoint returns the OAuth2 OIDC discovery endpoint.
  421. func (o *Options) OIDCDiscoveryEndpoint() string {
  422. return o.oidcDiscoveryEndpoint
  423. }
  424. // OIDCProviderName returns the OAuth2 OIDC provider's display name
  425. func (o *Options) OIDCProviderName() string {
  426. return o.oidcProviderName
  427. }
  428. // OAuth2Provider returns the name of the OAuth2 provider configured.
  429. func (o *Options) OAuth2Provider() string {
  430. return o.oauth2Provider
  431. }
  432. // DisableLocalAUth returns true if the local user database should not be used to authenticate users
  433. func (o *Options) DisableLocalAuth() bool {
  434. return o.disableLocalAuth
  435. }
  436. // HasHSTS returns true if HTTP Strict Transport Security is enabled.
  437. func (o *Options) HasHSTS() bool {
  438. return o.hsts
  439. }
  440. // RunMigrations returns true if the environment variable RUN_MIGRATIONS is not empty.
  441. func (o *Options) RunMigrations() bool {
  442. return o.runMigrations
  443. }
  444. // CreateAdmin returns true if the environment variable CREATE_ADMIN is not empty.
  445. func (o *Options) CreateAdmin() bool {
  446. return o.createAdmin
  447. }
  448. // AdminUsername returns the admin username if defined.
  449. func (o *Options) AdminUsername() string {
  450. return o.adminUsername
  451. }
  452. // AdminPassword returns the admin password if defined.
  453. func (o *Options) AdminPassword() string {
  454. return o.adminPassword
  455. }
  456. // FetchYouTubeWatchTime returns true if the YouTube video duration
  457. // should be fetched and used as a reading time.
  458. func (o *Options) FetchYouTubeWatchTime() bool {
  459. return o.fetchYouTubeWatchTime
  460. }
  461. // YouTubeApiKey returns the YouTube API key if defined.
  462. func (o *Options) YouTubeApiKey() string {
  463. return o.youTubeApiKey
  464. }
  465. // YouTubeEmbedUrlOverride returns the YouTube embed URL override if defined.
  466. func (o *Options) YouTubeEmbedUrlOverride() string {
  467. return o.youTubeEmbedUrlOverride
  468. }
  469. // YouTubeEmbedDomain returns the domain used for YouTube embeds.
  470. func (o *Options) YouTubeEmbedDomain() string {
  471. if o.youTubeEmbedDomain != "" {
  472. return o.youTubeEmbedDomain
  473. }
  474. return "www.youtube-nocookie.com"
  475. }
  476. // FetchNebulaWatchTime returns true if the Nebula video duration
  477. // should be fetched and used as a reading time.
  478. func (o *Options) FetchNebulaWatchTime() bool {
  479. return o.fetchNebulaWatchTime
  480. }
  481. // FetchOdyseeWatchTime returns true if the Odysee video duration
  482. // should be fetched and used as a reading time.
  483. func (o *Options) FetchOdyseeWatchTime() bool {
  484. return o.fetchOdyseeWatchTime
  485. }
  486. // FetchBilibiliWatchTime returns true if the Bilibili video duration
  487. // should be fetched and used as a reading time.
  488. func (o *Options) FetchBilibiliWatchTime() bool {
  489. return o.fetchBilibiliWatchTime
  490. }
  491. // MediaProxyMode returns "none" to never proxy, "http-only" to proxy non-HTTPS, "all" to always proxy.
  492. func (o *Options) MediaProxyMode() string {
  493. return o.mediaProxyMode
  494. }
  495. // MediaProxyResourceTypes returns a slice of resource types to proxy.
  496. func (o *Options) MediaProxyResourceTypes() []string {
  497. return o.mediaProxyResourceTypes
  498. }
  499. // MediaCustomProxyURL returns the custom proxy URL for medias.
  500. func (o *Options) MediaCustomProxyURL() string {
  501. return o.mediaProxyCustomURL
  502. }
  503. // MediaProxyHTTPClientTimeout returns the time limit in seconds before the proxy HTTP client cancel the request.
  504. func (o *Options) MediaProxyHTTPClientTimeout() int {
  505. return o.mediaProxyHTTPClientTimeout
  506. }
  507. // MediaProxyPrivateKey returns the private key used by the media proxy.
  508. func (o *Options) MediaProxyPrivateKey() []byte {
  509. return o.mediaProxyPrivateKey
  510. }
  511. // HasHTTPService returns true if the HTTP service is enabled.
  512. func (o *Options) HasHTTPService() bool {
  513. return o.httpService
  514. }
  515. // HasSchedulerService returns true if the scheduler service is enabled.
  516. func (o *Options) HasSchedulerService() bool {
  517. return o.schedulerService
  518. }
  519. // PocketConsumerKey returns the Pocket Consumer Key if configured.
  520. func (o *Options) PocketConsumerKey(defaultValue string) string {
  521. if o.pocketConsumerKey != "" {
  522. return o.pocketConsumerKey
  523. }
  524. return defaultValue
  525. }
  526. // HTTPClientTimeout returns the time limit in seconds before the HTTP client cancel the request.
  527. func (o *Options) HTTPClientTimeout() int {
  528. return o.httpClientTimeout
  529. }
  530. // HTTPClientMaxBodySize returns the number of bytes allowed for the HTTP client to transfer.
  531. func (o *Options) HTTPClientMaxBodySize() int64 {
  532. return o.httpClientMaxBodySize
  533. }
  534. // HTTPClientProxyURL returns the client HTTP proxy URL if configured.
  535. func (o *Options) HTTPClientProxyURL() *url.URL {
  536. return o.httpClientProxyURL
  537. }
  538. // HasHTTPClientProxyURLConfigured returns true if the client HTTP proxy URL if configured.
  539. func (o *Options) HasHTTPClientProxyURLConfigured() bool {
  540. return o.httpClientProxyURL != nil
  541. }
  542. // HTTPClientProxies returns the list of proxies.
  543. func (o *Options) HTTPClientProxies() []string {
  544. return o.httpClientProxies
  545. }
  546. // HTTPClientProxiesString returns true if the list of rotating proxies are configured.
  547. func (o *Options) HasHTTPClientProxiesConfigured() bool {
  548. return len(o.httpClientProxies) > 0
  549. }
  550. // HTTPServerTimeout returns the time limit in seconds before the HTTP server cancel the request.
  551. func (o *Options) HTTPServerTimeout() int {
  552. return o.httpServerTimeout
  553. }
  554. // AuthProxyHeader returns an HTTP header name that contains username for
  555. // authentication using auth proxy.
  556. func (o *Options) AuthProxyHeader() string {
  557. return o.authProxyHeader
  558. }
  559. // IsAuthProxyUserCreationAllowed returns true if user creation is allowed for
  560. // users authenticated using auth proxy.
  561. func (o *Options) IsAuthProxyUserCreationAllowed() bool {
  562. return o.authProxyUserCreation
  563. }
  564. // HasMetricsCollector returns true if metrics collection is enabled.
  565. func (o *Options) HasMetricsCollector() bool {
  566. return o.metricsCollector
  567. }
  568. // MetricsRefreshInterval returns the refresh interval in seconds.
  569. func (o *Options) MetricsRefreshInterval() int {
  570. return o.metricsRefreshInterval
  571. }
  572. // MetricsAllowedNetworks returns the list of networks allowed to connect to the metrics endpoint.
  573. func (o *Options) MetricsAllowedNetworks() []string {
  574. return o.metricsAllowedNetworks
  575. }
  576. func (o *Options) MetricsUsername() string {
  577. return o.metricsUsername
  578. }
  579. func (o *Options) MetricsPassword() string {
  580. return o.metricsPassword
  581. }
  582. // HTTPClientUserAgent returns the global User-Agent header for miniflux.
  583. func (o *Options) HTTPClientUserAgent() string {
  584. return o.httpClientUserAgent
  585. }
  586. // HasWatchdog returns true if the systemd watchdog is enabled.
  587. func (o *Options) HasWatchdog() bool {
  588. return o.watchdog
  589. }
  590. // InvidiousInstance returns the invidious instance used by miniflux
  591. func (o *Options) InvidiousInstance() string {
  592. return o.invidiousInstance
  593. }
  594. // WebAuthn returns true if WebAuthn logins are supported
  595. func (o *Options) WebAuthn() bool {
  596. return o.webAuthn
  597. }
  598. // FilterEntryMaxAgeDays returns the number of days after which entries should be retained.
  599. func (o *Options) FilterEntryMaxAgeDays() int {
  600. return o.filterEntryMaxAgeDays
  601. }
  602. // SortedOptions returns options as a list of key value pairs, sorted by keys.
  603. func (o *Options) SortedOptions(redactSecret bool) []*Option {
  604. var clientProxyURLRedacted string
  605. if o.httpClientProxyURL != nil {
  606. if redactSecret {
  607. clientProxyURLRedacted = o.httpClientProxyURL.Redacted()
  608. } else {
  609. clientProxyURLRedacted = o.httpClientProxyURL.String()
  610. }
  611. }
  612. var clientProxyURLsRedacted string
  613. if len(o.httpClientProxies) > 0 {
  614. if redactSecret {
  615. var proxyURLs []string
  616. for range o.httpClientProxies {
  617. proxyURLs = append(proxyURLs, "<redacted>")
  618. }
  619. clientProxyURLsRedacted = strings.Join(proxyURLs, ",")
  620. } else {
  621. clientProxyURLsRedacted = strings.Join(o.httpClientProxies, ",")
  622. }
  623. }
  624. var mediaProxyPrivateKeyValue string
  625. if len(o.mediaProxyPrivateKey) > 0 {
  626. mediaProxyPrivateKeyValue = "<binary-data>"
  627. }
  628. var keyValues = map[string]interface{}{
  629. "ADMIN_PASSWORD": redactSecretValue(o.adminPassword, redactSecret),
  630. "ADMIN_USERNAME": o.adminUsername,
  631. "AUTH_PROXY_HEADER": o.authProxyHeader,
  632. "AUTH_PROXY_USER_CREATION": o.authProxyUserCreation,
  633. "BASE_PATH": o.basePath,
  634. "BASE_URL": o.baseURL,
  635. "BATCH_SIZE": o.batchSize,
  636. "CERT_DOMAIN": o.certDomain,
  637. "CERT_FILE": o.certFile,
  638. "CLEANUP_ARCHIVE_BATCH_SIZE": o.cleanupArchiveBatchSize,
  639. "CLEANUP_ARCHIVE_READ_DAYS": o.cleanupArchiveReadDays,
  640. "CLEANUP_ARCHIVE_UNREAD_DAYS": o.cleanupArchiveUnreadDays,
  641. "CLEANUP_FREQUENCY_HOURS": o.cleanupFrequencyHours,
  642. "CLEANUP_REMOVE_SESSIONS_DAYS": o.cleanupRemoveSessionsDays,
  643. "CREATE_ADMIN": o.createAdmin,
  644. "DATABASE_CONNECTION_LIFETIME": o.databaseConnectionLifetime,
  645. "DATABASE_MAX_CONNS": o.databaseMaxConns,
  646. "DATABASE_MIN_CONNS": o.databaseMinConns,
  647. "DATABASE_URL": redactSecretValue(o.databaseURL, redactSecret),
  648. "DISABLE_HSTS": !o.hsts,
  649. "DISABLE_HTTP_SERVICE": !o.httpService,
  650. "DISABLE_SCHEDULER_SERVICE": !o.schedulerService,
  651. "FILTER_ENTRY_MAX_AGE_DAYS": o.filterEntryMaxAgeDays,
  652. "FETCH_YOUTUBE_WATCH_TIME": o.fetchYouTubeWatchTime,
  653. "FETCH_NEBULA_WATCH_TIME": o.fetchNebulaWatchTime,
  654. "FETCH_ODYSEE_WATCH_TIME": o.fetchOdyseeWatchTime,
  655. "FETCH_BILIBILI_WATCH_TIME": o.fetchBilibiliWatchTime,
  656. "HTTPS": o.HTTPS,
  657. "HTTP_CLIENT_MAX_BODY_SIZE": o.httpClientMaxBodySize,
  658. "HTTP_CLIENT_PROXIES": clientProxyURLsRedacted,
  659. "HTTP_CLIENT_PROXY": clientProxyURLRedacted,
  660. "HTTP_CLIENT_TIMEOUT": o.httpClientTimeout,
  661. "HTTP_CLIENT_USER_AGENT": o.httpClientUserAgent,
  662. "HTTP_SERVER_TIMEOUT": o.httpServerTimeout,
  663. "HTTP_SERVICE": o.httpService,
  664. "INVIDIOUS_INSTANCE": o.invidiousInstance,
  665. "KEY_FILE": o.certKeyFile,
  666. "LISTEN_ADDR": o.listenAddr,
  667. "LOG_FILE": o.logFile,
  668. "LOG_DATE_TIME": o.logDateTime,
  669. "LOG_FORMAT": o.logFormat,
  670. "LOG_LEVEL": o.logLevel,
  671. "MAINTENANCE_MESSAGE": o.maintenanceMessage,
  672. "MAINTENANCE_MODE": o.maintenanceMode,
  673. "METRICS_ALLOWED_NETWORKS": strings.Join(o.metricsAllowedNetworks, ","),
  674. "METRICS_COLLECTOR": o.metricsCollector,
  675. "METRICS_PASSWORD": redactSecretValue(o.metricsPassword, redactSecret),
  676. "METRICS_REFRESH_INTERVAL": o.metricsRefreshInterval,
  677. "METRICS_USERNAME": o.metricsUsername,
  678. "OAUTH2_CLIENT_ID": o.oauth2ClientID,
  679. "OAUTH2_CLIENT_SECRET": redactSecretValue(o.oauth2ClientSecret, redactSecret),
  680. "OAUTH2_OIDC_DISCOVERY_ENDPOINT": o.oidcDiscoveryEndpoint,
  681. "OAUTH2_OIDC_PROVIDER_NAME": o.oidcProviderName,
  682. "OAUTH2_PROVIDER": o.oauth2Provider,
  683. "OAUTH2_REDIRECT_URL": o.oauth2RedirectURL,
  684. "OAUTH2_USER_CREATION": o.oauth2UserCreationAllowed,
  685. "DISABLE_LOCAL_AUTH": o.disableLocalAuth,
  686. "POCKET_CONSUMER_KEY": redactSecretValue(o.pocketConsumerKey, redactSecret),
  687. "POLLING_FREQUENCY": o.pollingFrequency,
  688. "FORCE_REFRESH_INTERVAL": o.forceRefreshInterval,
  689. "POLLING_PARSING_ERROR_LIMIT": o.pollingParsingErrorLimit,
  690. "POLLING_SCHEDULER": o.pollingScheduler,
  691. "MEDIA_PROXY_HTTP_CLIENT_TIMEOUT": o.mediaProxyHTTPClientTimeout,
  692. "MEDIA_PROXY_RESOURCE_TYPES": o.mediaProxyResourceTypes,
  693. "MEDIA_PROXY_MODE": o.mediaProxyMode,
  694. "MEDIA_PROXY_PRIVATE_KEY": mediaProxyPrivateKeyValue,
  695. "MEDIA_PROXY_CUSTOM_URL": o.mediaProxyCustomURL,
  696. "ROOT_URL": o.rootURL,
  697. "RUN_MIGRATIONS": o.runMigrations,
  698. "SCHEDULER_ENTRY_FREQUENCY_MAX_INTERVAL": o.schedulerEntryFrequencyMaxInterval,
  699. "SCHEDULER_ENTRY_FREQUENCY_MIN_INTERVAL": o.schedulerEntryFrequencyMinInterval,
  700. "SCHEDULER_ENTRY_FREQUENCY_FACTOR": o.schedulerEntryFrequencyFactor,
  701. "SCHEDULER_ROUND_ROBIN_MIN_INTERVAL": o.schedulerRoundRobinMinInterval,
  702. "SCHEDULER_ROUND_ROBIN_MAX_INTERVAL": o.schedulerRoundRobinMaxInterval,
  703. "SCHEDULER_SERVICE": o.schedulerService,
  704. "SERVER_TIMING_HEADER": o.serverTimingHeader,
  705. "WATCHDOG": o.watchdog,
  706. "WORKER_POOL_SIZE": o.workerPoolSize,
  707. "YOUTUBE_API_KEY": redactSecretValue(o.youTubeApiKey, redactSecret),
  708. "YOUTUBE_EMBED_URL_OVERRIDE": o.youTubeEmbedUrlOverride,
  709. "WEBAUTHN": o.webAuthn,
  710. }
  711. keys := make([]string, 0, len(keyValues))
  712. for key := range keyValues {
  713. keys = append(keys, key)
  714. }
  715. sort.Strings(keys)
  716. var sortedOptions []*Option
  717. for _, key := range keys {
  718. sortedOptions = append(sortedOptions, &Option{Key: key, Value: keyValues[key]})
  719. }
  720. return sortedOptions
  721. }
  722. func (o *Options) String() string {
  723. var builder strings.Builder
  724. for _, option := range o.SortedOptions(false) {
  725. fmt.Fprintf(&builder, "%s=%v\n", option.Key, option.Value)
  726. }
  727. return builder.String()
  728. }
  729. func redactSecretValue(value string, redactSecret bool) string {
  730. if redactSecret && value != "" {
  731. return "<secret>"
  732. }
  733. return value
  734. }