summaryrefslogtreecommitdiff
path: root/src/stasis
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2021-08-15 10:11:17 +0200
committerChristian Grothoff <christian@grothoff.org>2021-08-15 10:11:17 +0200
commit3d7de36cdd35fbfe95ba20c30b37cd81249b076b (patch)
treee466ac66b7ad9d388ff4c1e72d28e8372c68cb3c /src/stasis
parent6f0432ed839d1f5a7a1e880f492ce162073b680b (diff)
downloadanastasis-3d7de36cdd35fbfe95ba20c30b37cd81249b076b.tar.gz
anastasis-3d7de36cdd35fbfe95ba20c30b37cd81249b076b.tar.bz2
anastasis-3d7de36cdd35fbfe95ba20c30b37cd81249b076b.zip
expand database plugin with logic to store wire transfer data made for authentication
Diffstat (limited to 'src/stasis')
-rw-r--r--src/stasis/plugin_anastasis_postgres.c194
-rw-r--r--src/stasis/stasis-0001.sql29
2 files changed, 223 insertions, 0 deletions
diff --git a/src/stasis/plugin_anastasis_postgres.c b/src/stasis/plugin_anastasis_postgres.c
index 25c4dd3..1544367 100644
--- a/src/stasis/plugin_anastasis_postgres.c
+++ b/src/stasis/plugin_anastasis_postgres.c
@@ -1122,6 +1122,174 @@ postgres_record_challenge_refund (
/**
+ * Store inbound IBAN payment made for authentication.
+ *
+ * @param cls closure
+ * @param wire_reference unique identifier inside LibEuFin/Nexus
+ * @param wire_subject subject of the wire transfer
+ * @param amount how much was transferred
+ * @param debit_account account that was debited
+ * @param credit_account Anastasis operator account credited
+ * @param execution_date when was the transfer made
+ * @return transaction status
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_record_auth_iban_payment (
+ void *cls,
+ uint64_t wire_reference,
+ const char *wire_subject,
+ const struct TALER_Amount *amount,
+ const char *debit_account,
+ const char *credit_account,
+ struct GNUNET_TIME_Absolute execution_date)
+{
+ struct PostgresClosure *pg = cls;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&wire_reference),
+ GNUNET_PQ_query_param_string (wire_subject),
+ TALER_PQ_query_param_amount (amount),
+ GNUNET_PQ_query_param_string (debit_account),
+ GNUNET_PQ_query_param_string (credit_account),
+ GNUNET_PQ_query_param_absolute_time (&execution_date),
+ GNUNET_PQ_query_param_end
+ };
+
+ check_connection (pg);
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "store_auth_iban_payment_details",
+ params);
+}
+
+
+/**
+ * Closure for #test_auth_cb.
+ */
+struct TestIbanContext
+{
+
+ /**
+ * Plugin context.
+ */
+ struct PostgresClosure *pg;
+
+ /**
+ * Function to call on each wire transfer found.
+ */
+ ANASTASIS_DB_AuthIbanTransfercheck cb;
+
+ /**
+ * Closure for @a cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Value to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #postgres_test_auth_iban_payment().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct TestIbanContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+test_auth_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct TestIbanContext *tic = cls;
+ struct PostgresClosure *pg = tic->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_Amount credit;
+ char *wire_subject;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_result_spec_amount ("credit",
+ pg->currency,
+ &credit),
+ GNUNET_PQ_result_spec_string ("wire_subject",
+ &wire_subject),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ tic->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ if (tic->cb (tic->cb_cls,
+ &credit,
+ wire_subject))
+ {
+ GNUNET_free (wire_subject);
+ tic->qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+ return;
+ }
+ GNUNET_free (wire_subject);
+ }
+}
+
+
+/**
+ * Function to check if we are aware of a wire transfer
+ * that satisfies the IBAN plugin's authentication check.
+ *
+ * @param cls closure
+ * @param debit_account which debit account to check
+ * @param earliest_date earliest date to check
+ * @param cb function to call on all entries found
+ * @param cb_cls closure for @a cb
+ * @return transaction status,
+ * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if @a cb
+ * returned 'true' once
+ * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if no
+ * wire transfers existed for which @a cb returned true
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_test_auth_iban_payment (
+ void *cls,
+ const char *debit_account,
+ struct GNUNET_TIME_Absolute earliest_date,
+ ANASTASIS_DB_AuthIbanTransfercheck cb,
+ void *cb_cls)
+{
+ struct PostgresClosure *pg = cls;
+ struct TestIbanContext tic = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg
+ };
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (debit_account),
+ TALER_PQ_query_param_absolute_time (&earliest_date),
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ check_connection (pg);
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "test_auth_iban_payment",
+ params,
+ &test_auth_cb,
+ &tic);
+ if (qs < 0)
+ return qs;
+ return tic.qs;
+}
+
+
+/**
* Check payment identifier. Used to check if a payment identifier given by
* the user is valid (existing and paid).
*
@@ -2210,6 +2378,30 @@ libanastasis_plugin_db_postgres_init (void *cls)
") VALUES "
"($1, $2, $3, $4, $5, $6);",
6),
+
+ GNUNET_PQ_make_prepare ("test_auth_iban_payment",
+ "SELECT"
+ " credit_val"
+ ",credit_frac"
+ ",wire_subject"
+ " FROM anastasis_auth_iban_in"
+ " WHERE debit_account_details=$1"
+ " AND execution_date>=$2;",
+ 2),
+ GNUNET_PQ_make_prepare ("store_auth_iban_payment_details",
+ "INSERT INTO anastasis_auth_iban_in "
+ "(wire_reference"
+ ",wire_subject"
+ ",credit_val"
+ ",credit_frac"
+ ",debit_account_details"
+ ",credit_account_details"
+ ",execution_date"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6, $7);",
+ 7),
+
+
GNUNET_PQ_make_prepare ("recovery_document_insert",
"INSERT INTO anastasis_recoverydocument "
"(user_id"
@@ -2410,6 +2602,8 @@ libanastasis_plugin_db_postgres_init (void *cls)
plugin->check_challenge_payment = &postgres_check_challenge_payment;
plugin->lookup_challenge_payment = &postgres_lookup_challenge_payment;
plugin->update_challenge_payment = &postgres_update_challenge_payment;
+ plugin->record_auth_iban_payment = &postgres_record_auth_iban_payment;
+ plugin->test_auth_iban_payment = &postgres_test_auth_iban_payment;
return plugin;
}
diff --git a/src/stasis/stasis-0001.sql b/src/stasis/stasis-0001.sql
index 87dde94..e0ebfa6 100644
--- a/src/stasis/stasis-0001.sql
+++ b/src/stasis/stasis-0001.sql
@@ -193,5 +193,34 @@ COMMENT ON INDEX anastasis_challengecode_expiration_index
IS 'for challenge garbage collection';
+CREATE TABLE IF NOT EXISTS anastasis_auth_iban_in
+ (auth_in_serial_id BIGSERIAL UNIQUE
+ ,wire_reference INT8 NOT NULL PRIMARY KEY
+ ,wire_subject TEXT NOT NULL
+ ,credit_val INT8 NOT NULL
+ ,credit_frac INT4 NOT NULL
+ ,debit_account_details TEXT NOT NULL
+ ,credit_account_details TEXT NOT NULL
+ ,execution_date INT8 NOT NULL
+ );
+COMMENT ON TABLE anastasis_auth_iban_in
+ IS 'list of IBAN wire transfers for authentication using the IBAN plugin';
+COMMENT ON COLUMN anastasis_auth_iban_in.wire_reference
+ IS 'Unique number identifying the wire transfer in LibEuFin/Nexus';
+COMMENT ON COLUMN anastasis_auth_iban_in.wire_subject
+ IS 'For authentication, this contains the code, but also additional text';
+COMMENT ON COLUMN anastasis_auth_iban_in.execution_date
+ IS 'Used both for (theoretical) garbage collection and to see if the transfer happened on time';
+COMMENT ON COLUMN anastasis_auth_iban_in.credit_account_details
+ IS 'Identifies the bank account of the Anastasis provider, which could change over time';
+COMMENT ON COLUMN anastasis_auth_iban_in.debit_account_details
+ IS 'Identifies the bank account of the customer, which must match what was given in the truth';
+
+CREATE INDEX IF NOT EXISTS anastasis_auth_iban_in_lookup_index
+ ON anastasis_auth_iban_in
+ (debit_account_details
+ ,execution_date
+ );
+
-- Complete transaction
COMMIT;