X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/e18c4734744e56b738ca2918dffe071f95f4c14b..b0b15b7ced28b3c6ddfcd4b0a7e46ee6432a243c:/disobedience/users.c?ds=sidebyside diff --git a/disobedience/users.c b/disobedience/users.c index d162e14..0590d69 100644 --- a/disobedience/users.c +++ b/disobedience/users.c @@ -33,9 +33,6 @@ * When you select 'add' a new empty set of details are displayed to be edited. * Again Apply will commit them. * - * TODO: @ref RIGHT_ADMIN and @ref RIGHT_USERINFO should be applied here, so we - * can give decent error messages. - * * TODO: it would be really nice if the Username entry could be removed and new * user names entered in the list, rather off in the details panel. This may * be possible with a sufficiently clever GtkCellRenderer. @@ -112,10 +109,16 @@ static int users_find_user(const char *user, * * If users_deferred_select is set then that user is selected. */ -static void users_got_list(void attribute((unused)) *v, int nvec, char **vec) { +static void users_got_list(void attribute((unused)) *v, + const char *error, + int nvec, char **vec) { int n; GtkTreeIter iter; + if(error) { + popup_protocol_error(0, error); + return; + } /* Present users in alphabetical order */ qsort(vec, nvec, sizeof (char *), usercmp); /* Set the list contents */ @@ -196,7 +199,7 @@ static void users_add_right(const char *title, GtkWidget **checkp = &users_details_rights[leftmost_bit(right)]; if(!(check = *checkp)) { - *checkp = check = gtk_check_button_new(); + *checkp = check = gtk_check_button_new_with_label(""); users_detail_generic(title, check); } gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), !!(value & right)); @@ -251,26 +254,26 @@ static void users_add_right_group(const char *title, rights_type mask) { const uint32_t first = mask / 7; const int bit = leftmost_bit(first); - GtkWidget **widgets = &users_details_rights[bit], *any, *mine, *random; + GtkWidget **widgets = &users_details_rights[bit], *any, *mine, *rnd; if(!*widgets) { GtkWidget *hbox = gtk_hbox_new(FALSE, 2); any = widgets[0] = gtk_check_button_new_with_label("Any"); mine = widgets[1] = gtk_check_button_new_with_label("Own"); - random = widgets[2] = gtk_check_button_new_with_label("Random"); + rnd = widgets[2] = gtk_check_button_new_with_label("Random"); gtk_box_pack_start(GTK_BOX(hbox), any, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), mine, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(hbox), random, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox), rnd, FALSE, FALSE, 0); users_detail_generic(title, hbox); g_signal_connect(any, "toggled", G_CALLBACK(users_any_toggled), NULL); users_details_rights[bit] = any; users_details_rights[bit + 1] = mine; - users_details_rights[bit + 2] = random; + users_details_rights[bit + 2] = rnd; } else { any = widgets[0]; mine = widgets[1]; - random = widgets[2]; + rnd = widgets[2]; } /* Discard irrelevant bits */ bits &= mask; @@ -278,7 +281,7 @@ static void users_add_right_group(const char *title, bits >>= bit; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(any), !!(bits & 1)); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mine), !!(bits & 2)); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(random), !!(bits & 4)); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rnd), !!(bits & 4)); } /** @brief Called when the details table is destroyed */ @@ -383,42 +386,38 @@ static rights_type users_get_rights(void) { return r; } -/** @brief Called when various things fail */ -static void users_op_failed(struct callbackdata attribute((unused)) *cbd, - int attribute((unused)) code, - const char *msg) { - popup_submsg(users_window, GTK_MESSAGE_ERROR, msg); +/** @brief Called when a user setting has been edited */ +static void users_edituser_completed(void attribute((unused)) *v, + const char *error) { + if(error) + popup_submsg(users_window, GTK_MESSAGE_ERROR, error); } /** @brief Called when a new user has been created */ -static void users_adduser_completed(void *v) { - struct callbackdata *cbd = v; - - /* Now the user is created we can go ahead and set the email address */ - if(*cbd->u.edituser.email) { - struct callbackdata *ncbd = xmalloc(sizeof *cbd); - ncbd->onerror = users_op_failed; - disorder_eclient_edituser(client, NULL, cbd->u.edituser.user, - "email", cbd->u.edituser.email, ncbd); +static void users_adduser_completed(void *v, + const char *error) { + if(error) { + popup_submsg(users_window, GTK_MESSAGE_ERROR, error); + mode(ADD); /* Let the user try again */ + } else { + const struct kvp *const kvp = v; + const char *user = kvp_get(kvp, "user"); + const char *email = kvp_get(kvp, "email"); /* maybe NULL */ + + /* Now the user is created we can go ahead and set the email address */ + if(email) + disorder_eclient_edituser(client, users_edituser_completed, user, + "email", email, NULL); + /* Refresh the list of users */ + disorder_eclient_users(client, users_got_list, 0); + /* We'll select the newly created user */ + users_deferred_select = user; } - /* Refresh the list of users */ - disorder_eclient_users(client, users_got_list, 0); - /* We'll select the newly created user */ - users_deferred_select = cbd->u.edituser.user; -} - -/** @brief Called if creating a new user fails */ -static void users_adduser_failed(struct callbackdata attribute((unused)) *cbd, - int attribute((unused)) code, - const char *msg) { - popup_submsg(users_window, GTK_MESSAGE_ERROR, msg); - mode(ADD); /* Let the user try again */ } /** @brief Called when the 'Apply' button is pressed */ static void users_apply(GtkButton attribute((unused)) *button, gpointer attribute((unused)) userdata) { - struct callbackdata *cbd; const char *password; const char *password2; const char *name; @@ -450,15 +449,14 @@ static void users_apply(GtkButton attribute((unused)) *button, popup_submsg(users_window, GTK_MESSAGE_ERROR, "Invalid email address"); return; } - cbd = xmalloc(sizeof *cbd); - cbd->onerror = users_adduser_failed; - cbd->u.edituser.user = name; - cbd->u.edituser.email = email; - disorder_eclient_adduser(client, users_adduser_completed, + disorder_eclient_adduser(client, + users_adduser_completed, name, password, rights_string(users_get_rights()), - cbd); + kvp_make("user", name, + "email", email, + (char *)0)); /* We switch to no-op mode while creating the user */ mode(NONE); break; @@ -475,26 +473,30 @@ static void users_apply(GtkButton attribute((unused)) *button, popup_submsg(users_window, GTK_MESSAGE_ERROR, "Invalid email address"); return; } - cbd = xmalloc(sizeof *cbd); - cbd->onerror = users_op_failed; - disorder_eclient_edituser(client, NULL, users_selected, - "email", email, cbd); - disorder_eclient_edituser(client, NULL, users_selected, - "password", password, cbd); - disorder_eclient_edituser(client, NULL, users_selected, - "rights", rights_string(users_get_rights()), cbd); + disorder_eclient_edituser(client, users_edituser_completed, users_selected, + "email", email, NULL); + disorder_eclient_edituser(client, users_edituser_completed, users_selected, + "password", password, NULL); + disorder_eclient_edituser(client, users_edituser_completed, users_selected, + "rights", rights_string(users_get_rights()), NULL); /* We remain in edit mode */ break; } } /** @brief Called when a user has been deleted */ -static void users_deleted(void *v) { - const struct callbackdata *const cbd = v; - GtkTreeIter iter[1]; - - if(!users_find_user(cbd->u.user, iter)) /* Find the user... */ - gtk_list_store_remove(users_list, iter); /* ...and remove them */ +static void users_delete_completed(void *v, + const char *error) { + if(error) + popup_submsg(users_window, GTK_MESSAGE_ERROR, error); + else { + const struct kvp *const kvp = v; + const char *const user = kvp_get(kvp, "user"); + GtkTreeIter iter[1]; + + if(!users_find_user(user, iter)) /* Find the user... */ + gtk_list_store_remove(users_list, iter); /* ...and remove them */ + } } /** @brief Called when the 'Delete' button is pressed */ @@ -502,7 +504,6 @@ static void users_delete(GtkButton attribute((unused)) *button, gpointer attribute((unused)) userdata) { GtkWidget *yesno; int res; - struct callbackdata *cbd; if(!users_selected) return; @@ -516,22 +517,35 @@ static void users_delete(GtkButton attribute((unused)) *button, res = gtk_dialog_run(GTK_DIALOG(yesno)); gtk_widget_destroy(yesno); if(res == GTK_RESPONSE_YES) { - cbd = xmalloc(sizeof *cbd); - cbd->onerror = users_op_failed; - cbd->u.user = users_selected; - disorder_eclient_deluser(client, users_deleted, cbd->u.user, cbd); + disorder_eclient_deluser(client, users_delete_completed, users_selected, + kvp_make("user", users_selected, + (char *)0)); } } -static void users_got_email(void attribute((unused)) *v, const char *value) { +static void users_got_email(void attribute((unused)) *v, + const char *error, + const char *value) { + if(error) + popup_protocol_error(0, error); users_email = value; } -static void users_got_rights(void attribute((unused)) *v, const char *value) { +static void users_got_rights(void attribute((unused)) *v, + const char *error, + const char *value) { + if(error) + popup_protocol_error(0, error); users_rights = value; } -static void users_got_password(void attribute((unused)) *v, const char *value) { +static void users_got_password(void attribute((unused)) *v, + const char *error, + const char *value) { + if(error) + popup_protocol_error(0, error); + /* TODO if an error occurred gathering user info, we should react in some + * different way */ users_password = value; users_makedetails(users_selected, users_email,