trailblazer-endpoint 0.0.5 → 0.0.9
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/CHANGES.md +21 -0
- data/README.md +40 -5
- data/lib/trailblazer/endpoint/controller.rb +55 -22
- data/lib/trailblazer/endpoint/dsl.rb +2 -0
- data/lib/trailblazer/endpoint/options.rb +0 -23
- 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 +45 -25
- data/test/docs/controller_test.rb +61 -1
- data/test/rails-app/Gemfile +17 -1
- data/test/rails-app/Gemfile.lock +134 -83
- data/test/rails-app/app/concepts/song/cell/create.rb +4 -0
- data/test/rails-app/app/concepts/song/cell/new.rb +4 -0
- data/test/rails-app/app/concepts/song/operation/create.rb +5 -1
- data/test/rails-app/app/concepts/song/view/create.erb +1 -0
- data/test/rails-app/app/concepts/song/view/new.erb +1 -0
- data/test/rails-app/app/controllers/api/v1/songs_controller.rb +13 -7
- data/test/rails-app/app/controllers/application_controller/api.rb +3 -1
- data/test/rails-app/app/controllers/application_controller/web.rb +35 -19
- data/test/rails-app/app/controllers/application_controller.rb +3 -1
- data/test/rails-app/app/controllers/auth_controller.rb +44 -0
- data/test/rails-app/app/controllers/home_controller.rb +5 -0
- data/test/rails-app/app/controllers/songs_controller.rb +255 -12
- data/test/rails-app/app/models/song.rb +4 -1
- data/test/rails-app/app/models/user.rb +3 -1
- data/test/rails-app/config/application.rb +1 -1
- data/test/rails-app/config/environments/test.rb +2 -0
- data/test/rails-app/config/routes.rb +21 -3
- data/test/rails-app/test/controllers/api_songs_controller_test.rb +6 -2
- data/test/rails-app/test/controllers/songs_controller_test.rb +125 -10
- data/trailblazer-endpoint.gemspec +2 -2
- metadata +23 -9
@@ -1,24 +1,267 @@
|
|
1
|
+
#:endpoint
|
2
|
+
#:or
|
3
|
+
#:create
|
1
4
|
class SongsController < ApplicationController::Web
|
2
|
-
endpoint
|
5
|
+
endpoint Song::Operation::Create
|
3
6
|
|
4
|
-
|
7
|
+
#:endpoint end
|
8
|
+
def create
|
9
|
+
endpoint Song::Operation::Create do |ctx, current_user:, model:, **|
|
10
|
+
render html: cell(Song::Cell::Create, model, current_user: current_user)
|
11
|
+
end.Or do |ctx, contract:, **| # validation failure
|
12
|
+
render html: cell(Song::Cell::New, contract)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
#:create end
|
16
|
+
|
17
|
+
#~oskip
|
18
|
+
class CreateOrController < SongsController
|
19
|
+
#~oskip end
|
20
|
+
def create
|
21
|
+
endpoint Song::Operation::Create do |ctx, current_user:, model:, **|
|
22
|
+
render html: cell(Song::Cell::Create, model, current_user: current_user)
|
23
|
+
end.Or do |ctx, contract:, **| # validation failure
|
24
|
+
render json: contract.errors, status: 422
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
#:or end
|
29
|
+
|
30
|
+
def create_without_block
|
31
|
+
endpoint Song::Operation::Create
|
32
|
+
end
|
33
|
+
|
34
|
+
class CreateWithOptionsController < SongsController
|
35
|
+
#:create-options
|
36
|
+
def create
|
37
|
+
endpoint Song::Operation::Create, session: {user_id: 2} do |ctx, current_user:, model:, **|
|
38
|
+
render html: cell(Song::Cell::Create, model, current_user: current_user)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
#:create-options end
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
class CreateWithOptionsForDomainCtxController < SongsController
|
46
|
+
#:domain_ctx
|
47
|
+
def create
|
48
|
+
endpoint Song::Operation::Create, options_for_domain_ctx: {params: {id: 999}} do |ctx, model:, **|
|
49
|
+
render html: cell(Song::Cell::Create, model)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
#:domain_ctx end
|
53
|
+
end
|
54
|
+
|
55
|
+
class CreateEndpointCtxController < SongsController
|
56
|
+
#:endpoint_ctx
|
57
|
+
def create
|
58
|
+
endpoint Song::Operation::Create do |ctx, endpoint_ctx:, **|
|
59
|
+
render html: "Created", status: endpoint_ctx[:status]
|
60
|
+
end.Or do |ctx, **| # validation failure
|
61
|
+
#~empty
|
62
|
+
#~empty end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
#:endpoint_ctx end
|
66
|
+
end
|
67
|
+
|
68
|
+
# end.Or do |ctx, endpoint_ctx:, **| # validation failure
|
69
|
+
# render json: endpoint_ctx.keys, status: 422
|
70
|
+
# end
|
71
|
+
|
72
|
+
|
73
|
+
class CreateWithProtocolFailureController < SongsController
|
74
|
+
#:protocol_failure
|
75
|
+
def create_with_protocol_failure
|
76
|
+
endpoint Song::Operation::Create do |ctx, **|
|
77
|
+
redirect_to dashboard_path
|
78
|
+
end.protocol_failure do |ctx, **|
|
79
|
+
render html: "wrong login, app crashed", status: 500
|
80
|
+
end
|
81
|
+
end
|
82
|
+
#:protocol_failure end
|
83
|
+
end
|
5
84
|
|
85
|
+
# {:process_model} is copied from {domain_ctx[:model]} via {#insert_copy_from_domain_ctx!}.
|
86
|
+
class Create1Controller < SongsController
|
6
87
|
def create
|
7
|
-
endpoint
|
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
|
8
212
|
end
|
9
213
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
14
227
|
end
|
15
228
|
end
|
16
229
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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
|
22
265
|
end
|
23
266
|
end
|
24
267
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
class User < Struct.new(:id, :email)
|
2
|
-
def self.find_by(id:)
|
2
|
+
def self.find_by(id: false, email: false)
|
3
|
+
return User.new(1, "yogi@trb.to") if email == "yogi@trb.to"
|
3
4
|
return User.new(id, "yogi@trb.to") if id.to_s == "1"
|
5
|
+
return User.new(id, "seuros@trb.to") if id.to_s == "2"
|
4
6
|
end
|
5
7
|
end
|
@@ -33,6 +33,6 @@ module RailsApp
|
|
33
33
|
# Only loads a smaller set of middleware suitable for API only apps.
|
34
34
|
# Middleware like session, flash, cookies can be added back manually.
|
35
35
|
# Skip views, helpers and assets when generating a new resource.
|
36
|
-
config.api_only =
|
36
|
+
config.api_only = false
|
37
37
|
end
|
38
38
|
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
|
@@ -1,11 +1,29 @@
|
|
1
1
|
Rails.application.routes.draw do
|
2
2
|
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
|
3
|
-
|
4
|
-
post "/songs/
|
5
|
-
post "/songs/
|
3
|
+
post "/songs/create_with_options", to: "songs_controller/create_with_options#create"
|
4
|
+
post "/songs/create_or", to: "songs_controller/create_or#create"
|
5
|
+
post "/songs/endpoint_ctx", to: "songs_controller/create_endpoint_ctx#create"
|
6
|
+
post "/songs/create_with_or", to: "songs#create"
|
7
|
+
post "/songs", to: "songs#create_without_block"
|
8
|
+
post "/songs/create_with_protocol_failure", to: "songs_controller/create_with_protocol_failure#create_with_protocol_failure"
|
9
|
+
post "/songs/create_with_options_for_domain_ctx", to: "songs_controller/create_with_options_for_domain_ctx#create"
|
10
|
+
post "/auth/sign_in", to: "auth#sign_in"
|
6
11
|
|
7
12
|
post "/v1/songs", to: "api/v1/songs#create"
|
8
13
|
get "/v1/songs/:id", to: "api/v1/songs#show"
|
9
14
|
|
10
15
|
get "/v1/songs_with_options/:id", to: "api/v1/songs_controller/with_options#show"
|
16
|
+
|
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"
|
11
29
|
end
|
@@ -32,11 +32,13 @@ class ApiSongsControllerTest < ActionDispatch::IntegrationTest
|
|
32
32
|
test "API interface" do
|
33
33
|
yogi_jwt = jwt(1)
|
34
34
|
|
35
|
+
# default {success}
|
36
|
+
#:success
|
35
37
|
post_json "/v1/songs", {id: 1}, yogi_jwt
|
36
38
|
|
37
|
-
# default {success}
|
38
39
|
assert_response 200
|
39
40
|
assert_equal "{\"id\":1}", response.body
|
41
|
+
#:success end
|
40
42
|
|
41
43
|
# no proper input/params
|
42
44
|
post_json "/v1/songs", {}, yogi_jwt
|
@@ -45,9 +47,11 @@ class ApiSongsControllerTest < ActionDispatch::IntegrationTest
|
|
45
47
|
assert_equal "{\"errors\":{\"message\":\"The submitted data is invalid.\"}}", response.body
|
46
48
|
|
47
49
|
# 401
|
48
|
-
|
50
|
+
#:not_authenticated
|
51
|
+
post_json "/v1/songs", {} # no token
|
49
52
|
assert_response 401
|
50
53
|
assert_equal "{\"errors\":{\"message\":\"Authentication credentials were not provided or are invalid.\"}}", response.body
|
54
|
+
#:not_authenticated end
|
51
55
|
|
52
56
|
# 403
|
53
57
|
post_json "/v1/songs", {id: 1, policy: false}, yogi_jwt
|
@@ -1,7 +1,18 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
3
|
class SongsControllerTest < ActionDispatch::IntegrationTest
|
4
|
-
test "
|
4
|
+
test "all possible outcomes with {Create}" do
|
5
|
+
# 401
|
6
|
+
post "/songs", params: {}
|
7
|
+
assert_response 401
|
8
|
+
assert_equal "", response.body
|
9
|
+
|
10
|
+
# sign in
|
11
|
+
post "/auth/sign_in", params: {username: "yogi@trb.to", password: "secret"}
|
12
|
+
assert_equal 1, session[:user_id]
|
13
|
+
# follow_redirect!
|
14
|
+
assert_equal 1, session[:user_id]
|
15
|
+
|
5
16
|
post "/songs", params: {id: 1}
|
6
17
|
# default {success} block doesn't do anything
|
7
18
|
assert_response 200
|
@@ -12,11 +23,6 @@ class SongsControllerTest < ActionDispatch::IntegrationTest
|
|
12
23
|
assert_response 422
|
13
24
|
assert_equal "", response.body
|
14
25
|
|
15
|
-
# 401
|
16
|
-
post "/songs", params: {authenticate: false}
|
17
|
-
assert_response 401
|
18
|
-
assert_equal "", response.body
|
19
|
-
|
20
26
|
# 403
|
21
27
|
post "/songs", params: {policy: false}
|
22
28
|
assert_response 403
|
@@ -25,7 +31,7 @@ class SongsControllerTest < ActionDispatch::IntegrationTest
|
|
25
31
|
post "/songs/create_with_options", params: {id: 1}
|
26
32
|
# {success} block renders model
|
27
33
|
assert_response 200
|
28
|
-
assert_equal "
|
34
|
+
assert_equal "<div>#<struct Song id=\"1\">#<struct User id=2, email=\"seuros@trb.to\"></div>\n", response.body
|
29
35
|
|
30
36
|
post "/songs/create_with_options", params: {}
|
31
37
|
# default {failure} block doesn't do anything
|
@@ -35,13 +41,122 @@ class SongsControllerTest < ActionDispatch::IntegrationTest
|
|
35
41
|
post "/songs/create_with_or", params: {id: 1}
|
36
42
|
# {success} block renders model
|
37
43
|
assert_response 200
|
38
|
-
assert_equal "
|
44
|
+
assert_equal "<div>#<struct Song id=\"1\">#<struct User id=1, email=\"yogi@trb.to\"></div>\n", response.body
|
39
45
|
|
40
46
|
post "/songs/create_with_or", params: {}
|
41
|
-
|
47
|
+
assert_response 200
|
48
|
+
assert_equal %{<div>#<struct errors=nil></div>\n}, response.body
|
49
|
+
|
50
|
+
# Or { render status: 422 }
|
51
|
+
post "/songs/create_or", params: {}
|
42
52
|
assert_response 422
|
43
|
-
assert_equal
|
53
|
+
assert_equal %{null}, response.body
|
54
|
+
|
55
|
+
# {:endpoint_ctx} is available in blocks
|
56
|
+
post "/songs/endpoint_ctx", params: {id: 1}
|
57
|
+
assert_response 200
|
58
|
+
assert_equal "Created", response.body
|
59
|
+
# assert_equal "[\"domain_ctx\",\"session\",\"controller\",\"config_source\",\"current_user\",\"domain_activity_return_signal\"]", response.body
|
60
|
+
|
61
|
+
# {:options_for_domain_ctx} overrides domain_ctx
|
62
|
+
post "/songs/create_with_options_for_domain_ctx", params: {id: 1} # params get overridden
|
63
|
+
assert_response 200
|
64
|
+
assert_equal "<div>#<struct Song id=999></div>\n", response.body
|
65
|
+
end
|
66
|
+
|
67
|
+
test "override protocol_failure" do
|
68
|
+
post "/songs/create_with_protocol_failure", params: {}
|
69
|
+
assert_response 500
|
70
|
+
assert_equal "wrong login, app crashed", response.body
|
71
|
+
end
|
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
|
+
|
147
|
+
test "sign_in" do
|
148
|
+
# wrong credentials
|
149
|
+
post "/auth/sign_in", params: {}
|
150
|
+
assert_response 401
|
151
|
+
assert_equal "", response.body
|
152
|
+
assert_nil session[:user_id]
|
44
153
|
|
154
|
+
# valid signin
|
155
|
+
post "/auth/sign_in", params: {username: "yogi@trb.to", password: "secret"}
|
156
|
+
assert_response 302
|
157
|
+
# assert_equal "", response.body
|
158
|
+
assert_equal 1, session[:user_id]
|
159
|
+
assert_redirected_to "/"
|
45
160
|
end
|
46
161
|
end
|
47
162
|
|
@@ -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.4.0", "< 0.5.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.9
|
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: 2021-11-10 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.4.0
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: 0.
|
22
|
+
version: 0.5.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.4.0
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: 0.
|
32
|
+
version: 0.5.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
|
@@ -129,13 +132,19 @@ files:
|
|
129
132
|
- test/rails-app/app/concepts/auth/jwt.rb
|
130
133
|
- test/rails-app/app/concepts/auth/operation/authenticate.rb
|
131
134
|
- test/rails-app/app/concepts/auth/operation/policy.rb
|
135
|
+
- test/rails-app/app/concepts/song/cell/create.rb
|
136
|
+
- test/rails-app/app/concepts/song/cell/new.rb
|
132
137
|
- test/rails-app/app/concepts/song/operation/create.rb
|
133
138
|
- test/rails-app/app/concepts/song/operation/show.rb
|
134
139
|
- test/rails-app/app/concepts/song/representer.rb
|
140
|
+
- test/rails-app/app/concepts/song/view/create.erb
|
141
|
+
- test/rails-app/app/concepts/song/view/new.erb
|
135
142
|
- test/rails-app/app/controllers/api/v1/songs_controller.rb
|
136
143
|
- test/rails-app/app/controllers/application_controller.rb
|
137
144
|
- test/rails-app/app/controllers/application_controller/api.rb
|
138
145
|
- test/rails-app/app/controllers/application_controller/web.rb
|
146
|
+
- test/rails-app/app/controllers/auth_controller.rb
|
147
|
+
- test/rails-app/app/controllers/home_controller.rb
|
139
148
|
- test/rails-app/app/controllers/songs_controller.rb
|
140
149
|
- test/rails-app/app/models/application_record.rb
|
141
150
|
- test/rails-app/app/models/concerns/.keep
|
@@ -178,7 +187,7 @@ files:
|
|
178
187
|
- test/rails-app/tmp/.keep
|
179
188
|
- test/test_helper.rb
|
180
189
|
- trailblazer-endpoint.gemspec
|
181
|
-
homepage: http://trailblazer.to/
|
190
|
+
homepage: http://trailblazer.to/
|
182
191
|
licenses:
|
183
192
|
- LGPL-3.0
|
184
193
|
metadata: {}
|
@@ -197,8 +206,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
197
206
|
- !ruby/object:Gem::Version
|
198
207
|
version: '0'
|
199
208
|
requirements: []
|
200
|
-
|
201
|
-
rubygems_version: 2.7.3
|
209
|
+
rubygems_version: 3.2.3
|
202
210
|
signing_key:
|
203
211
|
specification_version: 4
|
204
212
|
summary: Endpoints handle authentication, policies, run your domain operation and
|
@@ -222,13 +230,19 @@ test_files:
|
|
222
230
|
- test/rails-app/app/concepts/auth/jwt.rb
|
223
231
|
- test/rails-app/app/concepts/auth/operation/authenticate.rb
|
224
232
|
- test/rails-app/app/concepts/auth/operation/policy.rb
|
233
|
+
- test/rails-app/app/concepts/song/cell/create.rb
|
234
|
+
- test/rails-app/app/concepts/song/cell/new.rb
|
225
235
|
- test/rails-app/app/concepts/song/operation/create.rb
|
226
236
|
- test/rails-app/app/concepts/song/operation/show.rb
|
227
237
|
- test/rails-app/app/concepts/song/representer.rb
|
238
|
+
- test/rails-app/app/concepts/song/view/create.erb
|
239
|
+
- test/rails-app/app/concepts/song/view/new.erb
|
228
240
|
- test/rails-app/app/controllers/api/v1/songs_controller.rb
|
229
241
|
- test/rails-app/app/controllers/application_controller.rb
|
230
242
|
- test/rails-app/app/controllers/application_controller/api.rb
|
231
243
|
- test/rails-app/app/controllers/application_controller/web.rb
|
244
|
+
- test/rails-app/app/controllers/auth_controller.rb
|
245
|
+
- test/rails-app/app/controllers/home_controller.rb
|
232
246
|
- test/rails-app/app/controllers/songs_controller.rb
|
233
247
|
- test/rails-app/app/models/application_record.rb
|
234
248
|
- test/rails-app/app/models/concerns/.keep
|