anastasis-db_record_recdoc_payment.c (5490B)
1 /* 2 This file is part of Anastasis 3 Copyright (C) 2020-2022 Anastasis SARL 4 5 Anastasis is free software; you can redistribute it and/or modify it under the 6 terms of the GNU Affero General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. 12 13 You should have received a copy of the GNU Affero General Public License along with 14 Anastasis; see the file COPYING.GPL. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file stasis/anastasis-db_record_recdoc_payment.c 18 * @brief Anastasis database: record recdoc payment 19 * @author Christian Grothoff 20 */ 21 #include "platform.h" 22 #include "anastasis-db_pg.h" 23 #include "anastasis/anastasis-database/record_recdoc_payment.h" 24 #include "anastasis/anastasis-database/transaction.h" 25 #include "anastasis/anastasis-database/preflight.h" 26 #include <taler/taler_pq_lib.h> 27 28 29 /** 30 * Store payment. Used to begin a payment, not indicative 31 * that the payment actually was made. (That is done 32 * when we increment the account's lifetime.) 33 * 34 * @param account_pub anastasis's public key 35 * @param post_counter how many uploads does @a amount pay for 36 * @param payment_secret payment secret which the user must provide with every upload 37 * @param amount how much we asked for 38 * @return transaction status 39 */ 40 enum GNUNET_DB_QueryStatus 41 ANASTASIS_DB_record_recdoc_payment ( 42 const struct ANASTASIS_CRYPTO_AccountPublicKeyP *account_pub, 43 uint32_t post_counter, 44 const struct ANASTASIS_PaymentSecretP *payment_secret, 45 const struct TALER_Amount *amount) 46 { 47 struct GNUNET_TIME_Timestamp now = GNUNET_TIME_timestamp_get (); 48 struct GNUNET_TIME_Timestamp expiration; 49 struct GNUNET_PQ_QueryParam params[] = { 50 GNUNET_PQ_query_param_auto_from_type (account_pub), 51 GNUNET_PQ_query_param_uint32 (&post_counter), 52 TALER_PQ_query_param_amount (pg->conn, 53 amount), 54 GNUNET_PQ_query_param_auto_from_type (payment_secret), 55 GNUNET_PQ_query_param_timestamp (&now), 56 GNUNET_PQ_query_param_end 57 }; 58 enum GNUNET_DB_QueryStatus qs; 59 60 GNUNET_break (GNUNET_OK == 61 ANASTASIS_DB_preflight ()); 62 PREPARE ("user_select3", 63 "SELECT" 64 " expiration_date " 65 "FROM anastasis_user" 66 " WHERE user_id=$1" 67 " FOR UPDATE;"); 68 PREPARE ("user_insert3", 69 "INSERT INTO anastasis_user " 70 "(user_id" 71 ",expiration_date" 72 ") VALUES " 73 "($1, $2);"); 74 PREPARE ("recdoc_payment_insert", 75 "INSERT INTO anastasis_recdoc_payment " 76 "(user_id" 77 ",post_counter" 78 ",amount" 79 ",payment_identifier" 80 ",creation_date" 81 ") VALUES " 82 "($1, $2, $3, $4, $5);"); 83 84 /* because of constraint at user_id, first we have to verify 85 if user exists, and if not, create one */ 86 { 87 struct GNUNET_PQ_QueryParam iparams[] = { 88 GNUNET_PQ_query_param_auto_from_type (account_pub), 89 GNUNET_PQ_query_param_end 90 }; 91 struct GNUNET_PQ_ResultSpec rs[] = { 92 GNUNET_PQ_result_spec_timestamp ("expiration_date", 93 &expiration), 94 GNUNET_PQ_result_spec_end 95 }; 96 97 qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, 98 "user_select3", 99 iparams, 100 rs); 101 } 102 switch (qs) 103 { 104 case GNUNET_DB_STATUS_HARD_ERROR: 105 return qs; 106 case GNUNET_DB_STATUS_SOFT_ERROR: 107 GNUNET_break (0); 108 return GNUNET_DB_STATUS_HARD_ERROR; 109 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 110 { 111 /* create new user with short lifetime */ 112 struct GNUNET_TIME_Timestamp exp 113 = GNUNET_TIME_relative_to_timestamp (TRANSIENT_LIFETIME); 114 struct GNUNET_PQ_QueryParam iparams[] = { 115 GNUNET_PQ_query_param_auto_from_type (account_pub), 116 GNUNET_PQ_query_param_timestamp (&exp), 117 GNUNET_PQ_query_param_end 118 }; 119 120 qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, 121 "user_insert3", 122 iparams); 123 switch (qs) 124 { 125 case GNUNET_DB_STATUS_HARD_ERROR: 126 return GNUNET_DB_STATUS_HARD_ERROR; 127 case GNUNET_DB_STATUS_SOFT_ERROR: 128 GNUNET_break (0); 129 return GNUNET_DB_STATUS_HARD_ERROR; 130 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 131 GNUNET_break (0); 132 return GNUNET_DB_STATUS_HARD_ERROR; 133 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 134 /* successful, continue below */ 135 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 136 "Created new account %s with transient life until %s\n", 137 TALER_B2S (account_pub), 138 GNUNET_TIME_timestamp2s (exp)); 139 break; 140 } 141 } 142 /* continue below */ 143 break; 144 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 145 /* handle case below */ 146 break; 147 } 148 149 return GNUNET_PQ_eval_prepared_non_select (pg->conn, 150 "recdoc_payment_insert", 151 params); 152 } 153 154 155 /* end of anastasis-db_record_recdoc_payment.c */