Skip to content

Commit

Permalink
Merge branch 'main' into 1.0.X
Browse files Browse the repository at this point in the history
  • Loading branch information
mbish committed Feb 13, 2024
2 parents 3403735 + 4563d77 commit 38c798f
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 29 deletions.
113 changes: 84 additions & 29 deletions class-duouniversal-settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public function __construct(
) {
$this->duo_utils = $duo_utils;
}
function duo_settings_page() {
public function duo_settings_page() {
$this->duo_utils->duo_debug_log( 'Displaying duo setting page' );
?>
<div class="wrap">
Expand All @@ -48,12 +48,12 @@ function duo_settings_page() {
<?php
}

function duo_settings_client_id() {
public function duo_settings_client_id() {
$client_id = \esc_attr( $this->duo_utils->duo_get_option( 'duoup_client_id' ) );
return "<input id='duoup_client_id' name='duoup_client_id' size='40' type='text' value='" . \esc_attr( $client_id ) . "' />";
}

function duoup_client_id_validate( $client_id ) {
public function duoup_client_id_validate( $client_id ) {
$client_id = sanitize_text_field( $client_id );
if ( strlen( $client_id ) !== 20 ) {
\add_settings_error( 'duoup_client_id', '', __( 'Client ID is not valid', 'duo-universal' ) );
Expand All @@ -67,7 +67,7 @@ function duoup_client_id_validate( $client_id ) {
}
}

function duo_settings_client_secret() {
public function duo_settings_client_secret() {
$client_secret = \esc_attr( $this->duo_utils->duo_get_option( 'duoup_client_secret' ) );
if ( $client_secret ) {
$value = SECRET_PLACEHOLDER;
Expand All @@ -77,7 +77,7 @@ function duo_settings_client_secret() {
return "<input id='duoup_client_secret' name='duoup_client_secret' size='40' type='password' value='" . \esc_attr( $value ) . "' autocomplete='off' />";
}

function duoup_client_secret_validate( $client_secret ) {
public function duoup_client_secret_validate( $client_secret ) {
$client_secret = sanitize_text_field( $client_secret );
$current_secret = \esc_attr( $this->duo_utils->duo_get_option( 'duoup_client_secret' ) );
if ( strlen( $client_secret ) !== 40 ) {
Expand All @@ -94,12 +94,12 @@ function duoup_client_secret_validate( $client_secret ) {
}
}

function duo_settings_host() {
public function duo_settings_host() {
$host = \esc_attr( $this->duo_utils->duo_get_option( 'duoup_api_host' ) );
return "<input id='duoup_api_host' name='duoup_api_host' size='40' type='text' value='" . \esc_attr( $host ) . "' />";
}

function duoup_api_host_validate( $host ) {
public function duoup_api_host_validate( $host ) {
$host = sanitize_text_field( $host );
if ( ! preg_match( '/^api-[a-zA-Z\d\.-]*/', $host ) || str_starts_with( $host, 'api-api-' ) ) {
\add_settings_error( 'duoup_api_host', '', __( 'Host is not valid', 'duo-universal' ) );
Expand All @@ -113,7 +113,7 @@ function duoup_api_host_validate( $host ) {
return $host;
}

function duo_settings_failmode() {
public function duo_settings_failmode() {
$failmode = \esc_attr( $this->duo_utils->duo_get_option( 'duoup_failmode', 'open' ) );
$result = '';
$result .= '<select id="duoup_failmode" name="duoup_failmode" />';
Expand All @@ -128,7 +128,7 @@ function duo_settings_failmode() {
return $result;
}

function duoup_failmode_validate( $failmode ) {
public function duoup_failmode_validate( $failmode ) {
$failmode = sanitize_text_field( $failmode );
if ( ! in_array( $failmode, array( 'open', 'closed' ), true ) ) {
add_settings_error( 'duoup_failmode', '', __( 'Failmode value is not valid', 'duo-universal' ) );
Expand All @@ -138,7 +138,7 @@ function duoup_failmode_validate( $failmode ) {
return $failmode;
}

function duo_settings_roles() {
public function duo_settings_roles() {
$wp_roles = $this->duo_utils->duo_get_roles();
$roles = $wp_roles->get_names();
$newroles = array();
Expand All @@ -163,14 +163,16 @@ function duo_settings_roles() {
'<br />' ),
\esc_attr( $key ),
\esc_attr( $role ),
in_array( $role, $selected, true ) ? 'checked' : '',
// we have to use checked=true here because wp_kses doesn't
// handle boolean attributes
in_array( $role, $selected, true ) ? 'checked=true' : '',
\esc_html( $role )
);
}
return $result;
}

function duoup_roles_validate( $options ) {
public function duoup_roles_validate( $options ) {
// return empty array.
if ( ! is_array( $options ) || empty( $options ) || ( false === $options ) ) {
return array();
Expand All @@ -189,40 +191,42 @@ function duoup_roles_validate( $options ) {
return $options;
}

function duo_settings_text() {
public function duo_settings_text() {
printf( '<p>%s</p>', \esc_html__( 'To use this plugin you must have an account with Duo Security.', 'duo-universal' ) );
printf( '<p>%s</p>', \esc_html__( 'See the Duo for WordPress guide to enable Duo two-factor authentication for your WordPress logins.', 'duo-universal' ) );
printf( "<a target='_blank' href='https://www.duosecurity.com/docs/wordpress'>%s</a>", \esc_html__( 'Duo for WordPress guide', 'duo-universal' ) );
printf( '<p>%s</p>', \esc_html__( 'You can retrieve your Client ID, Client Secret, and API hostname by logging in to the Duo Admin Panel.', 'duo-universal' ) );
printf( '<p>%s</p>', \esc_html__( 'Note: After enabling the plugin, you will be immediately prompted for second factor authentication.', 'duo-universal' ) );
}

function duo_settings_xmlrpc() {
public function duo_settings_xmlrpc() {
$val = '';
if ( $this->duo_utils->duo_get_option( 'duoup_xmlrpc', 'off' ) === 'off' ) {
$val = 'checked';
// we have to use checked=true here because wp_kses doesn't
// handle boolean attributes
$val = 'checked=true';
}
$result = sprintf( "<input id='duoup_xmlrpc' name='duoup_xmlrpc' type='checkbox' value='off' %s /> %s<br />", \esc_attr( $val ), \esc_html__( 'Yes', 'duo-universal' ) );
$result .= \esc_html__( 'Using XML-RPC bypasses two-factor authentication and makes your website less secure. We recommend only using the WordPress web interface for managing your WordPress website.', 'duo-universal' );
return $result;
}

function duoup_xmlrpc_validate( $option ) {
public function duoup_xmlrpc_validate( $option ) {
$option = sanitize_text_field( $option );
if ( 'off' === $option ) {
return $option;
}
return 'on';
}

function duo_add_link( $links ) {
public function duo_add_link( $links ) {
$settings_link = sprintf( '<a href="options-general.php?page=duo_universal">%s</a>', \esc_html__( 'Settings', 'duo-universal' ) );
array_unshift( $links, $settings_link );
return $links;
}


function duo_add_page() {
public function duo_add_page() {
if ( ! is_multisite() ) {
add_options_page(
__( 'Duo Universal', 'duo-universal' ),
Expand All @@ -235,15 +239,15 @@ function duo_add_page() {
}


function duo_add_site_option( $option, $value = '' ) {
public function duo_add_site_option( $option, $value = '' ) {
// Add multisite option only if it doesn't exist already
// With WordPress versions < 3.3, calling add_site_option will override old values.
if ( $this->duo_utils->duo_get_option( $option ) === false ) {
\add_site_option( $option, $value );
}
}

function duoup_add_settings_field( $id, $title, $callback, $sanitize_callback, $text ) {
public function duoup_add_settings_field( $id, $title, $callback, $sanitize_callback, $text ) {
\add_settings_field(
$id,
$title,
Expand All @@ -258,12 +262,35 @@ function duoup_add_settings_field( $id, $title, $callback, $sanitize_callback, $
\register_setting( 'duo_universal_settings', $id, $sanitize_callback );
}

function printing_callback( $text ) {
// I wish we didn't need this but 'echo' is not a valid callback.
echo $text['text'];
public function printing_callback( $text ) {
echo(
\wp_kses(
$text['text'],
array(
'input' => array(
'id' => array(),
'name' => array(),
'size' => array(),
'type' => array(),
'value' => array(),
'autocomplete' => array(),
'checked' => array(),
),
'select' => array(
'id' => array(),
'name' => array(),
),
'option' => array(
'value' => array(),
'selected' => array(),
),
'br' => array(),
),
)
);
}

function duo_admin_init() {
public function duo_admin_init() {
if ( is_multisite() ) {
$wp_roles = $this->duo_utils->duo_get_roles();
$roles = $wp_roles->get_names();
Expand All @@ -289,16 +316,44 @@ function duo_admin_init() {
}
}

function print_field( $id, $label, $input ) {
printf( "<tr><th><label for='%s'>%s</label></th><td>%s</td></tr>\n", \esc_attr( $id ), \esc_html( $label ), $input );
public function print_field( $id, $label, $input ) {
printf(
"<tr><th><label for='%s'>%s</label></th><td>%s</td></tr>\n",
\esc_attr( $id ),
\esc_html( $label ),
\wp_kses(
$input,
array(
'input' => array(
'id' => array(),
'name' => array(),
'size' => array(),
'type' => array(),
'value' => array(),
'autocomplete' => array(),
'checked' => array(),
),
'select' => array(
'id' => array(),
'name' => array(),
),
'option' => array(
'value' => array(),
'selected' => array(),
),
'br' => array(),
),
)
);
}

function duo_mu_options() {
public function duo_mu_options() {
$this->duo_utils->duo_debug_log( 'Displaying multisite settings' );

printf( "<h3>%s</h3>\n", \esc_html__( 'Duo Security', 'duo-universal' ) );
echo( "<table class='form-table'>\n" );
printf( "%s</td></tr>\n", $this->duo_settings_text() );
$this->duo_settings_text();
printf( "</td></tr>\n" );
$this->print_field( 'duoup_client_id', \__( 'Client ID', 'duo-universal' ), $this->duo_settings_client_id() );
$this->print_field( 'duoup_client_secret', \__( 'Client Secret', 'duo-universal' ), $this->duo_settings_client_secret() );
$this->print_field( 'duoup_api_host', \__( 'API hostname', 'duo-universal' ), $this->duo_settings_host() );
Expand All @@ -308,7 +363,7 @@ function duo_mu_options() {
echo( "</table>\n" );
}

function duo_update_mu_options() {
public function duo_update_mu_options() {
check_admin_referer( 'siteoptions' );

if ( isset( $_POST['duoup_client_id'] ) ) {
Expand Down
1 change: 1 addition & 0 deletions tests/duoUniversalSettingsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,7 @@ public function testSettingsInputLabelsForMultisite(): void
// Return the default value provided to duo_get_option
$this->duo_utils->method('duo_get_option')->will($this->returnArgument(1));
WP_Mock::passthruFunction('before_last_bar');
WP_Mock::passthruFunction('wp_kses');
WP_Mock::userFunction('__', [ 'return_arg' => 0, ]);

$this->expectOutputRegex("/<label for='duoup_client_id'>Client ID<\/label>/");
Expand Down

0 comments on commit 38c798f

Please sign in to comment.