Files
rohnenedre/wp-content/plugins/wpclef/includes/class.clef-login.php

444 lines
18 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
require_once(CLEF_PATH . 'includes/class.clef-invite.php');
class ClefLogin {
private static $instance = null;
private $settings;
private function __construct($settings) {
$this->settings = $settings;
$this->initialize_hooks();
}
public function initialize_hooks() {
add_action('init', array($this, 'initialize_state'));
// Authenticate with Clef is there is a valid OAuth code present
add_action('authenticate', array($this, 'authenticate_clef'), 10, 3);
// Disable password authentication according to settings
add_action('wp_authenticate_user', array($this, 'disable_passwords'));
// Clear logout hook if the user is logging in again
add_filter('wp_authenticate_user', array($this, 'clear_logout_hook'));
// Connect Clef account if logging in with a clef ID
add_filter('wp_authenticate_user', array($this, 'connect_clef_account_on_login'));
// Check if account was connected on login and if so flash a success message
add_action('admin_notices', array($this, 'display_connect_clef_account_success'));
// adds classes which hide login form if appropriate
add_action('login_body_class', array($this, 'add_login_form_classes' ));
// Render the login form with the Clef button no matter what
add_action('login_form', array( $this, 'login_form' ) );
add_action('register_form', array( $this, 'register_form') );
add_filter('wp_login_failed', array($this, 'handle_login_failed'));
add_action('login_enqueue_scripts', array($this, 'load_base_styles'));
// Show an error message if there is an invite code but it is invalid
add_filter('login_message', array($this, 'validate_invite'));
// Disable password reset, according to settings
add_filter('allow_password_reset', array($this, 'disable_password_reset'), 10, 2);
// Redirect to an Clef onboarding page if a user logs in with an invite
// code
add_filter('login_redirect', array($this, 'redirect_if_invite_code'), 10, 3);
// Allow the Clef button to be rendered anywhere
add_action('clef_render_login_button', array($this, 'render_login_button'), 10, 4);
add_shortcode('clef_render_login_button', array($this, 'shortcode_render_login_button'));
if (defined('MEMBERSHIP_MASTER_ADMIN') && defined('MEMBERSHIP_SETACTIVATORAS_ADMIN')) {
add_action('signup_hidden_fields', array($this, 'add_clef_login_button_to_wpmu'));
add_action('bp_before_account_details_fields', array($this, 'add_clef_login_button_to_wpmu'));
add_action('membership_popover_extend_registration_form', array($this, 'add_clef_login_button_to_wpmu'));
add_action('signup_extra_fields', array($this, 'add_clef_login_button_to_wpmu'));
add_action('membership_popover_extend_login_form', array($this, 'add_clef_login_button_to_wpmu'));
}
$this->apply_filter_and_action_fixes('plugins_loaded');
}
public function add_clef_login_button_to_wpmu() {
if ($this->settings->is_configured()) {
$_REQUEST['redirect_to'] = $redirect_url = apply_filters('wdfb_registration_redirect_url', '');
do_action('clef_render_login_button');
}
}
public function load_base_styles() {
$ident = ClefUtils::register_style('main');
wp_enqueue_style($ident);
$ident = ClefUtils::register_script('login');
wp_enqueue_script($ident);
if (!has_action('login_enqueue_scripts', 'wp_print_styles'))
add_action('login_enqueue_scripts', 'wp_print_styles', 11);
}
public function redirect_if_invite_code($redirect_to, $request, $user) {
if (isset($_REQUEST['clef_invite_code'])) {
$invite_code = $_REQUEST['clef_invite_code'];
$invite_email = base64_decode(ClefUtils::isset_GET('clef_invite_id'));
$error = $this->validate_invite_code($invite_code, $invite_email);
if (!$error) {
return admin_url('admin.php?page=connect_clef_account');
}
}
return $redirect_to;
}
public function validate_invite($message) {
$invite_code = ClefUtils::isset_GET('clef_invite_code');
$invite_email = base64_decode(ClefUtils::isset_GET('clef_invite_id'));
$error = $this->validate_invite_code($invite_code, $invite_email);
if ($invite_code && $error) {
return '<div id="login_error">' . $error . '</div>';
} else {
return $message;
}
}
public function login_form() {
if($this->settings->is_configured()) {
$redirect_url = $this->get_callback_url();
$passwords_disabled = $this->settings->get('clef_password_settings_force');
$override_key = ClefUtils::isset_GET('override');
if (!$this->is_valid_override_key($override_key)) {
$override_key = null;
}
$invite_code = ClefUtils::isset_GET('clef_invite_code');
$invite_email_encoded = ClefUtils::isset_GET('clef_invite_id');
if (!$this->has_valid_invite_code()) {
$invite_code = null;
$invite_email = null;
} else {
$redirect_url = add_query_arg(array( 'invite_code' => $invite_code), $redirect_url);
}
$app_id = $this->settings->get( 'clef_settings_app_id' );
$clef_embedded = $this->settings->should_embed_clef_login();
if (ClefUtils::isset_GET('clefup') == 'true') $clef_embedded = false;
echo ClefUtils::render_template('login.tpl', array(
"passwords_disabled" => $passwords_disabled,
"clef_embedded" => $clef_embedded,
"override_key" => $override_key,
"redirect_url" => $redirect_url,
"invite_code" => $invite_code,
"invite_email" => $invite_email_encoded,
"clef_id" => (isset($this->clef_id_to_connect) ? $this->clef_id_to_connect : false),
"app_id" => $app_id
));
}
}
public function register_form() {
if ($this->settings->is_configured() && $this->settings->registration_with_clef_is_allowed()) {
echo ClefUtils::render_template('register.tpl', array(
"redirect_url" => $this->get_callback_url(),
"app_id" => $this->settings->get( 'clef_settings_app_id' )
));
}
}
public function shortcode_render_login_button($atts) {
$app_id = isset($atts['app_id']) ? $atts['app_id'] : false;
$redirect_url = isset($atts['redirect_url']) ? $atts['redirect_url'] : false;
$embed = isset($atts['embed']) ? $atts['embed'] : false;
$type = isset($atts['type']) ? $atts['type'] : "login";
ob_start();
$this->render_login_button($redirect_url, $app_id, $embed);
$output = ob_get_contents();
ob_end_clean();
return $output;
}
public function render_login_button($redirect_url=false, $app_id=false, $embed=false, $type="login") {
if (!$app_id) $app_id = $this->settings->get( 'clef_settings_app_id' );
if (!$redirect_url) $redirect_url = $this->get_callback_url();
echo ClefUtils::render_template('button.tpl', array(
"app_id" => $app_id,
"redirect_url" => $redirect_url,
"embed" => $embed,
"type" => $type,
"custom" => array(
"logo" => $this->settings->get('customization_logo'),
"message" => $this->settings->get('customization_message')
)
));
}
public function handle_login_failed($errors) {
if (isset($_POST['override'])) {
// if the person submitted an override before, automatically
// submit it for them the next time
$_GET['override'] = $_POST['override'];
}
}
private function is_valid_override_key($override_key) {
$valid_key = $this->settings->get( 'clef_override_settings_key' );
$is_valid_override_key =
(!empty($valid_key) &&
!empty($override_key) &&
$valid_key != '' &&
$override_key != '' &&
$override_key === $valid_key);
return $is_valid_override_key;
}
private function validate_invite_code($incoming_invite_code, $email) {
$generic_error_message = __("Sorry, that isn't a valid invite code.", "clef");
if (!$incoming_invite_code || !$email) {
return $generic_error_message;
}
$user = get_user_by('email', $email);
if (empty($user)) {
return $generic_error_message;
}
return $this->validate_invite_code_for_user($incoming_invite_code, $user);
}
private function validate_invite_code_for_user($incoming_invite_code, $user) {
$invite_code = get_user_meta($user->ID, 'clef_invite_code', true);
$three_days_ago = time() - 3 * 24 * 60 * 60;
if (empty($invite_code) ||
($invite_code->created_at < $three_days_ago) ||
($invite_code->code !== $incoming_invite_code)) {
return __("Sorry, this invite link has expired. Please contact your administrator for a new one.", "clef");
}
}
public function add_login_form_classes($classes) {
if (!$this->settings->is_configured()) return $classes;
array_push($classes, 'clef-login-form');
$override_key = ClefUtils::isset_GET('override');
$valid_override_or_invite = $this->is_valid_override_key($override_key) || $this->has_valid_invite_code();
if ($valid_override_or_invite) {
array_push($classes, 'clef-override-or-invite');
}
if ($this->settings->get( 'clef_password_settings_force' )) {
array_push($classes, 'clef-hidden');
}
if (isset($this->clef_id_to_connect)) {
array_push($classes, 'clef-auto-connect-account');
}
if ($this->settings->should_embed_clef_login()) {
array_push($classes, 'clef-login-form-embed');
}
// used to show username and password form in worst case scenario
// where javascript fails and on-page toggle fails
$show_username_password_form = ClefUtils::isset_GET('clefup') == 'true';
if ($show_username_password_form) {
array_push($classes, 'clef-show-username-password');
}
return $classes;
}
private function has_valid_invite_code() {
if (!isset($_REQUEST['clef_invite_code']) || !isset($_REQUEST['clef_invite_id'])) {
return false;
}
$incoming_invite_code = $_REQUEST['clef_invite_code'];
$invite_email = base64_decode($_REQUEST['clef_invite_id']);
if (!$incoming_invite_code || !$invite_email) {
return false;
}
$error = $this->validate_invite_code($incoming_invite_code, $invite_email);
return !$error;
}
public function disable_passwords($user) {
if (isset($_POST['override']) && $this->is_valid_override_key($_POST['override'])) {
return $user;
}
if ($this->has_valid_invite_code()) {
return $user;
}
$disabled_for_user = $this->settings->passwords_are_disabled_for_user($user);
$disabled_for_xml_rpc = !(defined('XMLRPC_REQUEST') && XMLRPC_REQUEST && $this->settings->xml_passwords_enabled());
if ($disabled_for_user && $disabled_for_xml_rpc) {
add_filter('xmlrpc_login_error', array($this, "return_xml_error_message"));
return new WP_Error('passwords_disabled', __("Passwords have been disabled for this user.", "clef"));
} else {
return $user;
}
}
public function authenticate_clef($user, $username, $password) {
if ( isset( $_REQUEST['clef'] ) && isset( $_REQUEST['code'] ) ) {
$this->apply_filter_and_action_fixes("authenticate");
// Authenticate
try {
$info = ClefUtils::exchange_oauth_code_for_info($_REQUEST['code'], $this->settings);
} catch (LoginException $e) {
return new WP_Error('clef', $e->getMessage());
} catch (ClefStateException $e) {
return new WP_Error('clef', $e->getMessage());
}
$clef_id = $info->id;
$email = isset($info->email) ? $info->email : "";
$first_name = isset($info->first_name) ? $info->first_name : "";
$last_name = isset($info->last_name) ? $info->last_name : "";
$users = get_users(array('meta_key' => 'clef_id', 'meta_value' => $clef_id, 'blog_id' => false));
if ($users) {
// already have a user with this clef_id
$user = $users[0];
} else {
$user = get_user_by('email', $email);
if (!$user) {
if (get_option('users_can_register') && $this->settings->registration_with_clef_is_allowed()) {
// Users can register, so create a new user
$id = wp_create_user($email, wp_generate_password(16, FALSE), $email);
if(is_wp_error($id)) {
return new WP_Error(
'clef',
__("An error occurred when creating your new account: ", 'clef') . $id->get_error_message()
);
}
$user = get_user_by('id', $id );
} else {
$this->clef_id_to_connect = $clef_id;
return new WP_Error(
'clef',
__("There's <b>no WordPress user</b> connected to your Clef account. <br></br> Log in with your standard username and password to <b>automatically connect your Clef account</b> now.", 'clef')
);
}
}
ClefUtils::associate_clef_id($clef_id, $user->ID);
}
do_action('clef_login', $user->ID);
// Log in the user
$session = ClefSession::start();
$session->set('logged_in_at', time());
return $user;
} else {
return $user;
}
}
public function disable_password_reset($allow, $user_id) {
$user = get_user_by('id', (int) $user_id);
return !$this->settings->passwords_are_disabled_for_user($user);
}
public function clear_logout_hook($user) {
$session = ClefSession::start();
if ($session->get('logged_in_at')) {
$session->set('logged_in_at', null);
}
return $user;
}
public function connect_clef_account_on_login($user) {
if (ClefUtils::isset_POST('clef_id') && $user && !is_wp_error($user)) {
ClefUtils::associate_clef_id(ClefUtils::isset_POST('clef_id'), $user->ID);
$session = ClefSession::start();
$session->set('clef_account_connected_on_login', true);
$session->set('logged_in_at', time());
}
return $user;
}
public function display_connect_clef_account_success() {
$session = ClefSession::start();
if ($session->get('clef_account_connected_on_login')) {
$session->set('clef_account_connected_on_login', null);
?>
<div class="updated clef-flash connect-clef-account-on-login-message">
<img src="<?php echo CLEF_URL . 'assets/dist/img/gradient_icon_32.png'?>" alt="Clef">
<p><?php _e('Success. <b>Your Clef account has been connected!</b>', 'clef'); ?></p>
</div>
<?php
}
}
public function return_xml_error_message() {
return new IXR_Error( 403, __("Passwords have been disabled for this user.", "clef") );
}
public function apply_filter_and_action_fixes($hook) {
if ($hook === "plugins_loaded") {
// Hack to make Clef work with theme my login. This works
// because Theme My Login only runs the login commands on their custom
// login page if the request is a POST. Could potentially cause
// other issues, so should be conscious of this.
if (isset($_REQUEST['clef']) && isset($_REQUEST['code']) && function_exists('is_plugin_active') && is_plugin_active('theme-my-login/theme-my-login.php')) {
$_SERVER['REQUEST_METHOD'] = 'POST';
$_POST['log'] = true;
}
}
if ($hook === "authenticate") {
// remove login filters that cause problems — not necessary if we're
// logging in with Clef. These filters suppress errors that
// this login function throws.
remove_filter('authenticate', 'dr_email_login_authenticate', 20, 3);
remove_filter('authenticate', 'wp_authenticate_username_password', 20, 3);
// remove google captcha filter that prevents redirect
remove_filter('login_redirect', 'gglcptch_login_check');
}
}
public function get_callback_url() {
$url = add_query_arg(array( 'clef' => 'true'), wp_login_url());
# add redirect to if it exists
if (isset($_REQUEST['redirect_to']) && $_REQUEST['redirect_to'] != '') {
$url = add_query_arg(
array('redirect_to' => urlencode($_REQUEST['redirect_to'])),
$url
);
}
if (isset($_REQUEST['interim-login'])) {
$url = add_query_arg(array('interim-login' => 1), $url);
}
return $url;
}
public function initialize_state() {
ClefUtils::initialize_state();
}
public static function start($settings) {
if (!isset(self::$instance) || self::$instance === null || defined('CLEF_TESTING')) {
self::$instance = new self($settings);
}
return self::$instance;
}
}
?>