exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

taler-exchange-helper-measure-tops-sms-check (5275B)


      1 #!/bin/bash
      2 #
      3 #  This file is part of TALER
      4 #  Copyright (C) 2024 Taler Systems SA
      5 #
      6 #  TALER is free software; you can redistribute it and/or modify it under the
      7 #  terms of the GNU General Public License as published by the Free Software
      8 #  Foundation; either version 3, or (at your option) any later version.
      9 #
     10 #  TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     11 #  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     12 #  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     13 #
     14 #  You should have received a copy of the GNU General Public License along with
     15 #  TALER; see the file COPYING.  If not, If not, see <http://www.gnu.org/license>
     16 #
     17 
     18 # Hard error reporting on.
     19 set -eu
     20 
     21 # Exit, with error message (hard failure)
     22 function exit_fail() {
     23     echo " FAIL: " "$@" >&2
     24     EXIT_STATUS=1
     25     exit "$EXIT_STATUS"
     26 }
     27 
     28 CONF="$HOME/.config/taler-exchange.conf"
     29 VERBOSE=0
     30 
     31 while getopts 'ac:hirvV' OPTION;
     32 do
     33     case "$OPTION" in
     34         a)
     35             # Phone number is required.
     36             echo "CONTACT_PHONE"
     37             exit 0
     38             ;;
     39         c)
     40             # shellcheck disable=SC2034
     41             CONF="$OPTARG"
     42             ;;
     43         h)
     44             echo "This is a KYC measure program that lifts restrictions on withdraw and P2P transfers after a phone number was confirmed via SMS. Expiration rules are set based on the context."
     45             echo 'Supported options:'
     46             echo '  -a           -- show required attributes'
     47             # shellcheck disable=SC2016
     48             echo '  -c $CONF     -- set configuration'
     49             echo '  -h           -- print this help'
     50             echo '  -i           -- show required inputs'
     51             echo '  -r           -- show required context'
     52             echo '  -v           -- show version'
     53             echo '  -V           -- be verbose'
     54             exit 0
     55             ;;
     56         i)
     57             # Need attributes, context and current_rules.
     58             echo "attributes"
     59             echo "context"
     60             echo "current_rules"
     61             echo "default_rules"
     62             exit 0
     63             ;;
     64         r)
     65             exit 0
     66             ;;
     67         v)
     68             echo "$0 v0.0.2"
     69             exit 0
     70             ;;
     71         V)
     72             VERBOSE=1
     73             ;;
     74         ?)
     75         exit_fail "Unrecognized command line option"
     76         ;;
     77     esac
     78 done
     79 
     80 if [ 1 = "$VERBOSE" ]
     81 then
     82     echo "Running $0" 1>&2
     83 fi
     84 
     85 # See https://docs.taler.net/taler-kyc-manual.html#tsref-type-AmlProgramInput
     86 # for the full JSON with possible inputs.
     87 
     88 # First, extract inputs we need
     89 INPUTS=$(jq '{"current_rules":(.current_rules // .default_rules // error("neither current_rules nor default_rules provided")),"attributes":.attributes,"context":.context}')
     90 
     91 # Get phone number.
     92 PHONE_NUMBER=$(echo "$INPUTS" | jq -r '.attributes.CONTACT_PHONE // null')
     93 # Get current rules.
     94 CURRENT_RULES=$(echo "$INPUTS" | jq '.current_rules // null')
     95 # Get context values.
     96 # How long the rules we emit are valid.  This must NOT be derived from
     97 # .attributes.expires: that is the challenger's address validation lifetime,
     98 # and a validation that has already aged out yields a rule set which expired
     99 # before it was written.  The exchange applies such a set, immediately falls
    100 # back to the default rules, and asks for this very same check again.
    101 VALIDITY_YEARS=$(echo "$INPUTS" | jq -r '.context.validity_years // 2')
    102 EXPIRATION_STAMP=$((VALIDITY_YEARS * 365 * 24 * 60 * 60 + $(date +%s)))
    103 EXPIRATION_TIME=$(echo "$INPUTS" | jq --argjson es "$EXPIRATION_STAMP" '.context.expiration_time // {"t_s":$es}')
    104 SUCCESSOR_MEASURE=$(echo "$INPUTS" | jq '.context.successor_measure // .current_rules.successor_measure // null')
    105 CUSTOM_MEASURES=$(echo "$INPUTS" | jq '.context.custom_measures // null')
    106 
    107 # Validate phone number
    108 if eval echo "$PHONE_NUMBER" | grep -E -e "${EXCHANGE_AML_PROGRAM_TOPS_SMS_CHECK_REGEX}" > /dev/null
    109 then
    110     # Valid phone number
    111     # Remove limitation from current rules.
    112     NEW_RULES=$(echo "$CURRENT_RULES" | jq 'del(.rules[] | select ((.rule_name=="p2p-domestic-identification-requirement") or (.rule_name=="withdraw-limit-low") ))')
    113 
    114 # Remove test rules that should now be satisfied
    115 NEW_RULES=$(echo "$NEW_RULES" | jq 'del(.rules[] | select (.rule_name=="balance-testing-limit1") )')
    116 
    117     TO_INVESTIGATE="false"
    118 else
    119     # Invalid phone number.  Repeating the check cannot change the outcome, so
    120     # hand the account to an AML officer.  Echoing the rules back unchanged
    121     # would leave the rule that asked for the SMS in place and the exchange
    122     # would request the very same check again, forever.
    123     echo "Phone number ${PHONE_NUMBER} invalid." 1>&2
    124     echo "$INPUTS" | taler-exchange-helper-measure-inform-investigate
    125     exit $?
    126 fi
    127 
    128 
    129 # Finally, output the new rules.
    130 # See https://docs.taler.net/taler-kyc-manual.html#tsref-type-AmlOutcome
    131 # for the required output format.
    132 
    133 exec jq -n \
    134     --argjson et "$EXPIRATION_TIME" \
    135     --argjson sm "$SUCCESSOR_MEASURE" \
    136     --argjson cm "$CUSTOM_MEASURES" \
    137     --argjson nr "$NEW_RULES" \
    138     --argjson inv "$TO_INVESTIGATE" \
    139     '{"new_rules":($nr+{"expiration_time":$et,"successor_measure":$sm,"custom_measures":({}+$nr.custom_measures+$cm)}),"to_investigate":$inv}|del(..|nulls)'