Salesforce and MediaWiki sitting in a tree, Q*U*E*R*Y*I*N*G

Sfdc_223x78
As I’ve mentioned in previous posts, I use MediaWiki as an intranet for my non-profit organization. It’s been a great way to document our implementation of Salesforce. 

With a number of users creating their own reports, I was looking for a way to document all the custom objects and fields we have. Moreover, I wanted it to dynamically update when future changes where made. So, I started playing with PHP and the Salesforce API as I’ve done for other useful widgets we use. Using the describe call, I was able to start retrieving that meta-data with a lot more detail than I expected.

Poweredby_mediawiki_88x31
The harder part involved shoehorning the standalone php code into the proper format of a MediWiki extension. After getting over that learning curve, I started getting ambitious and added a query option to the extension so end users could retrieve records using their own select statements. While writing queries using the api is bread and butter stuff, it was an interesting exercise to write code that could accommodate a user defined query. Normally, the select statement is hard coded as are the output fields. In this case, I had to write code that could handle any number of fields at runtime. Moreover, it had to handle queries that could  potential reference multiple objects and use varied notation styles. After a number of trials using string parsing, I was able to come up with a half-way elegant solution looping through the Sobject arrays. It’s funny what makes geeks proud. **pats self on back**

So after cleaning it all up and commenting the hell out of it, my baby is ready for the world. Version 0.1.0 of the Salesforce/MediaWiki Extension took its first steps today. Make your Papa proud.

Note: Don’t post requests for troubleshooting here. Add them to the MediaWiki page, http://www.mediawiki.org/wiki/Extension:Salesforce. Thanks.

Google Maps for MediaWiki

Google_maps_extension_editors_map_2
As I’ve mentioned in previous posts, my organization uses MediaWiki as an intranet. Recently, I wanted to give the rest of our staff insight into the ongoing office search. A quick peruse of the MediaWiki extensions page led me to  the GoogleMaps module. One of the more user friendly MW add-ons I’ve played with, this extension includes an editor that allows you to very easily search for and add locations to a Google map displayed on your post. It also offers a great deal of parameters to control exactly how you want your map to appear; size, zoom level, satellite/map, etc. Best of all there’s no need to remember any cryptic syntax. Simply, get the map in the editor to look like you want it to appear on the page by navigating the standard map controls. Then, copy and paste the wiki markup into your post. Quick and painless.

Configuring WikiMedia for an Active Directory based intranet – Part 3

A while ago, I wrote a post about setting up MediaWiki as an intranet for my non-profit organization. Not wanting to burden people with yet another set of login credentials, I set the wiki to authenticate off of our Active Directory server using the LDAPauthentication extension. At the time (version 1.0 f), the documentation for Windows and AD was spotty and I was glad to add the results of my trials and errors. One thing I was never able to do was have the user prefs (full name and email) pulled from the AD to the wiki user profile.

Since then, the extension has been updated to 1.1d and that feature is more readily available. There are new instructions for configuring an AD server on the Configurations Examples page. To my original code  in LocalSettings.php;

## attempt at authenticating off of  Active Directory at dc01.testAD.org
require_once( ‘LdapAuthentication.php’ );
$wgAuth = new LdapAuthenticationPlugin();
$wgLDAPDomainNames = array( "testAD" );
$wgLDAPServerNames = array( "testAD"=>"dc01.testAD.org"  );
$wgLDAPUseSSL = true;
$wgLDAPUseLocal = false;
$wgLDAPAddLDAPUsers = false;
$wgLDAPUpdateLDAP = false;
$wgLDAPMailPassword = false;
$wgLDAPRetrievePrefs = true;
$wgMinimalPasswordLength = 1;

I added the following;

$wgLDAPSearchStrings = array( "testAD"=>"testAD\\USER-NAME"  );
$wgLDAPEncryptionType = array( "testAD"=>"ssl" );
$wgLDAPSearchAttributes = array(

  "testAD=>"sAMAccountName"
  );
$wgLDAPBaseDNs = array(
  "testAD"=>"dc=testAD,dc=org"
  );

Success! Now the full name and email address appear in Special:Preferences after a user successfully logs in. Finally I can have closure.

Or not. Apparently this works for domain users who have already logged onto the wiki prior to the update, but not those created afterwards. Those users get a Internal Error page with a password-change-forbidden message. Luckily, some intrepid techies had found a solution and posted it (albeit cryptically) on the LDAPAuthentication discussion page. If you have version 1.1d you only need to make changes to the SpecialUserLogin.php in the Includes directory.

Since I don’t have access to the Patch util in Windows, I had to update the file by hand.  To do that, make a backup first. Open SpecialUserLogin.php and find the function initUser (lines 309 to 323). Replace the entire function with the the following code.

function initUser( $u ) {
        global $wgAuth;

        $u->addToDatabase();

               if ( $wgAuth->allowPasswordChange() ) {
                       $u->setPassword( $this->mPassword );
               }

        $u->setEmail( $this->mEmail );
        $u->setRealName( $this->mRealName );
        $u->setToken();

        $wgAuth->initUser( $u );

        $u->setOption( ‘rememberpassword’, $this->mRemember ? 1 : 0 );
        $u->saveSettings();

        return $u;
    }

Success? So far. I created a new domain account and then used it to log on to the intranet. No Internal Error, so I assume everything is Kosher now. I’ll keep you posted.

Flash Based Training on MediaWiki

As I’ve mentioned a few other times here, I established a wiki for my organization’s intranet. It’s really taken off as a way for users to quickly and easily post and share documents. I mostly use it to post how to’s to nip in the bud the kind of support requests that eat away at my day. Very often I’ll get a ‘how do I’ question via email, spend 20 minutes posting a page on the intranet (complete with screenshots), and email the person back the link to the page I just made. That way I never have to answer that question again. In theory. Not all my people RTM if you know what I mean.

One thing that has helped as been creating flash based tutorials and posting them to the intranet. I use a product called Camtasia Studio by TechSmith. Essentially its just like doing a screenshot but using video and audio. I start it up, put on my headset, click record, and talk and click my way through the task. When I feel especially generous I add titles and callouts. Otherwise its a breeze to publish to flash and post on the site. I use an MediaWiki extension called Flashow to add Flash to the intranet pages.

Configuring WikiMedia for an Active Directory based intranet – Part 2

Getting MediaWiki to securely authenticate off of a Win 2003 Active Directory ended up being much trickier than I first thought. The documentation at MediaWiki on the subject was missing some key pieces of information.

Getting Secure LDAP setup on my
AD server was a little beyond me. So I happily dropped that task on my
systems admin, who (I was glad to see) had a little difficulty there
himself. I was able to test the secure LDAP was configured properly
using a utility called LDP.exe which is part of the Windows Resource Kit (2000 or 2003). So while the wiki authentication still wasn’t working I was able to eliminate the AD as the problem.

After changing   $wgLDAPUseSSL = false; to   $wgLDAPUseSSL = true; I still had no luck. After a long bit of googling, I finally put together the missing pieces of info I needed.

Key 1
Found on http://www.php.net/ldap . To enable PHP’s LDAP functionality in Windows;

"Note to Win32 Users:
   In order to enable this module on a Windows environment, you must copy several files from the DLL folder of the PHP/Win32 binary package to the SYSTEM folder of your windows machine. (Ex: C:\WINNT\SYSTEM32, or C:\WINDOWS\SYSTEM). For PHP <= 4.2.0 copy
   libsasl.dll, for PHP >= 4.3.0 copy
libeay32.dll and ssleay32.dll to your SYSTEM folder."

Key 2
From a user post by jabba at zeelandnet dot nl on that same page. OpenLDAP requires that you create a ldap.conf file in the directory C:\OpenLDAP\sysconf\ . The first line of this text files must be
TLS_REQCERT never
. Weirdly enough, this seems to be a hard-coded requirement. You can’t even define the path in php.ini.

Success.
 

Since MediaWiki is used more in LAMP configurations, I can forgive the holes in documentation in the ldap_authenticate documentation around AD in a windows evironment. (In the spirit of digital karma, I will post there next.) But given the importance of these two points to get LDAP functions to work in PHP, I was surprised they were not more prominently noted in php’s documentation. The second point is even buried in the user comments. Perhaps PHP and other open source project might want to consider moving documentation to a Wiki to allow their users to help better document functions.

So as for my original requirments for our intranet wiki;

  1. Authenticate users using their standard Windows Domain username/password. – Done
  2. Resrtict access (read, write) to only authenticated users – Done

One remaining item is to pre-populate the user preferences (ie Full Name, email) when the account is logged in. Reportedly the line $wgLDAPRetrievePrefs = true; is supposed to trigger this but I haven’t seen it work. More to come then…

3/20/2007 – There is a new version (1.1) of the LDAPauthentication extension. Some of this article may be outmoded as a result. See Part 3 of the series.

Skype Extension for Wikimedia

I’m constantly championing Skype within my non-profit organization as a way to increase communication while decreasing costs. As part of our developing MediaWiki intranet I wanted to create a directory of staff members and their skype usernames. I also wanted to add buttons (http://www.skype.com/share/buttons/wizard.html) for calling, chatting, and adding skype users.

Existing skype extensions focused only on showing a users Skype status. (http://meta.wikimedia.org/wiki/Skype_extension) In true wiki style, I added my own variaton on the code to allow editors to create buttons for different skype actions.

<?php
  $wgExtensionFunctions[] = "wfskype";

function wfSkype() {
global $wgParser;
$wgParser->setHook( “skype”, “renderSkype” );
}

# The callback function for converting the input text to HTML output
function renderSkype( $input, $argv ) {

if( !isset( $argv[‘action’] ) ){
$skype_action = “call” ;
} else {
$skype_action = $argv[‘action’] ;
}

switch( $skype_action ){

case “call”:
$skype_width = 70 ;
$skype_height = 23 ;
$skype_style=”call_blue_transparent_70x23.png”;
break;

case “add”:
$skype_width = 118 ;
$skype_height = 23 ;
$skype_style=”add_blue_transparent_118x23.png”;
break;

case “chat”:
$skype_width = 97 ;
$skype_height = 23 ;
$skype_style=”chat_blue_transparent_97x23.png”;
break;

default:
$skype_action = “call” ;
$skype_width = 70 ;
$skype_height = 23 ;
$skype_style=”call_blue_transparent_70x23.png”;

}

$output = ‘<!– Skype buttons http://www.skype.com/go/skypebuttons –>’;
$output .= ‘<!– MediaWiki extension http://meta.wikimedia.org/w/&#8217;;

     $output .= 'index.php?title=Skype_extension -->';
     $output .= '     $output .= '/js/skypeCheck.js">';
     $output .= '<a href="skype:'.$input.'?'.$skype_action.'">';
     $output .= '<img src="http://download.skype.com/share/skypebuttons/';
     $output .= 'buttons/'.$skype_style.'" ' ;
     $output .= 'style="border: none; width: '.$skype_width.'px; height: '.$skype_height.'px;" alt="Skype me" /></a>';
     $output .= '<!-- end of skype button -->';

return $output;
}
?>

  1. Copy the code into a file (e.g. skype.php)
  2. Save the file in the extensions directory of your mediawiki folder
  3. Add the line include('extensions/skype.php'); to the end of your LocalSettings.php file

In any wiki post, you can add <skype action="specified_action">Skype-Username</skype> where specified_action is call, chat, or add and Skype-Username is a valid skype username.

Buttons appear as

Call me!
Add me to Skype

Chat with me

Configuring WikiMedia for an Active Directory based intranet

One of my current projects involves creating an internal knowledge base. Wiki’s being a natural for this sort of collaborative content building, I started exploring MediaWiki the engine behind Wikipedia.

An intranet implies a much more closed community than that of the typical Wiki implementation. That being the case, our requirements were;

  1. Authenticate users using their standard Windows Domain username/password.
  2. Resrtict access (read, write) to only authenticated users

I wasn’t sure if domain authentication would be possible using the standard LAMP setup. So, instead I opted to use IIS 6. A great step by step guide for installing MediaWiki on Windows 2003 can be found at http://meta.wikimedia.org/wiki/Installing_MediaWiki_on_Windows_Server_2003_SP1

After getting PHP, MySql, IIS, and MediaWiki installed, you can start configuring LocalSettings.php in the root directory of your wiki installation. To perform the following, simple append the code snippet to LocalSettings.php.

1. Restrict edit to logged in users

$wgGroupPermissions[‘*’][‘edit’] = false;
$wgGroupPermissions[‘user’][‘edit’] = true;

2. Prevent new registrations from anonymous users (Sysops can still create new account)

$wgGroupPermissions[‘*’][‘createaccount’] = false;

3. Define the pages un-authenticate users can see. This is crucial. Otherwise, there’s no way for people to login.

$wgWhitelistRead = array( "Main Page", "Special:Userlogin", "-", "MediaWiki:Monobook.css" );
$wgGroupPermissions[‘*’    ][‘read’]            = false;

4. Authenticate users from an Active Directory.

You will need to download LDAPauthenticate.php from http://bugzilla.wikipedia.org/show_bug.cgi?id=814 to the includes directory in the root of your wiki installation. Details on this file and its usage can be found at http://meta.wikimedia.org/wiki/LDAP. There are links to some configuration examples. However I found the one for AD did not work without modifcation. Here is what I eventually had success with. In my example, the AD name is ad_name.org and the hostname of the server hosting the AD (domain controller) is DC1 and the domain is Domain_name. Subsitute your AD name and Hostname in the following code. In some cases the Active Directory name and Domain name may be the same.

require_once( ‘LdapAuthentication.php’ );
$wgAuth = new LdapAuthenticationPlugin();
$wgLDAPDomainNames = array( "
ad_name.org" );
$wgLDAPServerNames = array( "
ad_name.org"=>"dc1"  );
$wgLDAPUseSSL = false;
$wgLDAPUseLocal = false;
$wgLDAPAddLDAPUsers = false;
$wgLDAPUpdateLDAP = false;
$wgLDAPMailPassword = false;
$wgLDAPRetrievePrefs = true;
$wgMinimalPasswordLength = 1;
$wgLDAPSearchStrings = array( "
ad_name.org"=>"Domain_name\\USER-NAME"  );

Viola. Your wiki is now restricted to only users with valid domain accounts. The lines, $wgLDAPAddLDAPUsers = false; and $wgLDAPUpdateLDAP = false; restrict users from updating their LDAP info via the wiki interface.

Unfortunately there are two things I have not had success with. I have not had success populating the fields (name, email, etc) in the preferences tab after a user has logged in. The tag $wgLDAPRetrievePrefs = true; is supposed to make this happen but it does not.

Additional, I have yet to secure authentication by implementing SSL. Note – $wgLDAPUseSSL = false; This I fairly important and should be done before rolling this out to my users.

I’ll update this post with any additonal information I find. Please let me know if you have an success with these last two items.

3/20/2007 – There is a new version (1.1) of the LDAPauthentication extension. Some of this article may be outmoded as a result. See Part 3 of the series.