Facebox: Users and Organizations

Overview

Facebox is named after Facebook, because it is responsible for Users, Organizations, Groups, and other 'profile' data such as UserFavorites.

API

Facebox uses the Messenger and Blockhead gRPC APIs for authorization use cases. Facebox often has to verify that a user has spaces or rooms in common with another user in order to authorize viewing a user.

NATS

Production

Whenever an entity owned by Facebox is mutated, it publishes a message to facebox.change_feed. For example, facebox.change_feed.user.{userId}.createdV1.

Consumption

  1. dealer.presence.userV1, .blockV1, and .spaceV1, to update each user's last_seen_at value, as described below.

Application presence (last_seen_at)

Clients report presence via the Dealer service. When viewing a space or a block, they do this for UI reasons; we need to render an avatar stack, cursors, etc. When they are not viewing a space or a block, clients still have a websocket connection to Dealer via Pilot and report presence every 10 seconds.

It is necessary for Facebox to consume these presence updates (which Dealer debounces per-scope but does not deduplicate across scopes) and update last_seen_at in the database. Facebox however does not then publish to change_feed.user.updated. last_seen_at updates can be consumed directly from Dealer like Facebox does, but are not republished by Facebox.

Note that Facebox might get messages that list timestamps prior to the current value in Facebox – it should do nothing in those cases, the last_seen_at goes forward, not back.

Databases

Facebox uses Postgres to store the user/organization related entities it is responsible for.

  1. User – Someone who logs into Pivot via the Visa service. Users also exist corresponding to each Integration stored in Rest. Facebox is not responsible for these API access keys, but it does store the user records.

  2. UserEmail – An email address for a user. May or may not be verified!

  3. UserFavorite – A sidebar favorite. Presumably a space or block, but that's beyond the scope of Facebox's understanding.

  4. Organization – Aka a 'tenant' or an 'org'. Every space is owned by an organization, who is responsible for paying for those members.

  5. OrganizationRole – A user who is an admin of an organization has a row in this table corresponding to that organization's ID. The user who creates an organization is its first role holder (aka 'admin').

  6. OrganizationPolicy – In order to dynamically add/remove/update/migrate our approach to boolean setting values on organizations to control what that organization as enabled/disabled, we have a separate table. This prevents the Organization table from becoming filled with can_do_this and can_do_that boolean columns.

  7. Domain – An organization can verify ownership of a domain to control things like single-sign-on and allowed email domains.

  8. Invite – If a user does not exist, their email address can be used to store future room/space memberships, which are then 'redeemed' when the user is created and 'attached' to that new userId.

  9. AuthorizedConnection – In the future, this table will be used to track which users have created OAuth integrations with which third party services (e.g., Google Calendar). This table is relevant whether the integration is direct or via some integration middleware layer we are using as a service.

  10. Group – An organization can put users into groups.

  11. CustomWebView – A group of users in an organization can be served with a custom sidebar tab, which is an iFrame to a third-party website.

  12. GroupMember – Users are associate to groups.

  13. BlockedUser – One user can block another. How this is implemented depends on each service that consumes the data. For example, presumably Messenger checks Facebox for blocked users when a direct room is created.

Temporal Workflows

  1. Domain Verification: When an organization adds a domain, we need to mark it verified when we are able to successfully see that the TXT value was added. Then if the TXT record is removed, we likely need to send a warning email then mark unverified after a while.

Deployment

Observability

Security