Class: Studio::GeoSetting
- Inherits:
-
ApplicationRecord
- Object
- ApplicationRecord
- Studio::GeoSetting
- Includes:
- Sluggable
- Defined in:
- app/models/studio/geo_setting.rb
Overview
The operator's geo choices for THIS app: whether the gate is live, which countries it refuses outright, and which subdivisions of which country.
One row per app (keyed by Studio.app_name), exactly like ThemeSetting — the engine's other "this deployment's settings" table. The gate reads this row and the published exclusion page renders THIS row, so the policy a visitor is told about can never drift from the policy that is enforced.
STORAGE VOCABULARY: banned_subdivisions holds region tokens — "US-WA", not
"WA" — because a bare code cannot say whether "CA" is California or Canada.
Bare codes are still accepted on the way in (an app migrating years of them
has a list of bare codes) and normalized against Studio.geo_home_country
before they are written. See Studio::Geo for the full vocabulary.
NIL-SAFE THROUGHOUT, because the table is installed by a migration the host runs. An app that has not run it yet must still boot, still serve, and still answer "is this visitor blocked?" — with "no", since an app with no geo row has declared no policy to enforce.
Class Method Summary collapse
-
.banned_subdivision_codes(country: Studio.geo_home_country) ⇒ Object
Bare subdivision codes for one country — what a checkbox grid renders and what a published list prints.
-
.blocked?(country:, subdivision:) ⇒ Boolean
The verdict for one visitor.
-
.current ⇒ Object
This app's row, or an unsaved instance carrying the configured defaults.
- .default_attributes ⇒ Object
- .effective_banned_countries ⇒ Object
-
.effective_banned_subdivisions ⇒ Object
The PUBLISHED exclusion list, as region tokens.
-
.enforcing? ⇒ Boolean
The gate is LIVE — a provisioned, enabled row.
- .normalize_tokens(list) ⇒ Object
- .table_ready? ⇒ Boolean
Instance Method Summary collapse
- #name_slug ⇒ Object
-
#subdivision_codes(country: Studio.geo_home_country) ⇒ Object
Bare codes for the grid — the instance half of .banned_subdivision_codes, reading THIS row rather than the effective list.
Methods included from Sluggable
Class Method Details
.banned_subdivision_codes(country: Studio.geo_home_country) ⇒ Object
Bare subdivision codes for one country — what a checkbox grid renders and what a published list prints. "US-WA" -> "WA" for country "US".
83 84 85 86 |
# File 'app/models/studio/geo_setting.rb', line 83 def banned_subdivision_codes(country: Studio.geo_home_country) prefix = "#{Studio::Geo.normalize_country(country)}-" effective_banned_subdivisions.filter_map { |token| token.delete_prefix(prefix) if token.start_with?(prefix) } end |
.blocked?(country:, subdivision:) ⇒ Boolean
The verdict for one visitor. Pure policy lives in Studio::Geo; this method's only job is to hand it this app's stored choices.
66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'app/models/studio/geo_setting.rb', line 66 def blocked?(country:, subdivision:) setting = current return false unless setting.persisted? && setting.enabled? Studio::Geo.blocked?( country: country, subdivision: subdivision, banned_countries: setting.banned_countries, banned_subdivisions: setting.banned_subdivisions, home_country: Studio.geo_home_country, enforcing: true, fail_closed: Studio.geo_fail_closed ) end |
.current ⇒ Object
This app's row, or an unsaved instance carrying the configured defaults. Never nil, so a caller can always ask it a question.
34 35 36 37 38 |
# File 'app/models/studio/geo_setting.rb', line 34 def current return new(default_attributes) unless table_ready? find_by(app_name: Studio.app_name) || new(default_attributes) end |
.default_attributes ⇒ Object
88 89 90 91 92 93 94 95 |
# File 'app/models/studio/geo_setting.rb', line 88 def default_attributes { app_name: Studio.app_name, enabled: false, banned_countries: Array(Studio.geo_default_banned_countries), banned_subdivisions: normalize_tokens(Studio.geo_default_banned_subdivisions) } end |
.effective_banned_countries ⇒ Object
49 50 51 52 53 |
# File 'app/models/studio/geo_setting.rb', line 49 def effective_banned_countries setting = current list = setting.persisted? ? setting.banned_countries : Studio.geo_default_banned_countries Array(list).filter_map { |code| Studio::Geo.normalize_country(code) }.uniq.sort end |
.effective_banned_subdivisions ⇒ Object
The PUBLISHED exclusion list, as region tokens. Falls back to the configured defaults when no row has been provisioned yet, so a fresh app publishes the same list it enforces from its first request.
43 44 45 46 47 |
# File 'app/models/studio/geo_setting.rb', line 43 def effective_banned_subdivisions setting = current list = setting.persisted? ? setting.banned_subdivisions : Studio.geo_default_banned_subdivisions normalize_tokens(list) end |
.enforcing? ⇒ Boolean
The gate is LIVE — a provisioned, enabled row. When false nothing is geo-restricted at all, including the fail-closed branch: that is the operator's kill switch, and it has to mean OFF rather than "off except for the visitors we cannot place".
59 60 61 62 |
# File 'app/models/studio/geo_setting.rb', line 59 def enforcing? setting = current setting.persisted? && setting.enabled? end |
.normalize_tokens(list) ⇒ Object
97 98 99 100 101 102 |
# File 'app/models/studio/geo_setting.rb', line 97 def normalize_tokens(list) Array(list) .filter_map { |token| Studio::Geo.normalize_region_token(token, home_country: Studio.geo_home_country) } .uniq .sort end |
.table_ready? ⇒ Boolean
104 105 106 107 108 |
# File 'app/models/studio/geo_setting.rb', line 104 def table_ready? table_exists? rescue ActiveRecord::ActiveRecordError, NameError false end |
Instance Method Details
#name_slug ⇒ Object
118 119 120 |
# File 'app/models/studio/geo_setting.rb', line 118 def name_slug "geo-#{app_name.to_s.parameterize}" end |
#subdivision_codes(country: Studio.geo_home_country) ⇒ Object
Bare codes for the grid — the instance half of .banned_subdivision_codes, reading THIS row rather than the effective list.
113 114 115 116 |
# File 'app/models/studio/geo_setting.rb', line 113 def subdivision_codes(country: Studio.geo_home_country) prefix = "#{Studio::Geo.normalize_country(country)}-" Array(banned_subdivisions).filter_map { |token| token.delete_prefix(prefix) if token.to_s.start_with?(prefix) } end |