├── .gitattributes ├── .gitignore ├── README.md ├── assets ├── css │ ├── admin.css │ ├── admin.less │ ├── frontend.css │ ├── frontend.less │ └── ussync-confirmation-email.css └── js │ ├── admin.js │ ├── admin.min.js │ ├── frontend.js │ ├── frontend.min.js │ ├── settings.js │ └── settings.min.js ├── includes ├── class-user-session-synchronizer-email-verification.php ├── class-user-session-synchronizer-session-control.php ├── class-user-session-synchronizer-settings.php ├── class-user-session-synchronizer.php ├── images │ ├── menu.png │ ├── right_arrow.png │ ├── send.png │ ├── time.png │ └── wrong_arrow.png ├── lib │ ├── class-user-session-synchronizer-admin-api.php │ ├── class-user-session-synchronizer-post-type.php │ └── class-user-session-synchronizer-taxonomy.php └── views │ ├── demo_email.html │ ├── email-setting.php │ ├── email-verification.php │ └── logging-in.php ├── index.php ├── lang └── user-session-synchronizer.pot ├── readme.txt ├── screenshot_1.png ├── screenshot_2.png ├── screenshot_3.png ├── screenshot_4.png ├── uninstall.php └── user-session-synchronizer.php /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.svn-base 2 | .svn/entries 3 | .svn/format -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Wordpress User Session Synchronizer 2 | 3 | Keep the user logged in from one wordpress to another by synchronizing user data and cookie session 4 | 5 | ## Description 6 | 7 | User Session Synchronizer allows you to keep the user logged in from one wordpress to another by synchronizing user data and cookie session based on a verified email. 8 | The user email is encrypted based on the current user ip and a secret key shared by the synchronized wordpress installations. 9 | 10 | ### Features 11 | 12 | - Synchronize session between installations 13 | - Verify user email through new registration 14 | - Verify user email through manual admin action 15 | - Verify user email through email verification code 16 | - Prevent user form changing email 17 | - Display historical sessions 18 | - Auto add new subscriber if user doesn't exist 19 | - Destroy session everywhere on logging out 20 | 21 | ### Upcoming 22 | 23 | - Multiple secret keys & networks 24 | - Enable ajax cross-domain requests 25 | 26 | ## Installation 27 | 28 | Installing "User Session Synchronizer" can be done either by searching for "User Session Synchronizer" via the "Plugins > Add New" screen in your WordPress dashboard, or by using the following steps: 29 | 30 | 1. Download the plugin via WordPress.org 31 | 2. Upload the ZIP file through the 'Plugins > Add New > Upload' screen in your WordPress dashboard 32 | 3. Activate the plugin through the 'Plugins' menu in WordPress 33 | 4. Set your first Secret Key throught the 'User Session Sync > Keys' 34 | 5. Repeat this installation process for every Wordpress you wish to sychnorize with the same Secret Key 35 | 36 | ## Screenshots 37 | 38 | ![Screenshot](https://raw.githubusercontent.com/rafasashi/user-session-synchronizer/master/screenshot_1.png) 39 | ![Screenshot](https://raw.githubusercontent.com/rafasashi/user-session-synchronizer/master/screenshot_2.png) 40 | ![Screenshot](https://raw.githubusercontent.com/rafasashi/user-session-synchronizer/master/screenshot_3.png) 41 | ![Screenshot](https://raw.githubusercontent.com/rafasashi/user-session-synchronizer/master/screenshot_4.png) 42 | 43 | ## Information 44 | 45 | - Contributors: rafasashi 46 | - Donate link: https://www.paypal.me/recuweb 47 | - Tags: user, session, synchronizer, cookie 48 | - Requires at least: 4.3 49 | - Tested up to: 4.7 50 | - Stable tag: 1.3.8 51 | - License: GPLv3 or later 52 | - License URI: http://www.gnu.org/licenses/gpl-3.0.html 53 | 54 | ## Frequently Asked Questions 55 | 56 | ### What is the plugin template for? 57 | 58 | This plugin template is designed to Keep the user logged in from one wordpress to another by synchronizing user data and cookie session 59 | 60 | ## Changelog ## 61 | 62 | ### 1.3.8 63 | 64 | * 2017-05-26 65 | * logout bug fixed 66 | 67 | ### 1.3.7 68 | 69 | * 2017-05-16 70 | * activate plugin email fixed 71 | 72 | ### 1.3.6 73 | 74 | * 2017-03-14 75 | * Logout everywhere fixed 76 | * Infinit loop fixed on SSL auth 77 | 78 | ### 1.3.5 79 | 80 | * 2017-02-09 81 | * Content-Security-Policy implementation 82 | * HTTPS supported 83 | 84 | ### 1.3.4 85 | 86 | * 2017-01-27 87 | * User IP detection improved 88 | * Synchronization via iframe instead of image 89 | 90 | ### 1.3.3 91 | 92 | * 2016-10-26 93 | * Resend validation email improved 94 | 95 | ### 1.3.2 96 | 97 | * 2016-10-14 98 | * Issue regarding email validation corrected 99 | 100 | ### 1.3.1 101 | 102 | * 2016-09-26 103 | * Multiple Logout issues corrected 104 | 105 | ### 1.2 106 | * 2016-09-26 107 | * Multiple subfolders under same domain 108 | 109 | ### 1.1 110 | * 2016-09-22 111 | * Theme footer hooked 112 | 113 | ### 1.0 114 | * 2016-09-06 115 | * Initial release 116 | 117 | ## Upgrade Notice 118 | 119 | ### 1.0 120 | * 2016-09-06 121 | * Initial release 122 | -------------------------------------------------------------------------------- /assets/css/admin.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafasashi/user-session-synchronizer/ebc2ba63e33266448b6954c0343243e8b4e14250/assets/css/admin.css -------------------------------------------------------------------------------- /assets/css/admin.less: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafasashi/user-session-synchronizer/ebc2ba63e33266448b6954c0343243e8b4e14250/assets/css/admin.less -------------------------------------------------------------------------------- /assets/css/frontend.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafasashi/user-session-synchronizer/ebc2ba63e33266448b6954c0343243e8b4e14250/assets/css/frontend.css -------------------------------------------------------------------------------- /assets/css/frontend.less: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafasashi/user-session-synchronizer/ebc2ba63e33266448b6954c0343243e8b4e14250/assets/css/frontend.less -------------------------------------------------------------------------------- /assets/css/ussync-confirmation-email.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Plugin Name: User Session Synchronizer 3 | * Version: 1.0 4 | * Plugin URI: https://github.com/rafasashi/user-session-synchronizer/archive/master.zip 5 | * Description: Keep the user logged in from one wordpress to another by synchronizing user data and cookie session. 6 | * Author: Rafasashi 7 | * Author URI: https://www.linkedin.com/in/raphaeldartigues 8 | * Requires at least: 4.6 9 | * Tested up to: 4.6 10 | * 11 | * Text Domain: user-session-synchronizer 12 | * Domain Path: /lang/ 13 | * 14 | * @package WordPress 15 | * @author Rafasashi 16 | * @since 1.0.0 17 | */ 18 | 19 | 20 | #login_register{ 21 | padding: 0px; 22 | border: none; 23 | margin: 0px; 24 | } 25 | .confirm_box{ 26 | display: none; 27 | margin-bottom: 6px; 28 | } 29 | input#confirmdCode { 30 | width: 100%; 31 | margin-bottom: 4px; 32 | } 33 | input#confirmcode_button { 34 | width: 100%; 35 | padding: 5px; 36 | height: 36px; 37 | } 38 | #resendverifycode{ 39 | width: 100%; 40 | padding: 5px; 41 | height: 36px; 42 | display:none; 43 | } 44 | 45 | .row.error_box { 46 | display:none; 47 | color: red; 48 | margin: 0px; 49 | font-size: 13px; 50 | border: 1px solid #B3B3B3; 51 | padding: 4px; 52 | } 53 | .width33{ 54 | float:left; 55 | } 56 | .oknotice{ 57 | color: #248805; 58 | border: 1px solid #248805; 59 | font-size: 13px; 60 | padding-left: 3px; 61 | } -------------------------------------------------------------------------------- /assets/js/admin.js: -------------------------------------------------------------------------------- 1 | jQuery( document ).ready( function ( e ) { 2 | 3 | }); -------------------------------------------------------------------------------- /assets/js/admin.min.js: -------------------------------------------------------------------------------- 1 | jQuery(document).ready(function(){}); -------------------------------------------------------------------------------- /assets/js/frontend.js: -------------------------------------------------------------------------------- 1 | jQuery( document ).ready( function ( e ) { 2 | 3 | }); -------------------------------------------------------------------------------- /assets/js/frontend.min.js: -------------------------------------------------------------------------------- 1 | jQuery(document).ready(function(){}); -------------------------------------------------------------------------------- /assets/js/settings.js: -------------------------------------------------------------------------------- 1 | jQuery(document).ready(function($) { 2 | 3 | /***** Colour picker *****/ 4 | 5 | $('.colorpicker').hide(); 6 | $('.colorpicker').each( function() { 7 | $(this).farbtastic( $(this).closest('.color-picker').find('.color') ); 8 | }); 9 | 10 | $('.color').click(function() { 11 | $(this).closest('.color-picker').find('.colorpicker').fadeIn(); 12 | }); 13 | 14 | $(document).mousedown(function() { 15 | $('.colorpicker').each(function() { 16 | var display = $(this).css('display'); 17 | if ( display == 'block' ) 18 | $(this).fadeOut(); 19 | }); 20 | }); 21 | 22 | 23 | /***** Uploading images *****/ 24 | 25 | var file_frame; 26 | 27 | jQuery.fn.uploadMediaFile = function( button, preview_media ) { 28 | var button_id = button.attr('id'); 29 | var field_id = button_id.replace( '_button', '' ); 30 | var preview_id = button_id.replace( '_button', '_preview' ); 31 | 32 | // If the media frame already exists, reopen it. 33 | if ( file_frame ) { 34 | file_frame.open(); 35 | return; 36 | } 37 | 38 | // Create the media frame. 39 | file_frame = wp.media.frames.file_frame = wp.media({ 40 | title: jQuery( this ).data( 'uploader_title' ), 41 | button: { 42 | text: jQuery( this ).data( 'uploader_button_text' ), 43 | }, 44 | multiple: false 45 | }); 46 | 47 | // When an image is selected, run a callback. 48 | file_frame.on( 'select', function() { 49 | attachment = file_frame.state().get('selection').first().toJSON(); 50 | jQuery("#"+field_id).val(attachment.id); 51 | if( preview_media ) { 52 | jQuery("#"+preview_id).attr('src',attachment.sizes.thumbnail.url); 53 | } 54 | file_frame = false; 55 | }); 56 | 57 | // Finally, open the modal 58 | file_frame.open(); 59 | } 60 | 61 | jQuery('.image_upload_button').click(function() { 62 | jQuery.fn.uploadMediaFile( jQuery(this), true ); 63 | }); 64 | 65 | jQuery('.image_delete_button').click(function() { 66 | jQuery(this).closest('td').find( '.image_data_field' ).val( '' ); 67 | jQuery(this).closest('td').find( '.image_preview' ).remove(); 68 | return false; 69 | }); 70 | 71 | }); -------------------------------------------------------------------------------- /assets/js/settings.min.js: -------------------------------------------------------------------------------- 1 | jQuery(document).ready(function(e){e(".colorpicker").hide();e(".colorpicker").each(function(){e(this).farbtastic(e(this).closest(".color-picker").find(".color"))});e(".color").click(function(){e(this).closest(".color-picker").find(".colorpicker").fadeIn()});e(document).mousedown(function(){e(".colorpicker").each(function(){var t=e(this).css("display");t=="block"&&e(this).fadeOut()})});var t;jQuery.fn.uploadMediaFile=function(e,n){var r=e.attr("id"),i=r.replace("_button",""),s=r.replace("_button","_preview");if(t){t.open();return}t=wp.media.frames.file_frame=wp.media({title:jQuery(this).data("uploader_title"),button:{text:jQuery(this).data("uploader_button_text")},multiple:!1});t.on("select",function(){attachment=t.state().get("selection").first().toJSON();jQuery("#"+i).val(attachment.id);n&&jQuery("#"+s).attr("src",attachment.sizes.thumbnail.url);t=!1});t.open()};jQuery(".image_upload_button").click(function(){jQuery.fn.uploadMediaFile(jQuery(this),!0)});jQuery(".image_delete_button").click(function(){jQuery(this).closest("td").find(".image_data_field").val("");jQuery(this).closest("td").find(".image_preview").remove();return!1})}); -------------------------------------------------------------------------------- /includes/class-user-session-synchronizer-email-verification.php: -------------------------------------------------------------------------------- 1 | parent = $parent; 38 | 39 | $this->user_id = get_current_user_id(); 40 | 41 | register_activation_hook(__FILE__, array($this, 'activate_plugins_email')); 42 | 43 | //add_action('wp_login', array( $this, 'ussync_after_user_loggedin'),10); 44 | 45 | add_shortcode('ussyncemailverificationcode', array($this, 'get_email_verification_link')); 46 | 47 | add_filter('manage_users_columns', array($this, 'update_user_table'), 10, 1); 48 | add_filter('manage_users_custom_column', array($this, 'modify_user_table_row'), 10, 3); 49 | 50 | add_action('user_register', array( $this, 'after_user_register'), 10, 1); 51 | add_action('admin_head', array($this, 'verify_user')); 52 | 53 | add_action('init', array($this, 'verify_registered_user')); 54 | } 55 | 56 | public function after_user_register($user_id){ 57 | 58 | // the new user just registered but never logged in yet 59 | add_user_meta($user_id, 'ussync_has_not_logged_in_yet', 'true'); 60 | } 61 | 62 | public function verify_registered_user(){ 63 | 64 | if(isset($_GET["ussync_confirmation_verify"])){ 65 | 66 | $user_meta = explode("@", base64_decode($_GET["ussync_confirmation_verify"])); 67 | 68 | if (get_user_meta((int) $user_meta[1], "ussync_email_verifiedcode", TRUE) == $user_meta[0]) { 69 | 70 | update_user_meta((int) $user_meta[1], "ussync_email_verified", "true"); 71 | 72 | delete_user_meta((int) $user_meta[1], "ussync_email_verifiedcode"); 73 | 74 | echo '

Congratulations your account has been successfully verified!

'; 75 | } 76 | elseif(get_user_meta((int) $user_meta[1], "ussync_email_verified", TRUE) == 'true'){ 77 | 78 | echo '

Your account has already been verified...

'; 79 | } 80 | else{ 81 | 82 | echo '

Oops something went wrong during your account validation...

'; 83 | } 84 | } 85 | elseif(is_user_logged_in()){ 86 | 87 | $user_id = get_current_user_id(); 88 | 89 | $user_meta = get_user_meta($user_id); 90 | 91 | if(isset($user_meta['ussync_has_not_logged_in_yet'])){ 92 | 93 | delete_user_meta($user_id, 'ussync_has_not_logged_in_yet'); 94 | 95 | update_user_meta($user_id, 'ussync_email_verified', 'true'); 96 | } 97 | } 98 | } 99 | 100 | public function activate_plugins_email() { 101 | 102 | ob_start(); 103 | include plugin_dir_path(__FILE__) . "views/demo_email.html"; 104 | $demo_email_content = ob_get_clean(); 105 | 106 | update_option("ussync-email-header", $demo_email_content); 107 | update_option("ussync_email_confemail", get_option("admin_email")); 108 | update_option("ussync_email_conf_title", "Please Verify Your email Account"); 109 | } 110 | 111 | public function view_email_setting() { 112 | 113 | include plugin_dir_path(__FILE__) . "views/email-setting.php"; 114 | } 115 | 116 | public function view_email_verification() { 117 | 118 | include plugin_dir_path(__FILE__) . "views/email-verification.php"; 119 | } 120 | 121 | public function codeMailSender($email) { 122 | 123 | $urlparts = parse_url(site_url()); 124 | $domain = $urlparts ['host']; 125 | 126 | $Email_title = get_option("ussync_email_conf_title"); 127 | $sender_email = get_option("ussync_email_confemail"); 128 | $message = get_option("ussync-email-header"); 129 | 130 | $headers = []; 131 | $headers[] = 'From: ' . get_bloginfo('name') . ' '; 132 | $headers[] = 'MIME-Version: 1.0'; 133 | $headers[] = 'Content-type: text/html'; 134 | 135 | $preMesaage = "
" . apply_filters('the_content', $message) . "
"; 136 | 137 | if(!wp_mail($email, $Email_title, $preMesaage, $headers)){ 138 | 139 | global $phpmailer; 140 | 141 | var_dump($phpmailer->ErrorInfo);exit; 142 | } 143 | } 144 | 145 | public function get_email_verification_link(){ 146 | 147 | $link=''; 148 | 149 | if(isset($_GET["user_id"]) && wp_verify_nonce($_GET["wp_nonce"], "ussync_email")){ 150 | 151 | $user_id = $_GET['user_id']; 152 | 153 | $secret = get_user_meta( (int) $user_id, "ussync_email_verifiedcode", true); 154 | 155 | $createLink = $secret . "@" . $user_id; 156 | 157 | $hyperlink = get_admin_url() . "profile.php?ussync_confirmation_verify=" . base64_encode($createLink); 158 | 159 | $link .= " Click here to verify"; 160 | } 161 | 162 | return $link; 163 | } 164 | 165 | public function update_user_table($column) { 166 | 167 | $column['ussync_verified'] = 'Verified user'; 168 | return $column; 169 | } 170 | 171 | public function modify_user_table_row($val, $column_name, $user_id) { 172 | 173 | $user_role = get_userdata($user_id); 174 | 175 | $row=''; 176 | 177 | if ($column_name == "ussync_verified") { 178 | 179 | if ($user_role->roles[0] != "administrator") { 180 | 181 | if (get_user_meta($user_id, "ussync_email_verified", true) != "true") { 182 | 183 | if (get_user_meta($user_id, "ussync_has_not_logged_in_yet", true) == "true") { 184 | 185 | $text = ""; 186 | $row .= " $user_id, "wp_nonce" => wp_create_nonce("ussync_email"), "ussync_confirm" => "true"), get_admin_url() . "users.php") . "\">" . apply_filters("ussync_email_confirmation_manual_verify", $text) . ""; 187 | } 188 | else{ 189 | 190 | $text = ""; 191 | $row .= " $user_id, "wp_nonce" => wp_create_nonce("ussync_email"), "ussync_confirm" => "true"), get_admin_url() . "users.php") . "\">" . apply_filters("ussync_email_confirmation_manual_verify", $text) . ""; 192 | } 193 | 194 | 195 | $text = ""; 196 | $row .= " $user_id, "wp_nonce" => wp_create_nonce("ussync_email"), "ussync_confirm" => "resend"), get_admin_url() . "users.php") . "\">" . apply_filters("ussync_email_confirmation_manual_verify", $text) . ""; 197 | } 198 | else{ 199 | 200 | $text = ""; 201 | $row .= " $user_id, "wp_nonce" => wp_create_nonce("ussync_email"), "ussync_confirm" => "false"), get_admin_url() . "users.php") . "\">" . apply_filters("ussync_email_confirmation_manual_verify", $text) . ""; 202 | } 203 | 204 | } 205 | else { 206 | 207 | $row .= "Admin"; 208 | } 209 | } 210 | 211 | return $row; 212 | } 213 | 214 | public function verify_user() { 215 | 216 | //var_dump(wp_verify_nonce($_GET["wp_nonce"], "ussync_email")); 217 | 218 | if(isset($_GET["user_id"]) && isset($_GET["wp_nonce"]) && wp_verify_nonce($_GET["wp_nonce"], "ussync_email") && isset($_GET["ussync_confirm"])) { 219 | 220 | if($_GET["ussync_confirm"] === 'true' || $_GET["ussync_confirm"] === 'false'){ 221 | 222 | update_user_meta($_GET["user_id"], "ussync_email_verified", $_GET["ussync_confirm"]); 223 | } 224 | elseif($_GET["ussync_confirm"] === 'resend'){ 225 | 226 | $user_id = intval($_GET['user_id']); 227 | 228 | $email_verified = get_user_meta(($user_id), "ussync_email_verified", TRUE); 229 | 230 | if( $email_verified !== 'true' ){ 231 | 232 | $user = get_user_by("id", $user_id); 233 | 234 | $scret_code = md5( $user->user_email . time() ); 235 | 236 | update_user_meta($user_id, "ussync_email_verifiedcode", $scret_code); 237 | 238 | $this->codeMailSender($user->user_email); 239 | 240 | echo '

Email sent to '.$user->user_email.'

'; 241 | } 242 | } 243 | } 244 | } 245 | 246 | /** 247 | * Main User_Session_Synchronizer_Email_Verification Instance 248 | * 249 | * Ensures only one instance of User_Session_Synchronizer_Email_Verification is loaded or can be loaded. 250 | * 251 | * @since 1.0.0 252 | * @static 253 | * @see User_Session_Synchronizer() 254 | * @return Main User_Session_Synchronizer_Email_Verification instance 255 | */ 256 | public static function instance ( $parent ) { 257 | 258 | if ( is_null( self::$_instance ) ) { 259 | 260 | self::$_instance = new self( $parent ); 261 | } 262 | return self::$_instance; 263 | } // End instance() 264 | 265 | /** 266 | * Cloning is forbidden. 267 | * 268 | * @since 1.0.0 269 | */ 270 | public function __clone () { 271 | _doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh?' ), $this->parent->_version ); 272 | } // End __clone() 273 | 274 | /** 275 | * Unserializing instances of this class is forbidden. 276 | * 277 | * @since 1.0.0 278 | */ 279 | public function __wakeup () { 280 | _doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh?' ), $this->parent->_version ); 281 | } // End __wakeup() 282 | 283 | } -------------------------------------------------------------------------------- /includes/class-user-session-synchronizer-session-control.php: -------------------------------------------------------------------------------- 1 | parent = $parent; 36 | 37 | 38 | } 39 | 40 | /** 41 | * Callback for the custom submenu screen content 42 | * 43 | * @return void 44 | */ 45 | public function session_control() { 46 | 47 | if ( 48 | ! empty( $_GET['_wpnonce'] ) 49 | && 50 | ! empty( $_GET['action'] ) 51 | && 52 | 'destroy_session' === $_GET['action'] 53 | && 54 | ! empty( $_GET['user_id'] ) 55 | && 56 | ! empty( $_GET['token_hash'] ) 57 | ) { 58 | $user_id = absint( $_GET['user_id'] ); 59 | 60 | if ( false === wp_verify_nonce( $_GET['_wpnonce'], sprintf( 'destroy_session_nonce-%d', $user_id ) ) ) { 61 | wp_die( __( 'Cheatin’ uh?', 'user-session-synchronizer' ) ); 62 | } 63 | 64 | $this->destroy_user_session( $user_id, $_GET['token_hash'] ); 65 | } 66 | 67 | $results = $this->get_all_sessions(); 68 | $sorted = array(); 69 | $spp = ! empty( $_GET['sessions_per_page'] ) ? absint( $_GET['sessions_per_page'] ) : 20; 70 | $paged = ! empty( $_GET['paged'] ) ? absint( $_GET['paged'] ) : 1; 71 | $offset = absint( ( $paged - 1 ) * $spp ); 72 | $orderby = ! empty( $_GET['orderby'] ) ? $_GET['orderby'] : 'created'; 73 | $order = ! empty( $_GET['order'] ) ? $_GET['order'] : 'desc'; 74 | 75 | foreach ( $results as $result ) { 76 | if ( 'ip' === $orderby ) { 77 | $sorted[] = str_replace( '.', '', $result[ $orderby ] ); 78 | } else { 79 | $sorted[] = $result[ $orderby ]; 80 | } 81 | } 82 | 83 | // Loose comparison needed 84 | if ( 'asc' == $order ) { 85 | 86 | array_multisort( $sorted, SORT_ASC, $results ); 87 | } 88 | else { 89 | 90 | array_multisort( $sorted, SORT_DESC, $results ); 91 | } 92 | 93 | $total_sessions = count( $results ); 94 | $pages = absint( ceil( $total_sessions / $spp ) ); 95 | 96 | $results = array_slice( $results, $offset, $spp ); 97 | 98 | switch ( $order ) { 99 | case 'asc': 100 | $order_flip = 'desc'; 101 | break; 102 | case 'desc': 103 | $order_flip = 'asc'; 104 | break; 105 | default: 106 | $order_flip = 'desc'; 107 | } 108 | 109 | $columns = array( 110 | 'username' => __( 'Username', 'user-session-synchronizer' ), 111 | //'name' => __( 'Name', 'user-session-synchronizer' ), 112 | 'email' => __( 'E-mail', 'user-session-synchronizer' ), 113 | 'role' => __( 'Role', 'user-session-synchronizer' ), 114 | 'created' => __( 'Created', 'user-session-synchronizer' ), 115 | 'expiration' => __( 'Expires', 'user-session-synchronizer' ), 116 | 'ip' => __( 'IP Address', 'user-session-synchronizer' ), 117 | ); 118 | 119 | if ( is_network_admin() ) { 120 | 121 | unset( $columns['role'] ); 122 | } 123 | 124 | $users = $this->get_users_with_sessions(); 125 | 126 | global $wp_roles; 127 | 128 | ob_start(); 129 | 130 | $first_link = $base_link = add_query_arg( 131 | array( 132 | 'page' => 'user-session-synchronizer', 133 | ), 134 | admin_url( 'users.php' ) 135 | ); 136 | $last_link = add_query_arg( array( 'paged' => $pages ), $first_link ); 137 | $prev_link = ( $paged > 2 ) ? add_query_arg( array( 'paged' => absint( $paged - 1 ), 'sessions_per_page' => $spp, ), $first_link ) : $first_link; 138 | $next_link = ( $pages > $paged ) ? add_query_arg( array( 'paged' => absint( $paged + 1 ), 'sessions_per_page' => $spp, ), $first_link ) : $last_link; 139 | ?> 140 |
141 | 142 | 143 | 1 ) : ?> 144 | 145 | 146 | « 147 | 148 | 149 | 150 | 151 | 152 | » 153 | 154 | 155 | 156 | 157 |
158 | 161 |
162 | 163 |

164 | 165 |

166 | 167 |

total_users ) ) ?>

168 | 169 |
170 | 171 |
172 | 173 | 174 | 175 |
176 | 177 |
178 | 179 | 180 | 181 | 182 | $name ) : ?> 183 | 189 | 190 | 191 | 192 | 193 | 194 | $name ) : ?> 195 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | roles[ $result['role'] ]['name'] ) ? translate_user_role( $wp_roles->roles[ $result['role'] ]['name'] ) : $result['role']; 209 | $date_format = get_option( 'date_format', 'F j, Y' ) . ' @ ' . get_option( 'time_format', 'g:i A' ); 210 | $user_id = absint( $result['user_id'] ); 211 | $edit_link = add_query_arg( 212 | array( 213 | 'wp_http_referer' => urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ), 214 | ), 215 | self_admin_url( sprintf( 'user-edit.php?user_id=%d', $user_id ) ) 216 | ); 217 | $destroy_link = add_query_arg( 218 | array( 219 | 'action' => 'destroy_session', 220 | 'user_id' => $user_id, 221 | 'token_hash' => $result['token_hash'], 222 | '_wpnonce' => wp_create_nonce( sprintf( 'destroy_session_nonce-%d', $user_id ) ), 223 | ) 224 | ); 225 | $created = is_network_admin() ? $result['created'] : strtotime( get_date_from_gmt( date( 'Y-m-d H:i:s', $result['created'] ) ) ); 226 | $expiration = is_network_admin() ? $result['expiration'] : strtotime( get_date_from_gmt( date( 'Y-m-d H:i:s', $result['expiration'] ) ) ); 227 | $ip_column = apply_filters( 'ussync_user_ip_html', esc_html( $result['ip'] ), $result ); 228 | ?> 229 | > 230 | 250 | 251 | 254 | 255 | 256 | 257 | 258 | 259 | 264 | 269 | 270 | 271 | 272 | 273 |
184 | 185 | 186 | 187 | 188 |
196 | 197 | 198 | 199 | 200 |
231 | 232 | 233 | 234 | 235 | 236 | 237 | - 238 | 239 | 240 |
241 |
242 | 243 | 244 | 245 | | 246 | 247 | 248 |
249 |
252 | 253 | 260 | 261 |
262 | 263 |
265 | 266 |
267 | 268 |
274 | 275 |
276 | 277 | 278 | 279 |
280 | 281 |
282 | 283 |
284 | 285 |
286 | get_results( "SELECT meta_value FROM $wpdb->usermeta WHERE meta_key = 'session_tokens' LIMIT 0, 9999" ); 299 | $sessions = wp_list_pluck( $sessions, 'meta_value' ); 300 | $sessions = array_map( 'maybe_unserialize', $sessions ); 301 | 302 | foreach ( $sessions as $session ) { 303 | 304 | $results = array_merge( $results, $session ); 305 | } 306 | 307 | return (array) $results; 308 | } 309 | 310 | /** 311 | * Get all users with active sessions 312 | * 313 | * @return object WP_User 314 | */ 315 | public function get_users_with_sessions() { 316 | $args = array( 317 | 'number' => 9999, 318 | 'blog_id' => is_network_admin() ? 0 : get_current_blog_id(), 319 | 'meta_query' => array( 320 | array( 321 | 'key' => 'session_tokens', 322 | 'compare' => 'EXISTS', 323 | ), 324 | ), 325 | ); 326 | 327 | $users = new WP_User_Query( $args ); 328 | 329 | return $users; 330 | } 331 | 332 | /** 333 | * Get all sessions from all users 334 | * 335 | * @return array 336 | */ 337 | public function get_all_sessions() { 338 | $results = array(); 339 | $users = $this->get_users_with_sessions()->get_results(); 340 | $sessions = $this->get_all_sessions_raw(); 341 | 342 | foreach ( $users as $user ) { 343 | $user_sessions = get_user_meta( $user->ID, 'session_tokens', true ); 344 | 345 | foreach ( $sessions as $session ) { 346 | foreach ( $user_sessions as $token_hash => $user_session ) { 347 | // Loose comparison needed 348 | if ( $user_session != $session ) { 349 | continue; 350 | } 351 | $results[] = array( 352 | 'user_id' => $user->ID, 353 | 'username' => $user->user_login, 354 | //'name' => $user->display_name, 355 | 'email' => $user->user_email, 356 | 'role' => ! empty( $user->roles[0] ) ? $user->roles[0] : '', 357 | 'created' => $user_session['login'], 358 | 'expiration' => $user_session['expiration'], 359 | 'ip' => $user_session['ip'], 360 | 'user_agent' => $user_session['ua'], 361 | 'token_hash' => $token_hash, 362 | ); 363 | } 364 | } 365 | } 366 | 367 | return (array) $results; 368 | } 369 | 370 | /** 371 | * Destroy a specfic session for a specfic user 372 | * 373 | * @param int $user_id 374 | * @param string $token_hash 375 | * 376 | * @return void 377 | */ 378 | public function destroy_user_session( $user_id, $token_hash ) { 379 | 380 | $session_tokens = get_user_meta( $user_id, 'session_tokens', true ); 381 | 382 | unset( $session_tokens[ $token_hash ] ); 383 | 384 | update_user_meta( $user_id, 'session_tokens', $session_tokens ); 385 | } 386 | 387 | /** 388 | * Main User_Session_Synchronizer_Session_Control Instance 389 | * 390 | * Ensures only one instance of User_Session_Synchronizer_Session_Control is loaded or can be loaded. 391 | * 392 | * @since 1.0.0 393 | * @static 394 | * @see User_Session_Synchronizer() 395 | * @return Main User_Session_Synchronizer_Session_Control instance 396 | */ 397 | public static function instance ( $parent ) { 398 | if ( is_null( self::$_instance ) ) { 399 | self::$_instance = new self( $parent ); 400 | } 401 | return self::$_instance; 402 | } // End instance() 403 | 404 | /** 405 | * Cloning is forbidden. 406 | * 407 | * @since 1.0.0 408 | */ 409 | public function __clone () { 410 | _doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh?' ), $this->parent->_version ); 411 | } // End __clone() 412 | 413 | /** 414 | * Unserializing instances of this class is forbidden. 415 | * 416 | * @since 1.0.0 417 | */ 418 | public function __wakeup () { 419 | _doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh?' ), $this->parent->_version ); 420 | } // End __wakeup() 421 | 422 | } -------------------------------------------------------------------------------- /includes/class-user-session-synchronizer-settings.php: -------------------------------------------------------------------------------- 1 | parent = $parent; 41 | 42 | $this->base = 'ussync_'; 43 | 44 | // Initialise settings 45 | add_action( 'init', array( $this, 'init_settings' ), 11 ); 46 | 47 | // Register plugin settings 48 | add_action( 'admin_init' , array( $this, 'register_settings' ) ); 49 | 50 | // Add settings page to menu 51 | add_action( 'admin_menu' , array( $this, 'add_menu_items' ) ); 52 | 53 | // Add settings link to plugins page 54 | add_filter( 'plugin_action_links_' . plugin_basename( $this->parent->file ) , array( $this, 'add_settings_link' ) ); 55 | } 56 | 57 | /** 58 | * Initialise settings 59 | * @return void 60 | */ 61 | public function init_settings () { 62 | $this->settings = $this->settings_fields(); 63 | } 64 | 65 | /** 66 | * Add settings page to admin menu 67 | * @return void 68 | */ 69 | public function add_menu_items () { 70 | 71 | //add menu in wordpress settings 72 | 73 | //$page = add_options_page( __( 'User Session Synchronizer', 'user-session-synchronizer' ) , __( 'User Session Synchronizer', 'user-session-synchronizer' ) , 'manage_options' , $this->parent->_token . '_settings' , array( $this, 'settings_page' ) ); 74 | //add_action( 'admin_print_styles' . $page, array( $this, 'settings_assets' ) ); 75 | 76 | //add menu in wordpress dashboard 77 | 78 | add_menu_page('User Session Sync', 'User Session Sync', 'manage_options', 'user-session-synchronizer', array($this, 'settings_page'),'dashicons-shield'); 79 | add_submenu_page("user-session-synchronizer", "User Verify ", "User Verify", 'administrator', 'view_email_verification', array( $this->parent->emailVerification, "view_email_verification")); 80 | add_submenu_page("user-session-synchronizer", "User Sessions", "User Sessions", 'administrator', 'session_control', array( $this->parent->sessionControl, "session_control") ); 81 | add_submenu_page("user-session-synchronizer", "Email Template", "Email Template", 'administrator', 'view_email_setting', array( $this->parent->emailVerification, "view_email_setting")); 82 | 83 | } 84 | 85 | /** 86 | * Load settings JS & CSS 87 | * @return void 88 | */ 89 | public function settings_assets () { 90 | 91 | // We're including the farbtastic script & styles here because they're needed for the colour picker 92 | // If you're not including a colour picker field then you can leave these calls out as well as the farbtastic dependency for the wpt-admin-js script below 93 | wp_enqueue_style( 'farbtastic' ); 94 | wp_enqueue_script( 'farbtastic' ); 95 | 96 | // We're including the WP media scripts here because they're needed for the image upload field 97 | // If you're not including an image upload then you can leave this function call out 98 | wp_enqueue_media(); 99 | 100 | wp_register_script( $this->parent->_token . '-settings-js', $this->parent->assets_url . 'js/settings' . $this->parent->script_suffix . '.js', array( 'farbtastic', 'jquery' ), '1.0.0' ); 101 | wp_enqueue_script( $this->parent->_token . '-settings-js' ); 102 | } 103 | 104 | /** 105 | * Add settings link to plugin list table 106 | * @param array $links Existing links 107 | * @return array Modified links 108 | */ 109 | public function add_settings_link ( $links ) { 110 | 111 | $settings_link = '' . __( 'Settings', 'user-session-synchronizer' ) . ''; 112 | array_push( $links, $settings_link ); 113 | return $links; 114 | } 115 | 116 | /** 117 | * Build settings fields 118 | * @return array Fields to be displayed on settings page 119 | */ 120 | private function settings_fields () { 121 | 122 | $settings['keys'] = array( 123 | 'title' => __( 'Keys', 'user-session-synchronizer' ), 124 | 'description' => __( 'This plugin uses the user email address as a unique ID to synchronize the session between two wordpress installations.', 'user-session-synchronizer' ), 125 | 'fields' => array( 126 | array( 127 | 'id' => 'secret_key_1', 128 | 'label' => __( 'Secret Key 1' , 'user-session-synchronizer' ), 129 | 'description' => __( 'The secret key is used to encrypt and decrypt the current user ID. It must be the same for every synchronized installations.', 'user-session-synchronizer' ), 130 | 'type' => 'text', 131 | 'default' => '', 132 | 'placeholder' => __( 'Your Secret Key 1', 'user-session-synchronizer' ) 133 | ), 134 | array( 135 | 'id' => 'domain_list_1', 136 | 'label' => __( 'List of domains 1' , 'user-session-synchronizer' ), 137 | 'description' => __( 'List of allowed domains to synchronize together. Separate multiple domains with line breaks.', 'user-session-synchronizer' ), 138 | 'type' => 'textarea', 139 | 'default' => '', 140 | 'placeholder' => __( $_SERVER['HTTP_HOST'], 'user-session-synchronizer' ) 141 | ), 142 | array( 143 | 'id' => 'no_user_1', 144 | 'label' => __( 'If user doesn\'t exist', 'user-session-synchronizer' ), 145 | 'description' => __( 'Action taken when a verified unknown user tries to synchronize with this installation', 'user-session-synchronizer' ), 146 | 'type' => 'radio', 147 | 'options' => array( 148 | 'do_nothing' => 'Do nothing', 149 | 'register_suscriber' => 'Register new subscriber' 150 | ), 151 | 'default' => 'do_nothing' 152 | ), 153 | /* 154 | array( 155 | 'id' => 'password_field', 156 | 'label' => __( 'A Password' , 'user-session-synchronizer' ), 157 | 'description' => __( 'This is a standard password field.', 'user-session-synchronizer' ), 158 | 'type' => 'password', 159 | 'default' => '', 160 | 'placeholder' => __( 'Placeholder text', 'user-session-synchronizer' ) 161 | ), 162 | array( 163 | 'id' => 'secret_text_field', 164 | 'label' => __( 'Some Secret Text' , 'user-session-synchronizer' ), 165 | 'description' => __( 'This is a secret text field - any data saved here will not be displayed after the page has reloaded, but it will be saved.', 'user-session-synchronizer' ), 166 | 'type' => 'text_secret', 167 | 'default' => '', 168 | 'placeholder' => __( 'Placeholder text', 'user-session-synchronizer' ) 169 | ), 170 | array( 171 | 'id' => 'ussync_add_user', 172 | 'label' => __( 'Add user', 'user-session-synchronizer' ), 173 | 'description' => __( 'Create a new user if it doesn\'t exist yet.', 'user-session-synchronizer' ), 174 | 'type' => 'checkbox', 175 | 'default' => '' 176 | ), 177 | */ 178 | /* 179 | array( 180 | 'id' => 'select_box', 181 | 'label' => __( 'A Select Box', 'user-session-synchronizer' ), 182 | 'description' => __( 'A standard select box.', 'user-session-synchronizer' ), 183 | 'type' => 'select', 184 | 'options' => array( 'drupal' => 'Drupal', 'joomla' => 'Joomla', 'wordpress' => 'WordPress' ), 185 | 'default' => 'wordpress' 186 | ), 187 | array( 188 | 'id' => 'multiple_checkboxes', 189 | 'label' => __( 'Some Items', 'user-session-synchronizer' ), 190 | 'description' => __( 'You can select multiple items and they will be stored as an array.', 'user-session-synchronizer' ), 191 | 'type' => 'checkbox_multi', 192 | 'options' => array( 'square' => 'Square', 'circle' => 'Circle', 'rectangle' => 'Rectangle', 'triangle' => 'Triangle' ), 193 | 'default' => array( 'circle', 'triangle' ) 194 | ) 195 | */ 196 | ) 197 | ); 198 | 199 | /* 200 | $settings['extra'] = array( 201 | 'title' => __( 'Iframes', 'user-session-synchronizer' ), 202 | 'description' => __( 'These are some extra input fields that maybe aren\'t as common as the others.', 'user-session-synchronizer' ), 203 | 'fields' => array( 204 | array( 205 | 'id' => 'number_field', 206 | 'label' => __( 'A Number' , 'user-session-synchronizer' ), 207 | 'description' => __( 'This is a standard number field - if this field contains anything other than numbers then the form will not be submitted.', 'user-session-synchronizer' ), 208 | 'type' => 'number', 209 | 'default' => '', 210 | 'placeholder' => __( '42', 'user-session-synchronizer' ) 211 | ), 212 | array( 213 | 'id' => 'colour_picker', 214 | 'label' => __( 'Pick a colour', 'user-session-synchronizer' ), 215 | 'description' => __( 'This uses WordPress\' built-in colour picker - the option is stored as the colour\'s hex code.', 'user-session-synchronizer' ), 216 | 'type' => 'color', 217 | 'default' => '#21759B' 218 | ), 219 | array( 220 | 'id' => 'an_image', 221 | 'label' => __( 'An Image' , 'user-session-synchronizer' ), 222 | 'description' => __( 'This will upload an image to your media library and store the attachment ID in the option field. Once you have uploaded an imge the thumbnail will display above these buttons.', 'user-session-synchronizer' ), 223 | 'type' => 'image', 224 | 'default' => '', 225 | 'placeholder' => '' 226 | ), 227 | array( 228 | 'id' => 'multi_select_box', 229 | 'label' => __( 'A Multi-Select Box', 'user-session-synchronizer' ), 230 | 'description' => __( 'A standard multi-select box - the saved data is stored as an array.', 'user-session-synchronizer' ), 231 | 'type' => 'select_multi', 232 | 'options' => array( 'linux' => 'Linux', 'mac' => 'Mac', 'windows' => 'Windows' ), 233 | 'default' => array( 'linux' ) 234 | ) 235 | ) 236 | ); 237 | */ 238 | 239 | $settings = apply_filters( $this->parent->_token . '_settings_fields', $settings ); 240 | 241 | return $settings; 242 | } 243 | 244 | /** 245 | * Register plugin settings 246 | * @return void 247 | */ 248 | public function register_settings () { 249 | 250 | if ( is_array( $this->settings ) ) { 251 | 252 | // Check posted/selected tab 253 | $current_section = ''; 254 | if ( isset( $_POST['tab'] ) && $_POST['tab'] ) { 255 | 256 | $current_section = $_POST['tab']; 257 | } 258 | else { 259 | 260 | if ( isset( $_GET['tab'] ) && $_GET['tab'] ) { 261 | 262 | $current_section = $_GET['tab']; 263 | } 264 | } 265 | 266 | foreach ( $this->settings as $section => $data ) { 267 | 268 | if ( $current_section && $current_section != $section ) continue; 269 | 270 | // Add section to page 271 | add_settings_section( $section, $data['title'], array( $this, 'settings_section' ), $this->parent->_token . '_settings' ); 272 | 273 | foreach ( $data['fields'] as $field ) { 274 | 275 | // Validation callback for field 276 | $validation = ''; 277 | if ( isset( $field['callback'] ) ) { 278 | 279 | $validation = $field['callback']; 280 | } 281 | 282 | // Register field 283 | $option_name = $this->base . $field['id']; 284 | register_setting( $this->parent->_token . '_settings', $option_name, $validation ); 285 | 286 | // Add field to page 287 | add_settings_field( $field['id'], $field['label'], array( $this->parent->admin, 'display_field' ), $this->parent->_token . '_settings', $section, array( 'field' => $field, 'prefix' => $this->base ) ); 288 | } 289 | 290 | if ( ! $current_section ) break; 291 | } 292 | } 293 | } 294 | 295 | public function settings_section ( $section ) { 296 | 297 | $html = '

' . $this->settings[ $section['id'] ]['description'] . '

' . "\n"; 298 | echo $html; 299 | } 300 | 301 | /** 302 | * Load settings page content 303 | * @return void 304 | */ 305 | public function settings_page () { 306 | 307 | // Build page HTML 308 | $html = '
' . "\n"; 309 | $html .= '

' . __( 'User Session Synchronizer' , 'user-session-synchronizer' ) . '

' . "\n"; 310 | 311 | $tab = ''; 312 | if ( isset( $_GET['tab'] ) && $_GET['tab'] ) { 313 | $tab .= $_GET['tab']; 314 | } 315 | 316 | // Show page tabs 317 | if ( is_array( $this->settings ) && 1 < count( $this->settings ) ) { 318 | 319 | $html .= '' . "\n"; 349 | } 350 | 351 | $html .= '
' . "\n"; 352 | 353 | // Get settings fields 354 | ob_start(); 355 | settings_fields( $this->parent->_token . '_settings' ); 356 | do_settings_sections( $this->parent->_token . '_settings' ); 357 | $html .= ob_get_clean(); 358 | 359 | $html .= '

' . "\n"; 360 | $html .= '' . "\n"; 361 | $html .= '' . "\n"; 362 | $html .= '

' . "\n"; 363 | $html .= '
' . "\n"; 364 | $html .= '
' . "\n"; 365 | 366 | echo $html; 367 | } 368 | 369 | /** 370 | * Main User_Session_Synchronizer_Settings Instance 371 | * 372 | * Ensures only one instance of User_Session_Synchronizer_Settings is loaded or can be loaded. 373 | * 374 | * @since 1.0.0 375 | * @static 376 | * @see User_Session_Synchronizer() 377 | * @return Main User_Session_Synchronizer_Settings instance 378 | */ 379 | public static function instance ( $parent ) { 380 | if ( is_null( self::$_instance ) ) { 381 | self::$_instance = new self( $parent ); 382 | } 383 | return self::$_instance; 384 | } // End instance() 385 | 386 | /** 387 | * Cloning is forbidden. 388 | * 389 | * @since 1.0.0 390 | */ 391 | public function __clone () { 392 | _doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh?' ), $this->parent->_version ); 393 | } // End __clone() 394 | 395 | /** 396 | * Unserializing instances of this class is forbidden. 397 | * 398 | * @since 1.0.0 399 | */ 400 | public function __wakeup () { 401 | _doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh?' ), $this->parent->_version ); 402 | } // End __wakeup() 403 | 404 | } -------------------------------------------------------------------------------- /includes/class-user-session-synchronizer.php: -------------------------------------------------------------------------------- 1 | _version = $version; 95 | $this->_token = 'user-session-synchronizer'; 96 | 97 | // Load plugin environment variables 98 | $this->file = $file; 99 | $this->dir = dirname( $this->file ); 100 | $this->assets_dir = trailingslashit( $this->dir ) . 'assets'; 101 | $this->assets_url = esc_url( trailingslashit( plugins_url( '/assets/', $this->file ) ) ); 102 | 103 | $this->script_suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; 104 | 105 | // set user ip 106 | 107 | $this->user_ip = $this->get_user_ip(); 108 | 109 | // set user agent 110 | 111 | $this->user_agent = $_SERVER['HTTP_USER_AGENT']; 112 | 113 | // set secret key number 114 | 115 | $this -> key_num = 1; 116 | 117 | if(isset($_GET['ussync-key'])){ 118 | 119 | $this -> key_num=(int)trim($_GET['ussync-key']); 120 | } 121 | 122 | //get secret_key 123 | 124 | $this -> secret_key = get_option('ussync_secret_key_'.$this -> key_num); 125 | 126 | // get proto 127 | 128 | if( (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443 ){ 129 | 130 | $this -> proto = 'https://'; 131 | } 132 | else{ 133 | 134 | $this -> proto = 'http://'; 135 | } 136 | 137 | // register plugin activation hook 138 | 139 | register_activation_hook( $this->file, array( $this, 'install' ) ); 140 | 141 | // Load frontend JS & CSS 142 | add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_styles' ), 10 ); 143 | add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ), 10 ); 144 | 145 | // Load admin JS & CSS 146 | add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ), 10, 1 ); 147 | add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_styles' ), 10, 1 ); 148 | 149 | // Load API for generic admin functions 150 | if ( is_admin() ) { 151 | 152 | $this->admin = new User_Session_Synchronizer_Admin_API(); 153 | } 154 | 155 | // Handle login synchronization 156 | add_action( 'init', array( $this, 'synchronize_session' ), 0 ); 157 | 158 | // Handle localisation 159 | $this->load_plugin_textdomain(); 160 | add_action( 'init', array( $this, 'load_localisation' ), 0 ); 161 | 162 | // Handle profile updates 163 | add_action( 'user_profile_update_errors', array( $this, 'prevent_email_change'), 10, 3 ); 164 | add_action( 'admin_init', array( $this, 'disable_user_profile_fields')); 165 | 166 | } // End __construct () 167 | 168 | public function get_user_ip() { 169 | 170 | foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key){ 171 | 172 | if (array_key_exists($key, $_SERVER) === true){ 173 | 174 | foreach (array_map('trim', explode(',', $_SERVER[$key])) as $ip){ 175 | 176 | if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false){ 177 | 178 | return $ip; 179 | } 180 | } 181 | } 182 | } 183 | } 184 | 185 | public function prevent_email_change( $errors, $update, $user ) { 186 | 187 | if( !empty($user->ID) ){ 188 | 189 | $old = get_user_by('id', $user->ID); 190 | 191 | if( $user->user_email != $old->user_email && (!current_user_can('create_users')) ){ 192 | 193 | $user->user_email = $old->user_email; 194 | } 195 | } 196 | } 197 | 198 | public function disable_user_profile_fields() { 199 | 200 | global $pagenow; 201 | 202 | // apply only to user profile or user edit pages 203 | if ($pagenow!=='profile.php' && $pagenow!=='user-edit.php') { 204 | 205 | return; 206 | } 207 | 208 | // do not change anything for the administrator 209 | if (current_user_can('administrator')) { 210 | 211 | return; 212 | } 213 | 214 | add_action( 'admin_footer', array( $this,'disable_user_profile_fields_js' )); 215 | } 216 | 217 | 218 | /** 219 | * Disables selected fields in WP Admin user profile (profile.php, user-edit.php) 220 | */ 221 | public function disable_user_profile_fields_js() { 222 | 223 | ?> 224 | 235 | user_id = get_current_user_id(); 243 | 244 | // check user verified 245 | 246 | if( current_user_can('administrator') ) { 247 | 248 | $this->user_verified = 'true'; 249 | } 250 | else{ 251 | 252 | $this->user_verified = get_user_meta( $this->user_id, "ussync_email_verified", TRUE); 253 | } 254 | 255 | // add cors header 256 | if(is_user_logged_in()){ 257 | 258 | add_action( 'send_headers', array($this, 'add_cors_header') ); 259 | add_action( 'send_headers', array($this, 'add_content_security_policy') ); 260 | } 261 | 262 | // synchronize sessions 263 | 264 | if( isset($_GET['action']) && $_GET['action']=='logout' ){ 265 | 266 | $this->get_domains(true); 267 | } 268 | elseif( isset($_GET['ussync-status']) && $_GET['ussync-status']=='loggedin' ){ 269 | 270 | echo 'User logged in!'; 271 | exit; 272 | } 273 | elseif( is_user_logged_in() && isset($_GET['redirect_to']) ){ 274 | 275 | if( !empty($_GET['reauth']) && $_GET['reauth'] == '1' ){ 276 | 277 | echo 'Error accessing the current session...'; 278 | } 279 | else{ 280 | 281 | wp_safe_redirect( trim( $_GET['redirect_to'] ) ); 282 | } 283 | 284 | exit; 285 | } 286 | elseif( isset($_GET['ussync-token']) && isset($_GET['ussync-id']) && isset($_GET['ussync-ref']) ){ 287 | 288 | //decrypted user_name 289 | 290 | $user_name = trim($_GET['ussync-id']); 291 | $user_name = $this->decrypt_uri($user_name); 292 | 293 | //decrypted user_name 294 | 295 | $user_ref = ($_GET['ussync-ref']); 296 | 297 | $user_ref = $this->decrypt_uri($user_ref); 298 | 299 | //decrypted user_email 300 | 301 | $user_email = trim($_GET['ussync-token']); 302 | $user_email = $this->decrypt_uri($user_email); 303 | 304 | //set user ID 305 | 306 | $user_email = sanitize_email($user_email); 307 | 308 | //get domain list 309 | 310 | $domain_list = get_option('ussync_domain_list_'.$this -> key_num); 311 | $domain_list = explode(PHP_EOL,$domain_list); 312 | 313 | //get valid domains 314 | 315 | $domains=[]; 316 | 317 | foreach($domain_list as $domain){ 318 | 319 | $domain = trim($domain); 320 | $domain = rtrim($domain,'/'); 321 | $domain = preg_replace("(^https?://)", "", $domain); 322 | 323 | $domains[$domain]=''; 324 | } 325 | 326 | //check referer 327 | 328 | $valid_referer=false; 329 | 330 | if(isset($domains[$user_ref])){ 331 | 332 | $valid_referer=true; 333 | } 334 | 335 | if($valid_referer===true){ 336 | 337 | if(isset($_GET['ussync-status']) && $_GET['ussync-status']=='loggingout'){ 338 | 339 | // Logout user 340 | 341 | if( $user = get_user_by('email', $user_email ) ){ 342 | 343 | // get all sessions for user with ID 344 | $sessions = WP_Session_Tokens::get_instance($user->ID); 345 | 346 | // we have got the sessions, destroy them all! 347 | $sessions->destroy_all(); 348 | 349 | echo 'User logged out...'; 350 | exit; 351 | } 352 | else{ 353 | 354 | $this->decrypt_uri($_GET['ussync-token']); 355 | 356 | echo 'Error logging out...'; 357 | exit; 358 | } 359 | } 360 | else{ 361 | 362 | $current_user = wp_get_current_user(); 363 | 364 | if(!is_user_logged_in()){ 365 | 366 | // check if the user exists 367 | 368 | if( !email_exists( $user_email ) ){ 369 | 370 | $ussync_no_user = get_option('ussync_no_user_'.$this -> key_num); 371 | 372 | if($ussync_no_user=='register_suscriber'){ 373 | 374 | // register new suscriber 375 | 376 | $user_data = array( 377 | 'user_login' => $user_name, 378 | 'user_email' => $user_email, 379 | ); 380 | 381 | if( get_userdatabylogin($user_name) ){ 382 | 383 | echo 'User name already exists!'; 384 | exit; 385 | } 386 | elseif( $user_id = wp_insert_user( $user_data ) ) { 387 | 388 | // update email status 389 | 390 | add_user_meta( $user_id, 'ussync_email_verified', 'true'); 391 | } 392 | else{ 393 | 394 | echo 'Error creating a new user!'; 395 | exit; 396 | } 397 | } 398 | else{ 399 | 400 | echo 'This user doesn\'t exist...'; 401 | exit; 402 | } 403 | } 404 | 405 | // destroy current user session 406 | 407 | $sessions = WP_Session_Tokens::get_instance($current_user->ID); 408 | $sessions->destroy_all(); 409 | 410 | // get new user 411 | 412 | $user = get_user_by('email',$user_email); 413 | 414 | if( isset($user->ID) && intval($user->ID) > 0 ){ 415 | 416 | //do the authentication 417 | 418 | clean_user_cache($user->ID); 419 | 420 | wp_clear_auth_cookie(); 421 | wp_set_current_user( $user->ID ); 422 | wp_set_auth_cookie( $user->ID , true, is_ssl()); 423 | 424 | update_user_caches($user); 425 | 426 | if(is_user_logged_in()){ 427 | 428 | //redirect after authentication 429 | 430 | //wp_safe_redirect( rtrim( get_site_url(), '/' ) . '/?ussync-status=loggedin'); 431 | 432 | echo 'User '.$user->ID . ' logged in...'; 433 | exit; 434 | } 435 | } 436 | else{ 437 | 438 | echo 'Error logging in...'; 439 | exit; 440 | } 441 | } 442 | elseif($current_user->user_email != $user_email){ 443 | 444 | //wp_mail($dev_email, 'Debug user sync id ' . $current_user->ID . ' - ip ' . $this->user_ip . ' user_email: '. $current_user->user_email .' request email: '. $user_email.' $_SERVER: ' . print_r($_SERVER,true)); 445 | 446 | echo 'Another user already logged in...'; 447 | exit; 448 | } 449 | else{ 450 | 451 | echo 'User already logged in...'; 452 | exit; 453 | } 454 | } 455 | } 456 | else{ 457 | 458 | echo 'Host not allowed to synchronize...'; 459 | exit; 460 | } 461 | } 462 | elseif(is_user_logged_in() && !isset($_GET['ussync-token']) && $this->user_verified === 'true'){ 463 | 464 | //add footers 465 | 466 | if( is_admin() ) { 467 | 468 | add_action( 'admin_footer_text', array( $this, 'get_domains' )); 469 | } 470 | else{ 471 | 472 | add_action( 'wp_footer', array( $this, 'get_domains' )); 473 | } 474 | } 475 | } 476 | 477 | public function add_cors_header() { 478 | 479 | // Allow from valid origin 480 | /* 481 | if(isset($_SERVER['HTTP_ORIGIN'])) { 482 | 483 | //header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}"); 484 | header("Access-Control-Allow-Origin: *"); 485 | header('Access-Control-Allow-Credentials: true'); 486 | header('Access-Control-Max-Age: 86400'); // cache for 1 day 487 | } 488 | 489 | // Access-Control headers are received during OPTIONS requests 490 | 491 | if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { 492 | 493 | if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) 494 | header("Access-Control-Allow-Methods: GET, POST, OPTIONS"); 495 | 496 | if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) 497 | header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}"); 498 | 499 | exit(0); 500 | } 501 | */ 502 | } 503 | 504 | public function add_content_security_policy() { 505 | 506 | if( (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443 ){ 507 | 508 | header("Content-Security-Policy: upgrade-insecure-requests"); 509 | } 510 | } 511 | 512 | public function get_domains($loggingout=false){ 513 | 514 | if($user = wp_get_current_user()){ 515 | 516 | //get list of domains 517 | 518 | $domains = get_option( 'ussync_domain_list_'.$this -> key_num ); 519 | $domains = explode( PHP_EOL, $domains ); 520 | 521 | //get encrypted user name 522 | 523 | $user_name = $user->user_login; 524 | $user_name = $this->encrypt_uri($user_name); 525 | 526 | //get encrypted user email 527 | 528 | $user_email = $user->user_email; 529 | $user_email = $this->encrypt_uri($user_email); 530 | 531 | //get current domain 532 | 533 | $current_domain = get_site_url(); 534 | $current_domain = rtrim($current_domain,'/'); 535 | $current_domain = preg_replace("(^https?://)", "", $current_domain); 536 | 537 | //get encrypted user referer 538 | 539 | //$user_ref = $_SERVER['HTTP_HOST']; 540 | $user_ref = $current_domain; 541 | $user_ref = $this->encrypt_uri($user_ref); 542 | 543 | if(!empty($domains)){ 544 | 545 | foreach($domains as $domain){ 546 | 547 | $domain = trim($domain); 548 | $domain = rtrim($domain,'/'); 549 | $domain = preg_replace("(^https?://)", "", $domain); 550 | 551 | if( $loggingout===true ){ 552 | 553 | $url = $this -> proto . $domain . '/?ussync-token='.$user_email.'&ussync-key='.$this -> key_num.'&ussync-id='.$user_name.'&ussync-ref='.$user_ref.'&ussync-status=loggingout'.'&_' . time(); 554 | 555 | $response = wp_remote_get( $url, array( 556 | 557 | 'timeout' => 5, 558 | 'user-agent' => $this -> user_agent, 559 | 'headers' => array( 560 | 561 | 'X-Forwarded-For' => $this->user_ip 562 | ), 563 | )); 564 | } 565 | elseif($current_domain != $domain){ 566 | 567 | //output html 568 | 569 | //echo ''; 570 | 571 | echo''; 572 | } 573 | } 574 | 575 | if( $loggingout === true ){ 576 | 577 | wp_logout(); 578 | 579 | if(!empty($_GET['redirect_to'])){ 580 | 581 | wp_safe_redirect( trim( $_GET['redirect_to'] ) ); 582 | } 583 | else{ 584 | 585 | wp_safe_redirect( wp_login_url() ); 586 | } 587 | 588 | exit; 589 | } 590 | } 591 | } 592 | } 593 | 594 | private function get_secret_iv(){ 595 | 596 | //$secret_iv = md5( $this->user_agent . $this->user_ip ); 597 | //$secret_iv = md5( $this->user_ip ); 598 | $secret_iv = md5( 'another-secret' ); 599 | 600 | return $secret_iv; 601 | } 602 | 603 | private function encrypt_str($string){ 604 | 605 | $output = false; 606 | 607 | $encrypt_method = "AES-256-CBC"; 608 | 609 | $secret_key = md5( $this -> secret_key ); 610 | 611 | $secret_iv = $this->get_secret_iv(); 612 | 613 | // hash 614 | $key = hash('sha256', $secret_key); 615 | 616 | // iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning 617 | $iv = substr(hash('sha256', $secret_iv), 0, 16); 618 | 619 | $output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv); 620 | $output = $this->base64_urlencode($output); 621 | 622 | return $output; 623 | } 624 | 625 | private function decrypt_str($string){ 626 | 627 | $output = false; 628 | 629 | $encrypt_method = "AES-256-CBC"; 630 | 631 | $secret_key = md5( $this->secret_key ); 632 | 633 | $secret_iv = $this->get_secret_iv(); 634 | 635 | // hash 636 | $key = hash( 'sha256', $secret_key); 637 | 638 | // iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning 639 | $iv = substr( hash( 'sha256', $secret_iv ), 0, 16); 640 | 641 | $output = openssl_decrypt($this->base64_urldecode($string), $encrypt_method, $key, 0, $iv); 642 | 643 | return $output; 644 | } 645 | 646 | private function encrypt_uri($uri,$len=250,$separator='/'){ 647 | 648 | $uri = wordwrap($this->encrypt_str($uri),$len,$separator,true); 649 | 650 | return $uri; 651 | } 652 | 653 | private function decrypt_uri($uri,$separator='/'){ 654 | 655 | $uri = $this->decrypt_str(str_replace($separator,'',$uri)); 656 | 657 | return $uri; 658 | } 659 | 660 | private function base64_urlencode($inputStr=''){ 661 | 662 | return strtr(base64_encode($inputStr), '+/=', '-_,'); 663 | } 664 | 665 | private function base64_urldecode($inputStr=''){ 666 | 667 | return base64_decode(strtr($inputStr, '-_,', '+/=')); 668 | } 669 | 670 | /** 671 | * Wrapper function to register a new post type 672 | * @param string $post_type Post type name 673 | * @param string $plural Post type item plural name 674 | * @param string $single Post type item single name 675 | * @param string $description Description of post type 676 | * @return object Post type class object 677 | */ 678 | public function register_post_type ( $post_type = '', $plural = '', $single = '', $description = '', $options = array() ) { 679 | 680 | if ( ! $post_type || ! $plural || ! $single ) return; 681 | 682 | $post_type = new User_Session_Synchronizer_Post_Type( $post_type, $plural, $single, $description, $options ); 683 | 684 | return $post_type; 685 | } 686 | 687 | /** 688 | * Wrapper function to register a new taxonomy 689 | * @param string $taxonomy Taxonomy name 690 | * @param string $plural Taxonomy single name 691 | * @param string $single Taxonomy plural name 692 | * @param array $post_types Post types to which this taxonomy applies 693 | * @return object Taxonomy class object 694 | */ 695 | public function register_taxonomy ( $taxonomy = '', $plural = '', $single = '', $post_types = array(), $taxonomy_args = array() ) { 696 | 697 | if ( ! $taxonomy || ! $plural || ! $single ) return; 698 | 699 | $taxonomy = new User_Session_Synchronizer_Taxonomy( $taxonomy, $plural, $single, $post_types, $taxonomy_args ); 700 | 701 | return $taxonomy; 702 | } 703 | 704 | /** 705 | * Load frontend CSS. 706 | * @access public 707 | * @since 1.0.0 708 | * @return void 709 | */ 710 | public function enqueue_styles () { 711 | 712 | wp_register_style( $this->_token . '-frontend', esc_url( $this->assets_url ) . 'css/frontend.css', array(), $this->_version ); 713 | wp_enqueue_style( $this->_token . '-frontend' ); 714 | } // End enqueue_styles () 715 | 716 | /** 717 | * Load frontend Javascript. 718 | * @access public 719 | * @since 1.0.0 720 | * @return void 721 | */ 722 | public function enqueue_scripts () { 723 | wp_register_script( $this->_token . '-frontend', esc_url( $this->assets_url ) . 'js/frontend' . $this->script_suffix . '.js', array( 'jquery' ), $this->_version ); 724 | wp_enqueue_script( $this->_token . '-frontend' ); 725 | } // End enqueue_scripts () 726 | 727 | /** 728 | * Load admin CSS. 729 | * @access public 730 | * @since 1.0.0 731 | * @return void 732 | */ 733 | public function admin_enqueue_styles ( $hook = '' ) { 734 | wp_register_style( $this->_token . '-admin', esc_url( $this->assets_url ) . 'css/admin.css', array(), $this->_version ); 735 | wp_enqueue_style( $this->_token . '-admin' ); 736 | } // End admin_enqueue_styles () 737 | 738 | /** 739 | * Load admin Javascript. 740 | * @access public 741 | * @since 1.0.0 742 | * @return void 743 | */ 744 | public function admin_enqueue_scripts ( $hook = '' ) { 745 | wp_register_script( $this->_token . '-admin', esc_url( $this->assets_url ) . 'js/admin' . $this->script_suffix . '.js', array( 'jquery' ), $this->_version ); 746 | wp_enqueue_script( $this->_token . '-admin' ); 747 | } // End admin_enqueue_scripts () 748 | 749 | /** 750 | * Load plugin localisation 751 | * @access public 752 | * @since 1.0.0 753 | * @return void 754 | */ 755 | public function load_localisation () { 756 | load_plugin_textdomain( 'user-session-synchronizer', false, dirname( plugin_basename( $this->file ) ) . '/lang/' ); 757 | } // End load_localisation () 758 | 759 | /** 760 | * Load plugin textdomain 761 | * @access public 762 | * @since 1.0.0 763 | * @return void 764 | */ 765 | public function load_plugin_textdomain () { 766 | $domain = 'user-session-synchronizer'; 767 | 768 | $locale = apply_filters( 'plugin_locale', get_locale(), $domain ); 769 | 770 | load_textdomain( $domain, WP_LANG_DIR . '/' . $domain . '/' . $domain . '-' . $locale . '.mo' ); 771 | load_plugin_textdomain( $domain, false, dirname( plugin_basename( $this->file ) ) . '/lang/' ); 772 | } // End load_plugin_textdomain () 773 | 774 | /** 775 | * Main User_Session_Synchronizer Instance 776 | * 777 | * Ensures only one instance of User_Session_Synchronizer is loaded or can be loaded. 778 | * 779 | * @since 1.0.0 780 | * @static 781 | * @see User_Session_Synchronizer() 782 | * @return Main User_Session_Synchronizer instance 783 | */ 784 | public static function instance ( $file = '', $version = '1.0.0' ) { 785 | if ( is_null( self::$_instance ) ) { 786 | self::$_instance = new self( $file, $version ); 787 | } 788 | return self::$_instance; 789 | } // End instance () 790 | 791 | /** 792 | * Cloning is forbidden. 793 | * 794 | * @since 1.0.0 795 | */ 796 | public function __clone () { 797 | _doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh?' ), $this->_version ); 798 | } // End __clone () 799 | 800 | /** 801 | * Unserializing instances of this class is forbidden. 802 | * 803 | * @since 1.0.0 804 | */ 805 | public function __wakeup () { 806 | _doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh?' ), $this->_version ); 807 | } // End __wakeup () 808 | 809 | /** 810 | * Installation. Runs on activation. 811 | * @access public 812 | * @since 1.0.0 813 | * @return void 814 | */ 815 | public function install () { 816 | $this->_log_version_number(); 817 | } // End install () 818 | 819 | /** 820 | * Log the plugin version number. 821 | * @access public 822 | * @since 1.0.0 823 | * @return void 824 | */ 825 | private function _log_version_number () { 826 | update_option( $this->_token . '_version', $this->_version ); 827 | } // End _log_version_number () 828 | } 829 | -------------------------------------------------------------------------------- /includes/images/menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafasashi/user-session-synchronizer/ebc2ba63e33266448b6954c0343243e8b4e14250/includes/images/menu.png -------------------------------------------------------------------------------- /includes/images/right_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafasashi/user-session-synchronizer/ebc2ba63e33266448b6954c0343243e8b4e14250/includes/images/right_arrow.png -------------------------------------------------------------------------------- /includes/images/send.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafasashi/user-session-synchronizer/ebc2ba63e33266448b6954c0343243e8b4e14250/includes/images/send.png -------------------------------------------------------------------------------- /includes/images/time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafasashi/user-session-synchronizer/ebc2ba63e33266448b6954c0343243e8b4e14250/includes/images/time.png -------------------------------------------------------------------------------- /includes/images/wrong_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafasashi/user-session-synchronizer/ebc2ba63e33266448b6954c0343243e8b4e14250/includes/images/wrong_arrow.png -------------------------------------------------------------------------------- /includes/lib/class-user-session-synchronizer-admin-api.php: -------------------------------------------------------------------------------- 1 | ID, $field['id'], true ); 42 | 43 | // Get data to display in field 44 | if ( isset( $option ) ) { 45 | $data = $option; 46 | } 47 | 48 | } 49 | else { 50 | 51 | // Get saved option 52 | $option_name .= $field['id']; 53 | $option = get_option( $option_name ); 54 | 55 | // Get data to display in field 56 | if ( isset( $option ) ) { 57 | $data = $option; 58 | } 59 | 60 | } 61 | 62 | // Show default data if no option saved and default is supplied 63 | if ( $data === false && isset( $field['default'] ) ) { 64 | $data = $field['default']; 65 | } elseif ( $data === false ) { 66 | $data = ''; 67 | } 68 | 69 | $html = ''; 70 | 71 | switch( $field['type'] ) { 72 | 73 | case 'text': 74 | case 'url': 75 | case 'email': 76 | $html .= '' . "\n"; 77 | break; 78 | 79 | case 'password': 80 | case 'number': 81 | case 'hidden': 82 | $min = ''; 83 | if ( isset( $field['min'] ) ) { 84 | $min = ' min="' . esc_attr( $field['min'] ) . '"'; 85 | } 86 | 87 | $max = ''; 88 | if ( isset( $field['max'] ) ) { 89 | $max = ' max="' . esc_attr( $field['max'] ) . '"'; 90 | } 91 | $html .= '' . "\n"; 92 | break; 93 | 94 | case 'text_secret': 95 | $html .= '' . "\n"; 96 | break; 97 | 98 | case 'textarea': 99 | $html .= '
'. "\n"; 100 | break; 101 | 102 | case 'checkbox': 103 | $checked = ''; 104 | if ( $data && 'on' == $data ) { 105 | $checked = 'checked="checked"'; 106 | } 107 | $html .= '' . "\n"; 108 | break; 109 | 110 | case 'checkbox_multi': 111 | foreach ( $field['options'] as $k => $v ) { 112 | $checked = false; 113 | if ( in_array( $k, (array) $data ) ) { 114 | $checked = true; 115 | } 116 | $html .= ' '; 117 | } 118 | break; 119 | 120 | case 'radio': 121 | foreach ( $field['options'] as $k => $v ) { 122 | $checked = false; 123 | if ( $k == $data ) { 124 | $checked = true; 125 | } 126 | $html .= ' '; 127 | } 128 | break; 129 | 130 | case 'select': 131 | $html .= ' '; 140 | break; 141 | 142 | case 'select_multi': 143 | $html .= ' '; 152 | break; 153 | 154 | case 'image': 155 | $image_thumb = ''; 156 | if ( $data ) { 157 | $image_thumb = wp_get_attachment_thumb_url( $data ); 158 | } 159 | $html .= '
' . "\n"; 160 | $html .= '' . "\n"; 161 | $html .= '' . "\n"; 162 | $html .= '
' . "\n"; 163 | break; 164 | 165 | case 'color': 166 | ?>
167 | 168 |
169 |
170 | ' . $field['description'] . ''; 181 | break; 182 | 183 | default: 184 | if ( ! $post ) { 185 | $html .= '' . "\n"; 192 | } 193 | break; 194 | } 195 | 196 | if ( ! $echo ) { 197 | return $html; 198 | } 199 | 200 | echo $html; 201 | 202 | } 203 | 204 | /** 205 | * Validate form field 206 | * @param string $data Submitted value 207 | * @param string $type Type of field to validate 208 | * @return string Validated value 209 | */ 210 | public function validate_field ( $data = '', $type = 'text' ) { 211 | 212 | switch( $type ) { 213 | case 'text': $data = esc_attr( $data ); break; 214 | case 'url': $data = esc_url( $data ); break; 215 | case 'email': $data = is_email( $data ); break; 216 | } 217 | 218 | return $data; 219 | } 220 | 221 | /** 222 | * Add meta box to the dashboard 223 | * @param string $id Unique ID for metabox 224 | * @param string $title Display title of metabox 225 | * @param array $post_types Post types to which this metabox applies 226 | * @param string $context Context in which to display this metabox ('advanced' or 'side') 227 | * @param string $priority Priority of this metabox ('default', 'low' or 'high') 228 | * @param array $callback_args Any axtra arguments that will be passed to the display function for this metabox 229 | * @return void 230 | */ 231 | public function add_meta_box ( $id = '', $title = '', $post_types = array(), $context = 'advanced', $priority = 'default', $callback_args = null ) { 232 | 233 | // Get post type(s) 234 | if ( ! is_array( $post_types ) ) { 235 | $post_types = array( $post_types ); 236 | } 237 | 238 | // Generate each metabox 239 | foreach ( $post_types as $post_type ) { 240 | add_meta_box( $id, $title, array( $this, 'meta_box_content' ), $post_type, $context, $priority, $callback_args ); 241 | } 242 | } 243 | 244 | /** 245 | * Display metabox content 246 | * @param object $post Post object 247 | * @param array $args Arguments unique to this metabox 248 | * @return void 249 | */ 250 | public function meta_box_content ( $post, $args ) { 251 | 252 | $fields = apply_filters( $post->post_type . '_custom_fields', array(), $post->post_type ); 253 | 254 | if ( ! is_array( $fields ) || 0 == count( $fields ) ) return; 255 | 256 | echo '
' . "\n"; 257 | 258 | foreach ( $fields as $field ) { 259 | 260 | if ( ! isset( $field['metabox'] ) ) continue; 261 | 262 | if ( ! is_array( $field['metabox'] ) ) { 263 | $field['metabox'] = array( $field['metabox'] ); 264 | } 265 | 266 | if ( in_array( $args['id'], $field['metabox'] ) ) { 267 | $this->display_meta_box_field( $field, $post ); 268 | } 269 | 270 | } 271 | 272 | echo '
' . "\n"; 273 | 274 | } 275 | 276 | /** 277 | * Dispay field in metabox 278 | * @param array $field Field data 279 | * @param object $post Post object 280 | * @return void 281 | */ 282 | public function display_meta_box_field ( $field = array(), $post ) { 283 | 284 | if ( ! is_array( $field ) || 0 == count( $field ) ) return; 285 | 286 | $field = '

' . $this->display_field( $field, $post, false ) . '

' . "\n"; 287 | 288 | echo $field; 289 | } 290 | 291 | /** 292 | * Save metabox fields 293 | * @param integer $post_id Post ID 294 | * @return void 295 | */ 296 | public function save_meta_boxes ( $post_id = 0 ) { 297 | 298 | if( !$post_id || ( isset($_POST['_inline_edit']) && wp_verify_nonce($_POST['_inline_edit'],'inlineeditnonce') ) ) return; 299 | 300 | $post_type = get_post_type( $post_id ); 301 | 302 | $fields = apply_filters( $post_type . '_custom_fields', array(), $post_type ); 303 | 304 | if ( ! is_array( $fields ) || 0 == count( $fields ) ) return; 305 | 306 | foreach ( $fields as $field ) { 307 | if ( isset( $_REQUEST[ $field['id'] ] ) ) { 308 | update_post_meta( $post_id, $field['id'], $this->validate_field( $_REQUEST[ $field['id'] ], $field['type'] ) ); 309 | } else { 310 | update_post_meta( $post_id, $field['id'], '' ); 311 | } 312 | } 313 | } 314 | 315 | } -------------------------------------------------------------------------------- /includes/lib/class-user-session-synchronizer-post-type.php: -------------------------------------------------------------------------------- 1 | post_type = $post_type; 53 | $this->plural = $plural; 54 | $this->single = $single; 55 | $this->description = $description; 56 | $this->options = $options; 57 | 58 | // Regsiter post type 59 | add_action( 'init' , array( $this, 'register_post_type' ) ); 60 | 61 | // Display custom update messages for posts edits 62 | add_filter( 'post_updated_messages', array( $this, 'updated_messages' ) ); 63 | add_filter( 'bulk_post_updated_messages', array( $this, 'bulk_updated_messages' ), 10, 2 ); 64 | } 65 | 66 | /** 67 | * Register new post type 68 | * @return void 69 | */ 70 | public function register_post_type () { 71 | 72 | $labels = array( 73 | 'name' => $this->plural, 74 | 'singular_name' => $this->single, 75 | 'name_admin_bar' => $this->single, 76 | 'add_new' => _x( 'Add New', $this->post_type , 'user-session-synchronizer' ), 77 | 'add_new_item' => sprintf( __( 'Add New %s' , 'user-session-synchronizer' ), $this->single ), 78 | 'edit_item' => sprintf( __( 'Edit %s' , 'user-session-synchronizer' ), $this->single ), 79 | 'new_item' => sprintf( __( 'New %s' , 'user-session-synchronizer' ), $this->single ), 80 | 'all_items' => sprintf( __( 'All %s' , 'user-session-synchronizer' ), $this->plural ), 81 | 'view_item' => sprintf( __( 'View %s' , 'user-session-synchronizer' ), $this->single ), 82 | 'search_items' => sprintf( __( 'Search %s' , 'user-session-synchronizer' ), $this->plural ), 83 | 'not_found' => sprintf( __( 'No %s Found' , 'user-session-synchronizer' ), $this->plural ), 84 | 'not_found_in_trash' => sprintf( __( 'No %s Found In Trash' , 'user-session-synchronizer' ), $this->plural ), 85 | 'parent_item_colon' => sprintf( __( 'Parent %s' ), $this->single ), 86 | 'menu_name' => $this->plural, 87 | ); 88 | 89 | $args = array( 90 | 'labels' => apply_filters( $this->post_type . '_labels', $labels ), 91 | 'description' => $this->description, 92 | 'public' => true, 93 | 'publicly_queryable' => true, 94 | 'exclude_from_search' => false, 95 | 'show_ui' => true, 96 | 'show_in_menu' => true, 97 | 'show_in_nav_menus' => true, 98 | 'query_var' => true, 99 | 'can_export' => true, 100 | 'rewrite' => true, 101 | 'capability_type' => 'post', 102 | 'has_archive' => true, 103 | 'hierarchical' => true, 104 | 'show_in_rest' => true, 105 | 'rest_base' => $this->post_type, 106 | 'rest_controller_class' => 'WP_REST_Posts_Controller', 107 | 'supports' => array( 'title', 'editor', 'excerpt', 'comments', 'thumbnail' ), 108 | 'menu_position' => 5, 109 | 'menu_icon' => 'dashicons-admin-post', 110 | ); 111 | 112 | $args = array_merge($args, $this->options); 113 | 114 | register_post_type( $this->post_type, apply_filters( $this->post_type . '_register_args', $args, $this->post_type ) ); 115 | } 116 | 117 | /** 118 | * Set up admin messages for post type 119 | * @param array $messages Default message 120 | * @return array Modified messages 121 | */ 122 | public function updated_messages ( $messages = array() ) { 123 | global $post, $post_ID; 124 | 125 | $messages[ $this->post_type ] = array( 126 | 0 => '', 127 | 1 => sprintf( __( '%1$s updated. %2$sView %3$s%4$s.' , 'user-session-synchronizer' ), $this->single, '', $this->single, '' ), 128 | 2 => __( 'Custom field updated.' , 'user-session-synchronizer' ), 129 | 3 => __( 'Custom field deleted.' , 'user-session-synchronizer' ), 130 | 4 => sprintf( __( '%1$s updated.' , 'user-session-synchronizer' ), $this->single ), 131 | 5 => isset( $_GET['revision'] ) ? sprintf( __( '%1$s restored to revision from %2$s.' , 'user-session-synchronizer' ), $this->single, wp_post_revision_title( (int) $_GET['revision'], false ) ) : false, 132 | 6 => sprintf( __( '%1$s published. %2$sView %3$s%4s.' , 'user-session-synchronizer' ), $this->single, '', $this->single, '' ), 133 | 7 => sprintf( __( '%1$s saved.' , 'user-session-synchronizer' ), $this->single ), 134 | 8 => sprintf( __( '%1$s submitted. %2$sPreview post%3$s%4$s.' , 'user-session-synchronizer' ), $this->single, '', $this->single, '' ), 135 | 9 => sprintf( __( '%1$s scheduled for: %2$s. %3$sPreview %4$s%5$s.' , 'user-session-synchronizer' ), $this->single, '' . date_i18n( __( 'M j, Y @ G:i' , 'user-session-synchronizer' ), strtotime( $post->post_date ) ) . '', '', $this->single, '' ), 136 | 10 => sprintf( __( '%1$s draft updated. %2$sPreview %3$s%4$s.' , 'user-session-synchronizer' ), $this->single, '', $this->single, '' ), 137 | ); 138 | 139 | return $messages; 140 | } 141 | 142 | /** 143 | * Set up bulk admin messages for post type 144 | * @param array $bulk_messages Default bulk messages 145 | * @param array $bulk_counts Counts of selected posts in each status 146 | * @return array Modified messages 147 | */ 148 | public function bulk_updated_messages ( $bulk_messages = array(), $bulk_counts = array() ) { 149 | 150 | $bulk_messages[ $this->post_type ] = array( 151 | 'updated' => sprintf( _n( '%1$s %2$s updated.', '%1$s %3$s updated.', $bulk_counts['updated'], 'user-session-synchronizer' ), $bulk_counts['updated'], $this->single, $this->plural ), 152 | 'locked' => sprintf( _n( '%1$s %2$s not updated, somebody is editing it.', '%1$s %3$s not updated, somebody is editing them.', $bulk_counts['locked'], 'user-session-synchronizer' ), $bulk_counts['locked'], $this->single, $this->plural ), 153 | 'deleted' => sprintf( _n( '%1$s %2$s permanently deleted.', '%1$s %3$s permanently deleted.', $bulk_counts['deleted'], 'user-session-synchronizer' ), $bulk_counts['deleted'], $this->single, $this->plural ), 154 | 'trashed' => sprintf( _n( '%1$s %2$s moved to the Trash.', '%1$s %3$s moved to the Trash.', $bulk_counts['trashed'], 'user-session-synchronizer' ), $bulk_counts['trashed'], $this->single, $this->plural ), 155 | 'untrashed' => sprintf( _n( '%1$s %2$s restored from the Trash.', '%1$s %3$s restored from the Trash.', $bulk_counts['untrashed'], 'user-session-synchronizer' ), $bulk_counts['untrashed'], $this->single, $this->plural ), 156 | ); 157 | 158 | return $bulk_messages; 159 | } 160 | 161 | } 162 | -------------------------------------------------------------------------------- /includes/lib/class-user-session-synchronizer-taxonomy.php: -------------------------------------------------------------------------------- 1 | taxonomy = $taxonomy; 53 | $this->plural = $plural; 54 | $this->single = $single; 55 | if ( ! is_array( $post_types ) ) { 56 | $post_types = array( $post_types ); 57 | } 58 | $this->post_types = $post_types; 59 | $this->taxonomy_args = $tax_args; 60 | 61 | // Register taxonomy 62 | add_action('init', array( $this, 'register_taxonomy' ) ); 63 | } 64 | 65 | /** 66 | * Register new taxonomy 67 | * @return void 68 | */ 69 | public function register_taxonomy () { 70 | 71 | $labels = array( 72 | 'name' => $this->plural, 73 | 'singular_name' => $this->single, 74 | 'menu_name' => $this->plural, 75 | 'all_items' => sprintf( __( 'All %s' , 'user-session-synchronizer' ), $this->plural ), 76 | 'edit_item' => sprintf( __( 'Edit %s' , 'user-session-synchronizer' ), $this->single ), 77 | 'view_item' => sprintf( __( 'View %s' , 'user-session-synchronizer' ), $this->single ), 78 | 'update_item' => sprintf( __( 'Update %s' , 'user-session-synchronizer' ), $this->single ), 79 | 'add_new_item' => sprintf( __( 'Add New %s' , 'user-session-synchronizer' ), $this->single ), 80 | 'new_item_name' => sprintf( __( 'New %s Name' , 'user-session-synchronizer' ), $this->single ), 81 | 'parent_item' => sprintf( __( 'Parent %s' , 'user-session-synchronizer' ), $this->single ), 82 | 'parent_item_colon' => sprintf( __( 'Parent %s:' , 'user-session-synchronizer' ), $this->single ), 83 | 'search_items' => sprintf( __( 'Search %s' , 'user-session-synchronizer' ), $this->plural ), 84 | 'popular_items' => sprintf( __( 'Popular %s' , 'user-session-synchronizer' ), $this->plural ), 85 | 'separate_items_with_commas' => sprintf( __( 'Separate %s with commas' , 'user-session-synchronizer' ), $this->plural ), 86 | 'add_or_remove_items' => sprintf( __( 'Add or remove %s' , 'user-session-synchronizer' ), $this->plural ), 87 | 'choose_from_most_used' => sprintf( __( 'Choose from the most used %s' , 'user-session-synchronizer' ), $this->plural ), 88 | 'not_found' => sprintf( __( 'No %s found' , 'user-session-synchronizer' ), $this->plural ), 89 | ); 90 | 91 | $args = array( 92 | 'label' => $this->plural, 93 | 'labels' => apply_filters( $this->taxonomy . '_labels', $labels ), 94 | 'hierarchical' => true, 95 | 'public' => true, 96 | 'show_ui' => true, 97 | 'show_in_nav_menus' => true, 98 | 'show_tagcloud' => true, 99 | 'meta_box_cb' => null, 100 | 'show_admin_column' => true, 101 | 'update_count_callback' => '', 102 | 'show_in_rest' => true, 103 | 'rest_base' => $this->taxonomy, 104 | 'rest_controller_class' => 'WP_REST_Terms_Controller', 105 | 'query_var' => $this->taxonomy, 106 | 'rewrite' => true, 107 | 'sort' => '', 108 | ); 109 | 110 | $args = array_merge($args, $this->taxonomy_args); 111 | 112 | register_taxonomy( $this->taxonomy, $this->post_types, apply_filters( $this->taxonomy . '_register_args', $args, $this->taxonomy, $this->post_types ) ); 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /includes/views/demo_email.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
Email Verification
Please Verify your email Account:
[ussyncemailverificationcode]
(c) 2000-2016
21 | -------------------------------------------------------------------------------- /includes/views/email-setting.php: -------------------------------------------------------------------------------- 1 | activate_plugins_email(); 19 | 20 | $email_title=get_option("ussync_email_conf_title"); 21 | $email_sender=get_option("ussync_email_confemail"); 22 | $email_content=get_option("ussync-email-header"); 23 | } 24 | ?> 25 | 56 | 57 |
58 |

Email Verification Template Settings

59 | $value) { 62 | update_option($ussync_em_key, stripslashes($value)); 63 | } 64 | echo "
Template Is saved
"; 65 | } 66 | // echo do_shortcode("[ussyncemailverificationcode]"); 67 | ?> 68 |
69 |
70 |
71 | 72 | 73 |
74 |
75 | 76 | 77 |
78 | 79 |
80 | 81 | 82 |
83 |
84 | "/> 85 |
86 |
87 |
88 |
89 | 94 |
95 |
96 |
-------------------------------------------------------------------------------- /includes/views/email-verification.php: -------------------------------------------------------------------------------- 1 | 32 |
33 | $_POST["ussync_email_user_role"]); 38 | $user_query = new WP_User_Query($args); 39 | $userEmail = array(); 40 | if (!empty($user_query->results)) { 41 | foreach ($user_query->results as $user) { 42 | update_user_meta($user->ID, "ussync_email_verified", "true"); 43 | $userEmail[] = "verified"; 44 | } 45 | ?> 46 |

users is verified.

47 | 50 |

users is verified.

51 | 55 | 56 |
57 |
58 |

User Email Verification

59 |
60 | 61 | 62 |
63 |
64 | 65 | 68 | "/> 69 |
70 |
71 |
72 | 73 |
-------------------------------------------------------------------------------- /includes/views/logging-in.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | Loading... 8 | 9 |
10 | 11 | 12 | 13 | get_domains(); ?> 14 | 15 | Loading... 16 | 17 | 18 | 19 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | \n" 13 | "Language-Team: LANGUAGE \n" 14 | 15 | #: classes/post-types/class-user-session-synchronizer-post_type.php:52 16 | #: includes/post-types/class-user-session-synchronizer-post_type.php:42 17 | msgctxt "post type general name" 18 | msgid "Post Type" 19 | msgstr "" 20 | 21 | #: classes/post-types/class-user-session-synchronizer-post_type.php:53 22 | #: includes/post-types/class-user-session-synchronizer-post_type.php:43 23 | msgctxt "post type singular name" 24 | msgid "Post Type" 25 | msgstr "" 26 | 27 | #: classes/post-types/class-user-session-synchronizer-post_type.php:55 28 | #: includes/post-types/class-user-session-synchronizer-post_type.php:45 29 | msgid "Add New %s" 30 | msgstr "" 31 | 32 | #: classes/post-types/class-user-session-synchronizer-post_type.php:55 33 | #: classes/post-types/class-user-session-synchronizer-post_type.php:56 34 | #: classes/post-types/class-user-session-synchronizer-post_type.php:57 35 | #: classes/post-types/class-user-session-synchronizer-post_type.php:59 36 | #: includes/post-types/class-user-session-synchronizer-post_type.php:45 37 | #: includes/post-types/class-user-session-synchronizer-post_type.php:46 38 | #: includes/post-types/class-user-session-synchronizer-post_type.php:47 39 | #: includes/post-types/class-user-session-synchronizer-post_type.php:49 40 | msgid "Post" 41 | msgstr "" 42 | 43 | #: classes/post-types/class-user-session-synchronizer-post_type.php:56 44 | #: includes/post-types/class-user-session-synchronizer-post_type.php:46 45 | msgid "Edit %s" 46 | msgstr "" 47 | 48 | #: classes/post-types/class-user-session-synchronizer-post_type.php:57 49 | #: includes/post-types/class-user-session-synchronizer-post_type.php:47 50 | msgid "New %s" 51 | msgstr "" 52 | 53 | #: classes/post-types/class-user-session-synchronizer-post_type.php:58 54 | #: includes/post-types/class-user-session-synchronizer-post_type.php:48 55 | msgid "All %s" 56 | msgstr "" 57 | 58 | #: classes/post-types/class-user-session-synchronizer-post_type.php:58 59 | #: classes/post-types/class-user-session-synchronizer-post_type.php:60 60 | #: classes/post-types/class-user-session-synchronizer-post_type.php:61 61 | #: classes/post-types/class-user-session-synchronizer-post_type.php:62 62 | #: includes/post-types/class-user-session-synchronizer-post_type.php:48 63 | #: includes/post-types/class-user-session-synchronizer-post_type.php:50 64 | #: includes/post-types/class-user-session-synchronizer-post_type.php:51 65 | #: includes/post-types/class-user-session-synchronizer-post_type.php:52 66 | msgid "Posts" 67 | msgstr "" 68 | 69 | #: classes/post-types/class-user-session-synchronizer-post_type.php:59 70 | #: includes/post-types/class-user-session-synchronizer-post_type.php:49 71 | msgid "View %s" 72 | msgstr "" 73 | 74 | #: classes/post-types/class-user-session-synchronizer-post_type.php:60 75 | #: includes/post-types/class-user-session-synchronizer-post_type.php:50 76 | msgid "Search %a" 77 | msgstr "" 78 | 79 | #: classes/post-types/class-user-session-synchronizer-post_type.php:61 80 | #: includes/post-types/class-user-session-synchronizer-post_type.php:51 81 | msgid "No %s Found" 82 | msgstr "" 83 | 84 | #: classes/post-types/class-user-session-synchronizer-post_type.php:62 85 | #: includes/post-types/class-user-session-synchronizer-post_type.php:52 86 | msgid "No %s Found In Trash" 87 | msgstr "" 88 | 89 | #: classes/post-types/class-user-session-synchronizer-post_type.php:64 90 | #: includes/post-types/class-user-session-synchronizer-post_type.php:54 91 | msgid "*Posts" 92 | msgstr "" 93 | 94 | #: classes/post-types/class-user-session-synchronizer-post_type.php:95 95 | #: classes/post-types/class-user-session-synchronizer-post_type.php:105 96 | #: includes/post-types/class-user-session-synchronizer-post_type.php:85 97 | #: includes/post-types/class-user-session-synchronizer-post_type.php:95 98 | msgid "Terms" 99 | msgstr "" 100 | 101 | #: classes/post-types/class-user-session-synchronizer-post_type.php:96 102 | #: includes/post-types/class-user-session-synchronizer-post_type.php:86 103 | msgid "Term" 104 | msgstr "" 105 | 106 | #: classes/post-types/class-user-session-synchronizer-post_type.php:97 107 | #: includes/post-types/class-user-session-synchronizer-post_type.php:87 108 | msgid "Search Terms" 109 | msgstr "" 110 | 111 | #: classes/post-types/class-user-session-synchronizer-post_type.php:98 112 | #: includes/post-types/class-user-session-synchronizer-post_type.php:88 113 | msgid "All Terms" 114 | msgstr "" 115 | 116 | #: classes/post-types/class-user-session-synchronizer-post_type.php:99 117 | #: includes/post-types/class-user-session-synchronizer-post_type.php:89 118 | msgid "Parent Term" 119 | msgstr "" 120 | 121 | #: classes/post-types/class-user-session-synchronizer-post_type.php:100 122 | #: includes/post-types/class-user-session-synchronizer-post_type.php:90 123 | msgid "Parent Term:" 124 | msgstr "" 125 | 126 | #: classes/post-types/class-user-session-synchronizer-post_type.php:101 127 | #: includes/post-types/class-user-session-synchronizer-post_type.php:91 128 | msgid "Edit Term" 129 | msgstr "" 130 | 131 | #: classes/post-types/class-user-session-synchronizer-post_type.php:102 132 | #: includes/post-types/class-user-session-synchronizer-post_type.php:92 133 | msgid "Update Term" 134 | msgstr "" 135 | 136 | #: classes/post-types/class-user-session-synchronizer-post_type.php:103 137 | #: includes/post-types/class-user-session-synchronizer-post_type.php:93 138 | msgid "Add New Term" 139 | msgstr "" 140 | 141 | #: classes/post-types/class-user-session-synchronizer-post_type.php:104 142 | #: includes/post-types/class-user-session-synchronizer-post_type.php:94 143 | msgid "New Term Name" 144 | msgstr "" 145 | 146 | #: classes/post-types/class-user-session-synchronizer-post_type.php:125 147 | #: includes/post-types/class-user-session-synchronizer-post_type.php:115 148 | msgid "Custom Field" 149 | msgstr "" 150 | 151 | #: classes/post-types/class-user-session-synchronizer-post_type.php:180 152 | #: includes/post-types/class-user-session-synchronizer-post_type.php:170 153 | msgid "Post updated. %sView post%s." 154 | msgstr "" 155 | 156 | #: classes/post-types/class-user-session-synchronizer-post_type.php:181 157 | #: includes/post-types/class-user-session-synchronizer-post_type.php:171 158 | msgid "Custom field updated." 159 | msgstr "" 160 | 161 | #: classes/post-types/class-user-session-synchronizer-post_type.php:182 162 | #: includes/post-types/class-user-session-synchronizer-post_type.php:172 163 | msgid "Custom field deleted." 164 | msgstr "" 165 | 166 | #: classes/post-types/class-user-session-synchronizer-post_type.php:183 167 | #: includes/post-types/class-user-session-synchronizer-post_type.php:173 168 | msgid "Post updated." 169 | msgstr "" 170 | 171 | #. translators: %s: date and time of the revision 172 | 173 | #: classes/post-types/class-user-session-synchronizer-post_type.php:185 174 | #: includes/post-types/class-user-session-synchronizer-post_type.php:175 175 | msgid "Post restored to revision from %s." 176 | msgstr "" 177 | 178 | #: classes/post-types/class-user-session-synchronizer-post_type.php:186 179 | #: includes/post-types/class-user-session-synchronizer-post_type.php:176 180 | msgid "Post published. %sView post%s." 181 | msgstr "" 182 | 183 | #: classes/post-types/class-user-session-synchronizer-post_type.php:187 184 | #: includes/post-types/class-user-session-synchronizer-post_type.php:177 185 | msgid "Post saved." 186 | msgstr "" 187 | 188 | #: classes/post-types/class-user-session-synchronizer-post_type.php:188 189 | #: includes/post-types/class-user-session-synchronizer-post_type.php:178 190 | msgid "Post submitted. %sPreview post%s." 191 | msgstr "" 192 | 193 | #: classes/post-types/class-user-session-synchronizer-post_type.php:189 194 | #: includes/post-types/class-user-session-synchronizer-post_type.php:179 195 | msgid "Post scheduled for: %1$s. %2$sPreview post%3$s." 196 | msgstr "" 197 | 198 | #: classes/post-types/class-user-session-synchronizer-post_type.php:189 199 | #: includes/post-types/class-user-session-synchronizer-post_type.php:179 200 | msgid "M j, Y @ G:i" 201 | msgstr "" 202 | 203 | #: classes/post-types/class-user-session-synchronizer-post_type.php:190 204 | #: includes/post-types/class-user-session-synchronizer-post_type.php:180 205 | msgid "Post draft updated. %sPreview post%s." 206 | msgstr "" 207 | 208 | #: classes/post-types/class-user-session-synchronizer-post_type.php:201 209 | #: includes/post-types/class-user-session-synchronizer-post_type.php:191 210 | msgid "Post Details" 211 | msgstr "" 212 | 213 | #: classes/post-types/class-user-session-synchronizer-post_type.php:295 214 | #: includes/post-types/class-user-session-synchronizer-post_type.php:285 215 | msgid "Enter the post title here" 216 | msgstr "" 217 | 218 | #: classes/post-types/class-user-session-synchronizer-post_type.php:308 219 | #: includes/post-types/class-user-session-synchronizer-post_type.php:298 220 | msgid "Custom field:" 221 | msgstr "" 222 | 223 | #: classes/post-types/class-user-session-synchronizer-post_type.php:309 224 | #: includes/post-types/class-user-session-synchronizer-post_type.php:299 225 | msgid "Description of this custom field." 226 | msgstr "" 227 | 228 | #: includes/class-user-session-synchronizer-settings.php:70 229 | #: includes/class-user-session-synchronizer-settings.php:405 230 | msgid "User Session Synchronizer" 231 | msgstr "" 232 | 233 | #: includes/class-user-session-synchronizer-settings.php:99 234 | msgid "Settings" 235 | msgstr "" 236 | 237 | #: includes/class-user-session-synchronizer-settings.php:111 238 | msgid "Standard" 239 | msgstr "" 240 | 241 | #: includes/class-user-session-synchronizer-settings.php:112 242 | msgid "These are fairly standard form input fields." 243 | msgstr "" 244 | 245 | #: includes/class-user-session-synchronizer-settings.php:116 246 | msgid "Some Text" 247 | msgstr "" 248 | 249 | #: includes/class-user-session-synchronizer-settings.php:117 250 | msgid "This is a standard text field." 251 | msgstr "" 252 | 253 | #: includes/class-user-session-synchronizer-settings.php:120 254 | #: includes/class-user-session-synchronizer-settings.php:128 255 | #: includes/class-user-session-synchronizer-settings.php:136 256 | msgid "Placeholder text" 257 | msgstr "" 258 | 259 | #: includes/class-user-session-synchronizer-settings.php:124 260 | msgid "A Password" 261 | msgstr "" 262 | 263 | #: includes/class-user-session-synchronizer-settings.php:125 264 | msgid "This is a standard password field." 265 | msgstr "" 266 | 267 | #: includes/class-user-session-synchronizer-settings.php:132 268 | msgid "Some Secret Text" 269 | msgstr "" 270 | 271 | #: includes/class-user-session-synchronizer-settings.php:133 272 | msgid "This is a secret text field - any data saved here will not be displayed after the page has reloaded, but it will be saved." 273 | msgstr "" 274 | 275 | #: includes/class-user-session-synchronizer-settings.php:140 276 | msgid "A Text Block" 277 | msgstr "" 278 | 279 | #: includes/class-user-session-synchronizer-settings.php:141 280 | msgid "This is a standard text area." 281 | msgstr "" 282 | 283 | #: includes/class-user-session-synchronizer-settings.php:144 284 | msgid "Placeholder text for this textarea" 285 | msgstr "" 286 | 287 | #: includes/class-user-session-synchronizer-settings.php:148 288 | msgid "An Option" 289 | msgstr "" 290 | 291 | #: includes/class-user-session-synchronizer-settings.php:149 292 | msgid "A standard checkbox - if you save this option as checked then it will store the option as 'on', otherwise it will be an empty string." 293 | msgstr "" 294 | 295 | #: includes/class-user-session-synchronizer-settings.php:155 296 | msgid "A Select Box" 297 | msgstr "" 298 | 299 | #: includes/class-user-session-synchronizer-settings.php:156 300 | msgid "A standard select box." 301 | msgstr "" 302 | 303 | #: includes/class-user-session-synchronizer-settings.php:163 304 | msgid "Some Options" 305 | msgstr "" 306 | 307 | #: includes/class-user-session-synchronizer-settings.php:164 308 | msgid "A standard set of radio buttons." 309 | msgstr "" 310 | 311 | #: includes/class-user-session-synchronizer-settings.php:171 312 | msgid "Some Items" 313 | msgstr "" 314 | 315 | #: includes/class-user-session-synchronizer-settings.php:172 316 | msgid "You can select multiple items and they will be stored as an array." 317 | msgstr "" 318 | 319 | #: includes/class-user-session-synchronizer-settings.php:181 320 | msgid "Extra" 321 | msgstr "" 322 | 323 | #: includes/class-user-session-synchronizer-settings.php:182 324 | msgid "These are some extra input fields that maybe aren't as common as the others." 325 | msgstr "" 326 | 327 | #: includes/class-user-session-synchronizer-settings.php:186 328 | msgid "A Number" 329 | msgstr "" 330 | 331 | #: includes/class-user-session-synchronizer-settings.php:187 332 | msgid "This is a standard number field - if this field contains anything other than numbers then the form will not be submitted." 333 | msgstr "" 334 | 335 | #: includes/class-user-session-synchronizer-settings.php:190 336 | msgid "42" 337 | msgstr "" 338 | 339 | #: includes/class-user-session-synchronizer-settings.php:194 340 | msgid "Pick a colour" 341 | msgstr "" 342 | 343 | #: includes/class-user-session-synchronizer-settings.php:195 344 | msgid "This uses WordPress' built-in colour picker - the option is stored as the colour's hex code." 345 | msgstr "" 346 | 347 | #: includes/class-user-session-synchronizer-settings.php:201 348 | msgid "An Image" 349 | msgstr "" 350 | 351 | #: includes/class-user-session-synchronizer-settings.php:202 352 | msgid "This will upload an image to your media library and store the attachment ID in the option field. Once you have uploaded an imge the thumbnail will display above these buttons." 353 | msgstr "" 354 | 355 | #: includes/class-user-session-synchronizer-settings.php:209 356 | msgid "A Multi-Select Box" 357 | msgstr "" 358 | 359 | #: includes/class-user-session-synchronizer-settings.php:210 360 | msgid "A standard multi-select box - the saved data is stored as an array." 361 | msgstr "" 362 | 363 | #: includes/class-user-session-synchronizer-settings.php:354 364 | msgid "Upload an image" 365 | msgstr "" 366 | 367 | #: includes/class-user-session-synchronizer-settings.php:354 368 | msgid "Use image" 369 | msgstr "" 370 | 371 | #: includes/class-user-session-synchronizer-settings.php:354 372 | msgid "Upload new image" 373 | msgstr "" 374 | 375 | #: includes/class-user-session-synchronizer-settings.php:355 376 | msgid "Remove image" 377 | msgstr "" 378 | 379 | #: includes/class-user-session-synchronizer-settings.php:410 380 | msgid "All" 381 | msgstr "" 382 | 383 | #: includes/class-user-session-synchronizer-settings.php:427 384 | msgid "Save Settings" 385 | msgstr "" 386 | 387 | #: includes/class-user-session-synchronizer-settings.php:458 388 | #: includes/class-user-session-synchronizer-settings.php:467 389 | #: includes/class-user-session-synchronizer.php:207 390 | #: includes/class-user-session-synchronizer.php:216 391 | msgid "Cheatin’ huh?" 392 | msgstr "" 393 | #. Plugin Name of the plugin/theme 394 | msgid "User Session Synchronizer" 395 | msgstr "" 396 | 397 | #. Plugin URI of the plugin/theme 398 | msgid "https://github.com/rafasashi/user-session-synchronizer/archive/master.zip" 399 | msgstr "" 400 | 401 | #. Author of the plugin/theme 402 | msgid "Hugh Lashbrooke" 403 | msgstr "" 404 | 405 | #. Author URI of the plugin/theme 406 | msgid "http://www.hugrafasashi.com/" 407 | msgstr "" 408 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | === User Session Synchronizer === 2 | Contributors: rafasashi 3 | Donate link: https://code.recuweb.com/get/user-session-synchronizer/ 4 | Tags: user, session, synchronizer, cookie 5 | Requires at least: 4.3 6 | Tested up to: 6.2 7 | Stable tag: 1.4.0 8 | License: GPLv3 or later 9 | License URI: http://www.gnu.org/licenses/gpl-3.0.html 10 | 11 | Keep the user logged in from one wordpress to another by synchronizing user data and cookie session 12 | 13 | == Description == 14 | 15 | User Session Synchronizer allows you to keep the user logged in from one wordpress to another by synchronizing user data and cookie session based on a verified email. 16 | The user email is encrypted based on the current user ip and a secret key shared by the synchronized wordpress installations. 17 | 18 | = Features = 19 | 20 | - Synchronize session between installations 21 | - Verify user email through new registration 22 | - Verify user email through manual admin action 23 | - Verify user email through email verification code 24 | - Prevent user form changing email 25 | - Display historical sessions 26 | - Auto add new subscriber if user doesn't exist 27 | - Destroy session everywhere on logging out 28 | 29 | = Upcoming = 30 | 31 | - Multiple secret keys & networks 32 | - Enable ajax cross-domain requests 33 | 34 | == Installation == 35 | 36 | Installing "User Session Synchronizer" can be done either by searching for "User Session Synchronizer" via the "Plugins > Add New" screen in your WordPress dashboard, or by using the following steps: 37 | 38 | 1. Download the plugin via WordPress.org 39 | 2. Upload the ZIP file through the 'Plugins > Add New > Upload' screen in your WordPress dashboard 40 | 3. Activate the plugin through the 'Plugins' menu in WordPress 41 | 4. Set your first Secret Key throught the 'User Session Sync > Keys' 42 | 5. Repeat this installation process for every Wordpress you wish to sychnorize with the same Secret Key 43 | 44 | == Screenshots == 45 | 46 | 1. https://raw.githubusercontent.com/rafasashi/user-session-synchronizer/master/screenshot_1.png 47 | 2. https://raw.githubusercontent.com/rafasashi/user-session-synchronizer/master/screenshot_2.png 48 | 3. https://raw.githubusercontent.com/rafasashi/user-session-synchronizer/master/screenshot_3.png 49 | 4. https://raw.githubusercontent.com/rafasashi/user-session-synchronizer/master/screenshot_4.png 50 | 51 | == Frequently Asked Questions == 52 | 53 | = What is the plugin template for? = 54 | 55 | This plugin template is designed to Keep the user logged in from one wordpress to another by synchronizing user data and cookie session 56 | 57 | == Changelog == 58 | 59 | = 1.3.8 = 60 | 61 | * 2017-05-26 62 | * logout bug fixed 63 | 64 | = 1.3.7 = 65 | 66 | * 2017-05-16 67 | * activate plugin email fixed 68 | 69 | = 1.3.6 = 70 | 71 | * 2017-03-14 72 | * Logout everywhere fixed 73 | * Infinit loop fixed on SSL auth 74 | 75 | = 1.3.5 = 76 | 77 | * 2017-02-09 78 | * Content-Security-Policy implementation 79 | * HTTPS supported 80 | 81 | = 1.3.4 = 82 | 83 | * 2017-01-27 84 | * User IP detection improved 85 | * Synchronization via iframe instead of image 86 | 87 | = 1.3.3 = 88 | 89 | * 2016-10-26 90 | * Resend validation email improved 91 | 92 | = 1.3.2 = 93 | 94 | * 2016-10-14 95 | * Issue regarding email validation corrected 96 | 97 | = 1.3.1 = 98 | 99 | * 2016-09-26 100 | * Multiple Logout issues corrected 101 | 102 | = 1.2 = 103 | * 2016-09-26 104 | * Multiple subfolders under same domain 105 | 106 | = 1.1 = 107 | * 2016-09-22 108 | * Theme footer hooked 109 | 110 | = 1.0 = 111 | * 2016-09-02 112 | * Initial release 113 | 114 | == Upgrade Notice == 115 | 116 | = 1.0 = 117 | * 2016-09-02 118 | * Initial release 119 | -------------------------------------------------------------------------------- /screenshot_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafasashi/user-session-synchronizer/ebc2ba63e33266448b6954c0343243e8b4e14250/screenshot_1.png -------------------------------------------------------------------------------- /screenshot_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafasashi/user-session-synchronizer/ebc2ba63e33266448b6954c0343243e8b4e14250/screenshot_2.png -------------------------------------------------------------------------------- /screenshot_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafasashi/user-session-synchronizer/ebc2ba63e33266448b6954c0343243e8b4e14250/screenshot_3.png -------------------------------------------------------------------------------- /screenshot_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafasashi/user-session-synchronizer/ebc2ba63e33266448b6954c0343243e8b4e14250/screenshot_4.png -------------------------------------------------------------------------------- /uninstall.php: -------------------------------------------------------------------------------- 1 | ' . __( 'Donate', 'cleanlogin' ) . '' ); 35 | $links = array_merge( $links, $new_links ); 36 | } 37 | return $links; 38 | } 39 | add_filter('plugin_row_meta', 'user_session_synchronizer_row_meta', 10, 2); 40 | 41 | // Load plugin class files 42 | require_once( 'includes/class-user-session-synchronizer.php' ); 43 | require_once( 'includes/class-user-session-synchronizer-email-verification.php' ); 44 | require_once( 'includes/class-user-session-synchronizer-settings.php' ); 45 | require_once( 'includes/class-user-session-synchronizer-session-control.php' ); 46 | 47 | // Load plugin libraries 48 | require_once( 'includes/lib/class-user-session-synchronizer-admin-api.php' ); 49 | require_once( 'includes/lib/class-user-session-synchronizer-post-type.php' ); 50 | require_once( 'includes/lib/class-user-session-synchronizer-taxonomy.php' ); 51 | 52 | /** 53 | * Returns the main instance of User_Session_Synchronizer to prevent the need to use globals. 54 | * 55 | * @since 1.0.0 56 | * @return object User_Session_Synchronizer 57 | */ 58 | function User_Session_Synchronizer () { 59 | 60 | $instance = User_Session_Synchronizer::instance( __FILE__, '1.0.0' ); 61 | 62 | if ( is_null( $instance->emailVerification ) ) { 63 | $instance->emailVerification = User_Session_Synchronizer_Email_Verification::instance( $instance ); 64 | } 65 | 66 | if ( is_null( $instance->settings ) ) { 67 | $instance->settings = User_Session_Synchronizer_Settings::instance( $instance ); 68 | } 69 | 70 | if ( is_null( $instance->sessionControl ) ) { 71 | $instance->sessionControl = User_Session_Synchronizer_Session_Control::instance( $instance ); 72 | } 73 | 74 | return $instance; 75 | } 76 | 77 | User_Session_Synchronizer(); --------------------------------------------------------------------------------