anastasis

Credential backup and recovery protocol and service
Log | Files | Refs | Submodules | README | LICENSE

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 */