trailblazer-endpoint 0.0.6 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +19 -0
- data/lib/trailblazer/endpoint/controller.rb +27 -8
- data/lib/trailblazer/endpoint/dsl.rb +2 -0
- data/lib/trailblazer/endpoint/protocol/cipher.rb +27 -0
- data/lib/trailblazer/endpoint/protocol/controller.rb +102 -0
- data/lib/trailblazer/endpoint/protocol/find_process_model.rb +15 -0
- data/lib/trailblazer/endpoint/protocol.rb +2 -3
- data/lib/trailblazer/endpoint/version.rb +1 -1
- data/lib/trailblazer/endpoint.rb +42 -24
- data/test/docs/controller_test.rb +2 -1
- data/test/rails-app/Gemfile +13 -1
- data/test/rails-app/Gemfile.lock +110 -84
- data/test/rails-app/app/controllers/application_controller/web.rb +4 -2
- data/test/rails-app/app/controllers/songs_controller.rb +183 -0
- data/test/rails-app/app/models/song.rb +4 -1
- data/test/rails-app/config/environments/test.rb +2 -0
- data/test/rails-app/config/routes.rb +11 -0
- data/test/rails-app/test/controllers/songs_controller_test.rb +74 -0
- data/trailblazer-endpoint.gemspec +2 -2
- metadata +11 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 57e2396200f20eb000c87f7b740ea31dd41c9db79ea6d3ba02bdb2e85e0b8ba0
|
4
|
+
data.tar.gz: 68fc7c66e7fdebe16cf6a347c0d7104efb520fcf2fc8aabcafd79914df5492d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 93f8b8b7e0fad7959cec6ac2f8b11955867ccc6276ee511748beb072df2f66e00ccb648f082c30e7f776cf3736442688d0334e9c59ea95c06d96b6b26ea6f6ec
|
7
|
+
data.tar.gz: 200822214d8146292f64390c63fb3104386496b2326e6fd026d61bd477592fb6bc86d3a3acb48c8e9acd279ac5375f8164da816c6744e6ec5e901ec9d3edf718
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
# 0.0.10
|
2
|
+
|
3
|
+
* Require `dsl-linear` >= 0.5.0.
|
4
|
+
|
5
|
+
# 0.0.9
|
6
|
+
|
7
|
+
* Fix Ruby 3.0 code.
|
8
|
+
* Update dependencies.
|
9
|
+
|
10
|
+
# 0.0.8
|
11
|
+
|
12
|
+
* Add `Protocol.insert_copy_from_domain_ctx!` to copy from `domain_ctx` to the `endpoint_ctx`.
|
13
|
+
|
14
|
+
# 0.0.7
|
15
|
+
|
16
|
+
* BREAKING: Remove `:domain_ctx_filter` in favor of `Controller.insert_copy_to_domain_ctx!`.
|
17
|
+
* Add support for serializing `:suspend_data` and deserializing `:resume_data` so session data can get automatically encrypted and passed to the next action. This used to sit in `workflow`.
|
18
|
+
* Add `:find_process_model`. This introduces a new protocol step before `policy` to find the "process model" instead of letting the domain operation or even the policy (or both!) find the "current model".
|
19
|
+
|
1
20
|
# 0.0.6
|
2
21
|
|
3
22
|
* `Controller::endpoint` short form introduced.
|
@@ -92,18 +92,19 @@ module Trailblazer
|
|
92
92
|
extended.directive(:endpoints, ->(*) { {} })
|
93
93
|
end
|
94
94
|
|
95
|
-
|
95
|
+
# Builds and registers an endpoint in a controller class.
|
96
|
+
def endpoint(name=nil, **options, &block)
|
96
97
|
options = options.merge(protocol_block: block) if block_given?
|
97
98
|
|
98
|
-
return generic_endpoint_config(**
|
99
|
-
|
99
|
+
return generic_endpoint_config(**options) if name.nil?
|
100
|
+
|
101
|
+
build_endpoint(name, **options)
|
100
102
|
end
|
101
103
|
|
102
|
-
|
104
|
+
# Configures generic {:adapter}, {:protocol}, etc.
|
105
|
+
def generic_endpoint_config(**options)
|
103
106
|
self.singleton_class.define_method :generic_options do |ctx,**|
|
104
107
|
{
|
105
|
-
protocol: protocol,
|
106
|
-
adapter: adapter,
|
107
108
|
**options
|
108
109
|
}
|
109
110
|
end
|
@@ -111,10 +112,10 @@ module Trailblazer
|
|
111
112
|
directive :generic_options, method(:generic_options) # FIXME: do we need this?
|
112
113
|
end
|
113
114
|
|
114
|
-
def
|
115
|
+
def build_endpoint(name, domain_activity: name, **options)
|
115
116
|
build_options = options_for(:generic_options, {}).merge(domain_activity: domain_activity, **options) # DISCUSS: why don't we add this as another directive option/step?
|
116
117
|
|
117
|
-
endpoint = Trailblazer::Endpoint.build(build_options)
|
118
|
+
endpoint = Trailblazer::Endpoint.build(**build_options)
|
118
119
|
|
119
120
|
directive :endpoints, ->(*) { {name.to_s => endpoint} }
|
120
121
|
end
|
@@ -134,6 +135,24 @@ module Trailblazer
|
|
134
135
|
|
135
136
|
endpoint = endpoint_for(name)
|
136
137
|
|
138
|
+
# raise name.inspect unless block_given?
|
139
|
+
# TODO: check {dsl: false}
|
140
|
+
# unless block_given? # FIXME
|
141
|
+
# config_source = self.class # FIXME
|
142
|
+
# block_options = config_source.options_for(:options_for_block_options, **action_options)
|
143
|
+
# block_options = Trailblazer::Endpoint::Options.merge_with(action_options, block_options)
|
144
|
+
|
145
|
+
# signal, (ctx, _) = Trailblazer::Endpoint::Controller.advance_endpoint_for_controller(
|
146
|
+
# endpoint: endpoint,
|
147
|
+
# block_options: block_options,
|
148
|
+
# config_source: config_source,
|
149
|
+
# **action_options
|
150
|
+
# )
|
151
|
+
|
152
|
+
# return ctx
|
153
|
+
# end
|
154
|
+
|
155
|
+
|
137
156
|
invoke_endpoint_with_dsl(endpoint: endpoint, **action_options, &block)
|
138
157
|
end
|
139
158
|
|
@@ -19,9 +19,11 @@ module Trailblazer
|
|
19
19
|
# #call
|
20
20
|
def to_args(default_block_options)
|
21
21
|
return options,
|
22
|
+
default_block_options.merge( # this adds :invoke.
|
22
23
|
success_block: success_block || default_block_options[:success_block],
|
23
24
|
failure_block: failure_block || default_block_options[:failure_block],
|
24
25
|
protocol_failure_block: protocol_failure_block || default_block_options[:protocol_failure_block]
|
26
|
+
)
|
25
27
|
end
|
26
28
|
end
|
27
29
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "openssl"
|
2
|
+
|
3
|
+
module Trailblazer
|
4
|
+
class Endpoint::Protocol
|
5
|
+
module Controller
|
6
|
+
module Cipher # FIXME: copied from Tyrant!
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def encrypt_value(ctx, value:, cipher_key:, **)
|
10
|
+
cipher = OpenSSL::Cipher.new('DES-EDE3-CBC').encrypt
|
11
|
+
cipher.key = Digest::SHA1.hexdigest(cipher_key)[0..23] # ArgumentError: key must be 24 bytes
|
12
|
+
s = cipher.update(value) + cipher.final
|
13
|
+
|
14
|
+
ctx[:encrypted_value] = s.unpack('H*')[0].upcase
|
15
|
+
end
|
16
|
+
|
17
|
+
def decrypt_value(ctx, encrypted_value:, cipher_key:, **)
|
18
|
+
cipher = OpenSSL::Cipher.new('DES-EDE3-CBC').decrypt
|
19
|
+
cipher.key = Digest::SHA1.hexdigest(cipher_key)[0..23]
|
20
|
+
s = [encrypted_value].pack("H*").unpack("C*").pack("c*")
|
21
|
+
|
22
|
+
ctx[:decrypted_value] = cipher.update(s) + cipher.final
|
23
|
+
end
|
24
|
+
end # Cipher
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module Trailblazer
|
2
|
+
class Endpoint::Protocol
|
3
|
+
# Deserialize incoming state.
|
4
|
+
# Serialize outgoing state.
|
5
|
+
# What else?
|
6
|
+
module Controller
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def decrypt?(ctx, encrypted_resume_data:, **)
|
10
|
+
encrypted_resume_data
|
11
|
+
end
|
12
|
+
|
13
|
+
def deserialize_resume_data(ctx, decrypted_value:, **)
|
14
|
+
ctx[:resume_data] = JSON.parse(decrypted_value)
|
15
|
+
end
|
16
|
+
|
17
|
+
def deserialize_process_model?(ctx, process_model_from_resume_data:, **)
|
18
|
+
process_model_from_resume_data
|
19
|
+
end
|
20
|
+
|
21
|
+
def deserialize_process_model_id(ctx, resume_data:, **)
|
22
|
+
ctx[:process_model_id] = resume_data["id"] # DISCUSS: overriding {:process_model_id}?
|
23
|
+
end
|
24
|
+
|
25
|
+
def encrypt?(ctx, domain_ctx:, **)
|
26
|
+
ctx[:suspend_data] = domain_ctx[:suspend_data]
|
27
|
+
end
|
28
|
+
|
29
|
+
def serialize_suspend_data(ctx, suspend_data:, **)
|
30
|
+
ctx[:serialized_suspend_data] = JSON.dump(suspend_data)
|
31
|
+
end
|
32
|
+
|
33
|
+
def copy_suspend_data_to_endpoint_ctx(ctx, domain_ctx:, **)
|
34
|
+
ctx[:suspend_data] = domain_ctx[:suspend_data] # FIXME: use {#insert_copy_from_domain_ctx!}
|
35
|
+
end
|
36
|
+
|
37
|
+
# FIXME: use Model() mechanics.
|
38
|
+
def deserialize_process_model_id_from_resume_data(ctx, resume_data:, **)
|
39
|
+
# DISCUSS: should we warn when overriding an existing {process_model_id}?
|
40
|
+
ctx[:process_model_id] = resume_data["id"] # DISCUSS: overriding {:process_model_id}? # FIXME: stolen from Advance___::Controller
|
41
|
+
end
|
42
|
+
|
43
|
+
def insert_deserialize_steps!(activity, deserialize_before: :policy)
|
44
|
+
activity.module_eval do
|
45
|
+
step Controller.method(:decrypt?), id: :decrypt?, before: deserialize_before # error out if no serialized_resume_data given.
|
46
|
+
step Controller::Cipher.method(:decrypt_value), id: :decrypt,
|
47
|
+
input: {cipher_key: :cipher_key, encrypted_resume_data: :encrypted_value} , before: deserialize_before,
|
48
|
+
# Output(:failure) => Track(:success),
|
49
|
+
Output(:success) => Path(connect_to: Track(:success), track_color: :deserialize, before: deserialize_before) do # usually, Path goes into {policy}
|
50
|
+
|
51
|
+
step Controller.method(:deserialize_resume_data), id: :deserialize_resume_data
|
52
|
+
# DISCUSS: unmarshall?
|
53
|
+
# step Controller.method(:deserialize_process_model_id?), id: :deserialize_process_model_id?, activity.Output(Trailblazer::Activity::Left, :failure) => activity.Id(around_activity_id)
|
54
|
+
# step Controller.method(:deserialize_process_model_id), id: :deserialize_process_model_id
|
55
|
+
|
56
|
+
step ->(*) { true } # FIXME: otherwise we can't insert an element AFTER :deserialize_resume_data
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def insert_serialize_steps!(activity, serialize_after: :domain_activity)
|
62
|
+
activity.module_eval do
|
63
|
+
# FIXME: reverse order for insertion
|
64
|
+
step Controller::Cipher.method(:encrypt_value), id: :encrypt , after: serialize_after,
|
65
|
+
input: {cipher_key: :cipher_key, serialized_suspend_data: :value}, output: {encrypted_value: :encrypted_suspend_data}
|
66
|
+
step Controller.method(:serialize_suspend_data), id: :serialize_suspend_data , after: serialize_after
|
67
|
+
pass Controller.method(:copy_suspend_data_to_endpoint_ctx), id: :copy_suspend_data_to_endpoint_ctx , after: serialize_after
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Insert the "experimental" {find_process_model} steps
|
72
|
+
def insert_find_process_model!(protocol, **options)
|
73
|
+
protocol.module_eval do
|
74
|
+
step Subprocess(FindProcessModel), Output(:failure) => End(:not_found),
|
75
|
+
id: :find_process_model,
|
76
|
+
**options
|
77
|
+
# after: :authenticate
|
78
|
+
end
|
79
|
+
|
80
|
+
insert_copy_to_domain_ctx!(protocol, {:process_model => :model})
|
81
|
+
end
|
82
|
+
|
83
|
+
def insert_copy_to_domain_ctx!(protocol, variables, before: :domain_activity) # FIXME: `:before` untested!
|
84
|
+
variables.each do |original_name, domain_name|
|
85
|
+
protocol.module_eval do
|
86
|
+
pass ->(ctx, domain_ctx:, **) { domain_ctx[domain_name] = ctx[original_name] if ctx.key?(original_name) },
|
87
|
+
id: :"copy_[#{original_name.inspect}]_to_domain_ctx[#{domain_name.inspect}]", before: before
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def insert_copy_from_domain_ctx!(protocol, variables, after: :domain_activity) # FIXME: `:after` untested!
|
93
|
+
variables.each do |domain_name, endpoint_name|
|
94
|
+
protocol.module_eval do
|
95
|
+
pass ->(ctx, domain_ctx:, **) { ctx[endpoint_name] = domain_ctx[domain_name] if domain_ctx.key?(domain_name) },
|
96
|
+
id: :"copy_[#{endpoint_name.inspect}]_from_domain_ctx[#{domain_name.inspect}]", after: after
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Trailblazer::Endpoint::Protocol
|
2
|
+
class FindProcessModel < Trailblazer::Activity::Railway
|
3
|
+
# step :find_process_model?, Output(:failure) => Id("End.success")
|
4
|
+
step :find_process_model#, Output(:failure) => End(:not_found) # DISCUSS: currently, {End.failure} implies {not_found}.
|
5
|
+
|
6
|
+
# DISCUSS: should the implementation remain in {Activity}?
|
7
|
+
# def find_process_model?(ctx, find_process_model:, **)
|
8
|
+
# find_process_model
|
9
|
+
# end
|
10
|
+
|
11
|
+
def find_process_model(ctx, process_model_class:, process_model_id:, **)
|
12
|
+
ctx[:process_model] = process_model_class.find_by(id: process_model_id)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -24,7 +24,7 @@ module Trailblazer
|
|
24
24
|
|
25
25
|
step :authenticate, Output(:failure) => _Path(semantic: :not_authenticated) do
|
26
26
|
# step :handle_not_authenticated
|
27
|
-
|
27
|
+
end
|
28
28
|
|
29
29
|
step :policy, Output(:failure) => _Path(semantic: :not_authorized) do # user from cookie, etc
|
30
30
|
# step :handle_not_authorized
|
@@ -113,7 +113,6 @@ module Trailblazer
|
|
113
113
|
[[Trailblazer::Activity::TaskWrap::Pipeline.method(:insert_after), "task_wrap.call_task", ["endpoint.end_signal", method(:terminus_handler)]]]
|
114
114
|
end
|
115
115
|
end
|
116
|
-
|
117
|
-
end
|
116
|
+
end # Protocol
|
118
117
|
end
|
119
118
|
end
|
data/lib/trailblazer/endpoint.rb
CHANGED
@@ -2,7 +2,12 @@ module Trailblazer
|
|
2
2
|
class Endpoint
|
3
3
|
# Create an {Endpoint} class with the provided adapter and protocol.
|
4
4
|
# This builder also sets up taskWrap filters around the {domain_activity} execution.
|
5
|
-
def self.build(protocol:, adapter:, domain_activity:, scope_domain_ctx: true,
|
5
|
+
def self.build(protocol:, adapter:, domain_activity:, scope_domain_ctx: true, protocol_block: ->(*) { Hash.new },
|
6
|
+
serialize: false, # TODO: plug-in, not hardcoded!
|
7
|
+
deserialize: false,# TODO: plug-in, not hardcoded!
|
8
|
+
find_process_model: false, # TODO: plug-in, not hardcoded!
|
9
|
+
deserialize_process_model_id_from_resume_data: false # TODO: plug-in, not hardcoded!
|
10
|
+
)
|
6
11
|
# special considerations around the {domain_activity} and its taskWrap:
|
7
12
|
#
|
8
13
|
# 1. domain_ctx_filter (e.g. to filter {current_user})
|
@@ -19,14 +24,41 @@ module Trailblazer
|
|
19
24
|
# scoping: {:domain_ctx} becomes ctx
|
20
25
|
extensions_options.merge!(Endpoint.options_for_scope_domain_ctx) if scope_domain_ctx # TODO: test flag
|
21
26
|
|
27
|
+
app_protocol = build_protocol(protocol, domain_activity: domain_activity, extensions_options: extensions_options, protocol_block: protocol_block, serialize: serialize, deserialize: deserialize,
|
28
|
+
find_process_model: find_process_model, deserialize_process_model_id_from_resume_data: deserialize_process_model_id_from_resume_data
|
29
|
+
)
|
30
|
+
|
31
|
+
# puts Trailblazer::Developer.render(app_protocol)
|
32
|
+
|
33
|
+
Class.new(adapter) do
|
34
|
+
step(Subprocess(app_protocol), {inherit: true, id: :protocol, replace: :protocol})
|
35
|
+
end # app_adapter
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
# @private
|
40
|
+
def self.build_protocol(protocol, domain_activity:, extensions_options:, protocol_block:, serialize:, deserialize:, find_process_model:, deserialize_process_model_id_from_resume_data:)
|
41
|
+
Class.new(protocol) do
|
42
|
+
if serialize
|
43
|
+
Protocol::Controller.insert_serialize_steps!(self)
|
44
|
+
end
|
45
|
+
|
46
|
+
if deserialize
|
47
|
+
Protocol::Controller.insert_deserialize_steps!(self)
|
48
|
+
end
|
49
|
+
|
50
|
+
if serialize || deserialize
|
51
|
+
Protocol::Controller.insert_copy_to_domain_ctx!(self, {:resume_data => :resume_data})
|
52
|
+
end
|
22
53
|
|
23
|
-
|
24
|
-
|
54
|
+
if find_process_model
|
55
|
+
Protocol::Controller.insert_find_process_model!(self, before: :policy) # TODO: test before: :policy
|
56
|
+
end
|
25
57
|
|
26
|
-
|
27
|
-
|
58
|
+
if deserialize_process_model_id_from_resume_data
|
59
|
+
pass Protocol::Controller.method(:deserialize_process_model_id_from_resume_data), after: :deserialize_resume_data, magnetic_to: :deserialize, Output(:success) => Track(:deserialize)
|
60
|
+
end
|
28
61
|
|
29
|
-
app_protocol = Class.new(protocol) do
|
30
62
|
step(Subprocess(domain_activity), {inherit: true, id: :domain_activity, replace: :domain_activity,
|
31
63
|
|
32
64
|
# FIXME: where does this go?
|
@@ -35,13 +67,6 @@ module Trailblazer
|
|
35
67
|
merge(instance_exec(&protocol_block)) # the block is evaluated in the {Protocol} context.
|
36
68
|
)
|
37
69
|
end
|
38
|
-
|
39
|
-
# puts Trailblazer::Developer.render(app_protocol)
|
40
|
-
|
41
|
-
Class.new(adapter) do
|
42
|
-
step(Subprocess(app_protocol), {inherit: true, id: :protocol, replace: :protocol})
|
43
|
-
end # app_adapter
|
44
|
-
|
45
70
|
end
|
46
71
|
|
47
72
|
def self.options_for_scope_domain_ctx()
|
@@ -51,16 +76,6 @@ module Trailblazer
|
|
51
76
|
}
|
52
77
|
end
|
53
78
|
|
54
|
-
def self.domain_ctx_filter(variables)
|
55
|
-
->(_ctx, ((ctx, a), b)) do # taskWrap interface
|
56
|
-
variables.each do |variable|
|
57
|
-
ctx[:domain_ctx][variable] = ctx[variable]
|
58
|
-
end
|
59
|
-
|
60
|
-
[_ctx, [[ctx, a], b]]
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
79
|
# Runtime
|
65
80
|
# Invokes the endpoint for you and runs one of the three outcome blocks.
|
66
81
|
def self.with_or_etc(activity, args, failure_block:, success_block:, protocol_failure_block:, invoke: Trailblazer::Activity::TaskWrap.method(:invoke))
|
@@ -116,7 +131,7 @@ module Trailblazer
|
|
116
131
|
end
|
117
132
|
|
118
133
|
# FIXME: name will change! this is for controllers, only!
|
119
|
-
def self.advance_from_controller(endpoint, success_block:, failure_block:, protocol_failure_block
|
134
|
+
def self.advance_from_controller(endpoint, success_block:, failure_block:, protocol_failure_block:, **argument_options)
|
120
135
|
args = Trailblazer::Endpoint.arguments_for(argument_options)
|
121
136
|
|
122
137
|
signal, (ctx, _ ) = Trailblazer::Endpoint.with_or_etc(
|
@@ -146,3 +161,6 @@ require "trailblazer/endpoint/adapter"
|
|
146
161
|
require "trailblazer/endpoint/dsl"
|
147
162
|
require "trailblazer/endpoint/controller"
|
148
163
|
require "trailblazer/endpoint/options"
|
164
|
+
require "trailblazer/endpoint/protocol/controller"
|
165
|
+
require "trailblazer/endpoint/protocol/find_process_model"
|
166
|
+
require "trailblazer/endpoint/protocol/cipher"
|
@@ -58,7 +58,8 @@ class DocsControllerTest < Minitest::Spec
|
|
58
58
|
include T.def_steps(:authenticate, :policy)
|
59
59
|
end
|
60
60
|
|
61
|
-
endpoint protocol: Protocol, adapter: Trailblazer::Endpoint::Adapter::Web,
|
61
|
+
endpoint protocol: Protocol, adapter: Trailblazer::Endpoint::Adapter::Web,
|
62
|
+
scope_domain_ctx: true
|
62
63
|
end
|
63
64
|
|
64
65
|
class HtmlController < ApplicationController
|
data/test/rails-app/Gemfile
CHANGED
@@ -13,7 +13,13 @@ gem 'sqlite3', '~> 1.4'
|
|
13
13
|
# Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible
|
14
14
|
# gem 'rack-cors'
|
15
15
|
|
16
|
-
gem "trailblazer-operation"
|
16
|
+
# gem "trailblazer-operation"
|
17
|
+
gem "trailblazer-operation", path: "../../../trailblazer-operation"
|
18
|
+
gem "trailblazer-context", path: "../../../trailblazer-context"
|
19
|
+
gem "trailblazer-activity-dsl-linear", path: "../../../trailblazer-activity-dsl-linear"
|
20
|
+
gem "trailblazer-activity", path: "../../../trailblazer-activity"
|
21
|
+
|
22
|
+
|
17
23
|
gem "trailblazer-endpoint", path: "../../."
|
18
24
|
gem "jwt"
|
19
25
|
gem "multi_json"
|
@@ -21,3 +27,9 @@ gem "minitest-line"
|
|
21
27
|
gem "trailblazer-cells"
|
22
28
|
gem "cells-erb"
|
23
29
|
gem "cells-rails"
|
30
|
+
|
31
|
+
|
32
|
+
# FIXME
|
33
|
+
# gem "trailblazer-workflow", path: "../../../trailblazer-workflow"
|
34
|
+
# gem "trailblazer-activity-dsl-linear", path: "../../../trailblazer-activity-dsl-linear"
|
35
|
+
# gem "trailblazer-activity-dsl-linear", ">= 0.3.4"
|
data/test/rails-app/Gemfile.lock
CHANGED
@@ -1,62 +1,89 @@
|
|
1
|
+
PATH
|
2
|
+
remote: ../../../trailblazer-activity-dsl-linear
|
3
|
+
specs:
|
4
|
+
trailblazer-activity-dsl-linear (0.5.0)
|
5
|
+
trailblazer-activity (>= 0.13.0, < 1.0.0)
|
6
|
+
|
7
|
+
PATH
|
8
|
+
remote: ../../../trailblazer-activity
|
9
|
+
specs:
|
10
|
+
trailblazer-activity (0.13.0)
|
11
|
+
trailblazer-context (~> 0.5.0)
|
12
|
+
trailblazer-option (~> 0.1.0)
|
13
|
+
|
14
|
+
PATH
|
15
|
+
remote: ../../../trailblazer-context
|
16
|
+
specs:
|
17
|
+
trailblazer-context (0.5.0)
|
18
|
+
hashie (>= 3.0.0)
|
19
|
+
|
20
|
+
PATH
|
21
|
+
remote: ../../../trailblazer-operation
|
22
|
+
specs:
|
23
|
+
trailblazer-operation (0.7.5)
|
24
|
+
trailblazer-activity (>= 0.12.2, < 1.0.0)
|
25
|
+
trailblazer-activity-dsl-linear (>= 0.4.1, < 1.0.0)
|
26
|
+
trailblazer-developer (>= 0.0.21, < 1.0.0)
|
27
|
+
|
1
28
|
PATH
|
2
29
|
remote: ../..
|
3
30
|
specs:
|
4
|
-
trailblazer-endpoint (0.0.
|
5
|
-
trailblazer-activity-dsl-linear (>= 0.
|
31
|
+
trailblazer-endpoint (0.0.9)
|
32
|
+
trailblazer-activity-dsl-linear (>= 0.5.0, < 0.6.0)
|
6
33
|
|
7
34
|
GEM
|
8
35
|
remote: https://rubygems.org/
|
9
36
|
specs:
|
10
|
-
actioncable (6.0.3.
|
11
|
-
actionpack (= 6.0.3.
|
37
|
+
actioncable (6.0.3.4)
|
38
|
+
actionpack (= 6.0.3.4)
|
12
39
|
nio4r (~> 2.0)
|
13
40
|
websocket-driver (>= 0.6.1)
|
14
|
-
actionmailbox (6.0.3.
|
15
|
-
actionpack (= 6.0.3.
|
16
|
-
activejob (= 6.0.3.
|
17
|
-
activerecord (= 6.0.3.
|
18
|
-
activestorage (= 6.0.3.
|
19
|
-
activesupport (= 6.0.3.
|
41
|
+
actionmailbox (6.0.3.4)
|
42
|
+
actionpack (= 6.0.3.4)
|
43
|
+
activejob (= 6.0.3.4)
|
44
|
+
activerecord (= 6.0.3.4)
|
45
|
+
activestorage (= 6.0.3.4)
|
46
|
+
activesupport (= 6.0.3.4)
|
20
47
|
mail (>= 2.7.1)
|
21
|
-
actionmailer (6.0.3.
|
22
|
-
actionpack (= 6.0.3.
|
23
|
-
actionview (= 6.0.3.
|
24
|
-
activejob (= 6.0.3.
|
48
|
+
actionmailer (6.0.3.4)
|
49
|
+
actionpack (= 6.0.3.4)
|
50
|
+
actionview (= 6.0.3.4)
|
51
|
+
activejob (= 6.0.3.4)
|
25
52
|
mail (~> 2.5, >= 2.5.4)
|
26
53
|
rails-dom-testing (~> 2.0)
|
27
|
-
actionpack (6.0.3.
|
28
|
-
actionview (= 6.0.3.
|
29
|
-
activesupport (= 6.0.3.
|
54
|
+
actionpack (6.0.3.4)
|
55
|
+
actionview (= 6.0.3.4)
|
56
|
+
activesupport (= 6.0.3.4)
|
30
57
|
rack (~> 2.0, >= 2.0.8)
|
31
58
|
rack-test (>= 0.6.3)
|
32
59
|
rails-dom-testing (~> 2.0)
|
33
60
|
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
34
|
-
actiontext (6.0.3.
|
35
|
-
actionpack (= 6.0.3.
|
36
|
-
activerecord (= 6.0.3.
|
37
|
-
activestorage (= 6.0.3.
|
38
|
-
activesupport (= 6.0.3.
|
61
|
+
actiontext (6.0.3.4)
|
62
|
+
actionpack (= 6.0.3.4)
|
63
|
+
activerecord (= 6.0.3.4)
|
64
|
+
activestorage (= 6.0.3.4)
|
65
|
+
activesupport (= 6.0.3.4)
|
39
66
|
nokogiri (>= 1.8.5)
|
40
|
-
actionview (6.0.3.
|
41
|
-
activesupport (= 6.0.3.
|
67
|
+
actionview (6.0.3.4)
|
68
|
+
activesupport (= 6.0.3.4)
|
42
69
|
builder (~> 3.1)
|
43
70
|
erubi (~> 1.4)
|
44
71
|
rails-dom-testing (~> 2.0)
|
45
72
|
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
46
|
-
activejob (6.0.3.
|
47
|
-
activesupport (= 6.0.3.
|
73
|
+
activejob (6.0.3.4)
|
74
|
+
activesupport (= 6.0.3.4)
|
48
75
|
globalid (>= 0.3.6)
|
49
|
-
activemodel (6.0.3.
|
50
|
-
activesupport (= 6.0.3.
|
51
|
-
activerecord (6.0.3.
|
52
|
-
activemodel (= 6.0.3.
|
53
|
-
activesupport (= 6.0.3.
|
54
|
-
activestorage (6.0.3.
|
55
|
-
actionpack (= 6.0.3.
|
56
|
-
activejob (= 6.0.3.
|
57
|
-
activerecord (= 6.0.3.
|
76
|
+
activemodel (6.0.3.4)
|
77
|
+
activesupport (= 6.0.3.4)
|
78
|
+
activerecord (6.0.3.4)
|
79
|
+
activemodel (= 6.0.3.4)
|
80
|
+
activesupport (= 6.0.3.4)
|
81
|
+
activestorage (6.0.3.4)
|
82
|
+
actionpack (= 6.0.3.4)
|
83
|
+
activejob (= 6.0.3.4)
|
84
|
+
activerecord (= 6.0.3.4)
|
58
85
|
marcel (~> 0.3.1)
|
59
|
-
activesupport (6.0.3.
|
86
|
+
activesupport (6.0.3.4)
|
60
87
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
61
88
|
i18n (>= 0.7, < 2)
|
62
89
|
minitest (~> 5.1)
|
@@ -71,7 +98,7 @@ GEM
|
|
71
98
|
cells-erb (0.1.0)
|
72
99
|
cells (~> 4.0)
|
73
100
|
erbse (>= 0.1.1)
|
74
|
-
cells-rails (0.1.
|
101
|
+
cells-rails (0.1.3)
|
75
102
|
actionpack (>= 5.0)
|
76
103
|
cells (>= 4.1.6, < 5.0.0)
|
77
104
|
concurrent-ruby (1.1.7)
|
@@ -82,15 +109,15 @@ GEM
|
|
82
109
|
declarative-option (0.1.0)
|
83
110
|
erbse (0.1.4)
|
84
111
|
temple
|
85
|
-
erubi (1.
|
112
|
+
erubi (1.10.0)
|
86
113
|
globalid (0.4.2)
|
87
114
|
activesupport (>= 4.2.0)
|
88
|
-
hashie (
|
115
|
+
hashie (5.0.0)
|
89
116
|
hirb (0.7.3)
|
90
|
-
i18n (1.8.
|
117
|
+
i18n (1.8.7)
|
91
118
|
concurrent-ruby (~> 1.0)
|
92
119
|
jwt (2.2.2)
|
93
|
-
loofah (2.
|
120
|
+
loofah (2.8.0)
|
94
121
|
crass (~> 1.0.2)
|
95
122
|
nokogiri (>= 1.5.9)
|
96
123
|
mail (2.7.1)
|
@@ -100,52 +127,56 @@ GEM
|
|
100
127
|
method_source (1.0.0)
|
101
128
|
mimemagic (0.3.5)
|
102
129
|
mini_mime (1.0.2)
|
103
|
-
mini_portile2 (2.
|
104
|
-
minitest (5.14.
|
130
|
+
mini_portile2 (2.5.0)
|
131
|
+
minitest (5.14.3)
|
105
132
|
minitest-line (0.6.5)
|
106
133
|
minitest (~> 5.0)
|
107
134
|
multi_json (1.15.0)
|
108
|
-
nio4r (2.5.
|
109
|
-
nokogiri (1.
|
110
|
-
mini_portile2 (~> 2.
|
135
|
+
nio4r (2.5.4)
|
136
|
+
nokogiri (1.11.1)
|
137
|
+
mini_portile2 (~> 2.5.0)
|
138
|
+
racc (~> 1.4)
|
139
|
+
nokogiri (1.11.1-x86_64-linux)
|
140
|
+
racc (~> 1.4)
|
141
|
+
racc (1.5.2)
|
111
142
|
rack (2.2.3)
|
112
143
|
rack-test (1.1.0)
|
113
144
|
rack (>= 1.0, < 3)
|
114
|
-
rails (6.0.3.
|
115
|
-
actioncable (= 6.0.3.
|
116
|
-
actionmailbox (= 6.0.3.
|
117
|
-
actionmailer (= 6.0.3.
|
118
|
-
actionpack (= 6.0.3.
|
119
|
-
actiontext (= 6.0.3.
|
120
|
-
actionview (= 6.0.3.
|
121
|
-
activejob (= 6.0.3.
|
122
|
-
activemodel (= 6.0.3.
|
123
|
-
activerecord (= 6.0.3.
|
124
|
-
activestorage (= 6.0.3.
|
125
|
-
activesupport (= 6.0.3.
|
145
|
+
rails (6.0.3.4)
|
146
|
+
actioncable (= 6.0.3.4)
|
147
|
+
actionmailbox (= 6.0.3.4)
|
148
|
+
actionmailer (= 6.0.3.4)
|
149
|
+
actionpack (= 6.0.3.4)
|
150
|
+
actiontext (= 6.0.3.4)
|
151
|
+
actionview (= 6.0.3.4)
|
152
|
+
activejob (= 6.0.3.4)
|
153
|
+
activemodel (= 6.0.3.4)
|
154
|
+
activerecord (= 6.0.3.4)
|
155
|
+
activestorage (= 6.0.3.4)
|
156
|
+
activesupport (= 6.0.3.4)
|
126
157
|
bundler (>= 1.3.0)
|
127
|
-
railties (= 6.0.3.
|
158
|
+
railties (= 6.0.3.4)
|
128
159
|
sprockets-rails (>= 2.0.0)
|
129
160
|
rails-dom-testing (2.0.3)
|
130
161
|
activesupport (>= 4.2.0)
|
131
162
|
nokogiri (>= 1.6)
|
132
163
|
rails-html-sanitizer (1.3.0)
|
133
164
|
loofah (~> 2.3)
|
134
|
-
railties (6.0.3.
|
135
|
-
actionpack (= 6.0.3.
|
136
|
-
activesupport (= 6.0.3.
|
165
|
+
railties (6.0.3.4)
|
166
|
+
actionpack (= 6.0.3.4)
|
167
|
+
activesupport (= 6.0.3.4)
|
137
168
|
method_source
|
138
169
|
rake (>= 0.8.7)
|
139
170
|
thor (>= 0.20.3, < 2.0)
|
140
|
-
rake (13.0.
|
141
|
-
representable (3.
|
171
|
+
rake (13.0.3)
|
172
|
+
representable (3.1.1)
|
142
173
|
declarative (< 0.1.0)
|
143
|
-
|
174
|
+
trailblazer-option (>= 0.1.1, < 0.2.0)
|
144
175
|
uber (< 0.2.0)
|
145
176
|
sprockets (4.0.2)
|
146
177
|
concurrent-ruby (~> 1.0)
|
147
178
|
rack (> 1, < 3)
|
148
|
-
sprockets-rails (3.2.
|
179
|
+
sprockets-rails (3.2.2)
|
149
180
|
actionpack (>= 4.0)
|
150
181
|
activesupport (>= 4.0)
|
151
182
|
sprockets (>= 3.0.0)
|
@@ -154,33 +185,25 @@ GEM
|
|
154
185
|
thor (1.0.1)
|
155
186
|
thread_safe (0.3.6)
|
156
187
|
tilt (2.0.10)
|
157
|
-
trailblazer-activity (0.11.3)
|
158
|
-
trailblazer-context (>= 0.3.1, < 0.4.0)
|
159
|
-
trailblazer-activity-dsl-linear (0.3.2)
|
160
|
-
trailblazer-activity (>= 0.11.2, < 1.0.0)
|
161
188
|
trailblazer-cells (0.0.3)
|
162
189
|
cells (>= 4.1.0.rc1, < 5.0.0)
|
163
|
-
trailblazer-
|
164
|
-
hashie (~> 4.1)
|
165
|
-
trailblazer-developer (0.0.16)
|
190
|
+
trailblazer-developer (0.0.22)
|
166
191
|
hirb
|
167
|
-
representable
|
168
|
-
trailblazer-activity (>= 0.
|
169
|
-
trailblazer-activity-dsl-linear
|
170
|
-
trailblazer-
|
171
|
-
|
172
|
-
trailblazer-activity-dsl-linear (>= 0.3.2, < 1.0.0)
|
173
|
-
trailblazer-developer (>= 0.0.8)
|
174
|
-
tzinfo (1.2.7)
|
192
|
+
representable (>= 3.1.1, < 4.0.0)
|
193
|
+
trailblazer-activity (>= 0.12.2, < 1.0.0)
|
194
|
+
trailblazer-activity-dsl-linear (>= 0.4.1, < 1.0.0)
|
195
|
+
trailblazer-option (0.1.2)
|
196
|
+
tzinfo (1.2.9)
|
175
197
|
thread_safe (~> 0.1)
|
176
198
|
uber (0.1.0)
|
177
199
|
websocket-driver (0.7.3)
|
178
200
|
websocket-extensions (>= 0.1.0)
|
179
201
|
websocket-extensions (0.1.5)
|
180
|
-
zeitwerk (2.4.
|
202
|
+
zeitwerk (2.4.2)
|
181
203
|
|
182
204
|
PLATFORMS
|
183
205
|
ruby
|
206
|
+
x86_64-linux
|
184
207
|
|
185
208
|
DEPENDENCIES
|
186
209
|
cells-erb
|
@@ -190,9 +213,12 @@ DEPENDENCIES
|
|
190
213
|
multi_json
|
191
214
|
rails (~> 6.0.3, >= 6.0.3.1)
|
192
215
|
sqlite3 (~> 1.4)
|
216
|
+
trailblazer-activity!
|
217
|
+
trailblazer-activity-dsl-linear!
|
193
218
|
trailblazer-cells
|
219
|
+
trailblazer-context!
|
194
220
|
trailblazer-endpoint!
|
195
|
-
trailblazer-operation
|
221
|
+
trailblazer-operation!
|
196
222
|
|
197
223
|
BUNDLED WITH
|
198
|
-
2.
|
224
|
+
2.2.11
|
@@ -30,12 +30,14 @@ class ApplicationController::Web < ApplicationController
|
|
30
30
|
def policy(ctx, domain_ctx:, **)
|
31
31
|
Policy.(domain_ctx)
|
32
32
|
end
|
33
|
+
|
34
|
+
Trailblazer::Endpoint::Protocol::Controller.insert_copy_to_domain_ctx!(self, {:current_user => :current_user})
|
35
|
+
Trailblazer::Endpoint::Protocol::Controller.insert_copy_from_domain_ctx!(self, {:model => :process_model})
|
33
36
|
end
|
34
37
|
#:protocol end
|
35
38
|
Policy = ->(domain_ctx) { domain_ctx[:params][:policy] == "false" ? false : true }
|
36
39
|
#~gskip end
|
37
|
-
endpoint protocol: Protocol, adapter: Trailblazer::Endpoint::Adapter::Web
|
38
|
-
domain_ctx_filter: ApplicationController.current_user_in_domain_ctx
|
40
|
+
endpoint protocol: Protocol, adapter: Trailblazer::Endpoint::Adapter::Web
|
39
41
|
end
|
40
42
|
#:generic end
|
41
43
|
|
@@ -81,4 +81,187 @@ end
|
|
81
81
|
end
|
82
82
|
#:protocol_failure end
|
83
83
|
end
|
84
|
+
|
85
|
+
# {:process_model} is copied from {domain_ctx[:model]} via {#insert_copy_from_domain_ctx!}.
|
86
|
+
class Create1Controller < SongsController
|
87
|
+
def create
|
88
|
+
endpoint Song::Operation::Create do |ctx, endpoint_ctx:, **|
|
89
|
+
render html: endpoint_ctx[:process_model].inspect.html_safe
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
# endpoint_ctx
|
96
|
+
# :resume_data
|
97
|
+
# domain_ctx
|
98
|
+
# :resume_data (copy)
|
99
|
+
|
100
|
+
|
101
|
+
# authenticate
|
102
|
+
|
103
|
+
# deserialize ==> {resume_data: {id: 1}}
|
104
|
+
# deserialize_process_model_id_from_resume_data
|
105
|
+
|
106
|
+
# find_process_model
|
107
|
+
# policy
|
108
|
+
# domain_activity
|
109
|
+
|
110
|
+
# serialize suspend_data and deserialize resume_data
|
111
|
+
class SerializeController < SongsController
|
112
|
+
endpoint Song::Operation::Create,
|
113
|
+
protocol: ApplicationController::Web::Protocol
|
114
|
+
# serialize: true
|
115
|
+
|
116
|
+
def self.options_for_block_options(ctx, **)
|
117
|
+
{
|
118
|
+
invoke: Trailblazer::Developer.method(:wtf?) # FIXME
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
def self.options_for_endpoint(ctx, controller:, **)
|
124
|
+
{
|
125
|
+
cipher_key: Rails.application.config.cipher_key,
|
126
|
+
|
127
|
+
encrypted_resume_data: controller.params[:encrypted_resume_data],
|
128
|
+
}
|
129
|
+
end
|
130
|
+
|
131
|
+
directive :options_for_block_options, method(:options_for_block_options)
|
132
|
+
directive :options_for_endpoint, method(:options_for_endpoint)
|
133
|
+
|
134
|
+
def create
|
135
|
+
encrypted_value = Trailblazer::Workflow::Cipher.encrypt_value({}, cipher_key: cipher_key, value: JSON.dump({id: "findings received", class: Object}))
|
136
|
+
|
137
|
+
endpoint Song::Operation::Create, encrypted_resume_data: encrypted_value, process_model_from_resume_data: false do |ctx, current_user:, endpoint_ctx:, **|
|
138
|
+
render html: cell(Song::Cell::Create, model, current_user: current_user)
|
139
|
+
end.Or do |ctx, contract:, **| # validation failure
|
140
|
+
render html: cell(Song::Cell::New, contract)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# TODO: not really a doc test.
|
146
|
+
# the entire deserialize cycle is skipped since we only use {:serialize}
|
147
|
+
class Serialize1Controller < SerializeController
|
148
|
+
class Create < Trailblazer::Operation
|
149
|
+
pass ->(ctx, **) { ctx[:model] = ctx.key?(:model) ? ctx[:model] : false }
|
150
|
+
end
|
151
|
+
|
152
|
+
endpoint "Create",
|
153
|
+
domain_activity: Create,
|
154
|
+
serialize: true,
|
155
|
+
deserialize: true
|
156
|
+
|
157
|
+
def create
|
158
|
+
# {:model} and {:memory} are from the domain_ctx.
|
159
|
+
# {:encrypted_suspend_data} from endpoint.
|
160
|
+
endpoint "Create" do |ctx, model:, endpoint_ctx:, **|
|
161
|
+
render html: "#{model.inspect}/#{ctx[:memory].inspect}/#{endpoint_ctx[:encrypted_suspend_data]}".html_safe
|
162
|
+
end.Or do |ctx, **| # validation failure
|
163
|
+
render html: "xxx", status: 500
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
# TODO: not really a doc test.
|
169
|
+
# ---------deserialize cycle is skipped.
|
170
|
+
# we serialize {:remember}.
|
171
|
+
class Serialize2Controller < Serialize1Controller # "render confirm page"
|
172
|
+
class Create < Trailblazer::Operation
|
173
|
+
pass ->(ctx, **) { ctx[:model] = ctx.key?(:model) ? ctx[:model] : false }
|
174
|
+
step ->(ctx, **) { ctx[:suspend_data] = {remember: OpenStruct.new(id: 1), id: 9} } # write to domain_ctx[:suspend_data]
|
175
|
+
end
|
176
|
+
|
177
|
+
endpoint "Create",
|
178
|
+
domain_activity: Create,
|
179
|
+
serialize: true
|
180
|
+
end
|
181
|
+
|
182
|
+
# we can read from {:resume_data}
|
183
|
+
class Serialize3Controller < Serialize1Controller # "process submitted confirm page"
|
184
|
+
class Create < Trailblazer::Operation
|
185
|
+
pass ->(ctx, **) { ctx[:model] = ctx.key?(:model) ? ctx[:model] : false }
|
186
|
+
pass ->(ctx, **) { ctx[:memory] = ctx[:resume_data] } # read/process the suspended data
|
187
|
+
end
|
188
|
+
|
189
|
+
endpoint "Create",
|
190
|
+
domain_activity: Create,
|
191
|
+
deserialize: true
|
192
|
+
end
|
193
|
+
|
194
|
+
# find process_model via id in suspend/resume data (used to be called {process_model_from_resume_data})
|
195
|
+
class Serialize4Controller < Serialize1Controller
|
196
|
+
class Create < Trailblazer::Operation
|
197
|
+
pass ->(ctx, **) { ctx[:model] = ctx.key?(:model) ? ctx[:model] : false }
|
198
|
+
pass ->(ctx, **) { ctx[:memory] = ctx[:resume_data] } # read/process the suspended data
|
199
|
+
end
|
200
|
+
|
201
|
+
endpoint "Create",
|
202
|
+
domain_activity: Create,
|
203
|
+
deserialize: true,
|
204
|
+
find_process_model: true,
|
205
|
+
deserialize_process_model_id_from_resume_data: true
|
206
|
+
|
207
|
+
def create
|
208
|
+
endpoint "Create", process_model_class: Song do |ctx, endpoint_ctx:, **|
|
209
|
+
render html: "#{endpoint_ctx[:process_model_id].inspect}/#{ctx[:memory].inspect}/#{endpoint_ctx[:encrypted_suspend_data]}".html_safe
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
# find process_model from resume
|
215
|
+
# FIXME: what is the diff to Controller4?
|
216
|
+
class Serialize5Controller < Serialize1Controller
|
217
|
+
endpoint "Create",
|
218
|
+
domain_activity: Serialize4Controller::Create,
|
219
|
+
deserialize: true,
|
220
|
+
find_process_model: true,
|
221
|
+
deserialize_process_model_id_from_resume_data: true
|
222
|
+
|
223
|
+
def create
|
224
|
+
endpoint "Create", find_process_model: true, process_model_class: Song, process_model_id: params[:id] do |ctx, model:, endpoint_ctx:, **|
|
225
|
+
render html: "#{model.inspect}/#{ctx[:memory].inspect}/#{endpoint_ctx[:encrypted_suspend_data]}".html_safe
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
# find process_model from action_options
|
231
|
+
class Serialize6Controller < Serialize1Controller
|
232
|
+
endpoint "Create",
|
233
|
+
domain_activity: Serialize4Controller::Create,
|
234
|
+
protocol: ApplicationController::Web::Protocol,
|
235
|
+
find_process_model: true
|
236
|
+
|
237
|
+
def create
|
238
|
+
endpoint "Create", find_process_model: true, process_model_class: Song, process_model_id: params[:id] do |ctx, model:, endpoint_ctx:, **|
|
239
|
+
render html: "#{model.inspect}/#{endpoint_ctx[:process_model].inspect}/#{endpoint_ctx[:encrypted_suspend_data]}".html_safe
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
# Configure only {:find_process_model} and {:protocol}.
|
245
|
+
class Serialize7Controller < Serialize1Controller
|
246
|
+
endpoint find_process_model: true # generic setting for all endpoints in this controller.
|
247
|
+
|
248
|
+
endpoint "Create", # no need to specify {:find_process_model}
|
249
|
+
domain_activity: Serialize4Controller::Create
|
250
|
+
|
251
|
+
endpoint "New",
|
252
|
+
find_process_model: false,
|
253
|
+
domain_activity: Serialize4Controller::Create
|
254
|
+
|
255
|
+
def create
|
256
|
+
endpoint "Create", process_model_class: Song, process_model_id: params[:id] do |ctx, model:, endpoint_ctx:, **|
|
257
|
+
render html: "#{model.inspect}/#{endpoint_ctx[:process_model].inspect}/#{endpoint_ctx[:encrypted_suspend_data]}".html_safe
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def new
|
262
|
+
endpoint "New", process_model_class: Song, process_model_id: params[:id] do |ctx, model:, endpoint_ctx:, **|
|
263
|
+
render html: "#{model.inspect}/#{endpoint_ctx[:process_model].inspect}/#{endpoint_ctx[:encrypted_suspend_data]}".html_safe
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
84
267
|
end
|
@@ -35,4 +35,6 @@ Rails.application.configure do
|
|
35
35
|
|
36
36
|
# Raises error for missing translations.
|
37
37
|
# config.action_view.raise_on_missing_translations = true
|
38
|
+
|
39
|
+
config.cipher_key = "e1e1cc87asdfasdfasdfasfdasdfasdfasvhnfvbdb" # FIXME: this usually happens via the new key mechanism in Rails 6
|
38
40
|
end
|
@@ -15,4 +15,15 @@ Rails.application.routes.draw do
|
|
15
15
|
get "/v1/songs_with_options/:id", to: "api/v1/songs_controller/with_options#show"
|
16
16
|
|
17
17
|
get "/", to: "home#dashboard"
|
18
|
+
|
19
|
+
post "/songs/serialize", to: "songs_controller/serialize#create"
|
20
|
+
post "/songs/copy_from_domain_ctx", to: "songs_controller/create1#create"
|
21
|
+
post "/songs/serialize1", to: "songs_controller/serialize1#create"
|
22
|
+
post "/songs/serialize2", to: "songs_controller/serialize2#create"
|
23
|
+
post "/songs/serialize3", to: "songs_controller/serialize3#create"
|
24
|
+
post "/songs/serialize4", to: "songs_controller/serialize4#create"
|
25
|
+
post "/songs/serialize5", to: "songs_controller/serialize5#create"
|
26
|
+
post "/songs/serialize6", to: "songs_controller/serialize6#create"
|
27
|
+
post "/songs/serialize7", to: "songs_controller/serialize7#create"
|
28
|
+
post "/songs/serialize72", to: "songs_controller/serialize7#new"
|
18
29
|
end
|
@@ -70,6 +70,80 @@ class SongsControllerTest < ActionDispatch::IntegrationTest
|
|
70
70
|
assert_equal "wrong login, app crashed", response.body
|
71
71
|
end
|
72
72
|
|
73
|
+
test "serializing/deserializing/find_process_model_from_resume_data" do
|
74
|
+
# # 401
|
75
|
+
# post "/songs/serialize/"
|
76
|
+
# assert_response 401
|
77
|
+
|
78
|
+
# sign in
|
79
|
+
post "/auth/sign_in", params: {username: "yogi@trb.to", password: "secret"}
|
80
|
+
assert_equal 1, session[:user_id]
|
81
|
+
|
82
|
+
|
83
|
+
# When {:encrypted_resume_data} is {nil} the entire deserialize cycle is skipped.
|
84
|
+
# Nothing gets serialized.
|
85
|
+
# This is considered an error since we're expecting resume data.
|
86
|
+
post "/songs/serialize1/", params: {} # encrypted_resume_data: nil
|
87
|
+
assert_response 500
|
88
|
+
assert_equal "xxx", response.body # DISCUSS: is this an application or a protocol error?
|
89
|
+
|
90
|
+
# Nothing deserialized, but {:remember} serialized
|
91
|
+
# "confirm_delete form"
|
92
|
+
post "/songs/serialize2/", params: {} # {:remember} serialized
|
93
|
+
assert_response 200
|
94
|
+
encrypted_string = "0109C4E535EDA2CCE8CD69E50C179F5950CC4A2A898504F951C995B6BCEAFE1DFAB02894854B96B9D11C23E25DB5FB03"
|
95
|
+
assert_equal "false/nil/#{encrypted_string}", response.body
|
96
|
+
|
97
|
+
# {:remember} deserialized
|
98
|
+
# "submit confirm_delete"
|
99
|
+
# We're expecting serialized data and don't serialize anything.
|
100
|
+
post "/songs/serialize3/", params: {encrypted_resume_data: encrypted_string} # {:remember} serialized
|
101
|
+
assert_response 200
|
102
|
+
assert_equal "false/{\"remember\"=>\"#<OpenStruct id=1>\", \"id\"=>9}/", response.body
|
103
|
+
|
104
|
+
# retrieve process_model via id in {:resume_data}
|
105
|
+
# we can see {endpoint_ctx[:process_model_id]}
|
106
|
+
# We're expecting serialized data and don't serialize anything.
|
107
|
+
post "/songs/serialize4/", params: {encrypted_resume_data: encrypted_string}
|
108
|
+
assert_response 200
|
109
|
+
assert_equal "9/{\"remember\"=>\"#<OpenStruct id=1>\", \"id\"=>9}/", response.body
|
110
|
+
|
111
|
+
# retrieve process_model via {:resume_data}'s serialized id.
|
112
|
+
# We're expecting serialized data and don't serialize anything.
|
113
|
+
post "/songs/serialize5/", params: {encrypted_resume_data: encrypted_string}
|
114
|
+
assert_response 200
|
115
|
+
assert_equal "#<struct Song id=9>/{\"remember\"=>\"#<OpenStruct id=1>\", \"id\"=>9}/", response.body
|
116
|
+
# model not found
|
117
|
+
post "/songs/serialize5/", params: {encrypted_resume_data: "36C61CCE30E6CFDE637DF0DA9257CC49"}
|
118
|
+
assert_response 404
|
119
|
+
assert_equal "", response.body
|
120
|
+
|
121
|
+
# find model without serialize from params, no serialized stuff passed
|
122
|
+
# DISCUSS: this could be a different test
|
123
|
+
post "/songs/serialize6/", params: {id: 1}
|
124
|
+
assert_response 200
|
125
|
+
assert_equal "#<struct Song id=\"1\">/#<struct Song id=\"1\">/", response.body
|
126
|
+
# model not found
|
127
|
+
post "/songs/serialize6/", params: {id: nil}
|
128
|
+
assert_response 404
|
129
|
+
assert_equal "", response.body
|
130
|
+
|
131
|
+
# {find_process_model: true} set on controller level, for all endpoints.
|
132
|
+
post "/songs/serialize7/", params: {id: 1}
|
133
|
+
assert_response 200
|
134
|
+
assert_equal "#<struct Song id=\"1\">/#<struct Song id=\"1\">/", response.body
|
135
|
+
# {find_process_model: false} overrides controller setting
|
136
|
+
post "/songs/serialize72/", params: {id: 1}
|
137
|
+
assert_response 200
|
138
|
+
assert_equal "false/false/", response.body
|
139
|
+
|
140
|
+
|
141
|
+
# {#insert_copy_from_domain_ctx!} provides {:process_model}
|
142
|
+
post "/songs/copy_from_domain_ctx", params: {id: 1}
|
143
|
+
assert_response 200
|
144
|
+
assert_equal %{#<struct Song id="1">}, response.body
|
145
|
+
end
|
146
|
+
|
73
147
|
test "sign_in" do
|
74
148
|
# wrong credentials
|
75
149
|
post "/auth/sign_in", params: {}
|
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.email = ["apotonick@gmail.com"]
|
10
10
|
spec.description = %q{Endpoints handle authentication, policies, run your domain operation and set up the rendering.}
|
11
11
|
spec.summary = %q{Endpoints handle authentication, policies, run your domain operation and set up the rendering.}
|
12
|
-
spec.homepage = "http://trailblazer.to/
|
12
|
+
spec.homepage = "http://trailblazer.to/"
|
13
13
|
spec.license = "LGPL-3.0"
|
14
14
|
|
15
15
|
spec.files = `git ls-files`.split($/)
|
@@ -17,7 +17,7 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
|
-
spec.add_dependency "trailblazer-activity-dsl-linear", ">= 0.
|
20
|
+
spec.add_dependency "trailblazer-activity-dsl-linear", ">= 0.5.0", "< 0.6.0"
|
21
21
|
|
22
22
|
spec.add_development_dependency "bundler"
|
23
23
|
spec.add_development_dependency "rake"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trailblazer-endpoint
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Sutterer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-02-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: trailblazer-activity-dsl-linear
|
@@ -16,20 +16,20 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.5.0
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: 0.
|
22
|
+
version: 0.6.0
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 0.
|
29
|
+
version: 0.5.0
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: 0.
|
32
|
+
version: 0.6.0
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: bundler
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -109,6 +109,9 @@ files:
|
|
109
109
|
- lib/trailblazer/endpoint/dsl.rb
|
110
110
|
- lib/trailblazer/endpoint/options.rb
|
111
111
|
- lib/trailblazer/endpoint/protocol.rb
|
112
|
+
- lib/trailblazer/endpoint/protocol/cipher.rb
|
113
|
+
- lib/trailblazer/endpoint/protocol/controller.rb
|
114
|
+
- lib/trailblazer/endpoint/protocol/find_process_model.rb
|
112
115
|
- lib/trailblazer/endpoint/rails.rb
|
113
116
|
- lib/trailblazer/endpoint/version.rb
|
114
117
|
- test/adapter/api_test.rb
|
@@ -184,7 +187,7 @@ files:
|
|
184
187
|
- test/rails-app/tmp/.keep
|
185
188
|
- test/test_helper.rb
|
186
189
|
- trailblazer-endpoint.gemspec
|
187
|
-
homepage: http://trailblazer.to/
|
190
|
+
homepage: http://trailblazer.to/
|
188
191
|
licenses:
|
189
192
|
- LGPL-3.0
|
190
193
|
metadata: {}
|
@@ -203,8 +206,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
203
206
|
- !ruby/object:Gem::Version
|
204
207
|
version: '0'
|
205
208
|
requirements: []
|
206
|
-
|
207
|
-
rubygems_version: 2.7.3
|
209
|
+
rubygems_version: 3.2.3
|
208
210
|
signing_key:
|
209
211
|
specification_version: 4
|
210
212
|
summary: Endpoints handle authentication, policies, run your domain operation and
|