Sunday, August 2, 2015

Users and Roles (Part 2)

In Part 1 I described the kind of situation you get into with a naive access control system based on tying everything to a user ID: it starts out easy, but then gets harder and harder to change as the business needs evolve.

In Part 2, I want to look at how we can create a more robust and flexible system by "de-complecting" the separate ideas of user identity and access control.



"Complecting" is a term Rich Hickey invented/resurrected meaning intertwining things that ought to be kept separate. The process of "de-complecting," then, means taking things that are intertwined and separating them into separate, simpler things.

If we look at our user ID based access control system, we see two things right away that are really separate things that we're mixing together: user identity, and resource ownership. They may look similar, and there may be a lot of overlap between the two, but they are different things, as we found out when business came back to us and said they needed to let multiple people from the same company all share the same data. Ownership may coincide with the identity of an individual user, but it isn't the same thing.

So let's de-complect this model. We're going to take the complex user/owner concept, and do two things. First, we're going to strip away everything to do with ownership, because that's the essence of de-complecting---taking things away. This gives us our simple user entity, with no concept of resource ownership.

Next, we take the user/owner concept and strip away everything that's not strictly related to ownership. In this case, there's not much left. We have a user ID field, but since this is an owner, and not a user, we have to rename it to owner ID. Everything else is user info, so we strip it away.

What does that give us? A user, and an owner. The owner is nothing more than an arbitrary ID number, separate from the user ID, but that's all we really need.

And now something interesting has happened. User and owner are now separate things. They don't have to coincide. We can mix and match them as needed to meet the business needs.

A user can be linked to more than one owner ID, so for example we can write code that allows a Tech Support rep to temporarily "log in" as an end user, and see exactly what the end user is seeing. Or we can associate an owner ID with a company, and share that owner ID with multiple employees at that company, so that they can all share the same data. And since each of these users can have their own personal owner ID as well as the company owner ID, they can have their own private data, that their co-workers do not have access to, while still having full access to shared company data. We can even have multiple owner ID's for the same company, corresponding to different levels of access (read-only vs read/write), or different departments, or different project groups, or whatever.

All this power and flexibility comes from simplifying a user/owner model that, at first glance, did not appear all that complex. Yet once we realized that it was needlessly complex, and once we simplified our entities, we almost accidentally ended up with a system that was much more powerful and flexible than anything we originally imagined.

All this I've learned the hard way, by writing bad code using complex models. How could I have avoided the painful lessons, and built models that were simple in the first place? I'll save that for one more post (last one, I promise).

No comments:

Post a Comment