This project was created in under a day in 2022 as a part of an assessment. It's a cat bookmarking web app! It consumes JSON representations of cat images accessible via the [Cataas](https://cataas.com) API, the links to which can be permanently stored in a bookmark database.
## Running the server
To run the server, you'll need:
* Elixir, which depends on Erlang. Detailed instructions on how to install Elixir and Erlang can be found on [the Elixir website](https://elixir-lang.org/install.html). In most cases, installing Elixir will get you a copy of Erlang as well.
* Node.js. If you've been blessed to have never needed to download Node on your device, you can end that streak now by visiting [the Node.js download page](https://nodejs.org/en/download)
* PostgreSQL, which you'll need running. You can find information on how to install it on [the PostgreSQL download page](https://www.postgresql.org/download/) as well.
## Aside: Setting up Postgres
By default this project assumes your PostgreSQL install has a user with the name "postgres" whose password is "postgres". Is that not the case? Either:
* Change the configuration to use the right credentials. Open `./config/dev.exs` and find and edit:
```elixir
config :bookmarker, Bookmarker.Repo,
username: "<YOURUSERNAME>",
password: "<YOURPASSWORD>",
```
* Change your password, say, to "postgres". If you're on Linux, this would look something like:
The first two are literally HTML input elements. The third is selected randomly by repeatedly pressing the "Show New Cat" button. The third is represented by a route both in Phoenix and using React Router.
The tech stack for this project is as follows:
- Elixir, the back-end programming language
- Phoenix, which is the Ruby On Rails of Elixir
- PostgreSQL as the database
- React for the front-end
The front-end of this project is a single-page app that uses React Router to navigate between the two "pages."
All of the API endpoints are under the `/api/v1/` route, and since this project only really does bookmarking, all of them ended up being under `/api/v1/bookmark`. The three required routes are as follows, followed by the other routes I added for convenience:
- POST /api/v1/bookmark - Accepts a JSON payload with keys `remote_id`, `notes`, and `category` and stores it in the database.
- GET /api/v1/bookmark/single/:id - Returns a single bookmark with the given ID. If The user doesn't have any bookmarks with that ID, the server returns an error with a 404 status code.
- GET /api/v1/bookmark - Returns all of the user's bookmarks.
- DELETE /api/v1/bookmark/:id - Deletes the bookmark
- GET /api/v1/bookmark/category/:category - Returns all bookmarks in `:category`
- GET /api/v1/bookmark/categories - Returns an array of strings, each representing the name of a category that has at least one bookmark
### Rudimentary authentication
Accounts are generated in the same way some conferencing software gives users semi-private meeting rooms represented by a random string of words. That way, anyone with the link can access it, but it's not particularly easy to find a given room without knowing the string of words in advance.
I didn't feel like putting together a large dictionary of words, so I just used JavaScript's pseudo-random number generator to generate a probably-unique user ID (or at least, there's only a one in a million chance of a clash).
The user's page is accessible by accessing the `/u/:id` route, where `:id` is the user's ID number
When making calls to the API, the client passes an `Authorization` header to their request including their ID, such as `Authorization: Basic 1234...`. If this header is omitted or malformed, the server returns a 401 status code. Not production-grade by any means, but not bad for a cat bookmarking app.