Class: Bible270::Configuration
- Inherits:
-
Object
- Object
- Bible270::Configuration
- Defined in:
- lib/bible270/configuration.rb
Constant Summary collapse
- PROVIDER_LABELS =
Human labels for providers we know; anything else is titleised.
{ github: 'GitHub', gitlab: 'GitLab', google_oauth2: 'Google', google: 'Google', facebook: 'Facebook', twitter: 'Twitter', apple: 'Apple', discord: 'Discord', microsoft_graph: 'Microsoft', azure_activedirectory_v2: 'Microsoft', openid_connect: 'OpenID Connect', saml: 'SSO' }.freeze
- PLACEMENTS =
%i[replace after before].freeze
- PLACEHOLDER_DOMAINS =
Reserved domains from RFC 2606 — a From: address at one of these will fail SPF for your real domain, and receiving servers routinely drop it without a bounce. The default value is one of them deliberately, so it has to be changed, but nothing was checking that it had been.
%w[example.com example.org example.net example.edu invalid localhost].freeze
Instance Attribute Summary collapse
-
#admin_emails ⇒ Object
Returns the value of attribute admin_emails.
-
#admin_resolver ⇒ Object
Returns the value of attribute admin_resolver.
-
#after_sign_in_path ⇒ Object
Where to send the reader after a successful sign-in / sign-out.
-
#after_sign_out_path ⇒ Object
Returns the value of attribute after_sign_out_path.
-
#allow_reader_start_date ⇒ Object
Whether an individual reader may set or change their own start date.
-
#app_name ⇒ Object
Public labels.
-
#avatar_max_bytes ⇒ Object
Returns the value of attribute avatar_max_bytes.
-
#bible_version ⇒ Object
Returns the value of attribute bible_version.
-
#bible_versions ⇒ Object
Default Bible translation and a builder for external passage links.
-
#chapter_breaks ⇒ Object
Returns the value of attribute chapter_breaks.
-
#chapter_breaks_path ⇒ Object
Optional YAML file holding the same thing, re-read whenever it changes so breaks can be tuned without restarting:.
-
#current_reader_resolver ⇒ Object
A callable (lambda) that receives the current controller and returns a Bible270::Reader (or nil).
-
#email_sign_in ⇒ Object
Offer sign-in by email link, so readers who don't have (or don't want to use) a GitHub/Google/etc.
-
#email_sign_in_ask_name ⇒ Object
Whether a reader may type the display name shown beside their reflections when signing in by email (otherwise it's derived from the address).
-
#email_sign_in_deliver_later ⇒ Object
Send the sign-in email via Active Job (deliver_later) instead of inline.
-
#email_sign_in_log_link ⇒ Object
Write the sign-in link to the log.
-
#email_sign_in_max_per_window ⇒ Object
Returns the value of attribute email_sign_in_max_per_window.
-
#email_sign_in_require_name ⇒ Object
Require a first AND last name when signing in by email.
-
#email_sign_in_ttl ⇒ Object
How long a magic link stays valid (seconds).
-
#email_sign_in_window ⇒ Object
Simple abuse guard: at most N links per address per window (seconds).
-
#enrollment_open ⇒ Object
Who may reach the admin panel.
-
#favicon ⇒ Object
Returns the value of attribute favicon.
-
#footer ⇒ Object
Returns the value of attribute footer.
-
#footer_html ⇒ Object
Returns the value of attribute footer_html.
-
#footer_partial ⇒ Object
Favicon for the engine's pages.
-
#footer_placement ⇒ Object
Where your footer goes relative to the engine's own: :replace (default), :after, or :before.
-
#layout ⇒ Object
Layout used to render engine pages.
-
#mailer_from ⇒ Object
From: address for the sign-in email.
-
#mailer_host ⇒ Object
Host for links in notification mail.
-
#mount_at ⇒ Object
Where the engine is mounted in the host application.
-
#omniauth_path_prefix ⇒ Object
OmniAuth's path_prefix, if you need to override it.
-
#omniauth_providers ⇒ Object
Providers to offer on the sign-in screen.
-
#parent_controller ⇒ Object
Controller the engine's controllers inherit from.
-
#passage_url_builder ⇒ Object
Returns the value of attribute passage_url_builder.
-
#registration_notice_deliver_later ⇒ Object
Send the notice through Active Job rather than inline: registration happens during a request, so inline delivery makes the new reader wait for SMTP.
-
#registration_notice_emails ⇒ Object
Who to email when someone new joins.
-
#require_sign_in_to_participate ⇒ Object
Only signed-in readers may check off and comment (viewing is always open).
-
#start_date ⇒ Object
Optional community-wide start date for the plan.
-
#tagline ⇒ Object
Returns the value of attribute tagline.
Instance Method Summary collapse
- #admin?(reader) ⇒ Boolean
- #admin_configured? ⇒ Boolean
-
#any_sign_in_method? ⇒ Boolean
Any way at all for a new person to sign in?.
-
#auth_path_prefix ⇒ Object
The prefix OmniAuth's middleware should serve its routes under.
- #email_sign_in? ⇒ Boolean
-
#footer_style ⇒ Object
:none, :partial, :html or :default.
-
#initialize ⇒ Configuration
constructor
A new instance of Configuration.
-
#keep_default_footer? ⇒ Boolean
Whether the engine's own footer is shown alongside yours.
- #label_for_provider(key) ⇒ Object
-
#mailer_from_problem ⇒ Object
Why the sign-in mail is likely to vanish, or nil if it looks fine.
- #notify_on_registration? ⇒ Boolean
- #omniauth_provider_keys ⇒ Object
-
#registration_notice_recipients ⇒ Object
The addresses to notify, normalised and de-duplicated.
- #resolved_footer_placement ⇒ Object
- #single_provider? ⇒ Boolean
Constructor Details
#initialize ⇒ Configuration
Returns a new instance of Configuration.
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 |
# File 'lib/bible270/configuration.rb', line 316 def initialize @parent_controller = 'ActionController::Base' @layout = 'bible270/application' @current_reader_resolver = nil @after_sign_in_path = nil @after_sign_out_path = nil @bible_version = 'NKJV' @bible_versions = Translations::VERSIONS.keys @passage_url_builder = ->(reference, version) do search = URI.encode_www_form_component(reference) # Translations.gateway_code maps 'NASB95' to Bible Gateway's 'NASB1995'. version = URI.encode_www_form_component(Translations.gateway_code(version)) "https://www.biblegateway.com/passage/?search=#{search}&version=#{version}" end @app_name = 'Daily Bread' @tagline = 'Journeying through Scripture in 9 months' @require_sign_in_to_participate = true self.mount_at = '/daily-bread' @start_date = nil @allow_reader_start_date = true self.omniauth_providers = [:github] @omniauth_path_prefix = nil @email_sign_in = true @mailer_from = 'no-reply@example.com' @email_sign_in_ttl = 20 * 60 # 20 minutes @email_sign_in_window = 15 * 60 # 15 minutes @email_sign_in_max_per_window = 5 @email_sign_in_ask_name = true @email_sign_in_require_name = true @email_sign_in_log_link = nil @enrollment_open = true @footer_partial = nil @footer_placement = :replace @footer_html = nil @footer = nil @favicon = nil @avatar_max_bytes = Avatars::DEFAULT_MAX_BYTES @chapter_breaks = {} @chapter_breaks_path = nil @registration_notice_emails = [] @registration_notice_deliver_later = false @mailer_host = nil @admin_emails = [] @admin_resolver = nil @email_sign_in_deliver_later = false end |
Instance Attribute Details
#admin_emails ⇒ Object
Returns the value of attribute admin_emails.
295 296 297 |
# File 'lib/bible270/configuration.rb', line 295 def admin_emails @admin_emails end |
#admin_resolver ⇒ Object
Returns the value of attribute admin_resolver.
295 296 297 |
# File 'lib/bible270/configuration.rb', line 295 def admin_resolver @admin_resolver end |
#after_sign_in_path ⇒ Object
Where to send the reader after a successful sign-in / sign-out.
63 64 65 |
# File 'lib/bible270/configuration.rb', line 63 def after_sign_in_path @after_sign_in_path end |
#after_sign_out_path ⇒ Object
Returns the value of attribute after_sign_out_path.
295 296 297 |
# File 'lib/bible270/configuration.rb', line 295 def after_sign_out_path @after_sign_out_path end |
#allow_reader_start_date ⇒ Object
Whether an individual reader may set or change their own start date. When false, everyone is pinned to config.start_date.
311 312 313 |
# File 'lib/bible270/configuration.rb', line 311 def allow_reader_start_date @allow_reader_start_date end |
#app_name ⇒ Object
Public labels.
298 299 300 |
# File 'lib/bible270/configuration.rb', line 298 def app_name @app_name end |
#avatar_max_bytes ⇒ Object
Returns the value of attribute avatar_max_bytes.
295 296 297 |
# File 'lib/bible270/configuration.rb', line 295 def avatar_max_bytes @avatar_max_bytes end |
#bible_version ⇒ Object
Returns the value of attribute bible_version.
295 296 297 |
# File 'lib/bible270/configuration.rb', line 295 def bible_version @bible_version end |
#bible_versions ⇒ Object
Default Bible translation and a builder for external passage links. Which translations readers may choose from. Defaults to all of Bible270::Translations::VERSIONS; narrow it to offer fewer.
276 277 278 |
# File 'lib/bible270/configuration.rb', line 276 def bible_versions @bible_versions end |
#chapter_breaks ⇒ Object
Returns the value of attribute chapter_breaks.
295 296 297 |
# File 'lib/bible270/configuration.rb', line 295 def chapter_breaks @chapter_breaks end |
#chapter_breaks_path ⇒ Object
Optional YAML file holding the same thing, re-read whenever it changes so breaks can be tuned without restarting:
# config/bible270_breaks.yml
Psalm 35: []
Psalm 78: [20, 39, 55]
205 206 207 |
# File 'lib/bible270/configuration.rb', line 205 def chapter_breaks_path @chapter_breaks_path end |
#current_reader_resolver ⇒ Object
A callable (lambda) that receives the current controller and returns a Bible270::Reader (or nil). Use this to bridge your host's users:
config.current_reader_resolver = ->(c) {
u = c.send(:current_user)
u && Bible270::Reader.for_owner(u, display_name: u.name, email: u.email)
}
Leave nil to use the built-in session-based sign-in (OmniAuth).
32 33 34 |
# File 'lib/bible270/configuration.rb', line 32 def current_reader_resolver @current_reader_resolver end |
#email_sign_in ⇒ Object
Offer sign-in by email link, so readers who don't have (or don't want to use) a GitHub/Google/etc. account can still take part. Requires the host app to have Action Mailer delivery configured.
105 106 107 |
# File 'lib/bible270/configuration.rb', line 105 def email_sign_in @email_sign_in end |
#email_sign_in_ask_name ⇒ Object
Whether a reader may type the display name shown beside their reflections when signing in by email (otherwise it's derived from the address).
118 119 120 |
# File 'lib/bible270/configuration.rb', line 118 def email_sign_in_ask_name @email_sign_in_ask_name end |
#email_sign_in_deliver_later ⇒ Object
Send the sign-in email via Active Job (deliver_later) instead of inline. Leave false unless you have a queue backend configured.
234 235 236 |
# File 'lib/bible270/configuration.rb', line 234 def email_sign_in_deliver_later @email_sign_in_deliver_later end |
#email_sign_in_log_link ⇒ Object
Write the sign-in link to the log. nil (default) means development and test only; true forces it on, for smoke-testing a production build locally before mail is wired up; false disables it everywhere. The link is a bearer credential, so true is not for a deployment real users can reach.
124 125 126 |
# File 'lib/bible270/configuration.rb', line 124 def email_sign_in_log_link @email_sign_in_log_link end |
#email_sign_in_max_per_window ⇒ Object
Returns the value of attribute email_sign_in_max_per_window.
295 296 297 |
# File 'lib/bible270/configuration.rb', line 295 def email_sign_in_max_per_window @email_sign_in_max_per_window end |
#email_sign_in_require_name ⇒ Object
Require a first AND last name when signing in by email. Names identify people to each other beside their reflections, so this is on by default.
128 129 130 |
# File 'lib/bible270/configuration.rb', line 128 def email_sign_in_require_name @email_sign_in_require_name end |
#email_sign_in_ttl ⇒ Object
How long a magic link stays valid (seconds).
111 112 113 |
# File 'lib/bible270/configuration.rb', line 111 def email_sign_in_ttl @email_sign_in_ttl end |
#email_sign_in_window ⇒ Object
Simple abuse guard: at most N links per address per window (seconds).
114 115 116 |
# File 'lib/bible270/configuration.rb', line 114 def email_sign_in_window @email_sign_in_window end |
#enrollment_open ⇒ Object
Who may reach the admin panel. Either a list of email addresses, or a lambda taking the current reader and returning true/false:
config.admin_emails = %w[andrew@example.org]
config.admin_resolver = ->(reader) { reader.email.end_with?('@example.org') }
With neither set the panel is unreachable and its routes 404. Break points set from the host app, overriding Plan::CHAPTER_BREAKS. Keys may be ['Psalm', 18] or 'Psalm 18'; [] keeps a chapter whole. Largest avatar a reader may upload, in bytes. Uploading needs Active Storage in the host app; without it the field is hidden and readers keep whatever avatar their sign-in provider gave them. Whether new readers may join this run of the plan. An admin can close it from the panel at runtime; setting this to false launches closed.
144 145 146 |
# File 'lib/bible270/configuration.rb', line 144 def enrollment_open @enrollment_open end |
#favicon ⇒ Object
Returns the value of attribute favicon.
295 296 297 |
# File 'lib/bible270/configuration.rb', line 295 def favicon @favicon end |
#footer ⇒ Object
Returns the value of attribute footer.
295 296 297 |
# File 'lib/bible270/configuration.rb', line 295 def @footer end |
#footer_html ⇒ Object
Returns the value of attribute footer_html.
295 296 297 |
# File 'lib/bible270/configuration.rb', line 295 def @footer_html end |
#footer_partial ⇒ Object
Favicon for the engine's pages. nil uses the built-in loaf, false renders no link tag at all (so the host's own favicon applies), and a string is used as the href — a path, a URL, or your own data URI. Footer for the engine's pages. Three ways to set it, and they're checked in this order:
config. = 'shared/footer' # a partial in your app
config. = '<p>…</p>' # raw HTML, marked safe
config. = false # no footer at all
With none of them set you get the engine's own note about how the plan works. Rails adds the leading underscore when looking a partial up, so 'layouts/_bible270_footer' would search for '__bible270_footer' and raise MissingTemplate. Accept either spelling and normalise.
160 161 162 |
# File 'lib/bible270/configuration.rb', line 160 def @footer_partial end |
#footer_placement ⇒ Object
Where your footer goes relative to the engine's own: :replace (default), :after, or :before. Anything else is treated as :replace.
175 176 177 |
# File 'lib/bible270/configuration.rb', line 175 def @footer_placement end |
#layout ⇒ Object
Layout used to render engine pages.
21 22 23 |
# File 'lib/bible270/configuration.rb', line 21 def layout @layout end |
#mailer_from ⇒ Object
From: address for the sign-in email.
108 109 110 |
# File 'lib/bible270/configuration.rb', line 108 def mailer_from @mailer_from end |
#mailer_host ⇒ Object
Host for links in notification mail. A mailer has no request to derive it from, so without this the notice names the reader but cannot link to them.
293 294 295 |
# File 'lib/bible270/configuration.rb', line 293 def mailer_host @mailer_host end |
#mount_at ⇒ Object
Where the engine is mounted in the host application. Set this once, in config/initializers/bible270.rb, and use it everywhere the path is needed:
# config/routes.rb
mount Bible270::Engine, at: Bible270.config.mount_at
# config/initializers/omniauth.rb
path_prefix Bible270.config.auth_path_prefix
Accepts "daily-bread" or "/daily-bread"; stored with a leading slash and no trailing one.
45 46 47 |
# File 'lib/bible270/configuration.rb', line 45 def mount_at @mount_at end |
#omniauth_path_prefix ⇒ Object
OmniAuth's path_prefix, if you need to override it. Normally leave this
nil: the engine derives "
80 81 82 |
# File 'lib/bible270/configuration.rb', line 80 def omniauth_path_prefix @omniauth_path_prefix end |
#omniauth_providers ⇒ Object
Providers to offer on the sign-in screen. Accepts symbols, or pairs of [provider, label] when you want to override the displayed name:
config.omniauth_providers = [:github]
config.omniauth_providers = [:github, [:google_oauth2, "Google"]]
The host application supplies the matching strategy gems and registers them in the OmniAuth builder (see the README, or run the install generator).
75 76 77 |
# File 'lib/bible270/configuration.rb', line 75 def omniauth_providers @omniauth_providers end |
#parent_controller ⇒ Object
Controller the engine's controllers inherit from. Set this to your host's "::ApplicationController" if you want to share layout, auth and helpers.
18 19 20 |
# File 'lib/bible270/configuration.rb', line 18 def parent_controller @parent_controller end |
#passage_url_builder ⇒ Object
Returns the value of attribute passage_url_builder.
295 296 297 |
# File 'lib/bible270/configuration.rb', line 295 def passage_url_builder @passage_url_builder end |
#registration_notice_deliver_later ⇒ Object
Send the notice through Active Job rather than inline: registration happens during a request, so inline delivery makes the new reader wait for SMTP.
289 290 291 |
# File 'lib/bible270/configuration.rb', line 289 def registration_notice_deliver_later @registration_notice_deliver_later end |
#registration_notice_emails ⇒ Object
Who to email when someone new joins. Three forms:
config.registration_notice_emails = %w[andrew@example.org] # an explicit list
config.registration_notice_emails = :admins # everyone in admin_emails
config.registration_notice_emails = [] # off (default)
An explicit list is used as given, so you can notify someone who isn't an admin.
285 286 287 |
# File 'lib/bible270/configuration.rb', line 285 def registration_notice_emails @registration_notice_emails end |
#require_sign_in_to_participate ⇒ Object
Only signed-in readers may check off and comment (viewing is always open).
314 315 316 |
# File 'lib/bible270/configuration.rb', line 314 def require_sign_in_to_participate @require_sign_in_to_participate end |
#start_date ⇒ Object
Optional community-wide start date for the plan. Set this when everyone reads together as a cohort (e.g. a church starting on a set Sunday):
config.start_date = Date.new(2026, 9, 6) # or the string "2026-09-06"
Leave nil for an undated plan, where each reader's own start date applies (defaulting to the day they first check something off).
307 308 309 |
# File 'lib/bible270/configuration.rb', line 307 def start_date @start_date end |
#tagline ⇒ Object
Returns the value of attribute tagline.
295 296 297 |
# File 'lib/bible270/configuration.rb', line 295 def tagline @tagline end |
Instance Method Details
#admin?(reader) ⇒ Boolean
207 208 209 210 211 212 |
# File 'lib/bible270/configuration.rb', line 207 def admin?(reader) return false if reader.nil? return !!admin_resolver.call(reader) if admin_resolver.respond_to?(:call) Array(admin_emails).map { |e| e.to_s.downcase }.include?(reader.email.to_s.downcase) end |
#admin_configured? ⇒ Boolean
228 229 230 |
# File 'lib/bible270/configuration.rb', line 228 def admin_configured? admin_resolver.respond_to?(:call) || Array(admin_emails).any? end |
#any_sign_in_method? ⇒ Boolean
Any way at all for a new person to sign in?
260 261 262 |
# File 'lib/bible270/configuration.rb', line 260 def any_sign_in_method? email_sign_in? || omniauth_providers.any? end |
#auth_path_prefix ⇒ Object
The prefix OmniAuth's middleware should serve its routes under. Derived from mount_at unless omniauth_path_prefix is set explicitly.
56 57 58 59 60 |
# File 'lib/bible270/configuration.rb', line 56 def auth_path_prefix return omniauth_path_prefix if omniauth_path_prefix mount_at == '/' ? '/auth' : "#{mount_at}/auth" end |
#email_sign_in? ⇒ Boolean
236 |
# File 'lib/bible270/configuration.rb', line 236 def email_sign_in? = !!@email_sign_in |
#footer_style ⇒ Object
:none, :partial, :html or :default.
190 191 192 193 194 195 196 197 |
# File 'lib/bible270/configuration.rb', line 190 def # Plain Ruby, not present?: this file has to load without ActiveSupport. return :none if == false return :partial unless .to_s.strip.empty? return :html unless .to_s.strip.empty? :default end |
#keep_default_footer? ⇒ Boolean
Whether the engine's own footer is shown alongside yours.
185 186 187 |
# File 'lib/bible270/configuration.rb', line 185 def != :none && %i[after before].include?() end |
#label_for_provider(key) ⇒ Object
266 267 268 269 270 271 |
# File 'lib/bible270/configuration.rb', line 266 def label_for_provider(key) found = omniauth_providers.find { |k, _| k.to_s == key.to_s } return found.last if found PROVIDER_LABELS[key.to_sym] || key.to_s.tr('_', ' ').split.map(&:capitalize).join(' ') end |
#mailer_from_problem ⇒ Object
Why the sign-in mail is likely to vanish, or nil if it looks fine.
245 246 247 248 249 250 251 252 253 254 255 256 257 |
# File 'lib/bible270/configuration.rb', line 245 def mailer_from_problem return nil unless email_sign_in? address = mailer_from.to_s.strip return 'config.mailer_from is blank' if address.empty? return "config.mailer_from (#{address}) is not a valid address" unless EmailSignIn.valid_email?(address) domain = address.split('@').last.to_s.downcase return nil unless PLACEHOLDER_DOMAINS.include?(domain) "config.mailer_from is still the placeholder #{address} — mail from a reserved domain " \ 'fails SPF and is usually dropped without a bounce' end |
#notify_on_registration? ⇒ Boolean
224 225 226 |
# File 'lib/bible270/configuration.rb', line 224 def notify_on_registration? registration_notice_recipients.any? end |
#omniauth_provider_keys ⇒ Object
98 |
# File 'lib/bible270/configuration.rb', line 98 def omniauth_provider_keys = omniauth_providers.map(&:first) |
#registration_notice_recipients ⇒ Object
The addresses to notify, normalised and de-duplicated. :admins follows admin_emails, the common case — but an explicit list wins, so a secretary who isn't an admin can still be told.
217 218 219 220 221 222 |
# File 'lib/bible270/configuration.rb', line 217 def registration_notice_recipients requested = registration_notice_emails requested = admin_emails if requested.to_s == 'admins' Array(requested).map { |address| EmailSignIn.normalize_email(address) }.compact.uniq end |
#resolved_footer_placement ⇒ Object
179 180 181 182 |
# File 'lib/bible270/configuration.rb', line 179 def placement = .to_s.downcase.to_sym PLACEMENTS.include?(placement) ? placement : :replace end |
#single_provider? ⇒ Boolean
264 |
# File 'lib/bible270/configuration.rb', line 264 def single_provider? = omniauth_providers.size == 1 |