So I've been toying with a new feature for Tabulas. It's an incredibly minor feature, but it's taken me far longer to implement than I expected.

The feature: you can now granularly choose which of your friends can see your friends-only content. It differentiates people you want to read with people whom you want to share. It basically adds one more tier between making casual friends on this site, and sharing your real entries with your friends.

I'm still not sold on this feature's usefulness (to me, there's blissful simplicity in forcing people to make a decision on "friending" by also tying the friends-only features to it - I'm a bit worried about rampant "friending" now, but I'm willing to explore it.

I've actually wanted to implement this for some time, but reading ree's post finally got me off my lazy non-coding ass (That and a comment from Max at work saying that coding "wasn't something you [i] do". Ouch!).

The point isn't to talk about this, but rather an amusing anecdote I ran into while implementing this feature. I didn't realize how complex Tabulas' ACL had been.

Tabulas has 3 ACL levels: public, friends-only, and private (only you can read it). Now with this new feature, friends is essentially broken down "you can read me" friends and "let me just be connected to you" friends.

So for a given user account, you can control your entry's privacy levels though:

  • Site-level (public, friends-only, private) : it blocks everything
  • Category-level (categories and entries share a many to one relationship, too)
  • Individual entries privacy levels

 I remember when writing the ACL code, how much of a pain it'd be to change - I remember thinking, "Well, I won't ever change the ACL levels... so who cares if this code is complex?"

Wrong.

Conceptually, what I described about isn't too complex to pull off. The additional complexities come from the "optimization" level code I cobbled together. At a very high level, doing the ACL checks at the PHP level is pretty costly, especially when doing pagination on your friends' page - so to simplify things, I have a column which stores the effective status of an entry (entry perms + category perms + site perms) and I do a SQL query against that to simplify the pagination code. The goal is to do implicit ACL checking at the data level, so the business logic doesn't have to worry about too much about ACL checking. And unlike certain MindTouch devs, I do NOT believe in using advanced SQL - no sprocs (or even sub-selects!). If it can't be done with a straightforward SQL query, it's not worth it. (I've been bit by trying to make mySQL do things it doesn't quite know how to do well - I utilize mySQL as simply as possible)

In pseudo SQL; the friends query looks like this: "SELECT * from entries where (entry_user = 'friend1' AND entry_estatus = 'public') OR (entry_user = 'friend2' AND entry_estatus = 'friends') ORDER BY timestamp LIMIT 0, 5;

This is one of maybe 3 or 4 other optimizations that make Tabulas run faster. Another nasty one I do is to throw all data through a "recent" table - for example, trying to do the previous pseudocode when you have 100 friends who have been posting for 4 years is incredibly inefficient. So, I store a prune-able table of recent entries to poll from first (limits the data set).

These optimizations each take a maintenance and development cost (additional layers of abstraction you have to muck through), which I just had to pay when trying out this filtering feature.

Posted by roy on June 17, 2009 at 11:46 PM in Tabulas | 1 Comments

Related Entries

Want to comment with Tabulas?. Please login.

Comment posted on June 18th, 2009 at 09:14 AM
I dig this new feature, Royo.