Skip to content

Commit

Permalink
Add ADR about link-sharing storage back-end
Browse files Browse the repository at this point in the history
  • Loading branch information
pylipp committed Jan 27, 2025
1 parent 7b5e30b commit 8fa3f37
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 47 deletions.
95 changes: 95 additions & 0 deletions docs/adr/adr_link-sharing-backend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# ADR: Back-end for shareable links

[Trello-card](https://trello.com/c/TVTCaM47/1628-20-draft-concept-for-public-link-sharing-of-statviz)

Decision Deadline: Jan 27, 2025

Discussion Participants: Philipp (@pylipp), Hans (@haguesto), James (@jamescrowley)

## Status

Accepted.

## Context

Users shall be enabled to publicly share certain views, e.g. the statviz dashboard, via a generate URL. The storage back-end for this functionality can either be implemented in-house, i.e. in the boxtribute MySQL database, or with a third-party service (here: PasswordPusher).

For more context, refer to the section "Draft for prototypical implementation" in [this document](../auth/public_sharing_of_statistics.md).

## Decision Drivers

1. Development speed
1. Maintenance overhead
1. Data control
1. Data insight
1. Third-party lock-in
1. Effect on UX
1. Security

## Considered Options

### In-house database table

We extend the boxtribute database by adding a `shareable_link` table. The v2-back-end business logic operates on the database.

### PasswordPusher (PP)

PP is a popular service for sharing secrets over the web: when provided with a secret, PP creates a URL that can be shared with others in order for them to view the secret. The URL can be configured to expire after a certain time or a certain number of views. Also at link creation one can set a passphrase that must be provided when viewing the secret. PP in its basic form can be used for free via [pwpush.com](https://pwpush.com/).

PP provides a [REST API](https://pwpush.com/api/1.1/pushes/show.en.html) for programmatic interaction with the service.

#### Usage as link-sharing back-end

It's possible to use PP as a back-end for the link-sharing feature:
1. When the user requests a link in v2, the parameters of the to-be-shared view are pushed to PP including appropriate configuration of link expiration and a passphrase. The unique URL code generated by PP is present to the user as the shareable link `shared.boxtribute.org/<code>`
1. When entering a shared link, the public FE fetches the view parameters stored for the given code (using the passphrase), and then redirects to this view (e.g. `/<code>/bases/1/statviz`)
1. The view requests data from the public back-end (e.g. the statviz GraphQL requests), sending the code along
1. The BE validates the code and returns the data

Second, favored option:
1. FE sends request to v2 BE to generate link for public sharing. BE generates code by sending a request to the PP REST API. We would need an admin user + password for this and possibly a passphrase if we think we have to secure the data stored in the PP. BE returns code as link URL
1. When resolving a link, the FE sends request to the public BE. BE validates code and retrieves information from PP.
1. BE returns information about view along with data, public FE redirects and shows view

Eventually PP can also be self-hosted (to keep take control, and to be independent of an external service) but this would come with increased DevOps effort, and the inconvenience of introducing a second database to store shared links.

### PP Alternatives

According to [this list](https://alternativeto.net/software/passwordpusher/), [onetimesecret](https://docs.onetimesecret.com/docs/rest-api) can be considered an alternative but it has the immense drawback that a secret can only be viewed once.

Other services in the list like [vanish.so](https://www.vanish.so/) are either fairly unpopular and/or don't provide any API.

The following uses PP as exemplary service.

## Discussion

### Advantages of PP

- development speed: we can save the database logic around storing shared links (incl. not having to take care of link expiration; plus having the passphrase as extra security mechanism (albeit it can be inspected easily when the public FE sends a request to the public BE))
- maintenance: PP provides unlimited creation of links, however with rate-limit
- security: PP is open-source and [trusted by many organisations and considered secure](https://docs.pwpush.com/docs/faq/#trust-is-a-concern--why-should-i-trust-and-use-password-pusher)
- data insight: Using a PP user account enables introspection of generated links

### Disadvantages of PP

- data control: we don't own the raw data of shared links
- increased complexity: we add a second interface that FE has to communicate with; and we have to define a data structure to store information on PP ("hacky" encoding of link metadata into string)
- increased complexity: we add an external service for the BE to communicate with. This complicates testing and test data generation since the service needs to be mocked
- effect on UX: communicating with an external service adds a latency, likely to be larger than a simple database query
- maintenance overhead: we have to create at least one PP user profile and share access in the team, and in CI and the production env
- dependency: using PP as storage, we become depend and have to update boxtribute (FE or BE or both) if the service becomes unavailable (PP has one core maintainer).

### Advantages of in-house DB table

- development speed: very little uncertainty working with the familiar DB and v2 business-logic
- data control and security: we own the raw data (...on GCloud) and can directly query it through SQL
- effect on UX: rapid communication with DB

### Disadvantages of in-house DB table

- data insight: no dashboard with immediate statistics about shared links
- complexity: we have to implement basic rate-limiting ourselves

## Conclusion

Implement the data storage ourselves. Using an external service only shifts development and maintenance work while bearing the risk of becoming unavailable
48 changes: 1 addition & 47 deletions docs/auth/public_sharing_of_statistics.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,50 +208,4 @@ union ShareableLinkResult = ShareableLink | ExpiredLinkError | UnknownLinkError

### Alternative back-end

This section discusses the use of an external password-storage service like [PasswordPusher](https://github.com/pglombardo/PasswordPusher?tab=readme-ov-file) as a replacement for an in-house link-sharing back-end implementation.

#### PasswordPusher (PP)

PP is a popular service for sharing secrets over the web: when provided with a secret, PP creates a URL that can be shared with others in order for them to view the secret. The URL can be configured to expire after a certain time or a certain number of views. Also at link creation one can set a passphrase that must be provided when viewing the secret. PP in its basic form can be used for free via pwpush.com.

PP provides a [REST API](https://pwpush.com/api/1.1/pushes/show.en.html) for programmatic interaction with the service.

#### PP Alternatives

According to [this list](https://alternativeto.net/software/passwordpusher/), [onetimesecret](https://docs.onetimesecret.com/docs/rest-api) can be considered an alternative but it has the immense drawback that a secret can only be viewed once.

Other services in the list like vanish.so are either fairly unpopular and/or dont' provide any API.

The following uses PP as exemplatory service.

#### Usage as link-sharing back-end

It's possible to use PP as a back-end for the link-sharing feature:
1. When the user requests a link in v2, the parameters of the to-be-shared view are pushed to PP including appropriate configuration of link expiration and a passphrase. The unique URL code generated by PP is present to the user as the shareable link `shared.boxtribute.org/<code>`
1. When entering a shared link, the public FE fetches the view parameters stored for the given code (using the passphrase), and then redirects to this view (e.g. `/<code>/bases/1/statviz`)
1. The view requests data from the public back-end (e.g. the statviz GraphQL requests), sending the code along
1. The BE validates the code and returns the data

Second option:
1. FE sends request to v2 BE to generate link for public sharing. BE generates code by sending a request to the PP REST API. We would need an admin user + password for this and possibly a passphrase if we think we have to secure the data stored in the PP. BE returns code as link URL
1. When resolving a link, the FE sends request to the public BE. BE validates code and retrieves information from PP.
1. BE returns information about view along with data, public FE redirects and shows view

Eventually PP can also be self-hosted (to keep take control, and to be independent of an external service) but this would come with increased DevOps effort, and the inconvenience of introducing a second database to store shared links.

#### Advantages

- we can save the entire BE business and database logic around creating and storing shared links (incl. not having to take care of link expiration; plus having the passphrase as extra security mechanism (albeit it can be inspected easily when the public FE sends a request to the public BE))
- PP provides unlimited creation of links, however with rate-limit
- PP is open-source and [trusted by many organisations and considered secure](https://docs.pwpush.com/docs/faq/#trust-is-a-concern--why-should-i-trust-and-use-password-pusher)

#### Disadvantages

- ~less data insight: we don't have control over created links (no information about amount or which views are being shared; at least not without further tracking)~ Using a PP user account enables introspection of generated links
- increased complexity: we add a second interface that FE has to communicate with; and we have to define a data structure to store information on PP ("hacky" encoding of link metadata into string)
- increased complexity: we add an external service for the BE to communicate with. This complicates testing since the service needs to be mocked, and adds a latency
- dependency: using PP as storage, we become depend and have to update boxtribute (FE or BE or both) if the service becomes unavailable

#### Conclusion

Implement the data storage ourselves. Using an external service only shifts development and maintenance work while bearing the risk of becoming unavailable
This section discusses the use of an external password-storage service like [PasswordPusher](https://github.com/pglombardo/PasswordPusher?tab=readme-ov-file) as a replacement for an in-house link-sharing back-end implementation. Please refer to [this ADR](../adr/adr_link-sharing-backend.md).

0 comments on commit 8fa3f37

Please # to comment.