Skip to content

suny-poly-cs-club/attendance-app-backend

Repository files navigation

Running

Docker Compose Instructions (recommended)

Development -- uses nodemon to automatically restart the server when changes are made

# copy `.env.example` to `.env` and change values accordingly
$ cp .env.example .env
# start the app
$ pnpm dev
# to stop everything, ctrl+c then run:
$ docker compose down

Production

# copy `.env.example` to `.env` and change values accordingly
$ cp .env.example .env
# start everything
$ docker compose up -d
# stop everything
$ docker compose down

Without Docker Compose

# copy `.env.example` to `.env` and change values accordingly
$ cp .env.example .env
# install external dependencies
$ pnpm install
# run database migrations
$ dbmate up
# run app
$ node src/index.js # runs the app on default port (3000)
$ PORT=8000 node src/index.js # runs the app on port 8000

Docs

Important

The following constraints exist and are enforced on various fields:

User:

  • password MUST be AT LEAST 5 characters
  • email MUST be AT MOST 255 characters
  • first, last name MUST be AT MOST 80 characters each

Club Day:

  • starts_at MUST COME BEFORE ends_at
  • ends_at MUST come AFTER the current time
  • the range from starts_at to ends_at MUST NOT OVERLP with another range

requests

  • Anywhere "Authorization" is present it refers to the http header of the same name
  • Omit<A, '',...> submit the object of the corresponding type but leave out specified information

Typedefs

type ISOTimestamp = string;
type Token = string;
type QRToken = string;

type User = {
  id: number;
  firstName: string;
  lastName: string;
  email: string;
  isAdmin: boolean; // default false
}

type ClubDay = {
  id: number;
  startsAt: ISOTimestamp;
  endsAt: ISOTimestamp;
  clubId: number;
}

type CheckIn = {
  id: number;
  userID: number;
  clubDayID: number;
  checkedInAt: ISOString;
}

Auth Routes

Register User

Request

POST /sign-up
Content-Type: application/json

{
 fisetName: string.
 lastName: string,
 email: string,
 password: string
}

Response

200 OK
Content-Type: application/json

{token: Token}

Log In

Request

POST /login
Content-Type: application/json

{email: string; password: string}

Response

200 OK
Content-Type: application/json

{token: Token}

Club Day Routes

Note

All of these routes require authentication, and the user to be a service admin (isAdmin=true) or and admin of the club.

Get All Club Days For a Club

Request

GET /clubs/<id>/club-days
Authorization: Token

parameter

Response

200 OK
Content-Type: application/json

ClubDay[]

Create Club Day

Request

POST /clubs/<id>/club-days
Authorization: Token
Content-Type: application/json

Omit<ClubDay, 'id'>

Response

200 OK
Content-Type: application/json

ClubDay

Get Club Day

Request

GET /clubs/<club id>/club-days/<club day id>
Authorization: Token

Response

200 OK
Content-Type: application/json

ClubDay

Get Club Day Attendees

Request

GET /clubs/<club id>/club-days/<club day id/attendees
Authorization: Token

Response

200 OK
Content-Type: application/json

User[]

Delete Club Day

Request

DELETE /clubs/<club id>/club-days/<club day id>
Authorization: Token

Response

200 OK
Content-Type: application/json

ClubDay

Get QR Token

Request

GET /clubs/<club id>/club-days/<club day id>/qr-token
Authorization: Token

Response

200 OK
Content-Type: application/json

{token: QRToken}

Get QR Code as PNG

Request

GET /clubs/<club id>/club-days/<club day id>/qr-token.png
Authorization: Token

Response

200 OK
Content-Type: image/png

NOTE: this is currently broken

Get QR Code as SVG

Request

GET /clubs/<club id>/club-days/<club day id>/qr-token.svg
Authorization: Token

Response

200 OK
Content-Type: image/svg+xml

Check In Routes

Check In

Request

POST /check-in
Authorization: Token
Content-Type: application/json

{code: QRToken}

Response

204 No Content

Get Club Name From Day Code

Request

GET /check-code/<QRToken>

Response

200 OK
Content-Type: application/json

{name: string}

Check if the current user has signed into this club Day

Request

POST /check-code/<QRToken>
Authorization: Token

Response

200 OK
Content-Type: application/json

{checkedIn: boolean}

User Routes

Get Current User

Request

GET /user
Authorization: Token

Response

200 OK
Content-Type: application/json

User

Get All Users

Request

GET /users
Authorization: Token (requires isAdmin=true)

Response

200 OK
Content-Type: application/json

[User]

Search Users

Request

POST /users/search
Authorization: Token
Content-Type: application/json

{querey: string} (space seperated list of words to search)

Response

200 OK
Content-Type: application/json

[User]

Modify a user (change weather they are a service admin)

Request

PATCH /users/<id>
Authorization: Token  (requires isAdmin=true)
Content-Type: application/json

{service_admin: boolean}

Response

204 No Content
Content-Type: application/json

User

Club Admin Routes

Note

All of these routes require authentication, and the user to be a service admin (isAdmin=true) or and admin of the club.

Get All Clubs a user is admin of

note: service admins are automaticly admin of all clubs Request

GET /clubs
Authorization: Token

Response

200 OK
Content-Type: application/json

[{id:number , name: string}]

Get All admins of a Clubs

note: service admins are automaticly admin of all clubs Request

GET /clubs/<id>/admins
Authorization: Token

Response

200 OK
Content-Type: application/json

[Users]

Make a User an Admin of a Club

Request

POST /clubs/<id>/admins
Authorization: Token
Content-Type: application/json

{userId: number, clubId: number}

Response

200 OK
Content-Type: application/json

{userId: number, clubId: number, isAdmin: boolean}

Make a User no Longer an Admin of a Club

Request

DELETE /clubs/<club id>/admins/<user id>
Authorization: Token
Content-Type: application/json

{userId: number, clubId: number}

Response

200 OK
Content-Type: application/json

{userId: number, clubId: number, isAdmin: boolean}

Create a New Club

Request

POST /clubs
Authorization: Token
Content-Type: application/json

{name: string}

Note: the user must be a service admin

Response

200 OK
Content-Type: application/json

{id: number, name: string}

Delete a club

Request

DELETE /clubs/<id>
Authorization: Token

Note: user must be a service admin

Response

200 OK
Content-Type: application/json

{id: number, name: string}

Error Codes

200 OK

A 200 error is the success code. This means the request completed successfully.

204 No Content

204 is another success code. It is used when the operation was successful, but there is no data to be returned.

400 Bad Request

A 400 error means bad the server received bad input. The error format will be one of the following:

// Form validation error (ex: login, sign up, create club day)
{
  type: 'validation_arror',
  issues: [
    name: string[], // which form field the error came from
    errors: string[] // the reason validation failed
  ]
}

// Non validation error
{
  message: string // the error message
}

401 Unauthorized

401 unauthorized is given when the supplied token is invalid. If you receive a 401 status code from any request, assume your token expired, and force the user to log back in (through a request to log in).

403 Forbidden

Getting a 403 forbidden status code means the user tried to access a resource they don't have access to. This is most likely a result of a non-admin user trying to access an admin-only resource.

404 Not Found

A 404 status code means the resource does not exist.

409 Conflict

A 409 error means the resource already exists. An example of this being used is trying to register an account for an email that already has an account.

500 Internal Server Error

500 errors should not happen. If one happens, that means there is an unhandled error somewhere in the API.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •