anastasis-gtk_handle-main-window-forward-clicked.c (13134B)
1 /* 2 This file is part of anastasis-gtk. 3 Copyright (C) 2020, 2021 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 * @file src/anastasis/anastasis-gtk_handle-main-window-forward-clicked.c 22 * @brief 23 * @author Christian Grothoff 24 * @author Dennis Neufeld 25 */ 26 #include "anastasis_gtk_config.h" 27 #define HAVE_USED_CONFIG_H 1 28 29 #include <gnunet/gnunet_util_lib.h> 30 #include "anastasis_gtk_util.h" 31 #include "anastasis-gtk_action.h" 32 #include "anastasis-gtk_attributes.h" 33 #include "anastasis-gtk_dispatch.h" 34 #include "anastasis-gtk_helper.h" 35 #include <jansson.h> 36 37 38 /** 39 * The user selected the 'forward' button. Move on with the 40 * country selection. 41 */ 42 static void 43 forward_country_selecting (void) 44 { 45 GtkTreeIter iter; 46 GtkTreeView *tv; 47 GtkTreeModel *model; 48 GtkTreeSelection *sel; 49 gchar *country_name; 50 gchar *country_code; 51 json_t *arguments; 52 53 tv = GTK_TREE_VIEW (GCG_get_main_window_object ( 54 "anastasis_gtk_country_treeview")); 55 sel = gtk_tree_view_get_selection (tv); 56 if (! gtk_tree_selection_get_selected (sel, 57 &model, 58 &iter)) 59 { 60 GNUNET_break (0); 61 return; 62 } 63 gtk_tree_model_get (model, 64 &iter, 65 AG_CCMC_COUNTRY_NAME, &country_name, 66 AG_CCMC_COUNTRY_CODE, &country_code, 67 -1); 68 arguments = GNUNET_JSON_PACK ( 69 GNUNET_JSON_pack_string ("country", 70 country_name), 71 GNUNET_JSON_pack_string ("country_code", 72 country_code)); 73 g_free (country_name); 74 g_free (country_code); 75 AG_freeze (); 76 AG_ra = ANASTASIS_redux_action (AG_redux_state, 77 "select_country", 78 arguments, 79 &AG_action_cb, 80 NULL); 81 json_decref (arguments); 82 } 83 84 85 /** 86 * The user has entered their personal attributes and 87 * confirmed they are correct. Move to the next state. 88 * Note that #AG_freeze() was already called. 89 */ 90 static void 91 confirm_attributes (void) 92 { 93 json_t *args; 94 95 args = AG_collect_attributes (false); 96 GNUNET_assert (NULL != args); 97 AG_ra = ANASTASIS_redux_action (AG_redux_state, 98 "enter_user_attributes", 99 args, 100 &AG_action_cb, 101 NULL); 102 json_decref (args); 103 } 104 105 106 /** 107 * Function called with the result of asking the user 108 * if they are sure about the personal details they 109 * entered. 110 * 111 * @param the dialog 112 * @param response_id must be GTK_RESPONSE_OK to proceed 113 * @param user_data the builder 114 */ 115 void 116 anastasis_gtk_user_sure_dialog_response_cb ( 117 GtkDialog *dialog, 118 gint response_id, 119 gpointer user_data) 120 { 121 GtkBuilder *builder = user_data; 122 123 gtk_widget_destroy (GTK_WIDGET (dialog)); 124 g_object_unref (G_OBJECT (builder)); 125 if (GTK_RESPONSE_OK != response_id) 126 { 127 AG_thaw (); 128 return; 129 } 130 confirm_attributes (); 131 } 132 133 134 /** 135 * Launch dialog to question certainty of user providing 136 * personal details during backup. 137 */ 138 static void 139 question_certainty (void) 140 { 141 GtkBuilder *builder; 142 GtkDialog *ad; 143 144 builder = ANASTASIS_GTK_get_new_builder ( 145 ANASTASIS_GTK_project_data (), 146 "anastasis_gtk_user_sure.glade", 147 NULL); 148 if (NULL == builder) 149 { 150 GNUNET_break (0); 151 return; 152 } 153 ad = GTK_DIALOG (gtk_builder_get_object (builder, 154 "anastasis_gtk_user_sure_dialog")); 155 if (NULL == ad) 156 { 157 GNUNET_break (0); 158 g_object_unref (G_OBJECT (builder)); 159 return; 160 } 161 /* show dialog */ 162 { 163 GtkWidget *toplevel; 164 GtkWidget *widget; 165 166 #if ! HAVE_HPDF_H 167 gtk_widget_hide ( 168 GTK_WIDGET ( 169 gtk_builder_get_object ( 170 builder, 171 "anastasis_gtk_print_details_button"))); 172 #endif 173 widget = GTK_WIDGET (GCG_get_main_window_object ( 174 "anastasis_gtk_auth_button_grid")); 175 toplevel = gtk_widget_get_toplevel (widget); 176 gtk_window_set_transient_for (GTK_WINDOW (ad), 177 GTK_WINDOW (toplevel)); 178 gtk_window_present (GTK_WINDOW (ad)); 179 } 180 } 181 182 183 /** 184 * The user clicked the 'next' button in the dialog where they enter 185 * their personal attributes. If we are in the backup process, make 186 * them first confirm that the attributes are correct and well-known 187 * to them. Otherwise, simply directly proceed. 188 */ 189 void 190 AG_forward_user_attributes_collecting (void) 191 { 192 bool in_backup; 193 194 AG_freeze (); 195 in_backup = (NULL != json_object_get (AG_redux_state, 196 "backup_state")); 197 if (in_backup) 198 question_certainty (); 199 else 200 confirm_attributes (); 201 } 202 203 204 /** 205 * Function called with the result of questioning the user 206 * if they really want to proceed with less than three 207 * authentication factors. 208 * 209 * @param the dialog 210 * @param response_id must be GTK_RESPONSE_OK to proceed 211 * @param user_data the builder 212 */ 213 void 214 anastasis_gtk_confirm_multifactor_dialog_response_cb ( 215 GtkDialog *dialog, 216 gint response_id, 217 gpointer user_data) 218 { 219 GtkBuilder *builder = user_data; 220 221 gtk_widget_destroy (GTK_WIDGET (dialog)); 222 g_object_unref (G_OBJECT (builder)); 223 if (GTK_RESPONSE_OK != response_id) 224 { 225 AG_thaw (); 226 return; 227 } 228 AG_ra = ANASTASIS_redux_action (AG_redux_state, 229 "next", 230 NULL, 231 &AG_action_cb, 232 NULL); 233 } 234 235 236 /** 237 * Function called with the result of telling the 238 * user that they cannot use 1-FA. 239 * 240 * @param the dialog 241 * @param response_id must be GTK_RESPONSE_OK to proceed 242 * @param user_data the builder 243 */ 244 void 245 anastasis_gtk_deny_singlefactor_dialog_response_cb ( 246 GtkDialog *dialog, 247 gint response_id, 248 gpointer user_data) 249 { 250 GtkBuilder *builder = user_data; 251 252 gtk_widget_destroy (GTK_WIDGET (dialog)); 253 g_object_unref (G_OBJECT (builder)); 254 AG_thaw (); 255 } 256 257 258 /** 259 * Launch dialog to question sanity of user providing 260 * too few authentication methods. 261 */ 262 static void 263 question_sanity (void) 264 { 265 GtkBuilder *builder; 266 GtkDialog *ad; 267 268 builder = ANASTASIS_GTK_get_new_builder ( 269 ANASTASIS_GTK_project_data (), 270 "anastasis_gtk_warn_multifactor.glade", 271 NULL); 272 if (NULL == builder) 273 { 274 GNUNET_break (0); 275 return; 276 } 277 ad = GTK_DIALOG (gtk_builder_get_object (builder, 278 "anastasis_gtk_confirm_multifactor_dialog")); 279 if (NULL == ad) 280 { 281 GNUNET_break (0); 282 g_object_unref (G_OBJECT (builder)); 283 return; 284 } 285 /* show dialog */ 286 { 287 GtkWidget *toplevel; 288 GtkWidget *widget; 289 290 widget = GTK_WIDGET (GCG_get_main_window_object ( 291 "anastasis_gtk_auth_button_grid")); 292 toplevel = gtk_widget_get_toplevel (widget); 293 gtk_window_set_transient_for (GTK_WINDOW (ad), 294 GTK_WINDOW (toplevel)); 295 gtk_window_present (GTK_WINDOW (ad)); 296 } 297 } 298 299 300 /** 301 * Launch dialog to deny 1-FA setups. 302 */ 303 static void 304 refuse_insanity (void) 305 { 306 GtkBuilder *builder; 307 GtkDialog *ad; 308 309 builder = ANASTASIS_GTK_get_new_builder ( 310 ANASTASIS_GTK_project_data (), 311 "anastasis_gtk_deny_singlefactor.glade", 312 NULL); 313 if (NULL == builder) 314 { 315 GNUNET_break (0); 316 return; 317 } 318 ad = GTK_DIALOG (gtk_builder_get_object (builder, 319 "anastasis_gtk_deny_singlefactor_dialog")); 320 if (NULL == ad) 321 { 322 GNUNET_break (0); 323 g_object_unref (G_OBJECT (builder)); 324 return; 325 } 326 /* show dialog */ 327 { 328 GtkWidget *toplevel; 329 GtkWidget *widget; 330 331 widget = GTK_WIDGET (GCG_get_main_window_object ( 332 "anastasis_gtk_auth_button_grid")); 333 toplevel = gtk_widget_get_toplevel (widget); 334 gtk_window_set_transient_for (GTK_WINDOW (ad), 335 GTK_WINDOW (toplevel)); 336 gtk_window_present (GTK_WINDOW (ad)); 337 } 338 } 339 340 341 /** 342 * The user has clicked 'next' in the 'authentications_editing' state. 343 * Check if the number of authentication methods configured is above 344 * a threshold. If no, warn before allowing to proceed. 345 */ 346 static void 347 forward_authentications_editing (void) 348 { 349 json_t *methods; 350 351 AG_freeze (); 352 methods = json_object_get (AG_redux_state, 353 "authentication_methods"); 354 if (json_array_size (methods) < 2) 355 { 356 refuse_insanity (); 357 return; 358 } 359 if (json_array_size (methods) < 3) 360 { 361 question_sanity (); 362 return; 363 } 364 AG_ra = ANASTASIS_redux_action (AG_redux_state, 365 "next", 366 NULL, 367 &AG_action_cb, 368 NULL); 369 } 370 371 372 /** 373 * The user has pressed 'next' in POLICIES_EDITING state. 374 * Proceed to secret editing. 375 */ 376 static void 377 forward_policies_reviewing (void) 378 { 379 AG_freeze (); 380 AG_ra = ANASTASIS_redux_action (AG_redux_state, 381 "next", 382 NULL, 383 &AG_action_cb, 384 NULL); 385 } 386 387 388 static void 389 forward_secret_editing (void) 390 { 391 AG_freeze (); 392 AG_ra = ANASTASIS_redux_action (AG_redux_state, 393 "next", 394 NULL, 395 &AG_action_cb, 396 NULL); 397 } 398 399 400 /** 401 * The user has pressed 'next' after selecting a secret to recover. 402 */ 403 static void 404 forward_secret_selecting (void) 405 { 406 GtkTreeSelection *selection; 407 GtkTreeModel *model; 408 GtkTreeIter iter; 409 json_t *args; 410 gchar *provider_url; 411 gchar *secret_name; 412 gint version; 413 gint mask; 414 const json_t *providers; 415 416 AG_freeze (); 417 AG_stop_long_action (); 418 selection = GTK_TREE_SELECTION ( 419 GCG_get_main_window_object ( 420 "anastasis_gtk_secret_selection_treeselection")); 421 422 if (! gtk_tree_selection_get_selected (selection, 423 &model, 424 &iter)) 425 { 426 GNUNET_break (0); 427 AG_insensitive ("anastasis_gtk_main_window_forward_button"); 428 return; 429 } 430 gtk_tree_model_get (model, 431 &iter, 432 AG_SSMC_PROVIDER_URL, &provider_url, 433 AG_SSMC_POLICY_VERSION, &version, 434 AG_SSMC_ATTRIBUTE_MASK, &mask, 435 AG_SSMC_SECRET_NAME, &secret_name, 436 AG_SSMC_POLICY_PROVIDER_JSON, &providers, 437 -1); 438 args = GNUNET_JSON_PACK ( 439 GNUNET_JSON_pack_array_incref ("providers", 440 (json_t *) providers), 441 GNUNET_JSON_pack_uint64 ("attribute_mask", 442 mask), 443 GNUNET_JSON_pack_string ("secret_name", 444 secret_name)); 445 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 446 "Proceeding with policy version %u at provider %s\n", 447 (unsigned int) version, 448 provider_url); 449 g_free (provider_url); 450 g_free (secret_name); 451 if (NULL != AG_pd) 452 { 453 ANASTASIS_policy_discovery_stop (AG_pd); 454 AG_pd = NULL; 455 } 456 AG_ra = ANASTASIS_redux_action (AG_redux_state, 457 "select_version", 458 args, 459 &AG_action_cb, 460 NULL); 461 json_decref (args); 462 } 463 464 465 /** 466 * Callback invoked if the the "forward"-button is clicked. 467 * 468 * @param object 469 * @param user_data unused 470 */ 471 void 472 anastasis_gtk_main_window_forward_clicked (GObject *object, 473 gpointer user_data) 474 { 475 struct DispatchItem actions[] = { 476 { .state = "COUNTRY_SELECTING", 477 .action = &forward_country_selecting }, 478 { .state = "USER_ATTRIBUTES_COLLECTING", 479 .action = &AG_forward_user_attributes_collecting }, 480 { .state = "AUTHENTICATIONS_EDITING", 481 .action = &forward_authentications_editing }, 482 { .state = "POLICIES_REVIEWING", 483 .action = &forward_policies_reviewing }, 484 { .state = "SECRET_EDITING", 485 .action = &forward_secret_editing }, 486 { .state = "SECRET_SELECTING", 487 .action = &forward_secret_selecting }, 488 { .state = NULL, 489 .action = NULL } 490 }; 491 492 AG_insensitive ("anastasis_gtk_main_window_forward_button"); 493 AG_dispatch (actions); 494 }