marty 1.0.42 → 1.0.43
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/Gemfile.lock +2 -2
- data/app/controllers/marty/rpc_controller.rb +20 -1
- data/lib/marty/migrations.rb +3 -1
- data/lib/marty/schema_helper.rb +42 -0
- data/lib/marty/version.rb +1 -1
- data/spec/controllers/rpc_controller_spec.rb +139 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b66276891458efd498648be59d402697d007be05
|
4
|
+
data.tar.gz: 6fd5ee9414488b17042c87bb1439ca1021d371b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: acff2e6a1842b34ed8ec5c17e8d15bd314723eae74cc11e043ca8f4f23bee95da6c0a46a56dca72bec7e248878f2849b517fb8f8397f3f1873ffd3658bd6c0d5
|
7
|
+
data.tar.gz: b596a59fd785a72531318a652dc9f20c71944df9a433e5b8db183316d4434015c974cc0276940ca7c3d418f94e49fbd07d6fbc228447c2fd63172f03bab0ff4c
|
data/Gemfile.lock
CHANGED
@@ -34,6 +34,24 @@ class Marty::RpcController < ActionController::Base
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
+
def _get_errors(errs)
|
38
|
+
if errs.is_a?(Array)
|
39
|
+
errs.map { |err| _get_errors(err) }
|
40
|
+
elsif errs.is_a?(Hash)
|
41
|
+
if !errs.include?(:failed_attribute)
|
42
|
+
errs.map { |k, v| _get_errors(v) }
|
43
|
+
else
|
44
|
+
fa, message, errors = errs.values_at(:failed_attribute,
|
45
|
+
:message, :errors)
|
46
|
+
(['AllOf','AnyOf','Not'].include?(fa) ? [] : [message]) +
|
47
|
+
_get_errors(errors || {})
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
def get_errors(errs)
|
52
|
+
_get_errors(errs).flatten
|
53
|
+
end
|
54
|
+
|
37
55
|
def do_eval(sname, tag, node, attrs, params, api_key, background)
|
38
56
|
return {error: "Malformed attrs"} unless attrs.is_a?(String)
|
39
57
|
|
@@ -95,7 +113,8 @@ class Marty::RpcController < ActionController::Base
|
|
95
113
|
rescue => ex
|
96
114
|
return {error: "#{attr}: #{ex.message}"}
|
97
115
|
end
|
98
|
-
|
116
|
+
|
117
|
+
validation_error[attr] = get_errors(er) if er.size > 0
|
99
118
|
err_count += er.size
|
100
119
|
end
|
101
120
|
end
|
data/lib/marty/migrations.rb
CHANGED
@@ -187,6 +187,7 @@ EOSQL
|
|
187
187
|
encode(line.encoding, :crlf_newline => true)
|
188
188
|
end
|
189
189
|
end
|
190
|
+
|
190
191
|
def self.generate_sql_migrations(migrations_dir, sql_files_dir)
|
191
192
|
sd = Rails.root.join(sql_files_dir)
|
192
193
|
md = Rails.root.join(migrations_dir)
|
@@ -218,7 +219,8 @@ EOSQL
|
|
218
219
|
newbase = "#{timestamp}_#{klass}"
|
219
220
|
mig_name = File.join(md, "#{newbase}.rb")
|
220
221
|
sql_snap_literal = Rails.root.join(md, 'sql', "#{newbase}.sql")
|
221
|
-
sql_snap_call =
|
222
|
+
sql_snap_call =
|
223
|
+
"Rails.root.join('#{migrations_dir}', 'sql', '#{newbase}.sql')"
|
222
224
|
|
223
225
|
File.open(sql_snap_literal, "w") do |f|
|
224
226
|
f.print sql_lines.join
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class Marty::SchemaHelper
|
2
|
+
include Delorean::Model
|
3
|
+
delorean_fn :enum_is, sig: 2 do
|
4
|
+
|var, value|
|
5
|
+
{"properties"=> {var => { "enum"=> value}}}
|
6
|
+
end
|
7
|
+
delorean_fn :bool_is, sig: 2 do
|
8
|
+
|var, value|
|
9
|
+
{"properties"=> {var => { "type"=> "boolean", "enum"=> [value]}}}
|
10
|
+
end
|
11
|
+
|
12
|
+
delorean_fn :or, sig: [1, 20] do
|
13
|
+
|*args|
|
14
|
+
{"anyOf"=>args}
|
15
|
+
end
|
16
|
+
|
17
|
+
delorean_fn :and, sig: [1, 20] do
|
18
|
+
|*args|
|
19
|
+
{"allOf"=>args}
|
20
|
+
end
|
21
|
+
|
22
|
+
delorean_fn :not, sig: 1 do
|
23
|
+
|arg|
|
24
|
+
{"not"=>{"allOf"=>[arg]}}
|
25
|
+
end
|
26
|
+
|
27
|
+
# if conds is true, var_array columns we be required
|
28
|
+
delorean_fn :required_if, sig: [2, 20] do
|
29
|
+
|var_array, *conds_array|
|
30
|
+
{"anyOf"=>[{"not"=>{"allOf"=> conds_array}},
|
31
|
+
{"required"=>var_array}]}
|
32
|
+
end
|
33
|
+
|
34
|
+
# if dep_column is present, checks must pass
|
35
|
+
delorean_fn :dep_check, sig: [2, 20] do
|
36
|
+
|dep_column, *checks|
|
37
|
+
{"dependencies"=> {dep_column =>
|
38
|
+
{"type"=>"object",
|
39
|
+
"allOf"=> checks}}}
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
data/lib/marty/version.rb
CHANGED
@@ -89,6 +89,35 @@ A:
|
|
89
89
|
result = [{"a": 1, "b": res}, {"a": 789, "b": res}]
|
90
90
|
eof
|
91
91
|
|
92
|
+
sample_script10 = <<eof
|
93
|
+
A:
|
94
|
+
opt1 =?
|
95
|
+
optn =?
|
96
|
+
opttf =?
|
97
|
+
opttrue =?
|
98
|
+
optfalse =?
|
99
|
+
req1 =?
|
100
|
+
req2 =?
|
101
|
+
req3 =?
|
102
|
+
|
103
|
+
optif = if opttf == true
|
104
|
+
then opttrue
|
105
|
+
else if opttf == false
|
106
|
+
then optfalse
|
107
|
+
else nil
|
108
|
+
|
109
|
+
v1 = if req1 == 'no opts'
|
110
|
+
then req2
|
111
|
+
else if req1 == "opt1"
|
112
|
+
then opt1
|
113
|
+
else if req2 != 'no opts'
|
114
|
+
then optn
|
115
|
+
else if req3 == "opttf"
|
116
|
+
then optif
|
117
|
+
else 'req3'
|
118
|
+
|
119
|
+
eof
|
120
|
+
|
92
121
|
script3_schema = <<eof
|
93
122
|
A:
|
94
123
|
pc = { "properties : {
|
@@ -227,6 +256,56 @@ A:
|
|
227
256
|
}
|
228
257
|
eof
|
229
258
|
|
259
|
+
script10_schema = <<eof
|
260
|
+
A:
|
261
|
+
properties = {
|
262
|
+
"opt1" : { "type" : "string" },
|
263
|
+
"opttf" : { "type" : "boolean" },
|
264
|
+
"opttrue" : { "type" : "string" },
|
265
|
+
"optfalse" : { "type" : "string" },
|
266
|
+
"req1" : { "pg_enum" : "CondEnum" },
|
267
|
+
"req2" : { "pg_enum" : "CondEnum" }
|
268
|
+
}
|
269
|
+
|
270
|
+
req1_is_opt1 = Marty::SchemaHelper.enum_is('req1', ['opt1'])
|
271
|
+
req2_is_not_no_opts = Marty::SchemaHelper.not(
|
272
|
+
Marty::SchemaHelper.enum_is('req2', ['no opts']))
|
273
|
+
req3_is_opttf = Marty::SchemaHelper.enum_is('req3', ['opttf'])
|
274
|
+
opttf_is_true = Marty::SchemaHelper.bool_is('opttf', true)
|
275
|
+
opttf_is_false = Marty::SchemaHelper.bool_is('opttf', false)
|
276
|
+
|
277
|
+
# opt1 is required if req1 == 'opt1'
|
278
|
+
opt1_check = Marty::SchemaHelper.required_if(['opt1'], req1_is_opt1)
|
279
|
+
|
280
|
+
# optn is required if req2 != 'no opts'
|
281
|
+
optn_check = Marty::SchemaHelper.required_if(['optn'], req2_is_not_no_opts)
|
282
|
+
|
283
|
+
# opttf is required if req3 == 'opttf'
|
284
|
+
opttf_check = Marty::SchemaHelper.required_if(['opttf'], req3_is_opttf)
|
285
|
+
|
286
|
+
# opttrue is required if opttf is true
|
287
|
+
opttrue_check = Marty::SchemaHelper.required_if(['opttrue'], opttf_is_true)
|
288
|
+
|
289
|
+
# optfalse is required if opttf is false
|
290
|
+
optfalse_check = Marty::SchemaHelper.required_if(['optfalse'],
|
291
|
+
opttf_is_false)
|
292
|
+
|
293
|
+
# opttf is optional (contingent on req3) so eval of opttrue_check
|
294
|
+
# and optfalse_check is dependent upon opttf existing
|
295
|
+
opttruefalse_check = Marty::SchemaHelper.dep_check('opttf',
|
296
|
+
opttrue_check,
|
297
|
+
optfalse_check)
|
298
|
+
|
299
|
+
v1 = { "properties": properties,
|
300
|
+
"required": ["req1", "req2", "req3"],
|
301
|
+
"allOf": [
|
302
|
+
opt1_check,
|
303
|
+
optn_check,
|
304
|
+
opttf_check,
|
305
|
+
opttruefalse_check
|
306
|
+
] }
|
307
|
+
eof
|
308
|
+
|
230
309
|
describe Marty::RpcController do
|
231
310
|
before(:each) {
|
232
311
|
@routes = Marty::Engine.routes
|
@@ -250,6 +329,7 @@ describe Marty::RpcController do
|
|
250
329
|
"M7" => sample_script7,
|
251
330
|
"M8" => sample_script8,
|
252
331
|
"M9" => sample_script9,
|
332
|
+
"M10" => sample_script10,
|
253
333
|
"M3Schemas" => script3_schema,
|
254
334
|
"M4Schemas" => script4_schema,
|
255
335
|
"M5Schemas" => script5_schema,
|
@@ -257,6 +337,7 @@ describe Marty::RpcController do
|
|
257
337
|
"M7Schemas" => script7_schema,
|
258
338
|
"M8Schemas" => script8_schema,
|
259
339
|
"M9Schemas" => script9_schema,
|
340
|
+
"M10Schemas" => script10_schema,
|
260
341
|
}, Date.today + 1.minute)
|
261
342
|
|
262
343
|
@p1 = Marty::Posting.do_create("BASE", Date.today + 2.minute, 'a comment')
|
@@ -792,6 +873,9 @@ describe Marty::RpcController do
|
|
792
873
|
class FruitsEnum
|
793
874
|
VALUES=Set['Apple', 'Banana', 'Orange']
|
794
875
|
end
|
876
|
+
class CondEnum
|
877
|
+
VALUES=Set['no opts','opt1','opt2','opttf']
|
878
|
+
end
|
795
879
|
|
796
880
|
it "validates schema with a pg_enum (Positive)" do
|
797
881
|
Marty::ApiConfig.create!(script: "M5",
|
@@ -1033,6 +1117,61 @@ describe Marty::RpcController do
|
|
1033
1117
|
expect(response.body).to match(/"error":"Permission denied"/)
|
1034
1118
|
end
|
1035
1119
|
|
1120
|
+
context "conditional validation" do
|
1121
|
+
before(:all) do
|
1122
|
+
Marty::ApiConfig.create!(script: "M10",
|
1123
|
+
node: "A",
|
1124
|
+
attr: nil,
|
1125
|
+
logged: false,
|
1126
|
+
input_validated: true,
|
1127
|
+
output_validated: false,
|
1128
|
+
strict_validate: false)
|
1129
|
+
end
|
1130
|
+
def do_call(req1, req2, req3, optionals={})
|
1131
|
+
attrs = ["v1"].to_json
|
1132
|
+
params = optionals.merge({"req1" => req1,
|
1133
|
+
"req2"=> req2,
|
1134
|
+
"req3"=> req3}).to_json
|
1135
|
+
get 'evaluate', {
|
1136
|
+
format: :json,
|
1137
|
+
script: "M10",
|
1138
|
+
node: "A",
|
1139
|
+
attrs: attrs,
|
1140
|
+
params: params
|
1141
|
+
}
|
1142
|
+
end
|
1143
|
+
|
1144
|
+
it "does conditional" do
|
1145
|
+
aggregate_failures "conditionals" do
|
1146
|
+
[# first group has all required fields
|
1147
|
+
[['opt1', 'no opts', 'no opts', opt1: 'hi mom'], "hi mom"],
|
1148
|
+
[['no opts', 'no opts', 'no opts', opt1: 'hi mom'], "no opts"],
|
1149
|
+
[['opt2', 'opt2', 'no opts', optn: 'foo'], 'foo'],
|
1150
|
+
[['opt2', 'no opts', 'opt2'], 'req3'],
|
1151
|
+
[['opt2', 'no opts', 'opttf', opttf: true, opttrue: 'bar'], 'bar'],
|
1152
|
+
[['opt2', 'no opts', 'opttf', opttf: false, optfalse: 'baz'], 'baz'],
|
1153
|
+
# second group is missing fields
|
1154
|
+
[['opt1', 'no opts', 'no opts'],
|
1155
|
+
"did not contain a required property of 'opt1'"],
|
1156
|
+
[['opt2', 'opt2', 'no opts',],
|
1157
|
+
"did not contain a required property of 'optn'"],
|
1158
|
+
[['opt2', 'no opts', 'opttf'],
|
1159
|
+
"did not contain a required property of 'opttf'"],
|
1160
|
+
[['opt2', 'no opts', 'opttf', opttf: true],
|
1161
|
+
"did not contain a required property of 'opttrue'"],
|
1162
|
+
[['opt2', 'no opts', 'opttf', opttf: false],
|
1163
|
+
"did not contain a required property of 'optfalse'"],
|
1164
|
+
].each do
|
1165
|
+
|a, exp|
|
1166
|
+
do_call(*a)
|
1167
|
+
res_hash = JSON.parse(response.body)
|
1168
|
+
got = res_hash.is_a?(Array) ? res_hash[0] : res_hash["error"]
|
1169
|
+
expect(got).to include(exp)
|
1170
|
+
end
|
1171
|
+
end
|
1172
|
+
end
|
1173
|
+
end
|
1174
|
+
|
1036
1175
|
context "error handling" do
|
1037
1176
|
it 'returns bad attrs if attrs is not a string' do
|
1038
1177
|
get :evaluate, format: :json, attrs: 0
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: marty
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.43
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arman Bostani
|
@@ -14,7 +14,7 @@ authors:
|
|
14
14
|
autorequire:
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
|
-
date: 2017-10-
|
17
|
+
date: 2017-10-09 00:00:00.000000000 Z
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
20
20
|
name: pg
|
@@ -499,6 +499,7 @@ files:
|
|
499
499
|
- lib/marty/railtie.rb
|
500
500
|
- lib/marty/relation.rb
|
501
501
|
- lib/marty/rpc_call.rb
|
502
|
+
- lib/marty/schema_helper.rb
|
502
503
|
- lib/marty/util.rb
|
503
504
|
- lib/marty/version.rb
|
504
505
|
- lib/marty/xl.rb
|