| Giorgi Lekveishvili | d4b76ee | 2023-12-19 18:39:06 +0400 | [diff] [blame] | 1 | # URL Shortener |
| 2 | URL shortener will be one of the first party applications developed and published by pcloud team. |
| 3 | |
| 4 | ## Background |
| 5 | PCloud customers, especially businesses, will want to share documents with easy to find and intuitive names. For example internal design document hosted at https://docs.google.com/document/d/X0N4-M0oI2P9l8NMRN6JZR9ETo1fpPIMUf_LUPB5Omgw/edit can be named and shared as **https://go/auth-service-dd** |
| 6 | |
| 7 | ## Goals |
| 8 | * Authenticated user must be able to assign name to any given URL address. |
| 9 | * User can choose name manually or generate it randomly. |
| 10 | * User must be able to view list of all named URLs owned by them. |
| 11 | * [Stretch] User must be able to transfer ownership of the name to the other user. |
| 12 | * [Stretch] Administrator of the system must be able to act as any other user. |
| 13 | |
| 14 | ## Non-goals |
| 15 | * Authentication will be implemented outside of this service. URL shortener can assume that if user can access the page that user has already been authorized. |
| 16 | * [Maybe] Changing address of alread created entry must not be possible. |
| 17 | |
| 18 | ## Technichal overview |
| 19 | URL Shortener service will serve only one page at the root path `/`. At the top of the page must be a form to create new named address entry. And below the form must be listed all the named addresses created by currently logged in user. |
| 20 | |
| 21 | Form will have two input texts: one to input the address user wants to name and second one for the name itself. Name can be either entered manually or auto-generated by server (user will have to click **Randomize** button. Clicking **Create** button must store new named entry in the storage. |
| 22 | |
| 23 | Storage component will have following interface: |
| 24 | |
| 25 | ```go |
| 26 | type NamedAddress struct { |
| 27 | // Name of the address. Must be unique across the service. |
| 28 | Name string |
| 29 | Address string |
| 30 | OwnerId string |
| 31 | Active bool |
| 32 | } |
| 33 | |
| 34 | type Store interface { |
| 35 | // Creates new named address. |
| 36 | Create(name, address, ownerId string) error |
| 37 | // Activates given named address. Does nothing if named address is already active. |
| 38 | Activate(name string) error |
| 39 | // Deactivates given named address. Does nothing if named address is already inactive. |
| 40 | Deactivate(name string) error |
| 41 | // Transfers ownership of the given named address to new owner. |
| 42 | ChangeOwner(name, ownerId string) error |
| 43 | // Retreives all named addresses owned by given owner. |
| 44 | List(ownerId string) ([]NamedAddress, error) |
| 45 | } |
| 46 | ``` |
| 47 | |
| 48 | We will have single implementation of the `Store` interface backed by [go-sqlite3](https://github.com/mattn/go-sqlite3). Path to the sqlite3 file will be passed as a flag, which can be parsed and accessed using standard [flag](https://pkg.go.dev/flag) package, for example `./url-shortener --db-path=/path/to/sqlite3.db`. At the startup server must check if file at given path exists and if not create and initialize (create table for named address entries) it with new sqlite db. |
| 49 | |
| 50 | Standard [net/http](https://pkg.go.dev/net/http) is sufficient to implement the web server. Server will have just two handlers registered: |
| 51 | * `GET /` - if request path is `/` render form and list of addresses owner by current user, otherwise (for example `/foo`) server will find named address for `foo` and send HTTP redirect (StatusSeeOther) to address given name was assigned to. |
| 52 | * `POST /` - to create new named address entry |
| 53 | |
| 54 | Single HTML template will be sufficient to render the home page via [html/template](https://pkg.go.dev/html/template) package. And [embed](https://pkg.go.dev/embed) package will be used to embed said HTML template into the final binary. |
| 55 | |
| 56 | Implementation will go to `apps/url-shortener` directory. |