From 91aa10d7ac4f45a44a4c026302085249f5542327 Mon Sep 17 00:00:00 2001
From: Akshay S Dinesh <akshay@learnlearn.in>
Date: Sun, 8 Jan 2023 22:35:49 +0530
Subject: [PATCH] feat: CSV Verification Provider

---
 .../prav/quicksy/CSVVerificationProvider.java | 78 +++++++++++++++++++
 1 file changed, 78 insertions(+)
 create mode 100644 src/main/java/app/prav/quicksy/CSVVerificationProvider.java

diff --git a/src/main/java/app/prav/quicksy/CSVVerificationProvider.java b/src/main/java/app/prav/quicksy/CSVVerificationProvider.java
new file mode 100644
index 0000000..cfdaf78
--- /dev/null
+++ b/src/main/java/app/prav/quicksy/CSVVerificationProvider.java
@@ -0,0 +1,78 @@
+package app.prav.quicksy;
+
+import com.google.common.util.concurrent.RateLimiter;
+import com.google.i18n.phonenumbers.PhoneNumberUtil;
+import com.google.i18n.phonenumbers.Phonenumber;
+import im.quicksy.server.verification.AbstractVerificationProvider;
+import im.quicksy.server.verification.RequestFailedException;
+import im.quicksy.server.verification.TokenExpiredException;
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Map;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CSVVerificationProvider extends AbstractVerificationProvider {
+    private static final String COMMA_DELIMITER = ",";
+    private static final Logger LOGGER = LoggerFactory.getLogger(CSVVerificationProvider.class);
+    private final PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
+    private final RateLimiter rateLimiter = RateLimiter.create(0.2);
+    private final String csvPath;
+
+    public CSVVerificationProvider(Map<String, String> parameter) {
+        super(parameter);
+        this.csvPath = parameter.get("csv_path");
+    }
+
+    @Override
+    public boolean verify(Phonenumber.PhoneNumber phoneNumber, String pin)
+            throws RequestFailedException {
+        LOGGER.info(getInPhoneNumberFormat(phoneNumber) + " attempting " + pin);
+        checkRateLimiter();
+        try (BufferedReader br = new BufferedReader(new FileReader(this.csvPath))) {
+            String line;
+            while ((line = br.readLine()) != null) {
+                String[] values = line.split(COMMA_DELIMITER);
+                if (pinAndPhoneMatches(phoneNumber, pin, values)) {
+                    LOGGER.info("PIN was correct");
+                    return true;
+                }
+            }
+        } catch (IOException e) {
+            LOGGER.error("Exception in reading" + this.csvPath);
+            LOGGER.error(String.valueOf(e));
+        }
+        LOGGER.info("PIN was wrong");
+        return false;
+    }
+
+    @Override
+    public void request(Phonenumber.PhoneNumber phoneNumber, Method method)
+            throws RequestFailedException {
+        this.request(phoneNumber, method, "en");
+    }
+
+    @Override
+    public void request(Phonenumber.PhoneNumber phoneNumber, Method method, String language)
+            throws RequestFailedException {
+        LOGGER.info(
+                getInPhoneNumberFormat(phoneNumber)
+                        + " has requested PIN. They should know it already");
+    }
+
+    private void checkRateLimiter() throws TokenExpiredException {
+        if (!rateLimiter.tryAcquire()) {
+            throw new TokenExpiredException("Rate limiter struck");
+        }
+    }
+
+    private boolean pinAndPhoneMatches(
+            Phonenumber.PhoneNumber phoneNumber, String pin, String[] values) {
+        return values[0].equals(getInPhoneNumberFormat(phoneNumber)) && values[1].equals((pin));
+    }
+
+    private String getInPhoneNumberFormat(Phonenumber.PhoneNumber phoneNumber) {
+        return this.phoneUtil.format(phoneNumber, PhoneNumberUtil.PhoneNumberFormat.E164);
+    }
+}
-- 
GitLab