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. This project is set up to assume that the database username is "postgres" and the password is "postgres"
```bash
$ cd bookmarker
$ mix deps.get # Install Elixir dependencies
$ mix ecto.setup # Set up the database
$ cd assets
$ npm install # Install Node dependencies
$ cd ..
$ mix phx.server # Run the server
```
You can then navigate to localhost:4000 to find the front end of the
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.