# rti-user-preferences-service

## Install

Prepare default `.env` file for development

    cp .env.template .env

Install node dependencies

    nvm use
    npm install

## Run

This setup starts the default Postgres container image from under `postgres/`.

    npm run watch

Test connection

    curl localhost:3333/health

## Test

Use same setup as for running the app. The test command will create a new
`postgres-test` database within the container Postgres server.

    npm run test

## Database

Connections to the development Postgres instances (assuming default setup):

    psql postgres://postgres:postgres@localhost:5432/postgres
    psql postgres://postgres:postgres@localhost:5432/postgres-test

**Migrations under `migrations/` will be run in the target environment when
a new service container image (built by Jenkins) is deployed by Octopus.**

## Develop

Commits pushed to `develop` branch get deployed to the development environment.

## Release

First, get the code into `master`

- Make a PR from `develop` to `master`.
- Check that the changelog is up-to-date
- Review and merge the PR

Next, bump the version to create a known release artifact

- Switch to master branch
- Run the appropriate `npm version [major|minor|patch]` - the hooks in `package.json` should create the new commit, tag, and push them to `master`
- Make sure that previous command succeeded, a pre-push hook runs tests and will block the release (push) if tests didn't pass
- Push to master will create a build in Octopus

Test that the new preferences api does not break production app

- In Octopus, deploy the new version to the 'stage artistapp'
- Test that the `staging` release channel in Expo has not broken

Promote to production

- In Octopus, deploy the new version to 'prod artistapp'
- Test that the production app in iOS and Android did not break
- Open a glass of champagne

## Architecture

- postgres
- typescript
- fp-ts + io-ts
- express

Auth0 is the canonical user database. Due to that reason most of the update operations are upserts - we can't be sure that the user already has an account in this service when an operation happens. The auth0 user id is used to get the database-internal id of the user, and that id is used to join the tables in postgres. No database indices have been created manually yet.

The service is deployed to AWS Fargate, and is only accessible by the RTI backend. Authentication happens at the RTI backend level. The `develop` branch is autodeployed to the dev environment. The `master` branch can be deployed to production via Octopus.

### Test

You need to first have a database running with default configs. Check
`init-test-db.js` for the expected configuration (host/port/credentials).

    docker-compose up postgres
    nvm use

To run the test suites

    npm run test

Test suites should truncate all tables at the beginning of each run.

## API

#### `GET /health`

Returns the service status.

    curl localhost:3333/health

```json
{ "status": "ok" }
```

#### `GET /users`

Lists all of the users.

    curl localhost:3333/users

```json
[
  {
    "id": 1,
    "auth0Id": "auth0%7C5e3aeecf84dda00e7c9e9c73",
    "createdAt": "2020-11-17T10:58:43.000Z"
  }
]
```

#### `GET /devices`

Lists all of the devices and their notification settings.

    curl localhost:3333/devices

```json
[{ "type": "ios", "token": "device_token-9", "notificationsEnabled": true }]
```

#### `GET /favorites`

Lists all of the favorited items along with the list of the device tokens whose users have favorited the items.

    curl localhost:3333/favorites

```json
[
  {
    "id": "USSM11002845",
    "artistId": "GRAS_123456",
    "devices": [
      {
        "type": "ios",
        "token": "device_token-9",
        "auth0_id": "auth0%7C5e3aeecf84dda00e7c9e9c73"
      }
    ]
  },
  {
    "id": "USSM19100017",
    "devices": [
      {
        "type": "ios",
        "token": "device_token-9",
        "auth0_id": "auth0%7C5e3aeecf84dda00e7c9e9c73"
      }
    ]
  }
]
```

#### `GET /users/:auth0_id`

Returns one user.

    curl localhost:3333/users/auth0%7C5e3aeecf84dda00e7c9e9c73

```json
{
  "id": 1,
  "auth0Id": "auth0|5e3aeecf84dda00e7c9e9c73",
  "createdAt": "2020-11-17T10:58:43.000Z"
}
```

#### `GET /users/:auth0_id/devices`

Lists all of the specified user's devices and their notification settings.

    curl localhost:3333/users/auth0%7C5e3aeecf84dda00e7c9e9c73/devices

```json
[{ "type": "ios", "token": "device_token-9", "notificationsEnabled": true }]
```

#### `GET /users/:auth0_id/favorites`

Lists all of the user's favorited items.

    curl localhost:3333/users/auth0%7C5e3aeecf84dda00e7c9e9c73/favorites

```json
[{ "id": "USSM11002845" }, { "id": "USSM19100017" }]
```

#### `GET /users/:auth0_id/notifications`

Lists all of the user's notifications.

    curl localhost:3333/users/auth0%7C5e3aeecf84dda00e7c9e9c73/notifications

```json
TODO
```

#### `POST /users`

Creates a new user.

    curl --request POST \
      --header 'content-type: application/json' \
      --data '{"auth0_id": "auth0%7C5e3aeecf84dda00e7c9e9c730"}' \
      'localhost:3333/users'

#### `POST /users/:auth0_id/devices`

Upserts both the user and the device.
In the post-mvp version, we should be using https://auth0.com/docs/hooks/extensibility-points/post-user-registration and do the upsert only on the device.

    curl --request POST \
      --header 'content-type: application/json' \
      --data '{"token": "device_token-9", "type": "ios", "notificationsEnabled": true}' \
      'localhost:3333/users/auth0%7C5e3aeecf84dda00e7c9e9c73/devices'

#### `POST /users/:auth0_id/favorites`

Inserts the favorite (if required) and adds it to the user's favorites.

    curl --request POST \
      --header 'content-type: application/json' \
      --data '{"id": "USSM11002845"}' \
      'localhost:3333/users/auth0%7C5e3aeecf84dda00e7c9e9c73/favorites'

#### `DELETE /users/:auth0_id/favorites/:favorite_id`

Deletes the item from the user's favorites. Doesn't drop it from the favorites table even if it's not referenced by any other user.

    curl --request DELETE \
      'localhost:3333/users/auth0%7C5e3aeecf84dda00e7c9e9c73/favorites/isrc-1'

#### `POST /users/:auth0_id/notifications`

Stores a notification receipt to the db.

curl --request POST \
 --header 'content-type: application/json' \
 --data '{"title": "notification title", "body": "notification body", "data": "{\"deepLink\": \"example.com\"}"}' \
 'localhost:3333/users/auth0%7C5e3aeecf84dda00e7c9e9c73/notifications'

#### `POST /users/:auth0_id/notifications/:notification_id`

Marks the notification as seen.

    curl --request POST \
      'localhost:3333/users/auth0%7C5e3aeecf84dda00e7c9e9c73/notifications/1'
