Making Register Plus Redux work with Nextend Google Connect - facebook

I'm trying to make two popular WordPress plug-ins work well together. Hopefully this question isn't too specific to my setup -- I think enough people use these plug-ins to make it a common issue.
I'm using Register Plus Redex (RPR) to require user registration to be accepted (by admin) before a user can log-in. Alone, this works fine.
I'm also using Nextend Google Connect (NGC) to allow users to log-in with Google. Those also need to be approved before they can log-in.
When NGC creates a new user in the database, it correctly has the "not activated" flag set. However, the user is still logged in. This allows them to see some blog pages that are protected by "Members Only" (another plug-in). I could maybe update Members Only or other areas to avoid this, but I would rather these users see the same behavior a normal user would see, one that just logs in with user/password, not Google. They get a nice "Your account has not been activated yet" message.
RPR has this code to authenticate, I think I need to use it from NGC some way:
public /*.object.*/ function rpr_authenticate( /*.object.*/ $user, /*.string.*/ $username, /*.string.*/ $password) {
if ( !empty($user) && !is_wp_error( $user ) ) {
if ( NULL !== get_role( 'rpr_unverified' ) && in_array( 'rpr_unverified', $user->roles ) ) {
return null;
}
}
return $user;
}
I think this is the section of NGC code I need to modify:
$secure_cookie = is_ssl();
$secure_cookie = apply_filters('secure_signon_cookie', $secure_cookie, array());
global $auth_secure_cookie; // XXX ugly hack to pass this to wp_authenticate_cookie
$auth_secure_cookie = $secure_cookie;
wp_set_auth_cookie($ID, true, $secure_cookie);
$user_info = get_userdata($ID);
do_action('wp_login', $user_info->user_login, $user_info);
do_action('nextend_google_user_logged_in', $ID, $u, $oauth2);
update_user_meta($ID, 'google_profile_picture', 'https://profiles.google.com/s2/photos/profile/' . $u['id']);
The NGC code uses what I think is a "hacked" method of log-in. It doesn't use any of the methods I have seen recommended online, like the new wp_signon or older wp_login functions.
Is what I'm trying to do a major project? If so, is there another combination of plug-ins (or a single one) that will handle the following:
Require users to be logged in to see any pages (what Members Only does)
Require admin to moderate/approve new users (what RPR does)
Support log-in via Facebook, Twitter, and Google (what the Nextend Connect plug-ins do)
Update:
I changed the NGC code to this, and now it doesn't log the user in, but it just leaves them on the log-in page with no error message. I'm not sure how I can add an error message to the default log-in page, everything I find online is related to custom log-in pages.
if ($ID) { // Login
$user_info = get_userdata($ID);
if ( !empty($user_info) && !is_wp_error( $user_info ) ) {
if ( NULL !== get_role( 'rpr_unverified' ) && in_array( 'rpr_unverified', $user_info->roles ) ) {
// TODO - How to add error message to log-in page?
return;
}
}
$secure_cookie = is_ssl();
$secure_cookie = apply_filters('secure_signon_cookie', $secure_cookie, array());
global $auth_secure_cookie; // XXX ugly hack to pass this to wp_authenticate_cookie
$auth_secure_cookie = $secure_cookie;
wp_set_auth_cookie($ID, true, $secure_cookie);
//
do_action('wp_login', $user_info->user_login, $user_info);
do_action('nextend_google_user_logged_in', $ID, $u, $oauth2);
update_user_meta($ID, 'google_profile_picture', 'https://profiles.google.com/s2/photos/profile/' . $u['id']);
}

I'm sure there is a better way to do this, one that will not be undone anytime I update the plug-in, but for now this works for me.
I updated nextend-google-connect.php, part of the Nextend Google Connect plug-in, and changed the Login code (starting around line 230 depending on your version) to this:
if ($ID) { // Login
$user_info = get_userdata($ID);
if ( !empty($user_info) && !is_wp_error( $user_info ) ) {
if ( NULL !== get_role( 'rpr_unverified' ) && in_array( 'rpr_unverified', $user_info->roles ) ) {
wp_redirect('wp-login.php?checkemail=registered');
exit;
}
}
$secure_cookie = is_ssl();
$secure_cookie = apply_filters('secure_signon_cookie', $secure_cookie, array());
global $auth_secure_cookie; // XXX ugly hack to pass this to wp_authenticate_cookie
$auth_secure_cookie = $secure_cookie;
wp_set_auth_cookie($ID, true, $secure_cookie);
do_action('wp_login', $user_info->user_login, $user_info);
do_action('nextend_google_user_logged_in', $ID, $u, $oauth2);
update_user_meta($ID, 'google_profile_picture', 'https://profiles.google.com/s2/photos/profile/' . $u['id']);
}
By redirecting to that special URL, the Redux plug-in already has code to display a nice message to the user letting them know the admin needs to verify the account.

Related

Integration of myBB with website

I want my website and my mybb board to be connected. I Googled and made the integration, and I'm able to get a username id, as long as I specify their ID, but nothing happens when I'm using the function as explained.
What I'm trying to do is verify a connection of one to the forums, via my website, and then show their name.
Here's my code, as well as my attempts to get a username:
PHP Code:
define('IN_MYBB', NULL);
require_once 'forums/global.php';
require_once 'forums/class.MyBBIntegrator.php';
$MyBBI = new MyBBIntegrator($mybb, $db, $cache, $plugins, $lang, $config);
$user = get_user($uid);
while ($forum_user = mysqli_fetch_array($user))
{
echo $forum_user['username'];
}
You could use:
define('IN_MYBB', NULL);
require_once 'forums/global.php';
if(isset($mybb->user['uid'])){
echo "User Found: ".$mybb->user['usernmae']."($mybb->user['uid'].")";
} else {
echo "No user found";
}
MyBBIntegrator isn't even required. But the above code will check if the user is logged in, and display the username and userid. If not it will display No User Found. Hopefully this helps.

Perl catalyst controller redirect not working

I have looked over this code and I can not understand the weirdness it exhibits. For a lack of understanding all I know
$c->res->redirect('qbo/home');
is being ignored, in favor of the redirect in the following if else condition. In other words, I always end up at the OAuthentication website.
If I block comment out the else condition I end up where I want to go qbo/home
sub index :Path :Args(0) {
my ($self, $c) = #_;
# Check to see if we have QBO::OAuth object in our user's session
# Create new object in session if we don't already have one
if(!($c->session->{qbo})) {
$c->log->info('Creating QBO::OAuth, save in user session');
$c->session->{qbo} = QBO::OAuth->new(
consumer_key => 'qyprddKpLkOclitN3cJCJno1fV5NzcT',
consumer_secret => 'ahwpSghVOzA142qOepNHoujyuHQFDbEzeGbZjEs3sPIc',
);
}
# Now we set our object variable to the session old or new
my $qbo = $c->session->{qbo};
######### GOTO 'qbo/home' ##########
$c->res->redirect('qbo/home');
####################################
if($c->req->params->{oauth_token}) {
$c->log->info('Now Redirect to access_endpoint');
# Get realmId and save it to our QBO::OAuth object in user session
$qbo->realmId($c->req->params->{realmId});
# Call QBO::OAuth->request_access_token
my $r = $qbo->request_access_token($c->req->params->{oauth_verifier});
$c->res->redirect('qbo/home');
} else {
my $callback = 'http://www.example.com/qbo';
# Request a token
my $r = $qbo->request_token($callback);
if($qbo->has_token) {
#Continue on down, Redirect to auth_user_endpoint
$c->res->redirect($qbo->auth_user_endpoint . '?oauth_token=' . $qbo->token);
}
}
}
Seems I am missing some basic fundamental about how this works. Any clues appreciated
From the fine manual...
This is a convenience method that sets the Location header to the redirect destination, and then sets the response status. You will want to return or $c->detach() to interrupt the normal processing flow if you want the redirect to occur straight away.
Note also the warning on that manual page about redirecting to a relative URL - you shouldn't do it. For your use-case, I'd recommend getting into the habit of using:
return $c->res->redirect($c->uri_for('qbo/home'));
or
$c->res->redirect($c->uri_for('qbo/home')) && $c->detach();
depending on your preference.

A Simple Login/Authorization system using Dancer and Postgres

As a newbie to Perl I'm struggling to find a simple way to do this. I've created a very simple table in my database:
CREATE TABLE users (
id SERIAL NOT NULL PRIMARY KEY,
username TEXT NOT NULL,
password TEXT NOT NULL);
So far I used a simple login system that has a hard coded username and password that I found online:
package Example;
use Dancer ':syntax';
our $VERSION = '0.1';
set session => "Simple";
get '/' => sub {
# template 'index',{},{layout => 0};
template 'index';
};
before sub {
if (! session('user') && request->path_info !~ m{^/login}) {
var requested_path => request->path_info;
request->path_info('/login');
}
};
get '/login' => sub {
# Display a login page; the original URL they requested is available as
# vars->{requested_path}, so could be put in a hidden field in the form
template 'login', { path => vars->{requested_path} }, {layout => 0};
};
post '/login' => sub {
# Validate the username and password they supplied
if (params->{user} eq 'user' && params->{pass} eq 'letmein') {
session user => params->{user};
redirect params->{path} || '/';
} else {
redirect printf 'login failed';
}
};
get '/logout' => sub {
session->destroy;
redirect '/';
};
How do I get started with linking the database and then matching what the user inputs with what's in the database? And also when do I implement the hashing of the passwords? Any tutorials will be greatly appreciated - I've been using metacpan but it's not providing as much detail as I need!
Dancer::Plugin::Auth::Extensible takes care of a lot of boilerplate code for you. You can get a simple login system up and running without having to write any of your own /login routes as follows.
Configure Dancer::Plugin::Auth::Extensible
Install Dancer::Plugin::Database and Dancer::Plugin::Auth::Extensible::Provider::Database and add this to config.yml:
session: "YAML"
plugins:
Auth::Extensible:
realms:
users:
provider: 'Database'
disable_roles: 1
Configure database connection
Configure your database connection in environments/development.yml so that you can have different configurations for dev and production. This is what the configuration looks like for MySQL, with the connection credentials (database name, host, username, and password) stored in a separate options file database.cfg:
plugins:
Database:
dsn: 'dbi:mysql:;mysql_read_default_file=/path/to/database.cfg'
dbi_params:
RaiseError: 1
AutoCommit: 1
For Postgres, you should use a .pgpass file to store your connection credentials. Make sure the file is not world readable. See this Stack Overflow post for an example. Test that your credentials file works on the command line and that your webserver can read it.
Your existing table appears to conform to the suggested schema in the docs, but even if it doesn't, you can adjust the table and column names in the configuration.
Lock down your routes
Add the require_login keyword to a route you want to protect. A /login route will be generated automatically with a basic login form, although you can create your own if you like.
lib/MyApp.pm
package MyApp;
use Dancer ':syntax';
use Dancer::Plugin::Auth::Extensible;
our $VERSION = '0.1';
get '/' => require_login sub {
template 'index';
};
true;
(Yes, that really is all the code you have to write. I told you it takes care of a lot of boilerplate.)
Crypt::SaltedHash is used to hash passwords automatically. Note that you should never store plaintext passwords in your database; when you add a user to your database, you should generate a hash of the password and store the hash.
Note that roles are disabled in this example. If you enable roles, you can do other nifty things like only allow users with the admin role to view admin pages.
The simplest way:
Dancer::Plugin::Authorize::Credentials::PostgreSQL
Here is a good write up how to do it properly: http://perlmaven.com/storing-passwords-in-a-an-easy-but-secure-way
post '/login' => sub {
# Validate the username and password they supplied
if (!params->{user} or !params->{pass}){
redirect printf 'login failed';
}
# use your own encryption
my $auth = auth($login, encrypt($password));
# login successful
if ($auth) {
session user => params->{user};
redirect params->{path} || '/';
} else {
redirect printf 'login failed';
}
};
Regards,
Andras

WordPress 3.5 Changed User.php Which Breaks Plugin, Can this function be the issue? Can it be fixed?

A plugin provides login for a WordPress multi-site network. This plugin now fails under WP 3.5 because the user.php file was changed. The old lines in /wp-includes/user.php can be added back in and the plugin would work. Obviously this is not a long term solution.
This is the old code from user.php
if ( empty( $user ) )
$user = wp_get_current_user();
else
$user = new WP_User( $user );
if ( ! isset( $user->ID ) )
return false;
This is the new code from 3.5
if ( empty( $user ) )
$user = get_current_user_id();
if ( ! $user = get_userdata( $user ) )
return false;
I'm a beginner trying to learn php and so I'm not sure on all of the meanings. However, I think this is the code in the plugin causing issue:
function get_userdata( $user_id ) {
global $wpdb;
if ( ! is_numeric( $user_id ) )
return false;
$user_id = absint( $user_id );
if ( ! $user_id )
return false;
$user = wp_cache_get( $user_id, 'users' ); //check to see if the cache object already has the user
if ( $user )
{
return $user; //it was in the cache
}
$user = new StdClass ();
global $XF;
XF_User_Data::fillUserData($XF->visitor, $user, $user_id);
update_user_caches($user);
return $user;
}
The new StdClass can be commented out and the error is removed but then no one can login.
How could I re-write this function to not cause the error?
*Fatal error: Call to undefined method stdClass::has_prop() /wp-includes/user.php*
The developer of the plugin is 'on vacation' and hasn't updated. He's waiting for some other changes, however, this needs to be fixed.
Any suggestions on fixing the code? Am I looking in the wrong place? Are other details needed before someone can help?
Even if you are a skilled PHP programmer, modifying WP core or any plugin script is really a bad idea. In my opinion, you should downgrade to previous version and wait for the plugin's update. Check this link to do it easily. In fact, many plugins had problems with version 3.5, including the popular CKEditor, but they are being updated and in this case, waiting seems to be the best option. Make sure all plugins are compatible with 3.5 before trying another update.
If you post which plugin you're using and a link to download it I'll take a look at it and see what the issue is.

Zend framework - Auth: additional validation

I want to check the user table for status=1 as extra validation. My getAuthAdapter() method looks like this:
private function getAuthAdapter (){
$authAdapter = new Zend_Auth_Adapter_DbTable(Zend_Db_Table::getDefaultAdapter());
$authAdapter->setTableName('vi_users')
->setIdentityColumn('email')
->setCredentialColumn('password');
return $authAdapter;
}
How would I alter this to include the extra validation?
I ran across this problem myself, and I'm not sure it is possible to check another column at the sametime. So I do it straight aftwerwards, with something like this:
$auth = Zend_Auth::getInstance();
....
if (process($form->getValues())) {
// login credentials are correct, so we now need to check if their account is activated
if ($auth->getIdentity()->active != 1) {
// if not, log them out and tell them to activate
Zend_Auth::getInstance()->clearIdentity();
$output .= "Your account has not yet been activated, please check your email (including spam bin) for the activation link.";
} else {
// if they're active then login is successful
$output .= "You are now logged in";
}
} else {
// username/password wrong
$output .= "Credentials invalid";
}
Update: Given Orlando's answer, it looks like what you've asked for originally is possible. You could use my solution though if you would like to distinguish between status value being 'wrong' and user/pass being wrong.
You could do something like:
$adapter = new Zend_Auth_Adapter_DbTable(
$db,
'users',
'username',
'password',
'MD5(?) AND status = 1'
);
where $db would be Zend_Db_Table::getDefaultAdapter()
Taken from http://framework.zend.com/manual/en/zend.auth.adapter.dbtable.html