| # URL Shortener |
| URL shortener will be one of the first party applications developed and published by pcloud team. |
| |
| ## Background |
| 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** |
| |
| ## Goals |
| * Authenticated user must be able to assign name to any given URL address. |
| * User can choose name manually or generate it randomly. |
| * User must be able to view list of all named URLs owned by them. |
| * [Stretch] User must be able to transfer ownership of the name to the other user. |
| * [Stretch] Administrator of the system must be able to act as any other user. |
| |
| ## Non-goals |
| * 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. |
| * [Maybe] Changing address of alread created entry must not be possible. |
| |
| ## Technichal overview |
| 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. |
| |
| 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. |
| |
| Storage component will have following interface: |
| |
| ```go |
| type NamedAddress struct { |
| // Name of the address. Must be unique across the service. |
| Name string |
| Address string |
| OwnerId string |
| Active bool |
| } |
| |
| type Store interface { |
| // Creates new named address. |
| Create(name, address, ownerId string) error |
| // Activates given named address. Does nothing if named address is already active. |
| Activate(name string) error |
| // Deactivates given named address. Does nothing if named address is already inactive. |
| Deactivate(name string) error |
| // Transfers ownership of the given named address to new owner. |
| ChangeOwner(name, ownerId string) error |
| // Retreives all named addresses owned by given owner. |
| List(ownerId string) ([]NamedAddress, error) |
| } |
| ``` |
| |
| 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. |
| |
| Standard [net/http](https://pkg.go.dev/net/http) is sufficient to implement the web server. Server will have just two handlers registered: |
| * `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. |
| * `POST /` - to create new named address entry |
| |
| 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. |
| |
| Implementation will go to `apps/url-shortener` directory. |