TheFileTree Design Log 4: Accounts

I mentionned needing to add accounts in design log 2. It is now implemented.

You go to /app/account/, which contains either your account information if you are logged in, or a form to get registered.

Create an Account

Congratulations for signing up

You get an email with a link back to the website, which gives you a httpOnly secure cookie with a token that the database will recognize and associate to a JSON blob containing your information (email, user name).

Email with link

Welcome page

Account page

As planned, I use email-login, which I improved for this purpose by adding support for CockroachDB, a serializable distributed SQL database that I plan on using more (maybe for file metadata).

All files now have an Access Control List (ACL) so that you can set the default access (none (404), reader, writer (can see and edit), owner (can also change the metadata, and therefore the ACL).

Folder ownership

ACLs on folders apply to all subfiles unless an explicit ACL overrides it. It works like variable scoping: the nearest containing metafolder with an explicit ACL that applies to you determines your access.

It works by setting the acl JSON object in the metadata. It is a map from username to right: - for none, r for reader, w for writer, x for owner. Does it remind you of Unix permissions?

JSON metadata

The * key is for other users (logged in or anonymous).

Canop Finishing Touches

Code and bugs are lovers. The monster that I am had to crush a handful of the latter, but it really was to save the former.

For instance, undo/redo was semantically wrong.

Why? Of course, CodeMirror supports undo/redo, but it keeps track of all changes. However, when you are editing code with others, you only want to undo your own changes. If you wrote a word and press Undo, you expect your word to be removed, not the operations that someone else did in the meantime.

That required managing my own undo stack

Another tricky situation arose while testing when I started using multiple cursors, a feature that every text editor under the sun stole from SublimeText (although Wikipedia mentions MIT’s LAPIS as the first to sport it, as part of their academic paper.)

I received the editing operations CodeMirror gave me from the change events after it had already updated the editor. The operation positions I dealt with could not easily be mapped back to indices, as they related to the editor’s state before the change.

I tried getting inspiration from ot.js, but ended up relying on a simpler algorithm using the beforeChange event.

It does have the downside that you don’t automatically have multiple changes that are semantically combined (like deleting multiple selections). Those end up having a single undo entry, for instance. I was getting used to reimplementing CodeMirror things, so naturally I implemented a time-based operation grouping system.

Deploying To Production

The first version of TheFileTree was located on a server under our college dormroom desks; the second in a college server; the third on a friend’s subletting server offer; the fourth on an OVH VPS. This one will be on Google Cloud, starting with their free tier, where it should fit for some time before it, hopefully starts generating revenue to be self-sustaining.

It did require some subtle tweaking to support the fact that sending emails is severely restricted on Google Cloud. There is a handful of partners that you have to go through; I picked MailJet. I tweaked the email-login npm package and my DNS zone file to make it work.

As far as administrator interfaces are concerned, Google Cloud is extremely polished, offering a clean interface with good configuration, and even a convenient remote SSH-in-a-tab.

While it is still slightly slower to get up and running with a fresh instance than on Digital Ocean, it is a step up from OVH. That said, OVH offers a predictable fixed cost and no egress cost, while GCP will have complicated costs to manage once I need to look after them.

Sadly, to get on the free tier, I was required to host the servers in South Carolina, US. There is a subtle bit more latency as a result from France.

All in all, it was a very interesting choice to have. The website is now much more robust than it was before. The only dark spot is the single-node CockroachDB server, which dies on a regular basis, seemingly because it does not like to be alone. I will have to investigate further later.