bp3-core 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/CLAUDE.md +99 -78
- data/Gemfile.lock +42 -40
- data/README.md +5 -1
- data/lib/bp3/core/actions.rb +1 -2
- data/lib/bp3/core/cookies.rb +2 -4
- data/lib/bp3/core/feature_flags.rb +6 -5
- data/lib/bp3/core/system_logs.rb +2 -4
- data/lib/bp3/core/tenantable.rb +29 -11
- data/lib/bp3/core/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 76165d42f4b28714655519eeddedc6d08dd0b5bc9a5e919b389f173aa0bf20a0
|
|
4
|
+
data.tar.gz: dba935fa44898891607c50b377cbb4d8636300c7285592838826331cc47d5da6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 548dd80c8000de996d2abe85c4e158b979e9c809957f1403f15519280ee2dcb3c1fa865bf4355bc6fa25d9a6cf19791bc09cf3d6d0a84b7c0a7888cdd4960c21
|
|
7
|
+
data.tar.gz: 6dbc07299dcc22c84643250fd8fe018dc2b8c94de6a30fe303431d61f38438ffa32c897f43132a49d4fa9d75491ceb33cf11e988c9c2a88e21406a7dd33e6abc
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.3.0] - 2026-10-26
|
|
4
|
+
|
|
5
|
+
### Breaking
|
|
6
|
+
- Scope Tenantable by the primary login
|
|
7
|
+
Tenantable default scopes reach as far as the primary login, the request state's
|
|
8
|
+
`current_login` (the least privileged one signed in), rather than as far as any root or admin signed
|
|
9
|
+
in. A root signed in beside a user or an admin no longer reaches every site, and an admin signed in
|
|
10
|
+
beside a user no longer reaches every tenant; with one login signed in, nothing changes
|
|
11
|
+
- Read request state through `Bp3::Core::Rqid.global_request_state_class`
|
|
12
|
+
Tenantable reads the request state through `Bp3::Core::Rqid.global_request_state_class`
|
|
13
|
+
rather than a `GlobalRequestState` constant, so `Bp3::Core::Rqid.global_request_state_class_name`
|
|
14
|
+
must be configured wherever Tenantable is used
|
|
15
|
+
- Add `Bp3::Core::Tenantable.reaches_every_site?`, `.reaches_every_tenant?` and `.global_request_state`
|
|
16
|
+
|
|
17
|
+
### Bug fixes
|
|
18
|
+
|
|
19
|
+
- Fix efon? and cfon?
|
|
20
|
+
Fix `efon?` and `cfon?` returning the default when the flag is explicitly off; `cfon` returns the
|
|
21
|
+
default when the config is not set
|
|
22
|
+
|
|
3
23
|
## [0.2.0] - 2026-01-09
|
|
4
24
|
|
|
5
25
|
- Add bp3-request_state dependency
|
data/CLAUDE.md
CHANGED
|
@@ -4,95 +4,116 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|
|
4
4
|
|
|
5
5
|
## Project Overview
|
|
6
6
|
|
|
7
|
-
bp3-core is a Ruby gem providing core ActiveSupport concerns for BP3 (persuavis/black_phoebe_3), a
|
|
7
|
+
bp3-core is a Ruby gem providing core ActiveSupport concerns for BP3 (persuavis/black_phoebe_3), a
|
|
8
|
+
multi-site multi-tenant Rails application. The concerns handle tenancy, request tracking, sequence
|
|
9
|
+
ordering, ransack, feature flags, cookies and system logging, for the application's models and controllers
|
|
10
|
+
and for the other bp3 gems, which mix them into third-party classes (noticed, friendly_id, pg_search,
|
|
11
|
+
ActionText, ActiveStorage, paper_trail, ActiveAdmin, Rails' mailer previews).
|
|
8
12
|
|
|
9
|
-
##
|
|
13
|
+
## Commands
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
- Run linting: `bundle exec rubocop` or `rake rubocop`
|
|
14
|
-
- Run both tests and linting (default): `rake`
|
|
15
|
-
- Run a single test file: `bundle exec rspec spec/path/to/file_spec.rb`
|
|
16
|
-
- Run a specific test: `bundle exec rspec spec/path/to/file_spec.rb:LINE_NUMBER`
|
|
15
|
+
The gems run on Ruby 3.4.6 (`.ruby-version`). Prefix commands with `~/.rvm/bin/rvm 3.4.6 do` when the
|
|
16
|
+
shell is not already on it; a missing `rspec` means the wrong Ruby, not a missing bundle.
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
- Generate documentation: `yard doc`
|
|
18
|
+
- `bundle exec rake` - specs and RuboCop (the default task)
|
|
19
|
+
- `bundle exec rspec spec/path/to/file_spec.rb[:LINE]` - one file or example
|
|
20
|
+
- `bundle exec rubocop` / `bundle exec rubocop -a`
|
|
21
|
+
- `bin/setup`, `bin/console`, `rake install`, `yard doc`
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
The specs have no database or Rails app: test a concern's decisions through plain Ruby (e.g.
|
|
24
|
+
`Tenantable.reaches_every_site?` with a struct standing in for the request state), and try a change against
|
|
25
|
+
the application by putting this repo's `lib` ahead of the bundled gem. `lib/bp3/core/test.rb` is a plain
|
|
26
|
+
class that stubs `before_action`, `belongs_to` and the like and includes every concern; the gem does not
|
|
27
|
+
require it.
|
|
27
28
|
|
|
28
29
|
## Architecture
|
|
29
30
|
|
|
30
|
-
###
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
- `
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
31
|
+
### Model concerns
|
|
32
|
+
|
|
33
|
+
**Tenantable** (`tenantable.rb`)
|
|
34
|
+
- `configure_tenancy` looks at which of `sites_site_id`, `tenant_id` and `workspaces_workspace_id` the
|
|
35
|
+
table has and only sets up those: `belongs_to` (optional when the column is nullable), `site`/`workspace`
|
|
36
|
+
aliases, `before_validation` callbacks that fill the column from the request state's `either_*_id`, and
|
|
37
|
+
validations that tenant and workspace belong to the record's site
|
|
38
|
+
- Site and tenant get default scopes from the request state's `either_site`/`either_tenant`. How far they
|
|
39
|
+
reach is decided by the primary login, `current_login`, the least privileged one signed in: a root reaches
|
|
40
|
+
every site and an admin every tenant of theirs, but not when a less privileged login is signed in beside
|
|
41
|
+
them -- see `Tenantable.reaches_every_site?` and `.reaches_every_tenant?`
|
|
42
|
+
- Including it calls `connection` to load column metadata, unless `IGNORE_NOTIFICATIONS` is set
|
|
43
|
+
- The gem does not know the application's `GlobalRequestState`, only its parent `Bp3::RequestState::Base`
|
|
44
|
+
(gem bp3-request_state): use that API -- `current_login`, `current_root`, `current_admin`, `either_site`
|
|
45
|
+
and the like -- through `Bp3::Core::Tenantable.global_request_state`, never the constant
|
|
46
|
+
|
|
47
|
+
**Rqid** (`rqid.rb`)
|
|
48
|
+
- `before_create` sets `rqid` from the configured request state class and method
|
|
49
|
+
- optional `belongs_to` `original_request`, `original_response` and `original_visit` on `rqid` (more than
|
|
50
|
+
one record may share an rqid)
|
|
51
|
+
- `Bp3::Core::Rqid.global_request_state_class` is where every bp3 gem gets the request state class
|
|
52
|
+
|
|
53
|
+
**Sqnr** (`sqnr.rb`): `sqnr` (ascending) and `rnqs` (descending) scopes; `use_sqnr_for_ordering` sets
|
|
54
|
+
`implicit_order_column`
|
|
55
|
+
|
|
56
|
+
**Ransackable** (`ransackable.rb`): `ransackable_attributes` (all columns), `ransackable_associations` (all
|
|
57
|
+
associations), `ransackable_scopes` (none), `ransackable_fields` (all three), `ransortable_attributes`,
|
|
58
|
+
minus the global `attribute_exceptions` and `association_exceptions`
|
|
59
|
+
|
|
60
|
+
**Displayable** (`displayable.rb`): `to_dom_id`, `display_name`/`admin_display_name` ("ClassName id"),
|
|
61
|
+
`i18n_key`, and `filtered_attributes`, which masks `Rails.application.config.filter_parameters` (also inside
|
|
62
|
+
`object`/`object_changes` for versions) with `version_filter_mask`; classes override the mask to tell
|
|
63
|
+
sources apart
|
|
64
|
+
|
|
65
|
+
### Controller concerns
|
|
66
|
+
|
|
67
|
+
**Actions** (`actions.rb`): the request pipeline. Prepended before actions, in order: `set_rqid`,
|
|
68
|
+
`check_site`, `check_workspace`, `check_tenant` (each finds or creates the record and stores it in the
|
|
69
|
+
request state); then paper_trail whodunnit, user agent and `Inbound::Request` records (skipped under do not
|
|
70
|
+
track), the maintenance-mode check, and `set_global_request_state` for the logins, locale and view context.
|
|
71
|
+
Also `info_for_paper_trail`, `user_for_paper_trail`, `pundit_user` and `default_url_options` with the
|
|
72
|
+
locale. The order of the prepends matters; do not change it
|
|
73
|
+
|
|
74
|
+
**Cookies** (`cookies.rb`): the `_bp3_visitor` signed cookie that finds or creates the `Users::Visitor`,
|
|
75
|
+
the do-not-track cookie, and migration from the old per-site/tenant cookie name
|
|
76
|
+
|
|
77
|
+
**Settings** (`settings.rb`): `create_request_record_is_on?`, `multi_tenant_is_on?`
|
|
78
|
+
|
|
79
|
+
**FeatureFlags** (`feature_flags.rb`): `efon?` (a `Feature::Enabler`), `cfon?` (a record's `configs`),
|
|
80
|
+
`efcfon?` (either, the config winning when both are set)
|
|
81
|
+
|
|
82
|
+
### Anywhere
|
|
83
|
+
|
|
84
|
+
**SystemLogs** (`system_logs.rb`): `log`, `log_debug`, `log_info`, `log_warn`, `log_error`,
|
|
85
|
+
`log_exception`, as instance methods and on the module itself. Each writes to the Rails log and to the
|
|
86
|
+
configured log and exception classes (`log_to_io:` and `log_to_db:` switch either off); a failing database
|
|
87
|
+
write is logged, not raised
|
|
88
|
+
|
|
89
|
+
### Configuration
|
|
90
|
+
|
|
91
|
+
Set in the application's `config/initializers/bp3-core.rb`; the class names are constantized and cached on
|
|
92
|
+
first use:
|
|
93
|
+
- `Bp3::Core::Rqid.global_request_state_class_name` (`'GlobalRequestState'`) and
|
|
94
|
+
`.global_request_state_method` (`:request_id`)
|
|
95
|
+
- `Bp3::Core::SystemLogs.system_log_name` (`'System::Log'`) and `.system_exception_name`
|
|
96
|
+
(`'System::Exception'`)
|
|
97
|
+
- `Bp3::Core::Ransackable.attribute_exceptions` and `.association_exceptions`
|
|
98
|
+
|
|
99
|
+
The concerns also name application classes directly: `Sites::Site`, `Tenant`, `Workspaces::Workspace`,
|
|
100
|
+
`Users::Visitor`, `Inbound::Request`, `Inbound::UserAgent`, `Feature::Enabler`, `UserContext`,
|
|
101
|
+
`DomainExtractor`.
|
|
81
102
|
|
|
82
103
|
### Dependencies
|
|
83
104
|
|
|
84
|
-
|
|
85
|
-
- `
|
|
86
|
-
- `actionview ~> 8.1` - For view helpers
|
|
87
|
-
- Development: `rspec`, `rubocop`, `rubocop-rake`, `rubocop-rspec`
|
|
105
|
+
- `activesupport ~> 8.1`, `actionview ~> 8.1`
|
|
106
|
+
- `bp3-request_state ~> 0.1` - `Bp3::RequestState::Base`, the parent of the application's request state
|
|
88
107
|
|
|
89
108
|
## Code Style
|
|
90
109
|
|
|
91
|
-
RuboCop
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
-
|
|
95
|
-
-
|
|
96
|
-
|
|
110
|
+
- RuboCop (`.rubocop.yml`): target Ruby 3.2.2, NewCops, rubocop-rake and rubocop-rspec; AbcSize 26,
|
|
111
|
+
MethodLength 15, ModuleLength 150, BlockLength 66, Cyclomatic/PerceivedComplexity 10; RSpec ExampleLength
|
|
112
|
+
10, MultipleExpectations 4; Style/Documentation off
|
|
113
|
+
- Every file starts with `# frozen_string_literal: true`
|
|
114
|
+
- American English; no trailing whitespace on any added or modified line
|
|
115
|
+
|
|
116
|
+
## Release
|
|
97
117
|
|
|
98
|
-
|
|
118
|
+
Bump `lib/bp3/core/version.rb` and add a `CHANGELOG.md` entry. `rake release` tags, pushes and publishes to
|
|
119
|
+
rubygems.org; leave releasing and committing to the user.
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
bp3-core (0.
|
|
4
|
+
bp3-core (0.3.0)
|
|
5
5
|
actionview (~> 8.1)
|
|
6
6
|
activesupport (~> 8.1)
|
|
7
7
|
bp3-request_state (~> 0.1)
|
|
@@ -9,9 +9,9 @@ PATH
|
|
|
9
9
|
GEM
|
|
10
10
|
remote: https://rubygems.org/
|
|
11
11
|
specs:
|
|
12
|
-
actionpack (8.1.
|
|
13
|
-
actionview (= 8.1.
|
|
14
|
-
activesupport (= 8.1.
|
|
12
|
+
actionpack (8.1.4)
|
|
13
|
+
actionview (= 8.1.4)
|
|
14
|
+
activesupport (= 8.1.4)
|
|
15
15
|
nokogiri (>= 1.8.5)
|
|
16
16
|
rack (>= 2.2.4)
|
|
17
17
|
rack-session (>= 1.0.1)
|
|
@@ -19,13 +19,13 @@ GEM
|
|
|
19
19
|
rails-dom-testing (~> 2.2)
|
|
20
20
|
rails-html-sanitizer (~> 1.6)
|
|
21
21
|
useragent (~> 0.16)
|
|
22
|
-
actionview (8.1.
|
|
23
|
-
activesupport (= 8.1.
|
|
22
|
+
actionview (8.1.4)
|
|
23
|
+
activesupport (= 8.1.4)
|
|
24
24
|
builder (~> 3.1)
|
|
25
25
|
erubi (~> 1.11)
|
|
26
26
|
rails-dom-testing (~> 2.2)
|
|
27
27
|
rails-html-sanitizer (~> 1.6)
|
|
28
|
-
activesupport (8.1.
|
|
28
|
+
activesupport (8.1.4)
|
|
29
29
|
base64
|
|
30
30
|
bigdecimal
|
|
31
31
|
concurrent-ruby (~> 1.0, >= 1.3.1)
|
|
@@ -40,53 +40,54 @@ GEM
|
|
|
40
40
|
uri (>= 0.13.1)
|
|
41
41
|
ast (2.4.3)
|
|
42
42
|
base64 (0.3.0)
|
|
43
|
-
bigdecimal (4.
|
|
43
|
+
bigdecimal (4.1.3)
|
|
44
44
|
bp3-request_state (0.1.3)
|
|
45
45
|
actionpack (~> 8.1)
|
|
46
46
|
activesupport (~> 8.1)
|
|
47
47
|
request_store (>= 1.5.1)
|
|
48
48
|
builder (3.3.0)
|
|
49
|
-
concurrent-ruby (1.3.
|
|
49
|
+
concurrent-ruby (1.3.8)
|
|
50
50
|
connection_pool (3.0.2)
|
|
51
|
-
crass (1.0.
|
|
51
|
+
crass (1.0.8)
|
|
52
52
|
diff-lcs (1.6.2)
|
|
53
53
|
drb (2.2.3)
|
|
54
54
|
erubi (1.13.1)
|
|
55
|
-
i18n (1.
|
|
55
|
+
i18n (1.15.2)
|
|
56
56
|
concurrent-ruby (~> 1.0)
|
|
57
|
-
json (
|
|
58
|
-
language_server-protocol (3.17.0.
|
|
57
|
+
json (3.1.0)
|
|
58
|
+
language_server-protocol (3.17.0.6)
|
|
59
59
|
lint_roller (1.1.0)
|
|
60
60
|
logger (1.7.0)
|
|
61
|
-
loofah (2.25.
|
|
61
|
+
loofah (2.25.2)
|
|
62
62
|
crass (~> 1.0.2)
|
|
63
63
|
nokogiri (>= 1.12.0)
|
|
64
|
-
minitest (6.0.
|
|
64
|
+
minitest (6.0.6)
|
|
65
|
+
drb (~> 2.0)
|
|
65
66
|
prism (~> 1.5)
|
|
66
|
-
nokogiri (1.19.
|
|
67
|
+
nokogiri (1.19.4-x86_64-darwin)
|
|
67
68
|
racc (~> 1.4)
|
|
68
|
-
parallel (
|
|
69
|
-
parser (3.3.
|
|
69
|
+
parallel (2.3.0)
|
|
70
|
+
parser (3.3.13.0)
|
|
70
71
|
ast (~> 2.4.1)
|
|
71
72
|
racc
|
|
72
|
-
prism (1.
|
|
73
|
+
prism (1.9.0)
|
|
73
74
|
racc (1.8.1)
|
|
74
|
-
rack (3.2.
|
|
75
|
-
rack-session (2.1.
|
|
75
|
+
rack (3.2.7)
|
|
76
|
+
rack-session (2.1.2)
|
|
76
77
|
base64 (>= 0.1.0)
|
|
77
78
|
rack (>= 3.0.0)
|
|
78
|
-
rack-test (2.
|
|
79
|
+
rack-test (2.3.0)
|
|
79
80
|
rack (>= 1.3)
|
|
80
81
|
rails-dom-testing (2.3.0)
|
|
81
82
|
activesupport (>= 5.0.0)
|
|
82
83
|
minitest
|
|
83
84
|
nokogiri (>= 1.6)
|
|
84
|
-
rails-html-sanitizer (1.
|
|
85
|
-
loofah (~> 2.
|
|
85
|
+
rails-html-sanitizer (1.7.1)
|
|
86
|
+
loofah (~> 2.25, >= 2.25.2)
|
|
86
87
|
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
|
|
87
88
|
rainbow (3.1.1)
|
|
88
|
-
rake (13.
|
|
89
|
-
regexp_parser (2.
|
|
89
|
+
rake (13.4.2)
|
|
90
|
+
regexp_parser (2.13.1)
|
|
90
91
|
request_store (1.7.0)
|
|
91
92
|
rack (>= 1.4)
|
|
92
93
|
rspec (3.13.2)
|
|
@@ -98,38 +99,39 @@ GEM
|
|
|
98
99
|
rspec-expectations (3.13.5)
|
|
99
100
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
100
101
|
rspec-support (~> 3.13.0)
|
|
101
|
-
rspec-mocks (3.13.
|
|
102
|
+
rspec-mocks (3.13.8)
|
|
102
103
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
103
104
|
rspec-support (~> 3.13.0)
|
|
104
|
-
rspec-support (3.13.
|
|
105
|
-
rubocop (1.
|
|
106
|
-
json (
|
|
105
|
+
rspec-support (3.13.7)
|
|
106
|
+
rubocop (1.92.1)
|
|
107
|
+
json (>= 2.3)
|
|
107
108
|
language_server-protocol (~> 3.17.0.2)
|
|
108
109
|
lint_roller (~> 1.1.0)
|
|
109
|
-
parallel (
|
|
110
|
+
parallel (>= 1.10)
|
|
110
111
|
parser (>= 3.3.0.2)
|
|
111
112
|
rainbow (>= 2.2.2, < 4.0)
|
|
112
|
-
regexp_parser (>= 2.
|
|
113
|
-
rubocop-ast (>= 1.
|
|
113
|
+
regexp_parser (>= 2.11.3, < 3.0)
|
|
114
|
+
rubocop-ast (>= 1.49.0, < 2.0)
|
|
114
115
|
ruby-progressbar (~> 1.7)
|
|
115
116
|
unicode-display_width (>= 2.4.0, < 4.0)
|
|
116
|
-
rubocop-ast (1.
|
|
117
|
+
rubocop-ast (1.50.0)
|
|
117
118
|
parser (>= 3.3.7.2)
|
|
118
119
|
prism (~> 1.7)
|
|
119
120
|
rubocop-rake (0.7.1)
|
|
120
121
|
lint_roller (~> 1.1)
|
|
121
122
|
rubocop (>= 1.72.1)
|
|
122
|
-
rubocop-rspec (3.
|
|
123
|
+
rubocop-rspec (3.10.2)
|
|
123
124
|
lint_roller (~> 1.1)
|
|
124
|
-
|
|
125
|
+
regexp_parser (>= 2.0)
|
|
126
|
+
rubocop (~> 1.86, >= 1.86.2)
|
|
125
127
|
ruby-progressbar (1.13.0)
|
|
126
128
|
securerandom (0.4.1)
|
|
127
129
|
tzinfo (2.0.6)
|
|
128
130
|
concurrent-ruby (~> 1.0)
|
|
129
|
-
unicode-display_width (3.
|
|
130
|
-
unicode-emoji (~> 4.
|
|
131
|
-
unicode-emoji (4.
|
|
132
|
-
uri (1.1.
|
|
131
|
+
unicode-display_width (3.3.0)
|
|
132
|
+
unicode-emoji (~> 4.3)
|
|
133
|
+
unicode-emoji (4.3.0)
|
|
134
|
+
uri (1.1.2)
|
|
133
135
|
useragent (0.16.11)
|
|
134
136
|
|
|
135
137
|
PLATFORMS
|
data/README.md
CHANGED
|
@@ -80,7 +80,11 @@ The specific columns expected by `Tenantable` are:
|
|
|
80
80
|
- site: `sites_site_id`
|
|
81
81
|
- tenant: `tenant_id`
|
|
82
82
|
- workspace: `workspaces_workspace_id`
|
|
83
|
-
Tenantable will use reflection to determine which one(s) exist, and will create associations and callbacks accordingly.
|
|
83
|
+
Tenantable will use reflection to determine which one(s) exist, and will create associations and callbacks accordingly.
|
|
84
|
+
|
|
85
|
+
Its default scopes reach as far as the primary login, the request state's `current_login`: a root
|
|
86
|
+
reaches every site and an admin every tenant of their site, unless a less privileged login is signed
|
|
87
|
+
in beside them. It reads the request state through `Bp3::Core::Rqid.global_request_state_class`.
|
|
84
88
|
|
|
85
89
|
## Development
|
|
86
90
|
|
data/lib/bp3/core/actions.rb
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Bp3
|
|
4
4
|
module Core
|
|
5
|
-
# rubocop:disable Metrics/ModuleLength
|
|
5
|
+
# rubocop:disable-next Metrics/ModuleLength
|
|
6
6
|
module Actions
|
|
7
7
|
extend ActiveSupport::Concern
|
|
8
8
|
|
|
@@ -209,6 +209,5 @@ module Bp3
|
|
|
209
209
|
@grsc ||= Bp3::Core::Rqid.global_request_state_class
|
|
210
210
|
end
|
|
211
211
|
end
|
|
212
|
-
# rubocop:enable Metrics/ModuleLength
|
|
213
212
|
end
|
|
214
213
|
end
|
data/lib/bp3/core/cookies.rb
CHANGED
|
@@ -58,7 +58,7 @@ module Bp3
|
|
|
58
58
|
}
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
-
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
61
|
+
# rubocop:disable-next Metrics/AbcSize, Metrics/MethodLength
|
|
62
62
|
def check_old_visitor_cookie
|
|
63
63
|
cookie_value = cookies.signed[visitor_cookie_name]
|
|
64
64
|
return if cookie_value.blank? && do_not_track
|
|
@@ -85,9 +85,8 @@ module Bp3
|
|
|
85
85
|
"check_visitor_cookie: cookie[#{visitor_cookie_name}]=#{cookies.signed[visitor_cookie_name]}"
|
|
86
86
|
end
|
|
87
87
|
end
|
|
88
|
-
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
|
89
88
|
|
|
90
|
-
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
89
|
+
# rubocop:disable-next Metrics/AbcSize, Metrics/MethodLength
|
|
91
90
|
def check_new_visitor_cookie
|
|
92
91
|
cookie_value = cookies.signed[new_visitor_cookie_name]
|
|
93
92
|
return if cookie_value.blank? && do_not_track
|
|
@@ -110,7 +109,6 @@ module Bp3
|
|
|
110
109
|
"check_visitor_cookie: cookie[#{new_visitor_cookie_name}]=#{cookies.signed[new_visitor_cookie_name]}"
|
|
111
110
|
end
|
|
112
111
|
end
|
|
113
|
-
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
|
114
112
|
|
|
115
113
|
def visitor_cookie_name
|
|
116
114
|
@visitor_cookie_name ||= "#{VISITOR_COOKIE_NAME_PREFIX}_#{cookie_site_id}_#{cookie_tenant_id}"
|
|
@@ -24,18 +24,19 @@ module Bp3
|
|
|
24
24
|
Feature::Enabler.on(flag, enablable: ref, default:)
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
+
# An explicit false wins over the default; the default applies only when the flag is not set
|
|
27
28
|
def efon?(flag, ref: nil, default: nil)
|
|
28
|
-
efon(flag, ref:, default:) ||
|
|
29
|
+
efon(flag, ref:, default:) || false
|
|
29
30
|
end
|
|
30
31
|
|
|
31
32
|
def cfon(flag, ref: nil, default: nil)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
ref.configs&.[](flag)
|
|
33
|
+
value = ref&.configs&.[](flag)
|
|
34
|
+
value.nil? ? default : value
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
+
# An explicit false wins over the default; the default applies only when the config is not set
|
|
37
38
|
def cfon?(flag, ref: nil, default: nil)
|
|
38
|
-
cfon(flag, ref:, default:) ||
|
|
39
|
+
cfon(flag, ref:, default:) || false
|
|
39
40
|
end
|
|
40
41
|
end
|
|
41
42
|
end
|
data/lib/bp3/core/system_logs.rb
CHANGED
|
@@ -21,7 +21,7 @@ module Bp3
|
|
|
21
21
|
|
|
22
22
|
# Class methods for use in contexts without instance methods
|
|
23
23
|
module ClassMethods
|
|
24
|
-
# rubocop:disable Metrics/ParameterLists, Metrics/MethodLength
|
|
24
|
+
# rubocop:disable-next Metrics/ParameterLists, Metrics/MethodLength
|
|
25
25
|
def log(level:, key:, message: nil, exception: nil, site: nil, details: {}, **system_log_options)
|
|
26
26
|
system_log_options = SYSTEM_LOG_DEFAULTS.dup.merge(system_log_options)
|
|
27
27
|
record = nil
|
|
@@ -43,7 +43,6 @@ module Bp3
|
|
|
43
43
|
nil
|
|
44
44
|
end
|
|
45
45
|
end
|
|
46
|
-
# rubocop:enable Metrics/ParameterLists, Metrics/MethodLength
|
|
47
46
|
|
|
48
47
|
def log_debug(key:, message:, details: {}, **system_log_options)
|
|
49
48
|
log(level: 'debug', key:, message:, details:, **system_log_options)
|
|
@@ -84,11 +83,10 @@ module Bp3
|
|
|
84
83
|
end
|
|
85
84
|
end
|
|
86
85
|
|
|
87
|
-
# rubocop:disable Metrics/ParameterLists
|
|
86
|
+
# rubocop:disable-next Metrics/ParameterLists
|
|
88
87
|
def log(level:, key:, message: nil, exception: nil, site: nil, details: {}, **system_log_options)
|
|
89
88
|
SystemLogs.log(level:, key:, message:, exception:, site:, details:, **system_log_options)
|
|
90
89
|
end
|
|
91
|
-
# rubocop:enable Metrics/ParameterLists
|
|
92
90
|
|
|
93
91
|
def log_debug(key:, message:, details: {}, **system_log_options)
|
|
94
92
|
SystemLogs.log_debug(key:, message:, details:, **system_log_options)
|
data/lib/bp3/core/tenantable.rb
CHANGED
|
@@ -5,6 +5,25 @@ module Bp3
|
|
|
5
5
|
module Tenantable
|
|
6
6
|
extend ActiveSupport::Concern
|
|
7
7
|
|
|
8
|
+
# The application's request state, the Bp3::RequestState::Base subclass Bp3::Core::Rqid is
|
|
9
|
+
# configured with
|
|
10
|
+
def self.global_request_state
|
|
11
|
+
Bp3::Core::Rqid.global_request_state_class
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# How far a default scope reaches is decided by the primary login, the request state's
|
|
15
|
+
# current_login: the least privileged one signed in. A root or an admin signed in beside a less
|
|
16
|
+
# privileged login has that login's reach rather than their own.
|
|
17
|
+
def self.reaches_every_site?(state = global_request_state)
|
|
18
|
+
login = state.current_login
|
|
19
|
+
!login.nil? && login == state.current_root
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.reaches_every_tenant?(state = global_request_state)
|
|
23
|
+
login = state.current_login
|
|
24
|
+
!login.nil? && (login == state.current_root || login == state.current_admin)
|
|
25
|
+
end
|
|
26
|
+
|
|
8
27
|
included do
|
|
9
28
|
# call connection to make sure the db meta data has been loaded
|
|
10
29
|
ignore_notifications_string = (ENV['IGNORE_NOTIFICATIONS'] || '').strip
|
|
@@ -16,13 +35,13 @@ module Bp3
|
|
|
16
35
|
def set_sites_site_id
|
|
17
36
|
return if sites_site_id || sites_site
|
|
18
37
|
|
|
19
|
-
self.sites_site_id =
|
|
38
|
+
self.sites_site_id = Bp3::Core::Tenantable.global_request_state.either_site_id
|
|
20
39
|
end
|
|
21
40
|
|
|
22
41
|
def set_tenant_id
|
|
23
42
|
return if tenant_id || tenant
|
|
24
43
|
|
|
25
|
-
self.tenant_id =
|
|
44
|
+
self.tenant_id = Bp3::Core::Tenantable.global_request_state.either_tenant_id
|
|
26
45
|
end
|
|
27
46
|
|
|
28
47
|
def tenant_matches_site
|
|
@@ -38,7 +57,7 @@ module Bp3
|
|
|
38
57
|
def set_workspaces_workspace_id
|
|
39
58
|
return if workspaces_workspace_id || workspaces_workspace
|
|
40
59
|
|
|
41
|
-
self.workspaces_workspace_id =
|
|
60
|
+
self.workspaces_workspace_id = Bp3::Core::Tenantable.global_request_state.either_workspace_id
|
|
42
61
|
end
|
|
43
62
|
|
|
44
63
|
def workspaces_workspace_matches_site
|
|
@@ -75,13 +94,13 @@ module Bp3
|
|
|
75
94
|
before_validation :set_sites_site_id
|
|
76
95
|
|
|
77
96
|
default_scope lambda {
|
|
78
|
-
site =
|
|
79
|
-
site = nil if
|
|
97
|
+
site = Bp3::Core::Tenantable.global_request_state.either_site
|
|
98
|
+
site = nil if Bp3::Core::Tenantable.reaches_every_site?
|
|
80
99
|
where(sites_site_id: site.id) if site
|
|
81
100
|
}
|
|
82
101
|
end
|
|
83
102
|
|
|
84
|
-
# rubocop:disable Metrics/MethodLength
|
|
103
|
+
# rubocop:disable-next Metrics/MethodLength
|
|
85
104
|
def may_belong_to_tenant
|
|
86
105
|
column = columns.detect { |c| c.name == 'tenant_id' }
|
|
87
106
|
return if column.nil?
|
|
@@ -95,10 +114,10 @@ module Bp3
|
|
|
95
114
|
validate :tenant_matches_site
|
|
96
115
|
|
|
97
116
|
default_scope lambda {
|
|
98
|
-
site =
|
|
99
|
-
site = nil if
|
|
100
|
-
tenant =
|
|
101
|
-
tenant = nil if
|
|
117
|
+
site = Bp3::Core::Tenantable.global_request_state.either_site
|
|
118
|
+
site = nil if Bp3::Core::Tenantable.reaches_every_site?
|
|
119
|
+
tenant = Bp3::Core::Tenantable.global_request_state.either_tenant
|
|
120
|
+
tenant = nil if Bp3::Core::Tenantable.reaches_every_tenant?
|
|
102
121
|
if site && tenant # for non admins (i.e. users)
|
|
103
122
|
where(sites_site_id: site.id, tenant_id: tenant.id)
|
|
104
123
|
elsif site # for site admins
|
|
@@ -108,7 +127,6 @@ module Bp3
|
|
|
108
127
|
end
|
|
109
128
|
}
|
|
110
129
|
end
|
|
111
|
-
# rubocop:enable Metrics/MethodLength
|
|
112
130
|
|
|
113
131
|
def may_belong_to_workspace
|
|
114
132
|
column = columns.detect { |c| c.name == 'workspaces_workspace_id' }
|
data/lib/bp3/core/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bp3-core
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Wim den Braven
|
|
@@ -177,7 +177,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
177
177
|
- !ruby/object:Gem::Version
|
|
178
178
|
version: '0'
|
|
179
179
|
requirements: []
|
|
180
|
-
rubygems_version:
|
|
180
|
+
rubygems_version: 4.0.4
|
|
181
181
|
specification_version: 4
|
|
182
182
|
summary: bp3-core provides core concerns for BP3 (persuavis/black_phoebe_3).
|
|
183
183
|
test_files: []
|