Archive for September, 2010

29 Sep 10

MindTouch 10.0.3 (RC1)

We just wrapped up the development cycle for the MindTouch 10.0.3 RC1 release.  The MindTouch Community Portal has already been updated and is running the latest RC1 bits.

We’d love to get some community testing and feedback on the latest bits to help us identify any regressions or other issues.  If you’d like to test out  10.0.3 RC1 on your own server, you’ll need synchronize your SVN tree to the proper branch and revision number.  For RC1, you’ll want to check out the 10.0 branch at revision 22198.  For example, you can check out the tree by doing the following using the command line SVN client.

svn co -r 22198 https://svn.mindtouch.com/source/public/dekiwiki/10.0

Take a look at the ChangeLog for a complete list of fixed bugs in RC1.  In the meantime, we’re busily working away at RC2 scheduled for Monday, October 11th.

28 Sep 10

What is ActivityStream?

So you’ve been poking around through the latest features of MindTouch, but you’re perplexed as to what ActivityStream really does?  We thought you’d never ask.

ActivityStream is an extension included in our Commercial release that provides Twitter-like messaging functionality.  When enabled, users can leave comments for other users using an “@” reply, which will then e-mail a notification to the recipient user.  So when User1 would like to comment on a page created by User2, User1 can leave the comment “@User2 This page is a great example of your work.  You’re getting a raise.”  User2 will then get an e-mail notification of this comment sent to the e-mail address defined in their user profile.

Thanks to ActivityStream, User2 is now reaping the rewards of their well-documented page.  Advanced details of this extension can be found here.

Have further questions about this functionality?  Feel free to submit a ticket at our Support Portal and we’ll be glad to help out.

22 Sep 10

A pattern for modifying method behavior by an unknown party

I’m currently doing some experimental work towards what i’m tentatively calling DReAM 3.0. I’ve got some ideas for additions and changes and welcome any and all feedback. A primary focus for this release is to make Dream more approachable and easier to use. Mind you, this is speculative work and nothing on that page nor mentioned in this post is set in stone yet.

Last night I was dealing with splitting up some DReAM functionality into client and server assemblies and running into a consistent pattern where certain classes have augmented behavior when running in the server context instead of the client context. Since the client assembly is used by the server assembly, and these classes are part of the client assembly, they do not even know about the concept of the server context. Which leads me to the dilemma, how do I inject different behavior into these classes when they run under the server context?

I originally posted this on my personal blog as a late night rambling about a solution I came up with, but wasn’t particularly enamored with, hoping to see if there was an obvious pattern or facility I was overlooking. Since then @jongalloway suggested on twitter that I look into using MEF. Since DReAM already does assembly discovery in a number of places, I’ve been meaning to look at MEF to replace that hand-rolled reflection code. So this might be the final nudge.

This is one way to do it…

Let’s assume that the server context can be discovered by static means (i.e. a static singleton accessor) which also lives in the server assembly. To let this context inject its behavior, I’ve extracted the affected behavior into an interface and use discovery to build a chain of implementations to handle the behavior. A sample interface might look like this:

public interface IFooHandler {
  ushort Priority { get; }
  bool TryFoo(string input, out string output);
}

TryFoo gives the handler implementation a chance to look at the inputs and decide whether to handle or pass on it. The handler chain is used with this linq expression:

public string Foo(string input) {
  string output = null;
  _handlers.Where(x => x.TryFoo(input, out output)).First();
  return output;
}

This assumes that _handlers is sorted by priority. The method returns the result of the first handler to report true on invocation. Building up the _handlers happens in the static constructor:

static Bar() {
  _handlers = typeof(IFooHandler)
    .DiscoverImplementors()
    .Instantiate()
    .Cast<IFooHandler>()
    .OrderBy(x => x.Priority)
    .ToArray(); 
}

where DiscoverImplementors and Instantiate are extension methods i’ll leave as an exercise to the reader.

Now the server assembly simply creates its implementation of IFooHandler, gives it a higher priority and on invocation checks its static accessor to see if it’s running in the server context and if not, lets the chain fall through to the next (likely the default) implementation.

Looking for alternatives

I’m about to do a deep dive into MEF to see how it can help. Whether it’ll just take over the discovery of handlers for the chain or has a way to better deal with the injection of the behavior as well, I don’t know yet. I’m of course open to other solutions as well.

Tags: , , ,
15 Sep 10

MindTouch 10.0.2 Released & Ready For Download

MindTouch version 10.0.2 is the latest stabilization release for the Olympic family of products (MindTouch 2010, MindTouch Platform v10, MindTouch Core v10).

For this incremental, we’ve focused on a streamlined universal install, cleaned up the editor experience for Webkit based browsers, and slimmed down the VMware package size. Stop by mindtouch.com to download your version today!

This release consists of fixes for 65 issues which are covered in the changelog – anybody running on an Olympic release should upgrade to 10.0.2.

Special thanks go out to our QA team for ensuring a rock solid release & for our OP team’s tireless efforts to get these packages down to a more slender size!

14 Sep 10

Behind the MindTouch OpenID add-on

First, an introduction. Hello, everybody!  I’m Craig. I’ve been a member of the MindTouch community since February 2008, when I was living in Canada and looking for a collaboration tool running on C# for a Windows software shop I was working at. MindTouch actually ran C# on Mono on Linux, which suited me fine, as I am a dual-purpose Windows and Linux guy, and it was good to have a reason to have Debian around at work again! I had a couple of opportunities to travel to southern California for work, and met the MindTouch gang; there are some great ‘enginerds’ working there, and a Christmas card from Roy & friends is a site to behold.

While I’ve since changed jobs (and countries), I’m still a very active member of the MindTouch community, and still enjoy contributing to the platform. Over last Christmas, I built an add-on for MindTouch to support OpenID, with an view to using it for an application in my new role at the Symbian Foundation. While we didn’t end up finding an opportunity to use MindTouch at Symbian, as an open source foundation we are happy to contribute work like this to to the greater community.

First, some terminology. An OP is an OpenID Provider: a site which provides an authentication servicew using the OpenID protocol. This is Site A in my other post. Your MindTouch site, Site B becomes an RP, also known as a Relying Party, formerly known as a consumer.

Anatomy of a MindTouch add-on

You could implement an OpenID extension entirely in the front-end (using PHP) if you wished, and an earlier attempt at OpenID support worked exactly this way. However, the service approach was more in line with the MindTouch model, and I like C# more than I like PHP!

Back-end service

It was a foregone conclusion that I should use DotNetOpenAuth as the engine for this project. It is the OpenID library that powers StackOverflow, and one of the primary authors, Andrew Arnott, is very active in supporting the library. Unfortunately, the 3.x version uses some new whizz-bang functionality in .NET which means it doesn’t work on Mono; rather than try and randomly disable code in a security library, I’ve stayed with using the 2.x series, from when it was known as DotNetOpenId.

The back-end only has two methods, both of which are called solely by the front-end:

  • authenticate: given an OpenID string, discover the endpoint for that string, and build a URL to redirect the user to; or throw an exception if that endpoint is invalid or unreachable.
  • validate: when given a signed response from an OP, check that it is correct, and return the details provided (full name, e-mail address etc), or throw an exception if it is somehow invalid.

Using trusted authentication

MindTouch’s trusted authentication is what makes this all so easy. A call to the API (with the site’s secret API key) will let you create a user of your choice; this means we can use front-end code to create users. If the user passes an API call and has a good OpenID, we can create a MindTouch user for them.

Front-end extension

We need to inject ourselves into the login process, so that the user knows that OpenID is an option; after that, there needs to be a page to display the OpenID selector, and handle the interaction with the user. That calls for a special page, using hooks to insert a link to our page on the UserLogin page.

The documentation on PHP special pages is a bit sparse, but you can gleam all you need to know from the examples, and looking at the existing pages. Ultimately, they’re just PHP, with handy functions for displaying the page chrome.

Following suggestions from Max and Guerric, I settled on this approach:

  • A user browses to /Special:OpenIDLogin and gets the endpoint selector.
  • User selects or enters their endpoint and hits Submit.
  • The selected ID is POSTed to /Special:OpenIDLogin.
  • If the /Special:OpenIDLogin is called as a POST, it sends a secondary POST to the OpenID API service, calling the ‘authenticate’ method. This validates the endpoint, and responds with either an error message, or a URI to redirect the user to.
  • If the response was an error, it is displayed to the user; if it is good, the front-end redirects the user to the OpenID provider with /Special:OpenIDLogin as the return URI.
  • The user logs in to their OpenID provider, or authorise your site to use your OpenID, and is redirected to /Special:OpenIDLogin again with signed OpenID parameters.
  • When /Special:OpenIDLogin is called with signed OpenID parameters, via POST or GET (both are supported by the OpenID spec), the page then POSTs the query parameters to the OpenID API service, calling the ‘validate’ method:
    • If the response was an error or failure, it is displayed to the user and the process ends.
  • The front-end queries the site properties store to see if your OpenID is associated with a MindTouch user already.
    • If your OpenID is found, the user has logged in previously, and we have stored their username; log that username in using trusted authentication, and return to the page they wanted to see.
    • If no property is found, they are redirected to Special:OpenIDCreateUser, with a hashed secret. On that page, they are asked to enter a username (which is validated by AJAX using jQuery, to indicate if the username is acceptable/in use). That username is stored in the property against their OpenID, and they are then logged in.

All that boils down to three pages:

The front-end makes use of another open source project; the jQuery OpenID selector by Reflejo.

Pitfalls and abandoned paths

I wanted to be able to use an OpenID URL as a username, but that introduces two problems: first, you may already have a user account; second, MindTouch doesn’t take nicely to usernames containing colons and slashes, especially as everyone gets a User: page. It was tried but ultimately abandoned.

Future additions

A wealth of possibilities for adding to this extension exist: here are but a few.

  • When you’re asked to create a new account, you should be able to pick an existing account to associate with, by username and password.
  • Conversely, you should be able to add OpenIDs, and verify yourself, from your user preferences page.
  • The add-on allows you to restrict the OpenIDs that are accepted (to, say, only your Google Apps domain). If you know this, you should also be able to make the front-end skip asking you for a provider and just redirect you to one.
  • Make a MindTouch installation an OpenID provider. Why not?

Getting the add-on

As this is an open source contribution to the platform released under the GPL, it’s available in source for you to improve. MindTouch Inc. have kindly integrated it into their build process so it’s available pre-built in the SVN tree. Thanks, guys!

To learn how to install this add-on into MindTouch, check out its page at the MindTouch App Catalog.

Copyright © 2011 MindTouch, Inc. Powered by