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.
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).
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).
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?
* 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
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.