|
17 | 17 | match/2, |
18 | 18 | match_failures/2, |
19 | 19 | has_required_fields/2, |
| 20 | + has_allowed_fields/2, |
20 | 21 | is_constant_field/2, |
21 | 22 | fields/1 |
22 | 23 | ]). |
@@ -883,6 +884,39 @@ has_required_fields_int([{[{Field, Cond}]} | Rest], RequiredFields) -> |
883 | 884 | has_required_fields_int(Rest, lists:delete(Field, RequiredFields)) |
884 | 885 | end. |
885 | 886 |
|
| 887 | +has_allowed_fields(Selector, AllowedFields) -> |
| 888 | + Paths = lists:map( |
| 889 | + fun(Field) -> |
| 890 | + {ok, Path} = mango_util:parse_field(Field), |
| 891 | + Path |
| 892 | + end, |
| 893 | + AllowedFields |
| 894 | + ), |
| 895 | + has_allowed_fields_int(Selector, Paths). |
| 896 | + |
| 897 | +has_allowed_fields_int({[{Field, Cond}]}, Paths) when is_list(Field) -> |
| 898 | + Stemmed = [match_prefix(Field, Path) || Path <- Paths], |
| 899 | + Matched = [Path || Path <- Stemmed, Path /= nil], |
| 900 | + case Matched of |
| 901 | + [] -> false; |
| 902 | + M -> has_allowed_fields_int(Cond, M) |
| 903 | + end; |
| 904 | +has_allowed_fields_int({[{_Op, Conds}]}, Paths) when is_list(Conds) -> |
| 905 | + lists:all(fun(Cond) -> has_allowed_fields_int(Cond, Paths) end, Conds); |
| 906 | +has_allowed_fields_int({[{_Op, Cond}]}, Paths) -> |
| 907 | + has_allowed_fields_int(Cond, Paths); |
| 908 | +has_allowed_fields_int(_, _) -> |
| 909 | + true. |
| 910 | + |
| 911 | +match_prefix([A | Rest1], [A | Rest2]) -> |
| 912 | + match_prefix(Rest1, Rest2); |
| 913 | +match_prefix([], Rest) -> |
| 914 | + Rest; |
| 915 | +match_prefix(_, []) -> |
| 916 | + []; |
| 917 | +match_prefix(_, _) -> |
| 918 | + nil. |
| 919 | + |
886 | 920 | % Returns true if a field in the selector is a constant value e.g. {a: {$eq: 1}} |
887 | 921 | is_constant_field(Selector, Field) when not is_list(Field) -> |
888 | 922 | {ok, Path} = mango_util:parse_field(Field), |
@@ -1262,6 +1296,23 @@ has_required_fields_or_nested_or_false_test() -> |
1262 | 1296 | Normalized = normalize(Selector), |
1263 | 1297 | ?assertEqual(false, has_required_fields(Normalized, RequiredFields)). |
1264 | 1298 |
|
| 1299 | +has_allowed_fields_test() -> |
| 1300 | + Sel1 = normalize({[{<<"a">>, 1}]}), |
| 1301 | + ?assertEqual(has_allowed_fields(Sel1, [<<"a">>]), true), |
| 1302 | + ?assertEqual(has_allowed_fields(Sel1, [<<"a">>, <<"b">>]), true), |
| 1303 | + ?assertEqual(has_allowed_fields(Sel1, [<<"b">>]), false), |
| 1304 | + |
| 1305 | + Sel2 = normalize({[{<<"$or">>, [{[{<<"a.b">>, 1}]}, {[{<<"c.d">>, 2}]}]}]}), |
| 1306 | + ?assertEqual(has_allowed_fields(Sel2, [<<"a">>, <<"c">>]), true), |
| 1307 | + ?assertEqual(has_allowed_fields(Sel2, [<<"a.b">>, <<"c.d">>]), true), |
| 1308 | + ?assertEqual(has_allowed_fields(Sel2, [<<"a">>]), false), |
| 1309 | + |
| 1310 | + Sel3 = normalize({[{<<"a">>, {[{<<"$or">>, [{[{<<"b">>, 1}]}, {[{<<"c">>, 2}]}]}]}}]}), |
| 1311 | + ?assertEqual(has_allowed_fields(Sel3, [<<"a">>]), true), |
| 1312 | + ?assertEqual(has_allowed_fields(Sel3, [<<"a.b">>, <<"a.c">>]), true), |
| 1313 | + ?assertEqual(has_allowed_fields(Sel3, [<<"a.c">>]), false), |
| 1314 | + ?assertEqual(has_allowed_fields(Sel3, [<<"b">>]), false). |
| 1315 | + |
1265 | 1316 | check_match(Selector) -> |
1266 | 1317 | % Call match_int/2 to avoid ERROR for missing metric; this is confusing |
1267 | 1318 | % in the middle of test output. |
|
0 commit comments