Monday, March 30, 2009

Using the Cloud

Over the years I've started countless projects by myself or with friends that have never been fully realized.  I'm still waiting for that one great idea that really drives me to create something from nothing.  In the mean time I am pretty happy bringing other people's ideas to light, most of the time.

Without giving away too much detail, one of my current client projects is a pretty cool combination of technologies.  We are building an iPhone application with Amazon Web Services back-end.  As we've been building this it has occurred to me how many of my ideas in the past died because we would get bogged down in the details about where and how we were going to host it rather than just building it.

It's thrilling to see all these cloud computing services springing up that really level the playing field for anyone with an idea to deploy, and more importantly scale if they find success.

I still don't have that one great idea, but I feel like the roadblocks that existed in years past have lessened.

Friday, February 6, 2009

Once-A-Month Blog Challenge

You might recall the Once-A-Week Blog Challenge that Joel and I started last year. Well, the wheels kinda fell off that wagon, but never fear, we have a new challenge, but this time we are lowering our expectations. We are both committing to getting at least once post up a month! Here is mine for February.

My Top 5 iPhone Applications Redux

Back in july I posted about my top 5 iPhone applications.  I figure it's been about 6 months and it would be a good time to revisit this topic as my top 5 have since changed.  So in no particular order, here they are...


I managed to pick this app up when it was initially released for free, now it runs $2.99, but I would still pay for it. Zenbe is a pretty straight forward list tracking app that allows you to create multiple lists, assign due dates and organize your items. It has the added bonus of having a pretty decent web front end that stays in sync at lists.zenbe.com


I continue to find Yelp very useful when looking for new restaurants and bars, the iPhone app is a nice compliment to the website.


I am pretty much addicted to iPhone solitaire, this version is great. They have a free version as well, but I think its worth the price for the added game variations you get.


I kinda hate to admit it, but I check Facebook on my phone way more than I probably need to be.


Mint is a great tool for tacking your expenses and investments, the iPhone application makes it even more useful.


Honorable Mentions...


I still thing Evernote is a great tool, I just don't use is at much as I should.


Shazam is one of the most clever apps I've seen. It has been able to identify songs in some pretty poor audio situations.


GasBag crashes way more than a public application should, but I do like the MPG tracking component of the application.


Remote is still a great app for controlling your music from anywhere in your house, even if your house is really only about 750 sq. feet.

Wednesday, October 15, 2008

Connecting to iPhone Applications via Peer-To-Peer Networking

I recently found myself wanting to copy some documents to the AirSharing application on my iPhone but I was not able to connect to a Wi-Fi network at the time.

As it turns out, this is really easy to do using peer-to-peer wireless networking, enabling applications like AirSharing or the Apple Remote to connect to your machine regardless of if there is an available wireless network.

Note: This can be done on Windows as well, however, I will only be covering the process on a Mac.
  1. First you need to create a new network on your Mac by selecting your AirPort menu item and choosing "Create Network...".

  2. Choose a name for your network, and optionally require a password (I would suggest adding a password to restrict access to your machine).

  3. On your iPhone, tap Setttings then Wi-Fi.

  4. Your phone should find the network you just created, tap it and enter your password if you chose to set one up.

  5. Now open AirSharing.

  6. Back on your Mac, from the Finder menu, select "Connect to Server..." (this can also be opened by pressing Command+K on your keyboard).

  7. Enter the address specified by AirSharing for connecting and click "Connect".

  8. A finder window will open with the AirSharing share and a mounted disk will appear on your desktop.

As I mentioned above, this tip is not limited to the AirSharing application.  Any iPhone application that uses wireless connectivity to interface with your machine, such as the Apple Remote, should work with this method.

Friday, August 15, 2008

Active Directory Role Provider


I've been using the ActiveDirectoryMembershipProvider to allow my users to login to a custom ASP.Net site with their AD credentials and it is pretty straight forward. Recently I needed to add more granularity to who can view various parts of the site. I wanted to take advantage of our existing AD groups so I assumed there would be something like an ActiveDirectoryRoleProvider as well. After a little searching, it became clear that wasn't the case, so I decided to roll my own.

Creating a custom role provider is pretty easy, all you have to do is create a new class and inherit RoleProvider:


public class ActiveDirectoryRoleProvider : RoleProvider
{}


You will have to create stubs for all the inherited members. We only need to implement a couple of them to get basic role membership checking. We need to get our AD configuration information out of the Web.Config values, so we'll create a few properties and override the Initialize method:



private string ConnectionStringName { get; set; }
private string ConnectionUsername { get; set; }
private string ConnectionPassword { get; set; }
private string AttributeMapUsername { get; set; }

public override void Initialize(string name, NameValueCollection config)
{
ConnectionStringName = config["connectionStringName"];
ConnectionUsername = config["connectionUsername"];
ConnectionPassword = config["connectionPassword"];
AttributeMapUsername = config["attributeMapUsername"];

base.Initialize(name, config);
}


Now we'll override GetRolesForUser which is the bulk of our implementation. We use the DirectorySearcher class in System.DirectoryServices to query AD for the passed username. We then pull the memberOf property from that user and extract the CN component for each entry as the role:



public override string[] GetRolesForUser(string username)
{
var allRoles = new List<string>();

var root = new DirectoryEntry(WebConfigurationManager.ConnectionStrings[ConnectionStringName].ConnectionString, ConnectionUsername, ConnectionPassword);

var searcher = new DirectorySearcher(root, string.Format(CultureInfo.InvariantCulture, "(&(objectClass=user)({0}={1}))", AttributeMapUsername, username));
searcher.PropertiesToLoad.Add("memberOf");

SearchResult result = searcher.FindOne();

if (result != null && !string.IsNullOrEmpty(result.Path))
{
DirectoryEntry user = result.GetDirectoryEntry();

PropertyValueCollection groups = user.Properties["memberOf"];

foreach (string path in groups)
{
string[] parts = path.Split(',');

if (parts.Length > 0)
{
foreach (string part in parts)
{
string[] p = part.Split('=');

if (p[0].Equals("cn", StringComparison.OrdinalIgnoreCase))
{
allRoles.Add(p[1]);
}
}
}
}
}

return allRoles.ToArray();
}


And finally we need to override IsUserInRole so we can easily check for role membership in code:



public override bool IsUserInRole(string username, string roleName)
{
string[] roles = GetRolesForUser(username);

foreach (string role in roles)
{
if (role.Equals(roleName, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}

return false;
}


Here's the the full code (minus the unimplemented inherited methods):



public class ActiveDirectoryRoleProvider : RoleProvider
{
private string ConnectionStringName { get; set; }
private string ConnectionUsername { get; set; }
private string ConnectionPassword { get; set; }
private string AttributeMapUsername { get; set; }

public override void Initialize(string name, NameValueCollection config)
{
ConnectionStringName = config["connectionStringName"];
ConnectionUsername = config["connectionUsername"];
ConnectionPassword = config["connectionPassword"];
AttributeMapUsername = config["attributeMapUsername"];

base.Initialize(name, config);
}

public override bool IsUserInRole(string username, string roleName)
{
string[] roles = GetRolesForUser(username);

foreach (string role in roles)
{
if (role.Equals(roleName, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}

return false;
}

public override string[] GetRolesForUser(string username)
{
var allRoles = new List<string>();

var root = new DirectoryEntry(WebConfigurationManager.ConnectionStrings[ConnectionStringName].ConnectionString, ConnectionUsername, ConnectionPassword);

var searcher = new DirectorySearcher(root, string.Format(CultureInfo.InvariantCulture, "(&(objectClass=user)({0}={1}))", AttributeMapUsername, username));
searcher.PropertiesToLoad.Add("memberOf");

SearchResult result = searcher.FindOne();

if (result != null && !string.IsNullOrEmpty(result.Path))
{
DirectoryEntry user = result.GetDirectoryEntry();

PropertyValueCollection groups = user.Properties["memberOf"];

foreach (string path in groups)
{
string[] parts = path.Split(',');

if (parts.Length > 0)
{
foreach (string part in parts)
{
string[] p = part.Split('=');

if (p[0].Equals("cn", StringComparison.OrdinalIgnoreCase))
{
allRoles.Add(p[1]);
}
}
}
}
}

return allRoles.ToArray();
}
}


Add the role provider to your Web.Config:



<system.web>
<roleManager enabled="true" defaultProvider="ADRoleProvider" cacheRolesInCookie="true" cookieName=".ASPXROLES" cookiePath="/"
cookieTimeout="30" cookieRequireSSL="false" cookieSlidingExpiration="true" createPersistentCookie="false" cookieProtection="All">
<providers>
<clear />
<add name="ActiveDirectoryRoleProvider" connectionStringName="ADConnectionString" connectionUsername="username"
connectionPassword="password" attributeMapUsername="sAMAccountName" type="ActiveDirectoryRoleProvider" />
</providers>
</roleManager>
</system.web>


You can then check the roles of your user in code like so:



Roles.IsUserInRole("My Group")


Or control access to entire directories via the Web.Config:



<location path="RestrictedSubDirectory">
<system.web>
<authorization>
<allow roles="My Group"/>
<deny users="*" />
</authorization>
</system.web>
</location>

Tuesday, July 29, 2008

My Fancy New 3G Wireless Card

Lately I have been finding myself in more and more situations where I am giving a presentation and I need wireless connectivity and it isn't readily available.  Yesterday I finally broke down and picked up a USBConnect 881 card from AT&T, and so far, I like it.  For about $60 a month the cost isn't too bad for what you are getting, and in using it last night, the 3G speeds were pretty good for doing what I needed to do.  I orginally wanted to go with an Express PCI card for my Mac, but opted for the USB card for more flexibility.

Saturday, July 19, 2008

My Top 5 iPhone Applications

So of course I picked up a shiny new iPhone 3G on launch day.  I was lucky to be in Hillsboro Oregon at the time which meant my line was not too long and I got to take advantage of no sales tax.  It's been a while since I've posted (I'm going to correct that in the next few weeks), so I thought I'd do a round-up of my top 5 favorite 3rd party applications.  In no particular order here they are...

This is Apple's fantastic iTunes remote.  I don't have an Apple TV yet, but I have been playing with this with my iTunes library on my laptop and it works flawlessly.  I can't wait to get my condo all setup so I can take full advantage of this tool.

This has to be one of the less polished games in the iTunes store, but it is addicting. The basic goal is to fly your little ship through a minefield of cubes, if you hit a cube, you die. You pretty much just compete against yourself for high score. The game could use stages, so you don't just end up playing the same first level over and over again, but short of that, it is an awesome first showing for a casual game.

Evernote is a great desktop tool for knowledge capture.  It works on Mac and Windows, and with their latest release they have included an iPhone client.  This comes in handy so often in my life when I have meetings where lots of white boarding occurs.  All I have to do is open Evernote and take a picture of the whiteboard and the image is automatically synced with my laptop.  On top of that, Evernote has fantastic OCR technology allowing you to then search all of your content, even my aweful whiteboard chicken scratch gets properly indexed.

I always have a terrible time picking a restaurant when it comes time to go out to eat.  This tool solves that problem in a fun way.  Using location based services, Urbanspoon will zero in on your city.  You then lock in your options, be it neighborhood, cuisine or price.  Then simply shake your phone and Urbanspoon will randomly pick a place for you, if you don't like it, shake it again!

Tie: Pandora and Last.fm
Both of these applications do very similar things. Based on the same technologies of their respective web sites, you can get a customized radio station based on your music tastes. Pandora is based on the Music Genome Project, which uses a more scientific approach to matching tunes. Last.fm relies on social networks and listening patterns to do something very similar. I am a Last.fm user, so I like this app for that reason, however, I believe Pandora streams much more reliably with less waiting for buffering.