livecore-api v1.0.0
LiveCORE
A set of APIs to the CORE entities in LiveStories.
NOTE: Deployment is done through CircleCI
Getting up and running
npm install
Then start all required services, build the DB, schema and Indices, and pre-populate the DBs and finally create entitlements.
npm run services:up
# You want to wait for Elasticsearch to be up (it takes a few seconds)
# Run this CURL until you get a response that starts with "yellow". It will be red first...:
# yellow open .marvel-2018.02.01 1 1 44 0 1.1mb 691.7kb
curl http://localhost:9200/_cat/indices
# Then proceed...
npm run db:create
npm run db:migrate
# Same thing Elasticsearch, it needs to catch up!
# Run curl until all indices are marked "yellow". You should eventually get something like
# yellow open topics 5 1 0 0 970b 575b
# yellow open dashboards 5 1 0 0 812b 575b
# yellow open charts 5 1 0 0 970b 575b
# yellow open stories 5 1 0 0 776b 460b
# yellow open autocomplete 5 1 0 0 970b 575b
# yellow open datasets 5 1 0 0 812b 575b
# yellow open .marvel-2018.02.01 1 1 243 0 1.3mb 609.2kb
curl http://localhost:9200/_cat/indices
npm run db:seed:all
NOTE: you need to install docker and docker-compose FIRST!
Then start livecore
:
npm start
Controlling services
change
npm services:up // Starts all services
npm services:stop // stops all services but doesn't destroy them (i.e. == suspend )
npm services:down // permanently destroy all services and associated storage.
Migrations
Sequelize-cli is used for migrations.
npm run db:create // create the PG DB
npm run db:migrate // run all migrations to HEAD
npm run db:migrate:undo // undo the last migration that was run.
npm run db:migrate:undo:all // undo all migrations
To create a new blank migration:
./node_modules/.bin/sequelize migration:generate --name <a-meaningful-name!>
NOTE: The sequelize-cli-typescript package that we currently use to manage migrations has a bug preventing the ability to generate migrations. This can be fixed by making this change in the file ./node_modules/sequelize-cli-typescript/lib/commands/migration_generate.js
, but that change will have to be undone to enable the ability to run the migrations.
Migrations are stored in /migrations
.
They are run at deployment time when master
deploys.
DB seeders
Sequelize-cli is also used to seed the DBs.
npm run db:seed:all // run all seeders
npm run db:seed:undo:all // undo all seeders
PS: Entitlements aren't using this mechanism because our seeders haven't yet been ported over to Typescript.
Entitlements
Swayze needs the system roles to be persisted in the database. The entitlements seed can set this up for you and can be run via the setup-entitlements.js script like so:
npm run ts-node scripts/setup-entitlements.ts
Authorization
We perform authorization with JWTs passed in the 'Authorization' header.
Example header: Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiNTg4N2FkYTE0MjFhYTkxMDMyMDVhMDNjIn0.SCidGbyk0iw16B0upnGBsDqqcnao8Go7Ygj33C4Zdoo
Testing
This section will explain how we are testing using Replay. Note that there are other testing approaches that are in development for LiveCore.
Here are the steps to run a Replay test:
Add prod creds to your services.manifest.json
, and connect to the LiveStories VPN.
Run npm run test:replay
. The tests currently take ~3 mins to complete. Note that in the case that a user makes a change while the Replay tests are running, the results may return a false positive.
You can update the production creds with a replay
key to map the replay file names to their auth tokens:
"replay": {
"no-auth-routes.csv": "",
"user-1.csv": "<user-1 auth token>",
"user-2.csv": "<user-2 auth token>"
},
(Note that our routes files in user-1.csv
and user-2.csv
can be generated from our log files by running the script in scripts/log-to-replay-routes.py
.)
Deployments
To deploy to staging, simply tag with a "staging-xxxxx" where xxxxx is a timestamps in seconds since epoch. The following shell command does the trick.
TAG="staging-$(date +%s)"; git tag $TAG; git push origin $TAG
This can be added as an alias in your .profile
(or equivalent) with
alias tag-staging='TAG="staging-$(date +%s)"; git tag $TAG; git push origin $TAG'
From then on you can simply do tag-staging
to push the current SHA to staging!
Endpoints
Session
- Endpoint:
/session
Methods:
POST
- Description: Authenticate a user
- Request: Email and password params
- Response: JWT with user_id
- Onboarded boolean
Team
- Endpoint:
/team/:teamId
Methods:
GET
- Description: Fetch team by ID
- Request:
- Response: team document
- Endpoint:
/team/:teamId
- Methods:
- Endpoint:
PATCH
- Description: Update team details
- Request:
- Response: team document
Endpoint:
/team/:teamId/membership
Methods:
GET
- Description: Get list of team memberships
- Request:
- Response: Array of team memberships
POST
- Description: Create team membership invite
- Request:
- Response: Membership
Endpoint:
/team/:teamId/membership/:membershipId
Methods:
PATCH
- Description: Update membership role
- Request:
- Response: Status code
DELETE
- Description: Remove a membership
- Request:
- Response: Status code
Endpoint:
/team/:teamId/dataset
Methods:
GET
- Description: retrieve full dataset documents
- Request:
- Response: list of dataset documents
Endpoint:
/team/:teamId/dataset/status
Methods:
GET
- Description: retrieve minimal dataset description along with upload status
- Request:
- Response: minimal dataset object along with upload/index status
Endpoint:
/team/:teamId/dataset/count
Methods:
GET
- Description: retrieve the number of objects that would be returned by a call to /count
- Request:
- Response: numeric count of objects
Endpoint:
/team/:teamId/story
Methods:
GET
- Description: retrieve list of stories for given team
- Request:
- Response: list of story documents
Endpoint:
/team/:teamId/story/count
Methods:
GET
- Description: retrieve count of stories for a given team
- Request:
- Response: numeric count of story documents for given team
Endpoint:
/team/:teamId/dashboard
Methods:
GET
- Description: retrieve list of dashboards for a given team
- Request:
- Response: list of dashboard documents
Endpoint:
/team/:teamId/dashboard/count
Methods:
GET
- Description: retrieve count of dashboards for given team
- Request:
- Response: numeric count of dashboard documents
Endpoint:
/team/:teamId/user
Methods:
GET
- Description: retrieve list of users for a given team
- Request:
- Response: list of users
User
- Endpoint:
/user/:userId
Methods:
GET
- Description: retrieve a full user document by ID
- Request:
- Response: numeric count of dashboard documents
Endpoint:
/user/:userId/team
Methods:
GET
- Description: retrieve the details about a users team memberships
- Request:
- Response: team objects and the users role within them
Endpoint:
/user/:userId/dataset
Methods:
GET
- Description: retrieve the datasets this user created or collaborated on.
- Request:
- Response: {entity,actions} array.
Endpoint:
/user/:userId/dataset/count
Methods:
GET
- Description: retrieve the number of datasets this user created or collaborated on.
- Request:
- Response: {entity,actions} array.
Endpoint:
/user/:userId/story
Methods:
GET
- Description: retrieve the stories this user created or collaborated on.
- Request:
- Response: {entity,actions} array.
Endpoint:
/user/:userId/story/count
Methods:
GET
- Description: retrieve the number of stories this user created or collaborated on.
- Request:
- Response: {entity,actions} array.
Endpoint:
/user/:userId/dashboard
Methods:
GET
- Description: retrieve the dashboards this user created or collaborated on.
- Request:
- Response: {entity,actions} array.
Endpoint:
/user/:userId/dashboard/count
Methods:
GET
- Description: retrieve the number of dashboards this user created or collaborated on.
- Request:
- Response: {entity,actions} array.
Endpoint:
/user/:userId/iq_chart
Methods:
GET
- Description: retrieve the IQCharts this user created or collaborated on.
- Request:
- Response: {entity,actions} array.
Endpoint:
/user/:userId/iq_chart/count
Methods:
GET
- Description: retrieve the number of IQCharts this user created or collaborated on.
- Request:
- Response: {entity,actions} array.
Endpoint:
/user/:userId/notification
Methods:
GET
- Description: retrieve a list of notifications for a given user
- Request:
- Response: a list of notification objects
Endpoint:
/user/:userId/notification/count
Methods:
GET
- Description: retrieve a full user document by ID
- Request:
- Response: numeric count of notifications
Endpoint:
/user/:userId/team/:teamId/switch
Methods:
POST
- Description: switch the 'active' team for a given user
- Request:
- Response:
Membership
- Endpoint:
/membership
Methods:
GET
- Description: Use token in query param to find membership by token
- Request:
- Response: A membership
Endpoint:
/membership/:membershipId
Methods:
PATCH
- Description: Update the
active
attribute of a membership - Request:
- Response: Status code
- Description: Update the
Endpoint:
/membership/:membershipId/signup
Methods:
POST
- Description: Update membership user params
- Request:
- Response: User
Dashboard
- Endpoint:
/dashboard/:dashboardId
Methods:
GET
- Description: retrieve a dashboard document by ID
- Request:
- Response: a dashboard document
Endpoint:
/dashboard/:dashboardId/trash
Methods:
PUT
- Description: update the 'trashed' status of a dashboard document to trashed
- Request:
- Response:
Endpoint:
/dashboard/:dashboardId/untrash
Methods:
PUT
- Description: update the 'trashed' status to no longer be trashed
- Request:
- Response:
Endpoint:
/dashboard/:dashboardId/comment
Methods:
GET
- Description: retrieve comments on the dashboard
- Request:
- Response: an array of comments
POST
- Description: create a comment on the dashboard
- Request:
- Response:
Dataset
- Endpoint:
/dataset/:datasetId
Methods:
GET
- Description: retrieve a dataset document
- Request:
- Response: a dataset document
Endpoint:
/dataset/:datasetId/trash
Methods:
PUT
- Description: update the 'trashed' status of a dataset document to trashed
- Request:
- Response:
Endpoint:
/dataset/:datasetId/untrash
Methods:
PUT
- Description: update the 'trashed' status to no longer be trashed
- Request:
- Response:
Endpoint:
/dataset/:datasetId/comment
Methods:
GET
- Description: retrieve comments on the dataset
- Request:
- Response: an array of comments
POST
- Description: create a comment on the dataset
- Request:
- Response:
IQChart
- Endpoint:
/iq_chart/:iqChartId/trash
Methods:
PUT
- Description: update the 'trashed' status of an iqChart to trashed
- Request:
- Response:
Endpoint:
/iq_chart/:iqChartId/untrash
Methods:
PUT
- Description: update the 'trashed' status to no longer be trashed
- Request:
- Response:
Endpoint:
/iq_chart/:iqChartId/comment
Methods:
GET
- Description: retrieve comments on the iqChart
- Request:
- Response: an array of comments
POST
- Description: create a comment on the iqChart
- Request:
- Response:
Endpoint:
/iq_chart/:iqChartId/image?filename=:filename
Methods:
POST
- Description: fetch urlbox.io image of desired chart
- Request:
- Response: S3-hosted image of desired chart
Endpoint:
/iq_chart/:iqChartId/image
Methods:
GET
- Description: fetch cached urlbox.io image of desired chart
- Request:
- Response: S3-hosted image of desired chart
Story
- Endpoint:
/story/:storyId
Methods:
GET
- Description: retrieve a story document. This is a public endpoint.
- Request:
- Response: a story document, with private fields omitted.
Endpoint:
/story/:storyId/trash
Methods:
PUT
- Description: update the 'trashed' status of a story document to trashed
- Request:
- Response:
Endpoint:
/story/:storyId/untrash
Methods:
PUT
- Description: update the 'trashed' status to no longer be trashed
- Request:
- Response:
Endpoint:
/story/:storyId/comment
Methods:
GET
- Description: retrieve comments on the story
- Request:
- Response: an array of comments
POST
- Description: create a comment on the story
- Request:
- Response:
Location
- Endpoint:
/location/user/:userId/team/:teamId
Methods:
GET
- Description: Retrieve the locations for the provided user, within that user's team
- Request:
- Response: A collection of locations (if any) that were saved by the user
Endpoint:
/location/user/:userId/team/:teamId
Methods:
PUT
- Description: upsert a location for the provided user, within that user's team
- Request:
- Response:
Notification
- Endpoint:
/notification/:notificationId/read
Methods:
POST
- Description: Mark notification as read
- Request:
- Response: Status code
Endpoint:
/notification/:notificationId/read
Methods:
DELETE
- Description: Mark notification as unread
- Request:
- Response: Status code
Endpoint:
/notification/trash
Methods:
PUT
- Description: Mark notification as unread
- Request:
notification_ids
: List of ids to trash - Response: Status code
Chart
- Endpoint:
/charts/:chartId/image?filename=:filename
Methods:
POST
- Description: fetch urlbox.io image of desired chart
- Request:
- Response: S3-hosted image of desired chart
Endpoint:
/charts/:chartId/image
Methods:
GET
- Description: fetch cached urlbox.io image of desired chart
- Request:
- Response: S3-hosted image of desired chart
5 years ago