Skip to content

Latest commit

 

History

History

README.md

First Round (API)

Quick Start

Node & NPM

Some of our packages are a bit finicky so we need specific (ish) versions of npm and node to install and run the api.

For npm:

If you have any version of npm installed you can use npm to install any version of itself:

sudo npm install -g npm@6.14.15

For node:

On linux, first check if you have node at all

whereis node

Then check the version:

node -v

Anything above 12.11.x should work. if not continue bellow.

sudo apt-get auto-remove nodejs
sudo apt-get install nodejs
node -v

You should now be on v12.22.6.

API

  1. In this directory run npm install
  2. To start in development mode with apollo playground npm run start-pg, to develop against the react frontend npm run start-ui
  3. Do your work in ./src

If it gets slow or you prefer you can compile the typescript to js on changes and then run nodemon on the compiled (build) js.

  1. In this directory run npm install, if you haven't already
  2. Open one terminal and run npm run watch
  3. Open another terminal and run npm run start-dev-bd
  4. Do your work in ./src

DB LOCAL!

Note: we now host the db remotely so you can skip this step unless you want to fiddle locally

Install mongo, docs

  1. sudo systemctl start mongod

  2. Check it booted sudo systemctl status mongod

  3. Connect mongosh

  4. Set the db (for dev) use firstround-dev

  5. Change the databaseUIR var in src/init/connectDB.ts to your local instance.

Modules

.
├── firebase-conf.json
├── firebase.json
├── package.json
├── package-lock.json
├── README.md
├── src
│   ├── entities
│   ├── index.ts
│   ├── init
│   ├── middleware
│   ├── resolvers
│   └── utils
├── storage.rules
└── tsconfig.json
  • tsconfig.json
    • This defines what the linter should complain about and to what detail
  • package.json holds the configs for dependencies and running the project
  • build holds the compiled js code generated by the bundler, you don't need to worry about this directory
  • src
    • entities is where schemas are defined using typegoose and type-gql decorators
    • index.ts is the heart of the server it starts the DMBS connection and handles top-level server configurations
    • init holds scripts to help with startup configurations
    • middleware defines middleware for use in @UseMiddleware() decorators
    • resolvers defines the primary logic for handling gql queries, most of the work happens here
    • utils assortment of helper functions and ts interfaces, importantly AppContext and jtw strategy is implemented here

Working With Cookies

To get CORS to behave and accept cookies you must change the CORs options in index.ts depending on the use case. At some stage i'll make this a runtime flag.

  1. If running the server for the frontend set the origin to process the CLIENT_ORIGIN environment variable
  2. If testing the server in apollo studio/playground set the origin to process the PLAYGROUND_OG environment variable

Note: if working in the playground you need to make sure that include credentials is turned on in the settings ⚙️ in the endpoint url.

Firefox: in firefox the cookie will not appear in the cookies list in storage when working in the apollo playground because Firefox has decided that any cookie with the domain localhost gets yeeted from the list. However, the cookie is actually present and will work correctly with the auth middleware.

Protecting Resolvers (Guards)

Sensitive API resolvers are protected from unauthenticated users based on whether:

  1. The client holds a valid (signed) JWT
  2. The clients valid JWT holds a specific user type

For the first case the Authorised middleware is used in the following fashion.

@UseMiddleware(Authorised)
@Query(() => String)
resolver(
    @Ctx() { jwtPayload }: any
) {
    // Only users with a valid token can cause this
    // resolver to fire

    // access to user info through `jwtPayload`
}

For the secondary case the above Authorised middleware must be called first to populate the context with the users JWT token. A secondary middleware can then be supplied to restrict access to the resolver based on user type/role. Valid secondary middleware's' are:

  • isBusiness
  • AdminRoute

Sample usage is as follows.

Note: middleware is called in the order it is defined.

@UseMiddleware(Authorised, isBusiness)
@Mutation(() => String)
adminHealth(
    @Ctx() { jwtPayload }: any
) {
  // only authenticated business users
  // can trigger this resolver
}

Installing Packages

  • Install @types/ as devDependencies, npm i <package> --save-dev
  • Install everything else as normal