foobara 0.4.1 → 0.4.2
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 +11 -0
- data/README.md +3 -1
- data/projects/command/src/command_pattern_implementation/concerns/transactions.rb +1 -0
- data/projects/command_connectors/Guardfile +1 -1
- data/projects/command_connectors/spec/auth_mappers_spec.rb +201 -0
- data/projects/command_connectors/spec/pre_commit_transformers/load_atoms_pre_commit_transformer_spec.rb +5 -2
- data/projects/command_connectors/spec/spec_helper.rb +8 -3
- data/projects/command_connectors/src/authenticator.rb +27 -16
- data/projects/command_connectors/src/command_connector/request.rb +27 -1
- data/projects/command_connectors/src/command_connector.rb +88 -3
- data/projects/command_connectors/src/transformed_command.rb +12 -2
- data/projects/entities/spec/spec_helper.rb +4 -2
- data/projects/entities_plumbing/Guardfile +6 -0
- data/projects/entities_plumbing/lib/foobara/entities_plumbing.rb +12 -0
- data/projects/entities_plumbing/spec/auth_mappers_spec.rb +159 -0
- data/projects/entities_plumbing/spec/spec_helper.rb +54 -0
- data/projects/entities_plumbing/spec/support/rubyprof.rb +32 -0
- data/projects/entities_plumbing/spec/support/term_trap.rb +6 -0
- data/projects/entities_plumbing/src/command_connectors_extension.rb +17 -0
- data/projects/entities_plumbing/src/extensions/authenticator.rb +13 -0
- data/projects/manifest/spec/spec_helper.rb +6 -3
- data/projects/typesystem/projects/builtin_types/src/builtin_types.rb +6 -6
- data/projects/typesystem/projects/domain/src/domain.rb +0 -15
- data/projects/typesystem/projects/domain/src/domain_module_extension.rb +0 -153
- data/projects/typesystem/projects/domain/src/module_extension.rb +0 -58
- data/projects/typesystem/projects/namespace/src/is_namespace.rb +8 -0
- data/projects/typesystem/projects/type_declarations/lib/foobara/type_declarations.rb +0 -15
- data/projects/typesystem/projects/type_declarations/src/type_declaration.rb +15 -12
- data/projects/typesystem/projects/type_declarations/src/typed_transformer.rb +13 -2
- data/projects/typesystem/spec/common/data_path_spec.rb +6 -8
- data/projects/typesystem/spec/spec_helper.rb +5 -3
- data/version.rb +1 -1
- metadata +11 -2
- data/projects/entities/projects/model/src/extensions/domain/module_extension.rb +0 -20
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 979ed0e27280b7f1183c77f8ca34eacaab8b232c719bf9f9ad4964ef309da64c
|
|
4
|
+
data.tar.gz: 819ad164acb49337551e91814f5faf3a78a825085c5b723d76fff701d4c1adcd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 488905b81c1b660af40b374cef9f34ebaf5548cae9202afdb2a90680abd78be9673a7b51de2431f1ce836b7815cf82ff1be245757e86da1ea0d4bcb4eed74294
|
|
7
|
+
data.tar.gz: 4a1d3377183c75ceea13be7d1501c686c97f9b6b29f76a01e9a9b9fa0e1addd18a0fdbef4bf6879e21f383aa3dc304d6ed2c1f9d1a3ac788be3db41ecc1793eb
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
# [0.4.2] - 2026-01-15
|
|
2
|
+
|
|
3
|
+
- Fix relaxed lookup bug for a symbol starting with a prefix
|
|
4
|
+
- Allow registered types to be looked up by string and in relaxed mode
|
|
5
|
+
- Create entities_plumbing project and implement auth mapping for entities
|
|
6
|
+
- Implement auth mappers concept
|
|
7
|
+
- Change authenticator to be a TypedTransformer
|
|
8
|
+
- Allow passing a block to a connector to simplify connecting stuff a bit
|
|
9
|
+
- Remove likely-unused automatic creation of Types module constants
|
|
10
|
+
- Support official ruby debug
|
|
11
|
+
|
|
1
12
|
# [0.4.1] - 2025-12-19
|
|
2
13
|
|
|
3
14
|
- Add a model_plumbing project and use it to fix up commands when models are reregistered
|
data/README.md
CHANGED
|
@@ -1578,7 +1578,9 @@ module FoobaraDemo
|
|
|
1578
1578
|
|
|
1579
1579
|
alias animal from
|
|
1580
1580
|
|
|
1581
|
-
|
|
1581
|
+
def first_name = animal.first_name
|
|
1582
|
+
def last_name = animal.last_name
|
|
1583
|
+
def birthday = animal.birthday
|
|
1582
1584
|
|
|
1583
1585
|
def birthday_to_age
|
|
1584
1586
|
today = Date.today
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
guard :rspec, all_after_pass:
|
|
1
|
+
guard :rspec, all_after_pass: false, all_on_start: true, cmd: "bundle exec rspec", failed_mode: :focus do
|
|
2
2
|
watch(%r{^spec/(.+)_spec\.rb$})
|
|
3
3
|
watch(%r{^src/(.+)\.rb$}) { "spec/" }
|
|
4
4
|
watch(%r{^lib/(.+)\.rb$}) { "spec/" }
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
RSpec.describe Foobara::CommandConnector do
|
|
2
|
+
after do
|
|
3
|
+
Foobara.reset_alls
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
let(:command_class) do
|
|
7
|
+
stub_class(:ComputeExponent, Foobara::Command) do
|
|
8
|
+
inputs exponent: :integer, base: :integer
|
|
9
|
+
result :integer
|
|
10
|
+
|
|
11
|
+
def execute = base ** exponent
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
let(:command_connector) do
|
|
16
|
+
described_class.new(authenticator:, current_user: current_user_mapper)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
let(:authenticator) do
|
|
20
|
+
proc { "some_user" }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
let(:base) { 2 }
|
|
24
|
+
let(:exponent) { 3 }
|
|
25
|
+
|
|
26
|
+
let(:response) { command_connector.run(full_command_name:, action:, inputs:) }
|
|
27
|
+
let(:errors_hash) { response.body.errors_hash }
|
|
28
|
+
|
|
29
|
+
let(:action) { "run" }
|
|
30
|
+
let(:full_command_name) { "ComputeExponent" }
|
|
31
|
+
let(:inputs) do
|
|
32
|
+
{ base:, exponent: }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe "#run_command" do
|
|
36
|
+
class << self
|
|
37
|
+
def with_current_user_allowed_rule
|
|
38
|
+
let(:allowed_rule) do
|
|
39
|
+
-> { current_user == "current_user is some_user" }
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def with_current_user_not_allowed_rule
|
|
44
|
+
let(:allowed_rule) do
|
|
45
|
+
-> { current_user == "asfdasdf" }
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def with_authenticated_user_allowed_rule
|
|
50
|
+
let(:allowed_rule) do
|
|
51
|
+
-> { authenticated_user == "some_user" }
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def with_authenticated_user_not_allowed_rule
|
|
56
|
+
let(:allowed_rule) do
|
|
57
|
+
-> { authenticated_user == "asfdasdf" }
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
shared_examples "a connector with auth mappers" do
|
|
63
|
+
before do
|
|
64
|
+
command_connector.connect(command_class, allowed_rule:)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
context "when using current_user in the allowed rule" do
|
|
68
|
+
context "when allowed" do
|
|
69
|
+
with_current_user_allowed_rule
|
|
70
|
+
|
|
71
|
+
it "runs the command" do
|
|
72
|
+
expect(response.status).to be(0)
|
|
73
|
+
expect(response.body).to eq(8)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
context "when not allowed" do
|
|
78
|
+
with_current_user_not_allowed_rule
|
|
79
|
+
|
|
80
|
+
it "fails with a relevant error" do
|
|
81
|
+
expect(response.status).to be(1)
|
|
82
|
+
expect(errors_hash.key?("runtime.not_allowed")).to be true
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
context "when calling current_user multiple times" do
|
|
87
|
+
let(:allowed_rule) do
|
|
88
|
+
-> { current_user && current_user == "current_user is some_user" }
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it "runs the command" do
|
|
92
|
+
expect(response.status).to be(0)
|
|
93
|
+
expect(response.body).to eq(8)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
context "when using authenticated_user in the allowed rule" do
|
|
99
|
+
context "when allowed" do
|
|
100
|
+
with_authenticated_user_allowed_rule
|
|
101
|
+
|
|
102
|
+
it "runs the command" do
|
|
103
|
+
expect(response.status).to be(0)
|
|
104
|
+
expect(response.body).to eq(8)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
context "when not allowed" do
|
|
109
|
+
with_authenticated_user_not_allowed_rule
|
|
110
|
+
|
|
111
|
+
it "fails with a relevant error" do
|
|
112
|
+
expect(response.status).to be(1)
|
|
113
|
+
expect(errors_hash.key?("runtime.not_allowed")).to be true
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
context "when auth user mapper is a hash" do
|
|
120
|
+
let(:current_user_mapper) do
|
|
121
|
+
{
|
|
122
|
+
to: :string,
|
|
123
|
+
map: ->(authenticated_user) { "current_user is #{authenticated_user}" }
|
|
124
|
+
}
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it_behaves_like "a connector with auth mappers"
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
context "when auth user mapper is an array" do
|
|
131
|
+
let(:current_user_mapper) { [:string, ->(authenticated_user) { "current_user is #{authenticated_user}" }] }
|
|
132
|
+
|
|
133
|
+
it_behaves_like "a connector with auth mappers"
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
context "when auth user mapper is a typed transformer class" do
|
|
137
|
+
let(:current_user_mapper) do
|
|
138
|
+
stub_class("SomeTypedTransformer", Foobara::TypeDeclarations::TypedTransformer) do
|
|
139
|
+
to :string
|
|
140
|
+
|
|
141
|
+
def transform(authenticated_user)
|
|
142
|
+
"current_user is #{authenticated_user}"
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it_behaves_like "a connector with auth mappers"
|
|
148
|
+
|
|
149
|
+
context "when it is an instance" do
|
|
150
|
+
let(:current_user_mapper) { super().instance }
|
|
151
|
+
|
|
152
|
+
it_behaves_like "a connector with auth mappers"
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
context "when auth user mapper is a domain mapper" do
|
|
157
|
+
let(:current_user_mapper) do
|
|
158
|
+
stub_class("SomeDomainMapper", Foobara::DomainMapper) do
|
|
159
|
+
from :string
|
|
160
|
+
to :string
|
|
161
|
+
|
|
162
|
+
def map = "current_user is #{from}"
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
it_behaves_like "a connector with auth mappers"
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
context "when auth user mapper is a command" do
|
|
170
|
+
context "with only one input" do
|
|
171
|
+
let(:current_user_mapper) do
|
|
172
|
+
stub_class("SomeCommand", Foobara::Command) do
|
|
173
|
+
inputs auth_user: :string
|
|
174
|
+
result :string
|
|
175
|
+
|
|
176
|
+
def execute = "current_user is #{auth_user}"
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
it_behaves_like "a connector with auth mappers"
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
context "with multiple inputs but only one required input" do
|
|
184
|
+
let(:current_user_mapper) do
|
|
185
|
+
stub_class("SomeCommand", Foobara::Command) do
|
|
186
|
+
inputs do
|
|
187
|
+
foo :string
|
|
188
|
+
bar :string
|
|
189
|
+
auth_user :string, :required
|
|
190
|
+
end
|
|
191
|
+
result :string
|
|
192
|
+
|
|
193
|
+
def execute = "current_user is #{auth_user}"
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
it_behaves_like "a connector with auth mappers"
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
@@ -76,14 +76,17 @@ RSpec.describe Foobara::CommandConnectors::Transformers::LoadAtomsPreCommitTrans
|
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
let(:command_connector) do
|
|
79
|
-
|
|
79
|
+
cc = command_class
|
|
80
|
+
Foobara::CommandConnector.new(default_pre_commit_transformers: described_class) do
|
|
81
|
+
command cc
|
|
82
|
+
end
|
|
80
83
|
end
|
|
81
84
|
|
|
82
85
|
let(:transformer) { described_class.new(to: type) }
|
|
83
86
|
|
|
84
87
|
describe "#transform" do
|
|
85
88
|
it "gives what was passed in because we expect this data to be cast where needed" do
|
|
86
|
-
command_connector
|
|
89
|
+
command_connector
|
|
87
90
|
response = command_connector.run(
|
|
88
91
|
full_command_name: command_class.full_command_name,
|
|
89
92
|
inputs: value,
|
|
@@ -2,9 +2,11 @@ ENV["FOOBARA_ENV"] = "test"
|
|
|
2
2
|
|
|
3
3
|
require "bundler/setup"
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
if ENV["RUBY_DEBUG"] == "true"
|
|
6
|
+
require "debug"
|
|
7
|
+
elsif ENV["SKIP_PRY"] != "true" && ENV["CI"] != "true"
|
|
6
8
|
require "pry"
|
|
7
|
-
require "pry-byebug"
|
|
9
|
+
require "pry-byebug" unless ENV["SKIP_BYEBUG"] == "true"
|
|
8
10
|
end
|
|
9
11
|
|
|
10
12
|
require "rspec/its"
|
|
@@ -22,13 +24,16 @@ end
|
|
|
22
24
|
|
|
23
25
|
require "foobara/all"
|
|
24
26
|
require "foobara/command_connectors"
|
|
27
|
+
# TODO: eliminate this require! We should not depend on entities in this project!
|
|
28
|
+
require "foobara/entities_plumbing"
|
|
25
29
|
|
|
26
30
|
RSpec.configure do |config|
|
|
27
31
|
# Need to do :all instead of :each because for specs that use .around,
|
|
28
32
|
# .after(:each) do |example| here is called after example.run but before any threads created in
|
|
29
33
|
# .around might have been cleaned up.
|
|
30
34
|
config.after(:suite) do
|
|
31
|
-
|
|
35
|
+
threads = Thread.list.reject { |t| t.name == "DEBUGGER__::SESSION@server" }
|
|
36
|
+
expect(threads.size).to eq(1)
|
|
32
37
|
end
|
|
33
38
|
config.filter_run_when_matching :focus
|
|
34
39
|
|
|
@@ -1,28 +1,39 @@
|
|
|
1
1
|
module Foobara
|
|
2
2
|
class CommandConnector
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
class Authenticator < TypeDeclarations::TypedTransformer
|
|
4
|
+
class << self
|
|
5
|
+
attr_writer :default_symbol
|
|
6
|
+
attr_accessor :default_explanation, :default_block
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
explanation ||= symbol
|
|
8
|
+
def subclass(to: nil, symbol: nil, explanation: nil, &default_block)
|
|
9
|
+
klass = super(to:, from: Request, &nil)
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
klass.default_symbol = symbol if symbol
|
|
12
|
+
klass.default_explanation = explanation if explanation
|
|
13
|
+
klass.default_block = default_block if default_block
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
klass
|
|
16
|
+
end
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
def default_symbol
|
|
19
|
+
@default_symbol || Util.non_full_name_underscore(self)&.to_sym
|
|
20
|
+
end
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
def instance
|
|
23
|
+
@instance ||= new
|
|
24
|
+
end
|
|
22
25
|
end
|
|
23
26
|
|
|
24
|
-
|
|
25
|
-
|
|
27
|
+
attr_accessor :symbol
|
|
28
|
+
attr_reader :block, :explanation
|
|
29
|
+
|
|
30
|
+
def initialize(symbol: nil, explanation: nil, &block)
|
|
31
|
+
self.symbol = symbol || self.class.default_symbol
|
|
32
|
+
@explanation = explanation || self.class.default_explanation || self.symbol
|
|
33
|
+
|
|
34
|
+
super()
|
|
35
|
+
|
|
36
|
+
@block = block || self.class.default_block
|
|
26
37
|
end
|
|
27
38
|
|
|
28
39
|
def transform(request)
|
|
@@ -63,6 +63,31 @@ module Foobara
|
|
|
63
63
|
command_class.authenticator
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
+
def auth_mappers
|
|
67
|
+
# TODO: make this consistent?
|
|
68
|
+
command_connector.auth_map
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def auth_mapped_method?(method_name)
|
|
72
|
+
auth_mappers&.key?(method_name)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def auth_mapper_for(name)
|
|
76
|
+
auth_mappers&.[](name.to_sym)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def auth_mapped_value_for(name)
|
|
80
|
+
return unless authenticated_user
|
|
81
|
+
|
|
82
|
+
@auth_mapper_cache ||= {}
|
|
83
|
+
|
|
84
|
+
if @auth_mapper_cache.key?(name)
|
|
85
|
+
@auth_mapper_cache[name]
|
|
86
|
+
else
|
|
87
|
+
@auth_mapper_cache[name] = auth_mapper_for(name)&.process_value!(authenticated_user)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
66
91
|
def serializer
|
|
67
92
|
return @serializer if defined?(@serializer)
|
|
68
93
|
|
|
@@ -113,11 +138,12 @@ module Foobara
|
|
|
113
138
|
outcome.error_collection
|
|
114
139
|
end
|
|
115
140
|
|
|
141
|
+
# TODO: move this to entity_plumbing
|
|
116
142
|
def relevant_entity_classes
|
|
117
143
|
if command_class.is_a?(::Class) && command_class < TransformedCommand
|
|
118
144
|
entity_classes = authenticator&.relevant_entity_classes(self)
|
|
119
145
|
[*entity_classes, *relevant_entity_classes_from_inputs_transformer]
|
|
120
|
-
end ||
|
|
146
|
+
end || EMPTY_ARRAY
|
|
121
147
|
end
|
|
122
148
|
|
|
123
149
|
private
|
|
@@ -63,7 +63,7 @@ module Foobara
|
|
|
63
63
|
case object
|
|
64
64
|
when Class
|
|
65
65
|
if object < Authenticator
|
|
66
|
-
object.
|
|
66
|
+
object.instance
|
|
67
67
|
else
|
|
68
68
|
# :nocov:
|
|
69
69
|
raise ArgumentError, "Expected a class that inherits from Authenticator"
|
|
@@ -116,17 +116,94 @@ module Foobara
|
|
|
116
116
|
end
|
|
117
117
|
end
|
|
118
118
|
end
|
|
119
|
+
|
|
120
|
+
# don't call this auth_user ?
|
|
121
|
+
def to_auth_user_mapper(object)
|
|
122
|
+
case object
|
|
123
|
+
when TypeDeclarations::TypedTransformer
|
|
124
|
+
object
|
|
125
|
+
when ::Class
|
|
126
|
+
if object < TypeDeclarations::TypedTransformer
|
|
127
|
+
object.instance
|
|
128
|
+
elsif object < Foobara::DomainMapper
|
|
129
|
+
build_auth_mapper(object.to_type) { |authenticated_user| object.map!(authenticated_user) }
|
|
130
|
+
elsif object < Foobara::Command
|
|
131
|
+
inputs_type = object.inputs_type
|
|
132
|
+
element_types = inputs_type.element_types
|
|
133
|
+
size = element_types.size
|
|
134
|
+
|
|
135
|
+
first_required_input = if size == 1
|
|
136
|
+
element_types.keys.first
|
|
137
|
+
elsif size > 1
|
|
138
|
+
declaration = inputs_type&.declaration_data
|
|
139
|
+
required_attribute_names = declaration&.[](:required) || EMPTY_ARRAY
|
|
140
|
+
|
|
141
|
+
if required_attribute_names.size == 1
|
|
142
|
+
required_attribute_names.first
|
|
143
|
+
else
|
|
144
|
+
# :nocov:
|
|
145
|
+
raise ArgumentError,
|
|
146
|
+
"Ambiguous inputs when trying to use #{object} as a mapper. " \
|
|
147
|
+
"Should have either only 1 input or only 1 required input."
|
|
148
|
+
# :nocov:
|
|
149
|
+
end
|
|
150
|
+
else
|
|
151
|
+
# :nocov:
|
|
152
|
+
raise ArgumentError, "To use a command as a mapper it must take an input to map"
|
|
153
|
+
# :nocov:
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
build_auth_mapper(object.result_type) do |authenticated_user|
|
|
157
|
+
object.run!(first_required_input => authenticated_user)
|
|
158
|
+
end
|
|
159
|
+
else
|
|
160
|
+
# :nocov:
|
|
161
|
+
raise ArgumentError, "not sure how to convert a #{object} to an auth mapper"
|
|
162
|
+
# :nocov:
|
|
163
|
+
end
|
|
164
|
+
when ::Hash
|
|
165
|
+
object => { to:, map: }
|
|
166
|
+
build_auth_mapper(to, &map)
|
|
167
|
+
when ::Array
|
|
168
|
+
object => [to, map]
|
|
169
|
+
build_auth_mapper(to, &map)
|
|
170
|
+
else
|
|
171
|
+
# :nocov:
|
|
172
|
+
raise ArgumentError, "Not sure how to convert #{object} to an auth mapper"
|
|
173
|
+
# :nocov:
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# TODO: make private
|
|
178
|
+
def build_auth_mapper(to_type, &)
|
|
179
|
+
TypeDeclarations::TypedTransformer.subclass(to: to_type, &).instance
|
|
180
|
+
end
|
|
119
181
|
end
|
|
120
182
|
|
|
121
|
-
attr_accessor :command_registry, :authenticator, :capture_unknown_error, :name
|
|
183
|
+
attr_accessor :command_registry, :authenticator, :capture_unknown_error, :name,
|
|
184
|
+
:auth_map
|
|
122
185
|
|
|
123
186
|
def initialize(name: nil,
|
|
124
187
|
authenticator: nil,
|
|
125
188
|
capture_unknown_error: nil,
|
|
126
189
|
default_serializers: nil,
|
|
127
|
-
default_pre_commit_transformers: nil
|
|
190
|
+
default_pre_commit_transformers: nil,
|
|
191
|
+
auth_map: nil,
|
|
192
|
+
current_user: nil,
|
|
193
|
+
&block)
|
|
128
194
|
authenticator = self.class.to_authenticator(authenticator)
|
|
129
195
|
|
|
196
|
+
if current_user
|
|
197
|
+
auth_map ||= {}
|
|
198
|
+
auth_map[:current_user] = current_user
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
if auth_map
|
|
202
|
+
self.auth_map = auth_map.transform_values do |mapper|
|
|
203
|
+
self.class.to_auth_user_mapper(mapper)
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
130
207
|
self.authenticator = authenticator
|
|
131
208
|
self.command_registry = CommandRegistry.new(authenticator:)
|
|
132
209
|
self.capture_unknown_error = capture_unknown_error
|
|
@@ -143,8 +220,15 @@ module Foobara
|
|
|
143
220
|
self.class.allowed_rules_to_register.each do |ruleish_args|
|
|
144
221
|
command_registry.allowed_rule(*ruleish_args)
|
|
145
222
|
end
|
|
223
|
+
|
|
224
|
+
if block
|
|
225
|
+
instance_eval(&block)
|
|
226
|
+
end
|
|
146
227
|
end
|
|
147
228
|
|
|
229
|
+
# TODO: should this be the official way to connect a command instead of #connect ?
|
|
230
|
+
def command(...) = connect(...)
|
|
231
|
+
|
|
148
232
|
def connect(*args, **opts)
|
|
149
233
|
args, opts = desugarize_connect_args(args, opts)
|
|
150
234
|
|
|
@@ -477,6 +561,7 @@ module Foobara
|
|
|
477
561
|
end
|
|
478
562
|
end
|
|
479
563
|
|
|
564
|
+
# TODO: get all this persistence stuff out of here and into entities plumbing somehow
|
|
480
565
|
def run_request(request)
|
|
481
566
|
command_class = determine_command_class(request)
|
|
482
567
|
request.command_class = command_class
|
|
@@ -782,7 +782,9 @@ module Foobara
|
|
|
782
782
|
end
|
|
783
783
|
|
|
784
784
|
def method_missing(method_name, ...)
|
|
785
|
-
if
|
|
785
|
+
if auth_mapped_method?(method_name)
|
|
786
|
+
auth_mapped_value_for(method_name)
|
|
787
|
+
elsif command.respond_to?(method_name)
|
|
786
788
|
command.send(method_name, ...)
|
|
787
789
|
else
|
|
788
790
|
# :nocov:
|
|
@@ -791,8 +793,16 @@ module Foobara
|
|
|
791
793
|
end
|
|
792
794
|
end
|
|
793
795
|
|
|
796
|
+
def auth_mapped_value_for(name)
|
|
797
|
+
request.auth_mapped_value_for(name)
|
|
798
|
+
end
|
|
799
|
+
|
|
800
|
+
def auth_mapped_method?(method_name)
|
|
801
|
+
request&.auth_mapped_method?(method_name)
|
|
802
|
+
end
|
|
803
|
+
|
|
794
804
|
def respond_to_missing?(method_name, private = false)
|
|
795
|
-
command.respond_to?(method_name, private) || super
|
|
805
|
+
command.respond_to?(method_name, private) || auth_mapped_method?(method_name) || super
|
|
796
806
|
end
|
|
797
807
|
|
|
798
808
|
private
|
|
@@ -2,9 +2,11 @@ ENV["FOOBARA_ENV"] = "test"
|
|
|
2
2
|
|
|
3
3
|
require "bundler/setup"
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
if ENV["RUBY_DEBUG"] == "true"
|
|
6
|
+
require "debug"
|
|
7
|
+
elsif ENV["SKIP_PRY"] != "true" && ENV["CI"] != "true"
|
|
6
8
|
require "pry"
|
|
7
|
-
require "pry-byebug"
|
|
9
|
+
require "pry-byebug" unless ENV["SKIP_BYEBUG"] == "true"
|
|
8
10
|
end
|
|
9
11
|
|
|
10
12
|
require "rspec/its"
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
guard :rspec, all_after_pass: false, all_on_start: true, cmd: "bundle exec rspec", failed_mode: :focus do
|
|
2
|
+
watch(%r{^spec/(.+)_spec\.rb$})
|
|
3
|
+
watch(%r{^src/(.+)\.rb$}) { "spec/" }
|
|
4
|
+
watch(%r{^lib/(.+)\.rb$}) { "spec/" }
|
|
5
|
+
watch(%r{^spec/spec_helper.rb$}) { "spec/" }
|
|
6
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require "foobara/command_connectors"
|
|
2
|
+
|
|
3
|
+
module Foobara
|
|
4
|
+
module EntitiesPlumbing
|
|
5
|
+
end
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
Foobara.project("entities_plumbing", project_path: "#{__dir__}/../..")
|
|
9
|
+
|
|
10
|
+
Foobara::CommandConnector.singleton_class.prepend(
|
|
11
|
+
Foobara::EntitiesPlumbing::CommandConnectorsExtension::ClassMethods
|
|
12
|
+
)
|