anastasis-gtk_handle-add-provider.c (8074B)
1 /* 2 This file is part of anastasis-gtk. 3 Copyright (C) 2022 Anastasis SARL 4 5 Anastasis is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published 7 by the Free Software Foundation; either version 3, or (at your 8 option) any later version. 9 10 Anastasis is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with Anastasis; see the file COPYING. If not, write to the 17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 Boston, MA 02110-1301, USA. 19 */ 20 21 /** 22 * @file src/anastasis/anastasis-gtk_handle-add-provider.c 23 * @brief Dialog to add a provider during recovery 24 * @author Christian Grothoff 25 */ 26 #include <gnunet/gnunet_util_lib.h> 27 #include "anastasis_gtk_util.h" 28 #include "anastasis-gtk_action.h" 29 #include "anastasis-gtk_helper.h" 30 #include <jansson.h> 31 #include <microhttpd.h> 32 33 /** 34 * State data for the provider, NULL if none is available. 35 */ 36 static json_t *pstate; 37 38 /** 39 * Current /config operation, or NULL if none. 40 */ 41 static struct ANASTASIS_ConfigOperation *co; 42 43 44 /** 45 * Function called with the result of a /config request. 46 * Note that an HTTP status of #MHD_HTTP_OK is no guarantee 47 * that @a acfg is non-NULL. @a acfg is non-NULL only if 48 * the server provided an acceptable response. 49 * 50 * @param cls closure with our `GtkBuilder *` 51 * @param acfg configuration obtained, NULL if we could not parse it 52 */ 53 static void 54 config_cb (void *cls, 55 const struct ANASTASIS_Config *acfg) 56 { 57 GtkBuilder *builder = GTK_BUILDER (cls); 58 GtkWidget *button; 59 json_t *methods_list; 60 GtkLabel *l; 61 62 co = NULL; 63 l = GTK_LABEL (gtk_builder_get_object (builder, 64 "error_label")); 65 if (MHD_HTTP_OK != acfg->http_status) 66 { 67 char *msg; 68 69 if (0 == acfg->http_status) 70 GNUNET_asprintf (&msg, 71 "Provider URL invalid (no response)"); 72 else 73 GNUNET_asprintf (&msg, 74 "Provider URL invalid (HTTP status %u)", 75 acfg->http_status); 76 gtk_widget_set_visible (GTK_WIDGET (l), 77 TRUE); 78 gtk_label_set_text (l, 79 msg); 80 free (msg); 81 return; 82 } 83 methods_list = json_array (); 84 GNUNET_assert (NULL != methods_list); 85 for (unsigned int i = 0; i<acfg->details.ok.methods_length; i++) 86 { 87 const struct ANASTASIS_AuthorizationMethodConfig *method 88 = &acfg->details.ok.methods[i]; 89 json_t *mj = GNUNET_JSON_PACK ( 90 GNUNET_JSON_pack_string ("type", 91 method->type), 92 TALER_JSON_pack_amount ("usage_fee", 93 &method->usage_fee)); 94 95 GNUNET_assert (0 == 96 json_array_append_new (methods_list, 97 mj)); 98 } 99 pstate = GNUNET_JSON_PACK ( 100 GNUNET_JSON_pack_array_steal ("methods", 101 methods_list), 102 TALER_JSON_pack_amount ("annual_fee", 103 &acfg->details.ok.annual_fee), 104 TALER_JSON_pack_amount ("truth_upload_fee", 105 &acfg->details.ok.truth_upload_fee), 106 TALER_JSON_pack_amount ("liability_limit", 107 &acfg->details.ok.liability_limit), 108 GNUNET_JSON_pack_string ("business_name", 109 acfg->details.ok.business_name), 110 GNUNET_JSON_pack_string ("status", 111 "enabled"), 112 GNUNET_JSON_pack_uint64 ("http_status", 113 MHD_HTTP_OK), 114 GNUNET_JSON_pack_uint64 ("storage_limit_in_megabytes", 115 acfg->details.ok.storage_limit_in_megabytes), 116 GNUNET_JSON_pack_data_auto ("provider_salt", 117 &acfg->details.ok.provider_salt), 118 GNUNET_JSON_pack_uint64 ("http_status", 119 acfg->http_status)); 120 button = GTK_WIDGET (gtk_builder_get_object (builder, 121 "add_button")); 122 gtk_widget_set_sensitive (button, 123 true); 124 gtk_widget_set_visible (GTK_WIDGET (l), 125 FALSE); 126 } 127 128 129 /** 130 * Function called when the user edits the URL in the "add_provider" 131 * dialog. Updates the visibility of the 'apply/add' button. 132 * 133 * @param entry the entry that changed 134 * @param user_data our `GtkBuilder *` 135 */ 136 void 137 add_provider_url_entry_changed_cb (GtkEntry *entry, 138 gpointer user_data) 139 { 140 GtkBuilder *builder = GTK_BUILDER (user_data); 141 GtkWidget *button; 142 const char *url; 143 144 json_decref (pstate); 145 pstate = NULL; 146 if (NULL != co) 147 { 148 ANASTASIS_config_cancel (co); 149 co = NULL; 150 } 151 button = GTK_WIDGET (gtk_builder_get_object (builder, 152 "add_button")); 153 gtk_widget_set_sensitive (button, 154 false); 155 url = gtk_editable_get_text (GTK_EDITABLE (entry)); 156 if ( (0 == strncasecmp (url, 157 "http://", 158 strlen ("http://"))) || 159 (0 == strncasecmp (url, 160 "https://", 161 strlen ("https://"))) ) 162 { 163 co = ANASTASIS_get_config (AG_ctx, 164 url, 165 &config_cb, 166 builder); 167 GNUNET_break (NULL != co); 168 } 169 } 170 171 172 /** 173 * Function called from the edit-provider dialog upon completion. 174 * 175 * @param dialog the pseudonym selection dialog 176 * @param response_id response code from the dialog 177 * @param user_data the builder of the dialog 178 */ 179 void 180 add_provider_dialog_response_cb (GtkDialog *dialog, 181 gint response_id, 182 gpointer user_data) 183 { 184 GtkBuilder *builder = GTK_BUILDER (user_data); 185 GtkEntry *entry; 186 const char *url; 187 json_t *ap; 188 189 if (NULL != co) 190 { 191 ANASTASIS_config_cancel (co); 192 co = NULL; 193 } 194 if (GTK_RESPONSE_APPLY != response_id) 195 { 196 gtk_window_destroy (GTK_WINDOW (dialog)); 197 g_object_unref (G_OBJECT (builder)); 198 json_decref (pstate); 199 pstate = NULL; 200 return; 201 } 202 if (NULL == pstate) 203 { 204 GNUNET_break (0); 205 return; 206 } 207 ap = json_object_get (AG_redux_state, 208 "authentication_providers"); 209 if (NULL == ap) 210 { 211 GNUNET_break (0); 212 return; 213 } 214 entry = GTK_ENTRY (gtk_builder_get_object (builder, 215 "url_entry")); 216 url = gtk_editable_get_text (GTK_EDITABLE (entry)); 217 ANASTASIS_policy_discovery_more (AG_pd, 218 url, 219 pstate); 220 GNUNET_break (0 == 221 json_object_set_new (ap, 222 url, 223 pstate)); 224 pstate = NULL; 225 gtk_window_destroy (GTK_WINDOW (dialog)); 226 g_object_unref (G_OBJECT (builder)); 227 } 228 229 230 /** 231 * Callback invoked if the the "Add"-provider button is clicked. 232 * 233 * @param object 234 * @param user_data unused 235 */ 236 void 237 anastasis_gtk_add_provider_button_clicked_cb (GtkButton *object, 238 gpointer user_data) 239 { 240 GtkWidget *ad; 241 GtkBuilder *builder; 242 GtkRoot *toplevel; 243 244 if (NULL == AG_pd) 245 { 246 GNUNET_break (0); 247 return; 248 } 249 builder = ANASTASIS_GTK_get_new_builder ( 250 ANASTASIS_GTK_project_data (), 251 "anastasis_gtk_add_provider.ui", 252 NULL); 253 if (NULL == builder) 254 { 255 GNUNET_break (0); 256 return; 257 } 258 ad = GTK_WIDGET (gtk_builder_get_object (builder, 259 "add_provider_dialog")); 260 toplevel = gtk_widget_get_root (GTK_WIDGET (object)); 261 gtk_window_set_transient_for (GTK_WINDOW (ad), 262 GTK_WINDOW (toplevel)); 263 gtk_window_present (GTK_WINDOW (ad)); 264 }