September 9th, 2010 |
Published in
Mind
As many of you know, I led the team that launched the College of Education at UGA’s new website (http://www.coe.uga.edu/) which is driven by WordPress Multi-Site. The first phase is complete, and the second phase has started up. Part of their second phase is to allow a custodian from each department to edit content on their own departmental site. UGA uses Active Directory campus wide, so I thought it would be best to incorporate the WordPress authentication mechanism into UGA’s current AD implementation.
When I first researched this there weren’t many plugins for WordPress Multi-Site that handled AD/LDAP authentication. I was planning on writing one myself, but I found one yesterday by Clifton Griffin called Simple LDAP Login. I installed in on a development website, put in the necessary information and BAM it worked… but it wasn’t really designed for WordPress Multi-Site. What I needed was every site to use the Active Directory authentication, without having to set each site up individually. So I paired down the code a bit (to just what I needed) and stuck the files in the mu-plugins dir.
Clifton used the opensource PHP LDAP Class in his plugin, which works great. So, in my version, I stripped out everything I didn’t need/want like auto account creation, non-AD functionality, etc. Basically, I just needed to authenticate users via Active Directory.
So I stuck this code into a file in my mu-plugins folder. Now whenever anyone tries to authenticate it, uses Active Directory instead of WordPress’ user table:
<?php
require_once( WPMU_PLUGIN_DIR . '/simple-ldap-login/adLDAP.php' );
define( 'DOMAIN_CONTROLLERS', 'active.directory.controller.domain' );
define( 'SECURITY_MODE', 'high' );
define( 'ACCOUNT_SUFFIX', '@account.edu');
define( 'BASE_DN', 'OU=OUOU,DC=DCDC,DC=EDU' );
define( 'USE_TLS', false );
define( 'USE_SSL', true );
//Authenticate function
function sll_authenticate( $user, $username, $password ) {
if ( is_a( $user, 'WP_User' ) ) { return $user; }
//Failed, should we let it continue to lower priority authenticate methods?
if( "high" === SECURITY_MODE ) {
remove_filter('authenticate', 'wp_authenticate_username_password', 20, 3);
}
if ( empty( $username ) || empty( $password ) ) {
$error = new WP_Error();
if ( empty( $username ) )
$error->add( 'empty_username', __( 'ERROR: The username field is empty.' ) );
if ( empty($password) )
$error->add( 'empty_password', __( 'ERROR: The password field is empty.' ) );
return $error;
}
if( sll_can_authenticate( $username, $password ) ) {
$user = get_userdatabylogin( $username );
if ( !$user || ( strtolower( $user->user_login ) != strtolower( $username ) ) ) {
do_action( 'wp_login_failed', $username );
return new WP_Error( 'invalid_username', __( 'Login Error An error occurred while attempting to log in. If this continues please contact coeweb@uga.edu for support.' ) );
} else {
//we're ready to return the user
return new WP_User( $user->ID );
}
} else {
return new WP_Error( 'invalid_username', __( 'Login Error An error occurred while attempting to log in. If this continues please contact coeweb@uga.edu for support.' ) );
}
}
add_filter( 'authenticate', 'sll_authenticate', 1, 3 );
function sll_can_authenticate( $username, $password ) {
$sll_options = array(
'account_suffix' => ACCOUNT_SUFFIX,
'base_dn' => BASE_DN,
'use_tls' => USE_TLS,
'use_ssl' => USE_SSL,
'domain_controllers' => explode( ';', DOMAIN_CONTROLLERS )
);
$adldap = new adLDAP( $sll_options );
$result = false;
$result = $adldap->authenticate( $username, $password );
return $result;
}
Tags: active directory, ldap, mu-plugins, open source, plugins, wordpress, wpms
August 11th, 2010 |
Published in
Mind
If you are using switch_to_blog() in your WordPress MultiSite installation and notice that your permalinks contain “/blog/” in them (or some other oddity). The give John James Jacoby’s plugin Switch Site Rewrite a go.
Today I ran into this problem with a WPMS site that I am developing. I needed to pull posts from the “news” site onto the main site. I used switch_to_blog() to do this, but when I tried to get specific category permalinks with get_category_links() it would automatically include “/blog/” in the URL.
This is because of the way that the $wp_rewrite variable is initialized and an attempt to reduce overhead when using switch_to_blog(). So, John’s plugin does come with a risk of added overhead, but I’m currently dealing with a 30 site installation and don’t see much of a cost. If you were really picky, you could modify his code a bit to only work in real specific situations.
If you get a chance, jump on over to twitter and thank him for this little plugin. It saved me a little more development work, although it also meant I wasted 2 hours tracking down the problem :).
Tags: get_category_links, permalinks, plugin, switch_to_blog, twitter, wordpress, wpms
July 29th, 2010 |
Published in
Mind
I’ve been working on a pretty complicated WordPress Multi-Site project for the College of Education at UGA. One of their sites will be controlling the master calendar for the main website. We wanted to display the calendar from the sub-site. One the main site of the page (an possibly on other sub-sites).
Generally speaking, in WPMS / WPMU you can get the content of one site by switching to that site ID using the switch_to_blog($id) function. However, this does not work with Event Calendar 3, because of the way it builds it’s global $ec3 variable.
The problem is, when you are on site id 1, the $ec3 creates a variable that points to the schedule table for site id 1. Even if you run switch_to_blog(2), $ec3 still tries to get the schedule from site id 1. So it was returning an empty calendar. The easiest way to fix this (until EC3 updates their code) was to re-instantiate the global $ec3 variable. Basically this is what I did:
switch_to_blog(10);
global $ec3;
$ec3 = new ec3_Options();
ec3_get_calendar();
restore_current_blog();
This re-instantiates the $ec3 variable for the schedule I needed to get from that specific site ID. It should be a fairly simple fix for EC3. Until then, this is the easiest fix if you need to do what I’m doing.
Tags: switch_to_blog, wordpress, wpms, wpmu
May 13th, 2010 |
Published in
Mind
I’ve been working on a pretty complex project with WordPress MultiUser (soon to be MultiSite). This client needs several sites with hundreds of users divided into each site. I will be integrating the backend authentication with LDAP and discovered that a small percentage of their users have usernames with fewer than four characters.
WordPress MU currently has a minimum limit of four characters set in its core. Unfortunately, this limit is still imposed in WordPress MS 3.0. The limit is probably there because usernames were used for the domain too and WP-Devs didn’t want to conflict with country codes. But that is not an issue for my client, so I wanted to kill the limit (without touching core).
Basically, I wrote a quick mu-plugin that unset the error message when someone tries to add a user with fewer than four characters. Doing this removes any halts that would stop processing the new user. Here is my code:
function remove_username_char_limit($result) {
if ( is_wp_error( $result[ 'errors' ] ) && !empty( $result[ 'errors' ]->errors ) ) {
// Get all the error messages from $result
$messages = $result['errors']->get_error_messages();
$i = 0;
foreach ( $messages as $message ) {
// Check if any message is the char limit message
if ( 0 == strcasecmp("Username must be at least 4 characters", $message)) {
// Unset whole 'user_name' error array if only 1 message exists
// and that message is the char limit error
if ( 1 == count($messages) ) {
unset( $result['errors']->errors['user_name'] );
} else {
// Otherwise just unset the char limit message
unset( $result['errors']->errors['user_name'][$i] );
}
}
$i++;
}
}
return $result;
}
add_action('wpmu_validate_user_signup', 'remove_username_char_limit');
Tags: development, functions.php, hacks, mu-plugins, wordpress, wpms, wpmu