exchange

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

age_restriction.c (7450B)


      1 /*
      2    This file is part of TALER
      3    Copyright (C) 2021-2022 Taler Systems SA
      4 
      5    TALER is free software; you can redistribute it and/or modify it under the
      6    terms of the GNU General Public License as published by the Free Software
      7    Foundation; either version 3, or (at your option) any later version.
      8 
      9    TALER 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 General Public License for more details.
     12 
     13    You should have received a copy of the GNU General Public License along with
     14    TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15  */
     16 /**
     17  * @file age_restriction.c
     18  * @brief Utility functions regarding age restriction
     19  * @author Özgür Kesim
     20  */
     21 #include "taler/platform.h"
     22 #include "taler/taler_util.h"
     23 #include "taler/taler_extensions.h"
     24 #include "stdint.h"
     25 
     26 /* ==================================================
     27  *
     28  * Age Restriction  TALER_Extension implementation
     29  *
     30  * ==================================================
     31  */
     32 
     33 /**
     34  * @brief local configuration
     35  */
     36 
     37 static struct TALER_AgeRestrictionConfig AR_config = {0};
     38 
     39 /**
     40  * @brief implements the TALER_Extension.disable interface.
     41  *
     42  * @param ext Pointer to the current extension
     43  */
     44 static void
     45 age_restriction_disable (
     46   struct TALER_Extension *ext)
     47 {
     48   if (NULL == ext)
     49     return;
     50 
     51   ext->enabled = false;
     52   ext->config = NULL;
     53 
     54   AR_config.mask.bits = 0;
     55   AR_config.num_groups = 0;
     56 }
     57 
     58 
     59 /**
     60  * @brief implements the TALER_Extension.load_config interface.
     61  *
     62  * @param ext if NULL, only tests the configuration
     63  * @param jconfig the configuration as json
     64  */
     65 static enum GNUNET_GenericReturnValue
     66 age_restriction_load_config (
     67   const json_t *jconfig,
     68   struct TALER_Extension *ext)
     69 {
     70   struct TALER_AgeMask mask = {0};
     71   enum GNUNET_GenericReturnValue ret;
     72 
     73   ret = TALER_JSON_parse_age_groups (jconfig, &mask);
     74   if (GNUNET_OK != ret)
     75     return ret;
     76 
     77   /* only testing the parser */
     78   if (ext == NULL)
     79     return GNUNET_OK;
     80 
     81   if (TALER_Extension_AgeRestriction != ext->type)
     82     return GNUNET_SYSERR;
     83 
     84   if (mask.bits > 0)
     85   {
     86     /* if the mask is not zero, the first bit MUST be set */
     87     if (0 == (mask.bits & 1))
     88       return GNUNET_SYSERR;
     89 
     90     AR_config.mask.bits = mask.bits;
     91     AR_config.num_groups = __builtin_popcount (mask.bits) - 1;
     92   }
     93 
     94   ext->config = &AR_config;
     95   ext->enabled = true;
     96 
     97   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     98               "loaded new age restriction config with age groups: %s\n",
     99               TALER_age_mask_to_string (&mask));
    100 
    101   return GNUNET_OK;
    102 }
    103 
    104 
    105 /**
    106  * @brief implements the TALER_Extension.manifest interface.
    107  *
    108  * @param ext if NULL, only tests the configuration
    109  * @return configuration as json_t* object, maybe NULL
    110  */
    111 static json_t *
    112 age_restriction_manifest (
    113   const struct TALER_Extension *ext)
    114 {
    115   json_t *conf;
    116 
    117   GNUNET_assert (NULL != ext);
    118 
    119   if (NULL == ext->config)
    120   {
    121     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    122                 "age restriction not configured");
    123     return json_null ();
    124   }
    125 
    126   conf = GNUNET_JSON_PACK (
    127     GNUNET_JSON_pack_string ("age_groups",
    128                              TALER_age_mask_to_string (&AR_config.mask))
    129     );
    130   return GNUNET_JSON_PACK (
    131     GNUNET_JSON_pack_bool ("critical",
    132                            ext->critical),
    133     GNUNET_JSON_pack_string ("version",
    134                              ext->version),
    135     GNUNET_JSON_pack_object_steal ("config",
    136                                    conf)
    137     );
    138 }
    139 
    140 
    141 /* The extension for age restriction */
    142 struct TALER_Extension TE_age_restriction = {
    143   .type = TALER_Extension_AgeRestriction,
    144   .name = "age_restriction",
    145   .critical = false,
    146   .version = "1",
    147   .enabled = false, /* disabled per default */
    148   .config = NULL,
    149   .disable = &age_restriction_disable,
    150   .load_config = &age_restriction_load_config,
    151   .manifest = &age_restriction_manifest,
    152 
    153   /* This extension is not a policy extension */
    154   .create_policy_details = NULL,
    155   .policy_get_handler = NULL,
    156   .policy_post_handler = NULL,
    157 };
    158 
    159 
    160 /**
    161  * @brief implements the init() function for GNUNET_PLUGIN_load
    162  *
    163  * @param arg Pointer to the GNUNET_CONFIGURATION_Handle
    164  * @return pointer to TALER_Extension on success or NULL otherwise.
    165  */
    166 void *
    167 libtaler_extension_age_restriction_init (void *arg);
    168 
    169 /* Declaration used to squash compiler warning */
    170 void *
    171 libtaler_extension_age_restriction_init (void *arg)
    172 {
    173   const struct GNUNET_CONFIGURATION_Handle *cfg = arg;
    174   char *groups = NULL;
    175   struct TALER_AgeMask mask = {0};
    176 
    177   if ((GNUNET_YES !=
    178        GNUNET_CONFIGURATION_have_value (cfg,
    179                                         TALER_EXTENSION_SECTION_AGE_RESTRICTION,
    180                                         "ENABLED"))
    181       ||
    182       (GNUNET_YES !=
    183        GNUNET_CONFIGURATION_get_value_yesno (cfg,
    184                                              TALER_EXTENSION_SECTION_AGE_RESTRICTION,
    185                                              "ENABLED")))
    186   {
    187     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    188                 "[age restriction] no section %s found in configuration\n",
    189                 TALER_EXTENSION_SECTION_AGE_RESTRICTION);
    190 
    191     return NULL;
    192   }
    193 
    194   /* Age restriction is enabled, extract age groups */
    195   if ((GNUNET_YES ==
    196        GNUNET_CONFIGURATION_have_value (cfg,
    197                                         TALER_EXTENSION_SECTION_AGE_RESTRICTION,
    198                                         "AGE_GROUPS"))
    199       &&
    200       (GNUNET_YES !=
    201        GNUNET_CONFIGURATION_get_value_string (cfg,
    202                                               TALER_EXTENSION_SECTION_AGE_RESTRICTION,
    203                                               "AGE_GROUPS",
    204                                               &groups)))
    205   {
    206     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    207                 "[age restriction] AGE_GROUPS in %s is not a string\n",
    208                 TALER_EXTENSION_SECTION_AGE_RESTRICTION);
    209 
    210     return NULL;
    211   }
    212 
    213   if (NULL == groups)
    214     groups = GNUNET_strdup (TALER_EXTENSION_AGE_RESTRICTION_DEFAULT_AGE_GROUPS);
    215 
    216   if (GNUNET_OK != TALER_parse_age_group_string (groups, &mask))
    217   {
    218     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    219                 "[age restriction] couldn't parse age groups: '%s'\n",
    220                 groups);
    221     return NULL;
    222   }
    223 
    224   AR_config.mask = mask;
    225   AR_config.num_groups = __builtin_popcount (mask.bits) - 1;   /* no underflow, first bit always set */
    226 
    227   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    228               "[age restriction] setting age mask to %s with #groups: %d\n",
    229               TALER_age_mask_to_string (&AR_config.mask),
    230               __builtin_popcount (AR_config.mask.bits) - 1);
    231 
    232   TE_age_restriction.config = &AR_config;
    233 
    234   /* Note: we do now have TE_age_restriction_config set, however the extension
    235    * is not yet enabled! For age restriction to become active, load_config must
    236    * have been called. */
    237 
    238   GNUNET_free (groups);
    239   return &TE_age_restriction;
    240 }
    241 
    242 
    243 /**
    244  * @brief implements the done() function for GNUNET_PLUGIN_load
    245  *
    246  * @param arg unused
    247  * @return pointer to TALER_Extension on success or NULL otherwise.
    248  */
    249 void *
    250 libtaler_extension_age_restriction_done (void *arg);
    251 
    252 /* Declaration used to squash compiler warning */
    253 void *
    254 libtaler_extension_age_restriction_done (void *arg)
    255 {
    256   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    257               "[age restriction] disabling and unloading");
    258   AR_config.mask.bits = 0;
    259   AR_config.num_groups = 0;
    260   return NULL;
    261 }
    262 
    263 
    264 /* end of age_restriction.c */