Manage Pledge: Allow pledge admins to change email (#113)

* Add the admin email field to the manage form
* Fix admin email processing: When the email is changed, the pledge needs to be set back to pending, until the email is re-confirmed
* Send confirmation emails for existing pledges to the "Manage Pledge" page
* Process the email confirmation & resending emails actions on both shortcodes
* Add a message for unconfirmed pledges
This commit is contained in:
Kelly Dwan 2019-11-26 15:37:19 -05:00 committed by GitHub
parent 544fe39199
commit 80b88399ae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 139 additions and 65 deletions

View file

@ -15,6 +15,11 @@ defined( 'WPINC' ) || die();
add_shortcode( '5ftf_pledge_form_new', __NAMESPACE__ . '\render_form_new' ); add_shortcode( '5ftf_pledge_form_new', __NAMESPACE__ . '\render_form_new' );
add_shortcode( '5ftf_pledge_form_manage', __NAMESPACE__ . '\render_form_manage' ); add_shortcode( '5ftf_pledge_form_manage', __NAMESPACE__ . '\render_form_manage' );
// Short-circuit out of both shortcodes for shared functionality (confirming admin email, resending the pledge
// confirmation email).
add_filter( 'pre_do_shortcode_tag', __NAMESPACE__ . '\process_confirmed_email', 10, 2 );
add_filter( 'pre_do_shortcode_tag', __NAMESPACE__ . '\process_resend_confirm_email', 10, 2 );
/** /**
* Render the form(s) for creating new pledges. * Render the form(s) for creating new pledges.
* *
@ -38,18 +43,6 @@ function render_form_new() {
} elseif ( is_int( $pledge_id ) ) { } elseif ( is_int( $pledge_id ) ) {
$complete = true; $complete = true;
} }
} elseif ( 'confirm_pledge_email' === $action ) {
$view = 'form-pledge-confirm-email.php';
$pledge_id = filter_input( INPUT_GET, 'pledge_id', FILTER_VALIDATE_INT );
$unverified_token = filter_input( INPUT_GET, 'auth_token', FILTER_SANITIZE_STRING );
$email_confirmed = process_pledge_confirmation_email( $pledge_id, $action, $unverified_token );
$pledge = get_post( $pledge_id );
} elseif ( filter_input( INPUT_GET, 'resend_pledge_confirmation' ) ) {
$pledge_id = filter_input( INPUT_GET, 'pledge_id', FILTER_VALIDATE_INT );
$complete = true;
Email\send_pledge_confirmation_email( $pledge_id, get_post()->ID );
} }
ob_start(); ob_start();
@ -106,44 +99,6 @@ function process_form_new() {
return $new_pledge_id; return $new_pledge_id;
} }
/**
* Process a request to confirm a company's email address.
*
* @param int $pledge_id
* @param string $action
* @param array $unverified_token
*
* @return bool
*/
function process_pledge_confirmation_email( $pledge_id, $action, $unverified_token ) {
$meta_key = PledgeMeta\META_PREFIX . 'pledge-email-confirmed';
$already_confirmed = get_post( $pledge_id )->$meta_key;
if ( $already_confirmed ) {
/*
* If they refresh the page after confirming, they'd otherwise get an error because the token had been
* used, and might be confused and think that the address wasn't confirmed.
*
* This leaks the fact that the address is confirmed, because it will return true even if the token is
* invalid, but there aren't any security/privacy implications of that.
*/
return true;
}
$email_confirmed = Auth\is_valid_authentication_token( $pledge_id, $action, $unverified_token );
if ( $email_confirmed ) {
update_post_meta( $pledge_id, $meta_key, true );
wp_update_post( array(
'ID' => $pledge_id,
'post_status' => 'publish',
) );
Email\send_contributor_confirmation_emails( $pledge_id );
}
return $email_confirmed;
}
/** /**
* Render the form(s) for managing existing pledges. * Render the form(s) for managing existing pledges.
* *
@ -182,6 +137,11 @@ function render_form_manage() {
$errors = $results->get_error_messages(); $errors = $results->get_error_messages();
} else { } else {
$messages = array( __( 'Your pledge has been updated.', 'wporg-5ftf' ) ); $messages = array( __( 'Your pledge has been updated.', 'wporg-5ftf' ) );
$meta_key = PledgeMeta\META_PREFIX . 'pledge-email-confirmed';
if ( ! get_post( $pledge_id )->$meta_key ) {
$messages[] = __( 'You must confirm your new email address before it will be visible.', 'wporg-5ftf' );
}
} }
} }
@ -260,6 +220,96 @@ function process_form_manage( $pledge_id, $auth_token ) {
return true; return true;
} }
/**
* Process a request to confirm a company's email address.
*
* @param string|false $value Short-circuit return value.
* @param string $tag Shortcode name.
*
* @return bool|string
*/
function process_confirmed_email( $value, $tag ) {
if ( ! in_array( $tag, [ '5ftf_pledge_form_new', '5ftf_pledge_form_manage' ] ) ) {
return $value;
}
$action = sanitize_text_field( $_REQUEST['action'] ?? '' );
if ( 'confirm_pledge_email' !== $action ) {
return $value;
}
$pledge_id = filter_input( INPUT_GET, 'pledge_id', FILTER_VALIDATE_INT );
$auth_token = filter_input( INPUT_GET, 'auth_token', FILTER_SANITIZE_STRING );
$meta_key = PledgeMeta\META_PREFIX . 'pledge-email-confirmed';
$already_confirmed = get_post( $pledge_id )->$meta_key;
$email_confirmed = false;
$is_new_pledge = '5ftf_pledge_form_new' === $tag;
if ( $already_confirmed ) {
/*
* If they refresh the page after confirming, they'd otherwise get an error because the token had been
* used, and might be confused and think that the address wasn't confirmed.
*
* This leaks the fact that the address is confirmed, because it will return true even if the token is
* invalid, but there aren't any security/privacy implications of that.
*/
$email_confirmed = true;
}
$email_confirmed = Auth\is_valid_authentication_token( $pledge_id, $action, $auth_token );
if ( $email_confirmed ) {
update_post_meta( $pledge_id, $meta_key, true );
wp_update_post( array(
'ID' => $pledge_id,
'post_status' => 'publish',
) );
if ( $is_new_pledge ) {
Email\send_contributor_confirmation_emails( $pledge_id );
}
}
ob_start();
$directory_url = home_url( 'pledges' );
$pledge = get_post( $pledge_id );
require FiveForTheFuture\get_views_path() . 'form-pledge-confirm-email.php';
return ob_get_clean();
}
/**
* Process a request to resed a company's confirmation email.
*
* @param string|false $value Short-circuit return value.
* @param string $tag Shortcode name.
*
* @return bool|string
*/
function process_resend_confirm_email( $value, $tag ) {
if ( ! in_array( $tag, [ '5ftf_pledge_form_new', '5ftf_pledge_form_manage' ] ) ) {
return $value;
}
$action = sanitize_text_field( $_REQUEST['action'] ?? '' );
if ( 'resend_pledge_confirmation' !== $action ) {
return $value;
}
$pledge_id = filter_input( INPUT_GET, 'pledge_id', FILTER_VALIDATE_INT );
Email\send_pledge_confirmation_email( $pledge_id, get_post()->ID );
$messages = array(
sprintf(
__( 'Weve emailed you a new link to confirm your address for %s.', 'wporg-5ftf' ),
get_the_title( $pledge_id )
),
);
ob_start();
require FiveForTheFuture\get_views_path() . 'partial-result-messages.php';
return ob_get_clean();
}
/** /**
* Get and sanitize $_POST values from a form submission. * Get and sanitize $_POST values from a form submission.
* *

View file

@ -280,10 +280,11 @@ function save_pledge( $pledge_id, $pledge ) {
save_pledge_meta( $pledge_id, $submitted_meta ); save_pledge_meta( $pledge_id, $submitted_meta );
// Fired if the "Resend Confirmation" button was clicked in wp-admin.
if ( filter_input( INPUT_POST, 'resend-pledge-confirmation' ) ) { if ( filter_input( INPUT_POST, 'resend-pledge-confirmation' ) ) {
Email\send_pledge_confirmation_email( Email\send_pledge_confirmation_email(
filter_input( INPUT_GET, 'resend-pledge-id', FILTER_VALIDATE_INT ), filter_input( INPUT_GET, 'resend-pledge-id', FILTER_VALIDATE_INT ),
get_page_by_path( 'for-organizations' )->ID get_page_by_path( 'manage-pledge' )->ID
); );
} }
} }
@ -350,8 +351,15 @@ function update_generated_meta( $meta_id, $object_id, $meta_key, $_meta_value )
update_post_meta( $object_id, META_PREFIX . 'org-domain', $domain ); update_post_meta( $object_id, META_PREFIX . 'org-domain', $domain );
break; break;
case META_PREFIX . 'pledge-email': case META_PREFIX . 'org-pledge-email':
$landing_page = get_page_by_path( 'manage-pledge' )->ID;
Email\send_pledge_confirmation_email( $object_id, $landing_page );
delete_post_meta( $object_id, META_PREFIX . 'pledge-email-confirmed' ); delete_post_meta( $object_id, META_PREFIX . 'pledge-email-confirmed' );
// Flip pledge back to pending.
wp_update_post( array(
'ID' => $object_id,
'post_status' => 'pending',
) );
break; break;
} }
} }

View file

@ -4,8 +4,9 @@ namespace WordPressDotOrg\FiveForTheFuture\View;
use WP_Post; use WP_Post;
/** /**
* @var bool $email_confirmed
* @var string $directory_url * @var string $directory_url
* @var bool $email_confirmed
* @var bool $is_new_pledge
* @var int $pledge_id * @var int $pledge_id
* @var WP_Post|null $pledge * @var WP_Post|null $pledge
*/ */
@ -16,10 +17,17 @@ use WP_Post;
<div class="notice notice-success notice-alt"> <div class="notice notice-success notice-alt">
<p> <p>
<?php <?php
if ( $is_new_pledge ) {
printf( printf(
wp_kses_post( __( 'Thank you for confirming your address! Weve emailed confirmation links to the contributors you mentioned, and your pledge will show up in <a href=\"%s\">the directory</a> once one contributor confirms their participation.', 'wporg-5ftf' ) ), wp_kses_post( __( 'Thank you for confirming your address! Weve emailed confirmation links to the contributors you mentioned, and your pledge will show up in <a href=\"%s\">the directory</a> once one contributor confirms their participation.', 'wporg-5ftf' ) ),
esc_url( $directory_url ) esc_url( $directory_url )
); );
} else {
printf(
wp_kses_post( __( 'Thank you for confirming your address! If you have confirmed contributors, your pledge is visible in <a href=\"%s\">the directory</a> again. Otherwise, your pledge wiill show up once one contributor confirms their participation.', 'wporg-5ftf' ) ),
esc_url( $directory_url )
);
}
?> ?>
</p> </p>
@ -54,11 +62,11 @@ use WP_Post;
<form action="" method="get"> <form action="" method="get">
<input type="hidden" name="pledge_id" value="<?php echo esc_attr( $pledge_id ); ?>" /> <input type="hidden" name="pledge_id" value="<?php echo esc_attr( $pledge_id ); ?>" />
<input type="hidden" name="action" value="resend_pledge_confirmation" />
<p> <p>
<input <input
type="submit" type="submit"
name="resend_pledge_confirmation"
value="Resend Confirmation" value="Resend Confirmation"
/> />
</p> </p>

View file

@ -23,6 +23,7 @@ require __DIR__ . '/partial-result-messages.php';
wp_nonce_field( 'manage_pledge_' . $pledge_id ); wp_nonce_field( 'manage_pledge_' . $pledge_id );
require get_views_path() . 'inputs-pledge-org-info.php'; require get_views_path() . 'inputs-pledge-org-info.php';
require get_views_path() . 'inputs-pledge-org-email.php';
?> ?>
<div> <div>

View file

@ -25,9 +25,16 @@ use WP_Post;
aria-describedby="5ftf-pledge-email-help" aria-describedby="5ftf-pledge-email-help"
<?php echo $readonly ? 'readonly' : ''; ?> <?php echo $readonly ? 'readonly' : ''; ?>
/> />
<p id="5ftf-pledge-email-help"> <div id="5ftf-pledge-email-help">
<p>
<?php esc_html_e( 'This address will be used to confirm your organizations contribution profile, and later manage any changes. Please make sure that its a group address (e.g., wp-contributors@example.com) so that it persists across employee transitions.', 'wporg-5ftf' ); ?> <?php esc_html_e( 'This address will be used to confirm your organizations contribution profile, and later manage any changes. Please make sure that its a group address (e.g., wp-contributors@example.com) so that it persists across employee transitions.', 'wporg-5ftf' ); ?>
</p> </p>
<?php if ( ! empty( $data['org-pledge-email'] ) ) : ?>
<p>
<?php esc_html_e( 'If you change this email, you will need to confirm the new email. Your pledge will be unpublished until the new email is confirmed.', 'wporg-5ftf' ); ?>
</p>
<?php endif; ?>
</div>
<?php if ( is_admin() ) : ?> <?php if ( is_admin() ) : ?>
<?php if ( $data['pledge-email-confirmed'] ) : ?> <?php if ( $data['pledge-email-confirmed'] ) : ?>

View file

@ -29,7 +29,7 @@
height: auto; height: auto;
} }
> p { [id*="help"] p {
margin-top: ms(-5); margin-top: ms(-5);
font-size: ms(-2); font-size: ms(-2);
} }