#!/bin/bash
# This file is part of TALER
# Copyright (C) 2014-2023 Taler Systems SA
#
# TALER is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 3, or
# (at your option) any later version.
#
# TALER is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with TALER; see the file COPYING.  If not, see
# <http://www.gnu.org/licenses/>
#

# Cleanup to run whenever we exit
function my_cleanup()
{
    for n in $(jobs -p)
    do
        kill "$n" 2> /dev/null || true
    done
    wait
    if [ -n "${LAST_RESPONSE+x}" ]
    then
        rm -f "${LAST_RESPONSE}"
    fi
}

. setup.sh

setup -c test_template.conf -m
CONF="test_template.conf.edited"
LAST_RESPONSE=$(mktemp -p "${TMPDIR:-/tmp}" test_response.conf-XXXXXX)

echo -n "Configuring 'admin' instance ..." >&2

STATUS=$(curl -H "Content-Type: application/json" -X POST \
    http://localhost:9966/management/instances \
    -d '{"auth":{"method":"token","password":"new_pw"},"id":"admin","name":"default","user_type":"business","address":{},"jurisdiction":{},"use_stefan":true,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' \
    -w "%{http_code}" -s -o /dev/null)

if [ "$STATUS" != "204" ]
then
    exit_fail "Expected 204, instance created. got: $STATUS" >&2
fi


BASIC_AUTH=$(echo -n admin:new_pw | base64)

STATUS=$(curl -H "Content-Type: application/json" -X POST \
    -H "Authorization: Basic $BASIC_AUTH" \
    http://localhost:9966/private/token \
    -d '{"scope":"spa"}' \
    -w "%{http_code}" -s -o $LAST_RESPONSE)


if [ "$STATUS" != "200" ]
then
    exit_fail "Expected 200 OK. Got: $STATUS"
fi

TOKEN=$(jq -e -r .access_token < $LAST_RESPONSE)

echo " OK" >&2

STATUS=$(curl -H "Content-Type: application/json" -X POST \
    -H "Authorization: Bearer $TOKEN" \
    http://localhost:9966/private/accounts \
    -d '{"payto_uri":"payto://x-taler-bank/localhost:8082/43?receiver-name=user43"}' \
    -w "%{http_code}" -s -o /dev/null)


if [ "$STATUS" != "200" ]
then
    exit_fail "Expected 200 OK. Got: $STATUS"
fi

echo " OK" >&2

# Kill merchant
kill -TERM "$SETUP_PID"
wait
unset SETUP_PID

setup -c test_template.conf \
      -ef \
      -u "exchange-account-2" \
      -r "merchant-exchange-default"

NEW_SECRET="different_value"

taler-merchant-exchangekeyupdate \
    -c "${CONF}" \
    -L DEBUG \
    2> taler-merchant-exchangekeyupdate2.log &
taler-merchant-passwd \
    -c "${CONF}" \
    -L DEBUG \
    "$NEW_SECRET" \
    2> taler-merchant-passwd.log
taler-merchant-httpd \
    -c "${CONF}" \
    -L DEBUG \
    2> taler-merchant-httpd2.log &
# Install cleanup handler (except for kill -9)
trap my_cleanup EXIT

echo -n "Waiting for the merchant..." >&2
# Wait for merchant to be available (usually the slowest)
for n in $(seq 1 50)
do
    echo -n "." >&2
    sleep 0.1
    OK=0
    # merchant
    wget --waitretry=0 \
         --timeout=1 \
         http://localhost:9966/ \
         -o /dev/null \
         -O /dev/null \
         >/dev/null || continue
    OK=1
    break
done

if [ "x$OK" != "x1" ]
then
    exit_fail "Failed to (re)start merchant backend"
fi

echo " OK" >&2

BASIC_AUTH=$(echo -n "admin:$NEW_SECRET" | base64)

STATUS=$(curl -H "Content-Type: application/json" -X POST \
    -H "Authorization: Basic $BASIC_AUTH" \
    http://localhost:9966/private/token \
    -d '{"scope":"spa"}' \
    -w "%{http_code}" -s -o $LAST_RESPONSE)


if [ "$STATUS" != "200" ]
then
    exit_fail "Expected 200 OK. Got: $STATUS"
fi

TOKEN=$(jq -e -r .access_token < $LAST_RESPONSE)

echo -n "Creating order to test auth is ok..." >&2
STATUS=$(curl -H "Content-Type: application/json" -X POST \
    'http://localhost:9966/private/orders' \
    -H 'Authorization: Bearer '"$TOKEN" \
    -d '{"order":{"amount":"TESTKUDOS:1","summary":"payme"}}' \
    -w "%{http_code}" -s -o "$LAST_RESPONSE")

if [ "$STATUS" != "200" ]
then
    cat "$LAST_RESPONSE" >&2
    exit_fail "Expected 200, order created. got: $STATUS"
fi

ORDER_ID=$(jq -e -r .order_id < "$LAST_RESPONSE")
ORD_TOKEN=$(jq -e -r .token < "$LAST_RESPONSE")

STATUS=$(curl "http://localhost:9966/private/orders/${ORDER_ID}" \
     -H 'Authorization: Bearer '"$TOKEN" \
     -w "%{http_code}" -s -o "$LAST_RESPONSE")

if [ "$STATUS" != "200" ]
then
    cat "$LAST_RESPONSE" >&2
    exit_fail "Expected 200, getting order info before claming it. got: $STATUS"
fi

PAY_URL=$(jq -e -r .taler_pay_uri < "$LAST_RESPONSE")

echo "OK order ${ORDER_ID} with ${ORD_TOKEN} and ${PAY_URL}" >&2

echo -n "Configuring 'second' instance ..." >&2

STATUS=$(curl -H "Content-Type: application/json" -X POST \
    -H 'Authorization: Bearer '"$TOKEN" \
    http://localhost:9966/management/instances \
    -d '{"auth":{"method":"token","password":"second"},"id":"second","name":"second","address":{},"jurisdiction":{},"use_stefan":true,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' \
    -w "%{http_code}" -s -o /dev/null)

if [ "$STATUS" != "204" ]
then
    exit_fail "Expected 204, instance created. got: $STATUS"
fi

echo "OK" >&2

echo -n "Configuring 'third' instance ..." >&2

STATUS=$(curl -H "Content-Type: application/json" -X POST \
    -H 'Authorization: Bearer '"$TOKEN" \
    http://localhost:9966/management/instances \
    -d '{"auth":{"method":"token","password":"third"},"id":"third","name":"third","address":{},"jurisdiction":{},"use_stefan":true,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' \
    -w "%{http_code}" -s -o /dev/null)

if [ "$STATUS" != "204" ]
then
    exit_fail "Expected 204, instance created. got: $STATUS"
fi

echo "OK" >&2

echo -n "Updating 'second' instance token using the 'new_one' auth token..." >&2

STATUS=$(curl -H "Content-Type: application/json" -X POST \
    -H 'Authorization: Bearer '"$TOKEN" \
    http://localhost:9966/management/instances/second/auth \
    -d '{"method":"token","password":"new_one"}' \
    -w "%{http_code}" -s -o /dev/null)

if [ "$STATUS" != "204" ]
then
    exit_fail "Expected 204, instance auth token changed. got: $STATUS"
fi
NEW_SECRET="new_one"
echo " OK" >&2

BASIC_AUTH2=$(echo -n second:$NEW_SECRET | base64)

echo -n "Requesting login token..." >&2

STATUS=$(curl -H "Content-Type: application/json" -X POST \
    -H 'Authorization: Basic '"$BASIC_AUTH2" \
    http://localhost:9966/instances/second/private/token \
    -d '{"scope":"readonly","refreshable":true}' \
    -w "%{http_code}" -s -o "$LAST_RESPONSE")

if [ "$STATUS" != "200" ]
then
    jq < "$LAST_RESPONSE" >&2
    exit_fail "Expected 200, login token created. got: $STATUS"
fi

TOKEN=$(jq -e -r .access_token < "$LAST_RESPONSE")

echo " OK" >&2

echo -n "Requesting login token... (spa)" >&2

STATUS=$(curl -H "Content-Type: application/json" -X POST \
    -H 'Authorization: Basic '"$BASIC_AUTH2" \
    http://localhost:9966/instances/second/private/token \
    -d '{"scope":"spa"}' \
    -w "%{http_code}" -s -o "$LAST_RESPONSE")

if [ "$STATUS" != "200" ]
then
    jq < "$LAST_RESPONSE" >&2
    exit_fail "Expected 200, login token created. got: $STATUS"
fi

RWTOKEN=$(jq -e -r .access_token < "$LAST_RESPONSE")

echo " OK" >&2

echo -n "Using login token..." >&2

STATUS=$(curl "http://localhost:9966/instances/second/private/orders" \
     -H 'Authorization: Bearer '"$TOKEN" \
     -w "%{http_code}" -s -o "$LAST_RESPONSE")

if [ "$STATUS" != "200" ]
then
    jq < "$LAST_RESPONSE" >&2
    exit_fail "Expected 200, getting orders. got: $STATUS"
fi

echo " OK" >&2

echo -n "Updating 'second' instance token using the 'second' auth token..." >&2

STATUS=$(curl -H "Content-Type: application/json" -X POST \
    -H 'Authorization: Bearer '"$RWTOKEN" \
    http://localhost:9966/instances/second/private/auth \
    -d '{"method":"token","password":"again"}' \
    -w "%{http_code}" -s -o "$LAST_RESPONSE")

BASIC_AUTH2=$(echo -n second:again | base64)

if [ "$STATUS" != "204" ]
then
    cat $LAST_RESPONSE
    exit_fail "Expected 204, instance not authorized. got: $STATUS"
fi

echo " OK" >&2

echo -n "Updating 'third' instance token using the 'second' auth token..." >&2

STATUS=$(curl -H "Content-Type: application/json" -X POST \
    -H 'Authorization: Bearer '"$RWTOKEN" \
    http://localhost:9966/management/instances/third/auth \
    -d '{"method":"token","password":"new_one"}' \
    -w "%{http_code}" -s -o /dev/null)

if [ "$STATUS" != "401" ]
then
    exit_fail "Expected 401, instance not authorized. got: $STATUS"
fi

echo " OK" >&2

echo -n "Refreshing login token... (expected failure)" >&2

STATUS=$(curl -H "Content-Type: application/json" -X POST \
    -H 'Authorization: Bearer '"$TOKEN" \
    http://localhost:9966/instances/second/private/token \
    -d '{"scope":"spa","refreshable":true}' \
    -w "%{http_code}" -s -o "$LAST_RESPONSE")

if [ "$STATUS" != "403" ]
then
    jq < "$LAST_RESPONSE" >&2
    exit_fail "Expected 403, refused to upgrade login token. got: $STATUS"
fi

echo " OK" >&2

echo -n "Refreshing login token... (expected failure)" >&2

STATUS=$(curl -H "Content-Type: application/json" -X POST \
    -H 'Authorization: Bearer '"$RWTOKEN" \
    http://localhost:9966/instances/second/private/token \
    -d '{"scope":"spa","refreshable":true}' \
    -w "%{http_code}" -s -o "$LAST_RESPONSE")

if [ "$STATUS" != "401" ]
then
    jq < "$LAST_RESPONSE" >&2
    exit_fail "Expected 401, refused to upgrade login token. got: $STATUS"
fi

echo " OK" >&2

STATUS=$(curl -H "Content-Type: application/json" -X POST \
    -H 'Authorization: Basic '"$BASIC_AUTH2" \
    http://localhost:9966/instances/second/private/token \
    -d '{"scope":"spa:refreshable"}' \
    -w "%{http_code}" -s -o "$LAST_RESPONSE")

if [ "$STATUS" != "200" ]
then
    jq < "$LAST_RESPONSE" >&2
    exit_fail "Expected 200, login token created. got: $STATUS"
fi

RWTOKEN=$(jq -e -r .access_token < "$LAST_RESPONSE")

STATUS=$(curl -H "Content-Type: application/json" -X POST \
    -H 'Authorization: Bearer '"$RWTOKEN" \
    http://localhost:9966/instances/second/private/token \
    -d '{"scope":"spa","refreshable":true}' \
    -w "%{http_code}" -s -o "$LAST_RESPONSE")

if [ "$STATUS" != "200" ]
then
    jq < "$LAST_RESPONSE" >&2
    exit_fail "Expected 200. got: $STATUS"
fi

echo " OK" >&2


echo -n "Requesting another login token... (read)" >&2

STATUS=$(curl -H "Content-Type: application/json" -X POST \
    -H 'Authorization: Basic '"$BASIC_AUTH2" \
    http://localhost:9966/instances/second/private/token \
    -d '{"scope":"readonly", "refreshable": false}' \
    -w "%{http_code}" -s -o "$LAST_RESPONSE")

if [ "$STATUS" != "200" ]
then
    jq < "$LAST_RESPONSE" >&2
    exit_fail "Expected 200, login token created. got: $STATUS"
fi

RTOKEN=$(jq -e -r .access_token < "$LAST_RESPONSE")

echo " OK" >&2

echo -n "Requesting another login token... (read:refreshable)" >&2

STATUS=$(curl -H "Content-Type: application/json" -X POST \
    -H 'Authorization: Basic '"$BASIC_AUTH2" \
    http://localhost:9966/instances/second/private/token \
    -d '{"scope":"readonly:refreshable", "description": "readonly but refreshable"}' \
    -w "%{http_code}" -s -o "$LAST_RESPONSE")

if [ "$STATUS" != "200" ]
then
    jq < "$LAST_RESPONSE" >&2
    exit_fail "Expected 200, login token created. got: $STATUS"
fi

RTOKEN=$(jq -e -r .access_token < "$LAST_RESPONSE")

echo " OK" >&2

echo "Getting last 2 login tokens." >&2

STATUS=$(curl -H "Content-Type: application/json" \
    -H "Authorization: Bearer $RWTOKEN" \
    'http://localhost:9966/instances/second/private/tokens?limit=-2' \
    -w "%{http_code}" -s -o $LAST_RESPONSE)

if [ "$STATUS" != "200" ]
then
    jq < "$LAST_RESPONSE" >&2
    exit_fail "Expected 200 OK. Got: $STATUS"
fi

TOKEN_SERIAL=$(jq -e -r .tokens[0].serial < "$LAST_RESPONSE")

echo -n "Deleting second login token by serial..." >&2

STATUS=$(curl -H "Content-Type: application/json" -X DELETE \
    -H 'Authorization: Bearer '"$RWTOKEN" \
    http://localhost:9966/instances/second/private/tokens/$TOKEN_SERIAL \
    -w "%{http_code}" -s -o "$LAST_RESPONSE")

if [ "$STATUS" != "204" ]
then
    jq < "$LAST_RESPONSE" >&2
    exit_fail "Expected 204, login token deleted. got: $STATUS"
fi
echo " OK" >&2

echo -n "Using deleted login token $RTOKEN..." >&2

STATUS=$(curl "http://localhost:9966/instances/second/private/orders" \
     -H 'Authorization: Bearer '"$RTOKEN" \
     -w "%{http_code}" -s -o "$LAST_RESPONSE")

if [ "$STATUS" != "401" ]
then
    jq < "$LAST_RESPONSE" >&2
    exit_fail "Expected 401, token was deleted. got: $STATUS"
fi

echo " OK" >&2


echo -n "Deleting login token..." >&2

STATUS=$(curl -H "Content-Type: application/json" -X DELETE \
    -H 'Authorization: Bearer '"$TOKEN" \
    http://localhost:9966/instances/second/private/token \
    -w "%{http_code}" -s -o "$LAST_RESPONSE")

if [ "$STATUS" != "204" ]
then
    jq < "$LAST_RESPONSE" >&2
    exit_fail "Expected 204, login token deleted. got: $STATUS"
fi
echo " OK" >&2

echo -n "Using deleted login token..." >&2

STATUS=$(curl "http://localhost:9966/instances/second/private/orders" \
     -H 'Authorization: Bearer '"$TOKEN" \
     -w "%{http_code}" -s -o "$LAST_RESPONSE")

if [ "$STATUS" != "401" ]
then
    jq < "$LAST_RESPONSE" >&2
    exit_fail "Expected 401, token was deleted. got: $STATUS"
fi

echo " OK" >&2


echo "Test PASSED"

exit 0
