diff --git a/pom.xml b/pom.xml index 848a990..97ac52f 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ fraudo - 0.0.19 + 0.0.20 Fraudo Language for describing antifraud patterns diff --git a/src/main/antlr4/com.rbkmoney.fraudo/FraudoPayment.g4 b/src/main/antlr4/com.rbkmoney.fraudo/FraudoPayment.g4 index 4095a8c..26fc5a5 100644 --- a/src/main/antlr4/com.rbkmoney.fraudo/FraudoPayment.g4 +++ b/src/main/antlr4/com.rbkmoney.fraudo/FraudoPayment.g4 @@ -36,6 +36,8 @@ relationalExpression | in_grey_list | in_list | like + | is_mobile + | is_recurrent ; unaryExpression @@ -97,4 +99,12 @@ sum_refund in : 'in' LPAREN (stringExpression) DELIMETER string_list RPAREN + ; + +is_mobile + : 'isMobile' LPAREN RPAREN + ; + +is_recurrent + : 'isRecurrent' LPAREN RPAREN ; \ No newline at end of file diff --git a/src/main/antlr4/imports/Fraudo.g4 b/src/main/antlr4/imports/Fraudo.g4 index c9fedd0..df91aee 100644 --- a/src/main/antlr4/imports/Fraudo.g4 +++ b/src/main/antlr4/imports/Fraudo.g4 @@ -32,6 +32,14 @@ currency : 'currency' LPAREN RPAREN ; +payer_type + : 'payerType' LPAREN RPAREN + ; + +token_provider + : 'tokenProvider' LPAREN RPAREN + ; + count : 'count' LPAREN STRING time_window (group_by)? RPAREN ; diff --git a/src/main/java/com/rbkmoney/fraudo/payment/factory/FraudVisitorFactory.java b/src/main/java/com/rbkmoney/fraudo/payment/factory/FraudVisitorFactory.java index 5ec4a85..04daa09 100644 --- a/src/main/java/com/rbkmoney/fraudo/payment/factory/FraudVisitorFactory.java +++ b/src/main/java/com/rbkmoney/fraudo/payment/factory/FraudVisitorFactory.java @@ -7,6 +7,7 @@ import com.rbkmoney.fraudo.payment.aggregator.CountPaymentAggregator; import com.rbkmoney.fraudo.payment.aggregator.SumPaymentAggregator; import com.rbkmoney.fraudo.payment.resolver.PaymentGroupResolver; import com.rbkmoney.fraudo.payment.resolver.PaymentTimeWindowResolver; +import com.rbkmoney.fraudo.payment.resolver.PaymentTypeResolver; import com.rbkmoney.fraudo.payment.visitor.impl.FirstFindVisitorImpl; import com.rbkmoney.fraudo.resolver.CountryResolver; import com.rbkmoney.fraudo.resolver.FieldResolver; @@ -20,6 +21,7 @@ public interface FraudVisitorFactory { InListFinder listFinder, FieldResolver fieldPairResolver, PaymentGroupResolver paymentGroupResolver, - PaymentTimeWindowResolver timeWindowResolver); + PaymentTimeWindowResolver timeWindowResolver, + PaymentTypeResolver paymentTypeResolver); } diff --git a/src/main/java/com/rbkmoney/fraudo/payment/factory/FraudVisitorFactoryImpl.java b/src/main/java/com/rbkmoney/fraudo/payment/factory/FraudVisitorFactoryImpl.java index d7ce304..46e613d 100644 --- a/src/main/java/com/rbkmoney/fraudo/payment/factory/FraudVisitorFactoryImpl.java +++ b/src/main/java/com/rbkmoney/fraudo/payment/factory/FraudVisitorFactoryImpl.java @@ -7,6 +7,7 @@ import com.rbkmoney.fraudo.payment.aggregator.CountPaymentAggregator; import com.rbkmoney.fraudo.payment.aggregator.SumPaymentAggregator; import com.rbkmoney.fraudo.payment.resolver.PaymentGroupResolver; import com.rbkmoney.fraudo.payment.resolver.PaymentTimeWindowResolver; +import com.rbkmoney.fraudo.payment.resolver.PaymentTypeResolver; import com.rbkmoney.fraudo.payment.visitor.CountVisitor; import com.rbkmoney.fraudo.payment.visitor.CustomFuncVisitor; import com.rbkmoney.fraudo.payment.visitor.ListVisitor; @@ -26,12 +27,18 @@ public class FraudVisitorFactoryImpl implements FraudVisitorFactory { InListFinder listFinder, FieldResolver fieldResolver, PaymentGroupResolver paymentGroupResolver, - PaymentTimeWindowResolver timeWindowResolver) { + PaymentTimeWindowResolver timeWindowResolver, + PaymentTypeResolver paymentTypeResolver) { CountVisitor countVisitor = new CountVisitorImpl<>(countPaymentAggregator, fieldResolver, paymentGroupResolver, timeWindowResolver); SumVisitor sumVisitor = new SumVisitorImpl<>(sumPaymentAggregator, fieldResolver, paymentGroupResolver, timeWindowResolver); ListVisitor listVisitor = new ListVisitorImpl<>(listFinder, fieldResolver); CustomFuncVisitor customFuncVisitor = new CustomFuncVisitorImpl<>( - uniqueValueAggregator, countryResolver, fieldResolver, paymentGroupResolver, timeWindowResolver); + uniqueValueAggregator, + countryResolver, + fieldResolver, + paymentGroupResolver, + timeWindowResolver, + paymentTypeResolver); return new FirstFindVisitorImpl<>(countVisitor, sumVisitor, listVisitor, customFuncVisitor, fieldResolver); } diff --git a/src/main/java/com/rbkmoney/fraudo/payment/factory/FullVisitorFactoryImpl.java b/src/main/java/com/rbkmoney/fraudo/payment/factory/FullVisitorFactoryImpl.java index 0531610..bcaa0ec 100644 --- a/src/main/java/com/rbkmoney/fraudo/payment/factory/FullVisitorFactoryImpl.java +++ b/src/main/java/com/rbkmoney/fraudo/payment/factory/FullVisitorFactoryImpl.java @@ -7,6 +7,7 @@ import com.rbkmoney.fraudo.payment.aggregator.CountPaymentAggregator; import com.rbkmoney.fraudo.payment.aggregator.SumPaymentAggregator; import com.rbkmoney.fraudo.payment.resolver.PaymentGroupResolver; import com.rbkmoney.fraudo.payment.resolver.PaymentTimeWindowResolver; +import com.rbkmoney.fraudo.payment.resolver.PaymentTypeResolver; import com.rbkmoney.fraudo.payment.visitor.CountVisitor; import com.rbkmoney.fraudo.payment.visitor.CustomFuncVisitor; import com.rbkmoney.fraudo.payment.visitor.ListVisitor; @@ -26,12 +27,18 @@ public class FullVisitorFactoryImpl implements FraudVisitorFactory { InListFinder listFinder, FieldResolver fieldResolver, PaymentGroupResolver paymentGroupResolver, - PaymentTimeWindowResolver timeWindowResolver) { + PaymentTimeWindowResolver timeWindowResolver, + PaymentTypeResolver paymentTypeResolver) { CountVisitor countVisitor = new CountVisitorImpl<>(countPaymentAggregator, fieldResolver, paymentGroupResolver, timeWindowResolver); SumVisitor sumVisitor = new SumVisitorImpl<>(sumPaymentAggregator, fieldResolver, paymentGroupResolver, timeWindowResolver); ListVisitor listVisitor = new ListVisitorImpl<>(listFinder, fieldResolver); CustomFuncVisitor customFuncVisitor = new CustomFuncVisitorImpl<>( - uniqueValueAggregator, countryResolver, fieldResolver, paymentGroupResolver, timeWindowResolver); + uniqueValueAggregator, + countryResolver, + fieldResolver, + paymentGroupResolver, + timeWindowResolver, + paymentTypeResolver); return new FullVisitorImpl<>(countVisitor, sumVisitor, listVisitor, customFuncVisitor, fieldResolver); } diff --git a/src/main/java/com/rbkmoney/fraudo/payment/resolver/PaymentTypeResolver.java b/src/main/java/com/rbkmoney/fraudo/payment/resolver/PaymentTypeResolver.java new file mode 100644 index 0000000..372c14b --- /dev/null +++ b/src/main/java/com/rbkmoney/fraudo/payment/resolver/PaymentTypeResolver.java @@ -0,0 +1,9 @@ +package com.rbkmoney.fraudo.payment.resolver; + +public interface PaymentTypeResolver { + + Boolean isMobile(T model); + + Boolean isRecurrent(T model); + +} diff --git a/src/main/java/com/rbkmoney/fraudo/payment/visitor/CustomFuncVisitor.java b/src/main/java/com/rbkmoney/fraudo/payment/visitor/CustomFuncVisitor.java index 8960d5b..77558cb 100644 --- a/src/main/java/com/rbkmoney/fraudo/payment/visitor/CustomFuncVisitor.java +++ b/src/main/java/com/rbkmoney/fraudo/payment/visitor/CustomFuncVisitor.java @@ -10,4 +10,8 @@ public interface CustomFuncVisitor { Integer visitUnique(UniqueContext ctx, T model); + boolean visitCheckMobile(Is_mobileContext ctx, T model); + + boolean visitCheckRecurrent(Is_recurrentContext ctx, T model); + } diff --git a/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/CustomFuncVisitorImpl.java b/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/CustomFuncVisitorImpl.java index 4b9e77e..30f59b3 100644 --- a/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/CustomFuncVisitorImpl.java +++ b/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/CustomFuncVisitorImpl.java @@ -4,6 +4,7 @@ import com.rbkmoney.fraudo.aggregator.UniqueValueAggregator; import com.rbkmoney.fraudo.model.Pair; import com.rbkmoney.fraudo.payment.resolver.PaymentGroupResolver; import com.rbkmoney.fraudo.payment.resolver.PaymentTimeWindowResolver; +import com.rbkmoney.fraudo.payment.resolver.PaymentTypeResolver; import com.rbkmoney.fraudo.payment.visitor.CustomFuncVisitor; import com.rbkmoney.fraudo.resolver.CountryResolver; import com.rbkmoney.fraudo.resolver.FieldResolver; @@ -20,6 +21,7 @@ public class CustomFuncVisitorImpl implements CustomFuncVisitor { private final FieldResolver fieldResolver; private final PaymentGroupResolver groupResolver; private final PaymentTimeWindowResolver timeWindowResolver; + private final PaymentTypeResolver paymentTypeResolver; @Override public String visitCountryBy(Country_byContext ctx, T model) { @@ -49,4 +51,14 @@ public class CustomFuncVisitorImpl implements CustomFuncVisitor { ); } + @Override + public boolean visitCheckMobile(Is_mobileContext ctx, T model) { + return paymentTypeResolver.isMobile(model); + } + + @Override + public boolean visitCheckRecurrent(Is_recurrentContext ctx, T model) { + return paymentTypeResolver.isRecurrent(model); + } + } diff --git a/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/FirstFindVisitorImpl.java b/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/FirstFindVisitorImpl.java index a642955..845221a 100644 --- a/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/FirstFindVisitorImpl.java +++ b/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/FirstFindVisitorImpl.java @@ -365,4 +365,13 @@ public class FirstFindVisitorImpl extends FraudoPaymentB ); } + @Override + public Boolean visitIs_mobile(Is_mobileContext ctx) { + return customFuncVisitor.visitCheckMobile(ctx, threadLocalModel.get()); + } + + @Override + public Boolean visitIs_recurrent(Is_recurrentContext ctx) { + return customFuncVisitor.visitCheckRecurrent(ctx, threadLocalModel.get()); + } } diff --git a/src/test/java/com/rbkmoney/fraudo/AbstractPaymentTest.java b/src/test/java/com/rbkmoney/fraudo/AbstractPaymentTest.java index c387a5b..0de7598 100644 --- a/src/test/java/com/rbkmoney/fraudo/AbstractPaymentTest.java +++ b/src/test/java/com/rbkmoney/fraudo/AbstractPaymentTest.java @@ -10,6 +10,7 @@ import com.rbkmoney.fraudo.payment.factory.FraudVisitorFactoryImpl; import com.rbkmoney.fraudo.payment.factory.FullVisitorFactoryImpl; import com.rbkmoney.fraudo.payment.resolver.PaymentGroupResolver; import com.rbkmoney.fraudo.payment.resolver.PaymentTimeWindowResolver; +import com.rbkmoney.fraudo.payment.resolver.PaymentTypeResolver; import com.rbkmoney.fraudo.resolver.CountryResolver; import com.rbkmoney.fraudo.resolver.FieldResolver; import com.rbkmoney.fraudo.test.constant.PaymentCheckedField; @@ -36,6 +37,8 @@ public class AbstractPaymentTest { InListFinder inListFinder; @Mock PaymentTimeWindowResolver timeWindowResolver; + @Mock + PaymentTypeResolver paymentModelPaymentTypeResolver; private FieldResolver fieldResolver = new PaymentModelFieldResolver(); private PaymentGroupResolver paymentGroupResolver = new PaymentGroupResolver<>(fieldResolver); @@ -60,7 +63,8 @@ public class AbstractPaymentTest { inListFinder, fieldResolver, paymentGroupResolver, - timeWindowResolver) + timeWindowResolver, + paymentModelPaymentTypeResolver) .visit(parse, model); } @@ -74,7 +78,8 @@ public class AbstractPaymentTest { inListFinder, fieldResolver, paymentGroupResolver, - timeWindowResolver) + timeWindowResolver, + paymentModelPaymentTypeResolver) .visit(parse, model); } diff --git a/src/test/java/com/rbkmoney/fraudo/CustomTest.java b/src/test/java/com/rbkmoney/fraudo/CustomTest.java index fe7f41b..7dee2ae 100644 --- a/src/test/java/com/rbkmoney/fraudo/CustomTest.java +++ b/src/test/java/com/rbkmoney/fraudo/CustomTest.java @@ -123,6 +123,28 @@ public class CustomTest extends AbstractPaymentTest { assertEquals(ResultStatus.ACCEPT, ResultUtils.findFirstNotNotifyStatus(result).get().getResultStatus()); } + @Test + public void tokenProviderTest() throws Exception { + InputStream resourceAsStream = CustomTest.class.getResourceAsStream("/rules/is_mobile.frd"); + when(paymentModelPaymentTypeResolver.isMobile(any())).thenReturn(true); + + ParseContext parseContext = getParseContext(resourceAsStream); + PaymentModel model = new PaymentModel(); + ResultModel result = invoke(parseContext, model); + assertEquals(ResultStatus.ACCEPT, ResultUtils.findFirstNotNotifyStatus(result).get().getResultStatus()); + } + + @Test + public void payerTypeTest() throws Exception { + InputStream resourceAsStream = CustomTest.class.getResourceAsStream("/rules/is_recurrent.frd"); + when(paymentModelPaymentTypeResolver.isRecurrent(any())).thenReturn(true); + + ParseContext parseContext = getParseContext(resourceAsStream); + PaymentModel model = new PaymentModel(); + ResultModel result = invoke(parseContext, model); + assertEquals(ResultStatus.DECLINE, ResultUtils.findFirstNotNotifyStatus(result).get().getResultStatus()); + } + @Test public void amountTest() throws Exception { InputStream resourceAsStream = CustomTest.class.getResourceAsStream("/rules/amount.frd"); diff --git a/src/test/resources/rules/is_mobile.frd b/src/test/resources/rules/is_mobile.frd new file mode 100644 index 0000000..c5a6107 --- /dev/null +++ b/src/test/resources/rules/is_mobile.frd @@ -0,0 +1 @@ +rule: isMobile() -> accept; \ No newline at end of file diff --git a/src/test/resources/rules/is_recurrent.frd b/src/test/resources/rules/is_recurrent.frd new file mode 100644 index 0000000..e73d668 --- /dev/null +++ b/src/test/resources/rules/is_recurrent.frd @@ -0,0 +1 @@ +rule: isRecurrent() -> decline; \ No newline at end of file